Notifications
Clear all

[Closed] Send Maxscript commands from External App to 3dsmax

I’ve searched google about this and roughly got 5 to 6 threads explaining how to send maxscript commands to 3dsmax from an external program.

I did tried all the alternatives posted here and elsewhere but none of them is working in flawless manner. Though the EXTERNAL MAXSCRIPT IDE ( http://www.scriptspot.com/3ds-max/scripts/external-maxscript-ide ) works fine but I cannot integrate this into my application.

In maya, we have something called command port, I am looking for something like that.

I tried creating dotnet command port for listening mxs commands, but its quite buggy.

Any help will be appreciated.

(I am using DELPHI for making programs.)

28 Replies

not sure if this is an up-to-date methodology but in max 10 i use the
mxs registerOLEInterface system. only for for very simple stuff mostly, tell max to save the file and then shut down from a post plugin build python script. It’s a bit fiddly to set up but afterward pretty straight foward.

type “OLE automation” in mxs help index for more info

yes, simple stuff like sending “max preview”, no issues. problem starts with the complicated stuff, like creating custom dialogs,rollouts.

The code below is use to create a socket for listening on port 7500.

Fn BackgroundTcpListenerDoWork theSender theEvent = 
(
	IPAddress = DotNetClass "System.Net.IPAddress"
	theIPAddress = IPAddress.Parse "127.0.0.1"
	theTcpListener = DotNetObject "System.Net.Sockets.TcpListener" theIPAddress 7500
	theTcpListener.Start()
	theString="";
	theSocket = theTcpListener.AcceptSocket()
	while theString!="exit" do
	(
		theByteStream = DotNetObject "System.Byte[]" 10000
		theSocket.Receive theByteStream
		Encoding = DotnetClass "System.Text.Encoding"
		theString = trimright (Encoding.UTF8.GetString(theByteStream))

		if theString!="" do (try(execute theString)catch(print "Error Occured!") )

	)
	theTcpListener.Stop()
	theSocket.Close()
)

BackgroundWorker = DotNetObject "System.ComponentModel.BackgroundWorker"
DotNet.AddEventHandler BackgroundWorker "DoWork" BackgroundTcpListenerDoWork 
BackgroundWorker.WorkerSupportsCancellation = true
BackgroundWorker.RunWorkerAsync()

Ok, to make this more interesting I’m sharing the stuff I built.

Attached is the EXE file which sends MXS Commands to 3dsmax.

It works fine when we send easy MXS commands like max preview, but if I send this command,

rollout myRollout "My Dialog" width:162 height:147
(
	button btn1 "My Button" pos:[24,14] width:117 height:53
	checkbox chk2 "My Checkbox" pos:[17,89] width:133 height:19
)
createDialog myRollout

3dsmax stops responding till the time I close my exe program.

If anyone have any clue about what’s wrong then please help.

interesting challenge…

I think part of the problem is using the backgroundworker. Although it works fine for a lot of commands it seems to have trouble with “createdialog”, in your case at least. Maybe you could try to use a timer object instead of a backgroundworker+while loop. If max freezes there’s also the windows.processpostedmessages() command which will breathe back life into max.

David

2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

the backgroundworker is not a friend for any max UI creation. i might be wrong but every max ui element (including dialog) can be created only in the same as max thread. maybe .net forms can be made in another thread.

(@coolankur49)
Joined: 10 months ago

Posts: 0

So, what do you suggest, how do I go about creating dialogs.

One more issue is that if I open any native 3dsmax dialog like “max vptconfig” and try to send message (switch tab, check checkbox, etc) using my external program, it simply doesn’t work.

windows.processpostedmessages() doesn’t help.

Gave a try with Timer also, max ui stilll freezes on create dialog.

3 Replies
(@denist)
Joined: 11 months ago

Posts: 0

i don’t believe. what timer do you use? and how do you use it?

(@coolankur49)
Joined: 10 months ago

Posts: 0
IPAddress = DotNetClass "System.Net.IPAddress"
theIPAddress = IPAddress.Parse "127.0.0.1"
theTcpListener = DotNetObject "System.Net.Sockets.TcpListener" theIPAddress 7500
theTcpListener.Start()
theString=""
print "Socket Open!"
theSocket = theTcpListener.AcceptSocket()

Fn BackgroundTcpListenerDoWork= 
(
	while theString!="exit" do
	(
		theByteStream = DotNetObject "System.Byte[]" 10000
		theSocket.Receive theByteStream
		Encoding = DotnetClass "System.Text.Encoding"
		theString = trimright (Encoding.UTF8.GetString(theByteStream))
		if theString!="" do try(execute theString;)catch(print "Error Occured!")
	)
	
	theTcpListener.Stop()
theSocket.Close()
)

myTimer =DotNetObject "System.Timers.Timer"
myTimer.Interval = 5000
dotnet.addEventHandler myTimer "Elapsed" BackgroundTcpListenerDoWork
myTimer.Start()

Command:

rollout myRollout "My Dialog" width:162 height:147
(
	button btn1 "My Button" pos:[24,14] width:117 height:53
	checkbox chk2 "My Checkbox" pos:[17,89] width:133 height:19
)
createDialog myRollout
myTimer.Stop()

(@denist)
Joined: 11 months ago

Posts: 0

you still do UI creation in other than MAX thread…
here is a sample that shows how creation in right thread (FORMS TIMER) works and in wrong thread (TIMERS TIMER) doesn’t


 /*
 tt = dotnetobject "System.Timers.Timer"
 tt.Interval = 1000
 
 fn makeRollout s e = 
 (
 	rollout rol "From Timer" width:200
 	(
 		button bt "Button" pos:[4,4] width:190 
 	)
 	createDialog rol
 	s.Stop()
 )
 dotnet.addEventHandler tt "Elapsed" makeRollout
 tt.Start()
 */
 
 tt = dotnetobject "System.Windows.Forms.Timer"
 tt.Interval = 1000
 
 fn makeRollout s e = 
 (
 	rollout rol "From Timer" width:200
 	(
 		button bt "Button" pos:[4,4] width:190 
 	)
 	createDialog rol
 	s.Stop()
 )
 dotnet.addEventHandler tt "Tick" makeRollout
 tt.Start()
 

if you run commented part of the code above it freezes the max.

Actually I thought you should use the timer instead of the while function. Checking every 100 milliseconds if a new string has arrived.

I have never used these dotnet functions, but you might even need to open and close the socket each time…

1 Reply
(@coolankur49)
Joined: 10 months ago

Posts: 0

As denis said and as I think that the real problem is the creation of UI in right thread.

denis code

 tt = dotnetobject "System.Windows.Forms.Timer"
 tt.Interval = 1000
 
 fn makeRollout s e = 
 (
 	rollout rol "From Timer" width:200
 	(
 		button bt "Button" pos:[4,4] width:190 
 	)
 	createDialog rol
 	s.Stop()
 )
 dotnet.addEventHandler tt "Tick" makeRollout
 tt.Start()

works fine, but I need to send MXS command from an external program. If I stop the timer on every successful execution then how do I send the next command.

I also tried various combinations using timer and open close socket, but no luck.

This kind of freezing is different from what I am talking about.

Here you have to restart 3dsmax, but in my case, I can send the destroydialog command to get back the max ui.

Page 1 / 3