Notifications
Clear all

[Closed] Execute maxscript safely from external program

 MZ1

I found an article showing there is a way to execute code safely in the main thread of 3ds Max:
http://area.autodesk.com/blogs/chris/25-things-you-probably-didn039t-know-about-the-3ds-max-sdk

Execute code safely in the main thread in 3ds Max by either creating a Windows timer object using the main 3ds Max window as the window handle, or by using the following function to trigger code as soon as 3ds Max is idle next.
#define WM_TRIGGER_CALLBACK WM_USER+4764
void PostCallback( void (*funcPtr)(UINT_PTR), UINT_PTR param )
{
  PostMessage( GetAppHWnd(), WM_TRIGGER_CALLBACK, 
    (UINT_PTR)funcPtr, (UINT_PTR)param );
}

Can anyone show me an example of how we can use those functions to execute a maxscript by using SDK?

14 Replies

not sure how you want to used this or if it actually has any value. but here’s one way of doing it.

as an mxs extension function…

void executeScript(MCHAR* script)
  {
  	ExecuteMAXScriptScript(script,TRUE);
  }
  
  #define WM_TRIGGER_CALLBACK WM_USER+4764
  
  def_visible_primitive(delayedscript, "delayedscript");
  
  Value* delayedscript_cf(Value** arg_list, int count)
  {
  	check_arg_count(delayedscript, 1, count);
  	MCHAR* script = arg_list[0]->to_string();
  	PostMessage(MAXScript_interface->GetMAXHWnd(), WM_TRIGGER_CALLBACK, (UINT_PTR)&executeScript, (UINT_PTR)script);
  	return &ok;
  }

then in a start up script use the following…

fn OLEExecuteScript script = ( delayedscript script; )
  registerOLEInterface #(OLEExecuteScript)

then say from something like python you could run a script like this assuming you have Max OLE installed and running

import win32com.client;
  
  MaxApp = "MAX.Application"
  script = "for i = 1 to 100 do print i"
  max_functions = ["OLEExecuteScript"];
  
  conn = win32com.client.Dispatch(MaxApp);
  for funcs in max_functions: # add our OLE functions
  	conn._FlagAsMethod(funcs);
  
  conn.OLEExecuteScript(script) ; 

not sure on the claim about it waiting on max to be idle to run. It will interrupt an in progress render to run the script. Anyway hope it gives you pointers on how to use it.

I really doubt doing it in the above manner has any benefit over doing it something like this…

an mxs extension function

def_visible_primitive(runscript, "runscript");
 
 Value* runscript_cf(Value** arg_list, int count)
 {
 	check_arg_count(runscript, 1, count);
 	ExecuteMAXScriptScript(arg_list[0]->to_string(),TRUE);
 	return &ok;
 }

then the start up script OLE registration

fn OLERunScript script = ( runscript script; )
 registerOLEInterface #(OLERunScript)

an then from python

import win32com.client;
 
 MaxApp = "MAX.Application"
 script = "for i = 1 to 100 do print i"
 max_functions = ["OLEExecuteScript","OLERunScript"];
 
 conn = win32com.client.Dispatch(MaxApp);
 for funcs in max_functions: # add our OLE functions
 	conn._FlagAsMethod(funcs);
 
 conn.OLERunScript(script) ; 

you can cut out the middle man an just register the mxs extension function with

registerOLEInterface #(runscript)

then from python it would be

import win32com.client;

MaxApp = "MAX.Application"
script = "clearlistener();
 for i = 1 to 100 do print i"
max_functions = ["OLEExecuteScript","runscript"];

conn = win32com.client.Dispatch(MaxApp);
for funcs in max_functions: # add our OLE functions
	conn._FlagAsMethod(funcs);

conn.runscript(script) ; 
1 Reply
(@jonadb)
Joined: 11 months ago

Posts: 0

Are you sure those are thread-safe? If you alter the Max’s scene from anything but the main thread it crashes.

For what it’s worth, here is a mxs implementation I once used in another project. You can push lines of mxs on to the array from any external thread and they are safely executed in max’s main thread:


 fn scanScript = (
 
 	if (script_queue.count>0) do
 	(
 		scr=script_queue[1];
 		deleteItem script_queue 1
 		
 		try(
 		
 			execute scr
 		
 		) catch
 		(
 			print "*ERROR*"
 		)
 	)   
 )
 scriptExecuter = dotNetObject "System.Windows.Forms.Timer"
 dotnet.addEventHandler scriptExecuter "tick" scanScript
 scriptExecuter.interval = 100
 scriptExecuter.start()
 
 script_queue=#("print 12345", "print 67890")
 

I think so using the COM interface to “MAX.Application” will connect to the main max application thread which will then call the function.

 MZ1

My first goal is to protect Maxscript for commercial use. secend, I want to create trial-registration system (not by cloud!).
I’m pretty sure that:

  • Maxscript,plugin dll and web socket methods are not safe.
  • Using multiple Max as the same time is not possible by using OLE system.
  • Only safe encryption method is to use an exe file.
    So I decided to use SDK,C++,exe… or any external program that help. My main challenge is to run a maxscript inside opened max from encrypted win32 executable written by cpp.
3 Replies
(@spacefrog)
Joined: 11 months ago

Posts: 0

Why not embed the maxscript you want to protect inside a DLX or DLU ?
You could implement any encryption routines you want in a plugin without having to care for external Max<> Exe communication. Make the plugin project structure flexible enough, implement some strong encryption mechanisms using/allowing different keys -> Sell the result to Max developers=immediate win
But i guess in reality everything will be cracked, and such an idea would’nt be the first or last to fail ultimately. Or maybe i’m misunderstandig your goals completely…

 MZ1
(@mz1)
Joined: 11 months ago

Posts: 0

Are you sure plugins(DLL,DLX,…) are safe? I think plugins are crackable either.

(@denist)
Joined: 11 months ago

Posts: 0

everything is crackable… including an external program.

you should be able to use that PostMessage function from any exe your problem is then getting Hwnd for the main max window to post it on, probably iterating through all the open windows with win32 api function EnumWindows should do it. You might be also able link to the maxscript libraries and call the ExecuteMaxScriptScript function too.

I don’t think that particular (postmessage)functionality wins you anything, I don’t think it’s of any benefit to anyone.

“Anything devised by a human mind can be solved by a lesser or equal mind” – Sherlock Holmes

 MZ1

So, How we can make a plugin commercial?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

using c++ and max sdk is probably most secure solution today. who do you want to sell the product? if you want to sell it to companies you are absolutely safe. not any serious company wants to work legally on the market and use cracked software. if you want to sell it to individuals, it’s very unlikely that hackers will be very interested by hacking 10-40 buck thing. of course someone can crack it just for fun and find a way to distribute it… but it must be cool plugin in this case just only your name associated with this plugin will make you more money than the plugin itself being sold.