Notifications
Clear all

[Closed] Script kills MacroRecorder somehow, why?

Hello, I’m working on a script, but when I run it, it kills the MacroRecorder in all Max versions before 2011.

Basicly I’m starting Max, turn on the MacroRecorder and it works fine, then starting my script and the MacroRecorder doesn’t show any output anymore. I’ve tested it with Max 9sp2, 2008, 2009, 2010, 2011 and only in Max 2011 the MacroRecorder isn’t affected (all versions are 32bit).

In my script I’m using DotNet controls, also ComboBoxes. ComboBoxes seem to have issues with the GarbageCollection gc() of Max. So I protected them using the solution in the last post of this thread. But I also tryed my script without the ComboBoxes and it still killed the MacroRecorder. I dunno what info would be useful to know for you guys. I’m showing my DotNet Form using .Show() (MaxCustomControls.MaxForm in Max 2008 and higher, System.Windows.Forms.Form just in Max 9sp2), the plugin Krakatoa for Max wasn’t installed on any of the Max versions (just mentioning it cause it seems Krakatoa + enabling its VFB extension can kill the MacroRecorder aswell).

It seems like a bug of 3ds Max / Maxscript handling of DotNet, which seems to be resolved in 2011. Maybe someone got a suggestion how to avoid this problem. For now the workaround is to open Max twice, one to run the script and one to get the MacroRecorder output, not very comfy. Thanks for help!

7 Replies

I’ve had the same problem from time to time using dotnet.
3dsMax 2011 here by the way…

I’ll try to figure out the steps to reproduce it, next time it happens.

We have the same issue with Krakatoa (which contains a lot of scripted code) killing the MacroRecorder, and I have been unable to pinpoint the real problem. I don’t even think it is dotNet related in my particular case.

After a lot of attempts I managed to get the MacroRecorder PARTIALLY working by removing a dozen simple MacroScripts that were interacting with the rest of the UI and by disabling the Krakatoa-specific VFB extensions. Still, I cannot get the MacroRecorder to work completely, short of uninstalling Krakatoa.

I would love to figure this one out… Good luck!

I do most of my scripting in plain maxscript in 3dsmax 9 and I’ve had the listener stop working many times.

Quite annoying, altho I’m beginning to rely on it less and less

Since MacroRecorder disable/enable calls are nested, my guess is that an exception is being thrown in between a pair of them:

try {
	macroRecorder->Disable(); 

		// Call some function that throws an exception.

	macroRecorder->Enable();
}
catch (...)
{
	// In the 'catch' we neglect to re-enable the recorder, and if the try/catch
	// is in maxscript we can't even access the recorder to enable it!
}

Here is an exception safe way of disabling the recorder suggested by the SDK:

{
	MacroRecorder::MacroRecorderDisable dummy;
	// Do some work that might throw an exception
}

The destructor for the MacroRecorderDisable will automatically re-enable the recorder.

To test my theory, I wrote a DLX that allowed me to directly manipulate the disable state:

Value* set_macrorecorder_state_cf(Value** arg_list, int count)
{
	check_arg_count(set_macrorecorder_state, 1, count);

	Interface* iface = GetCOREInterface();
	if (iface != NULL)
	{
		MacroRecorder* recorder = iface->GetMacroRecorder();
		if(recorder != NULL)
		{
			if (arg_list[0]->to_bool())
			{
				recorder->Enable();
			}
			else
			{
				recorder->Disable();
			}
			return recorder->Enabled() ? &true_value : &false_value;
		}
	}

	return &undefined;
}

Using this code I was able to simulate this pattern of execution and effectively ‘turn off’ the recorder.

Since disable operations are nested you ought to be able to get unstuck with something like:

while recorderIsDisabled() do enableRecorder()

Note: Even when the recorder was off and no commands were showing up I was still able to write directly to the recorder panel’s WindowStream using MXS code like:


	format "Hello, World!
" to:macrorecorder

If your recorder becomes disabled and you CAN’T print to that window then there is probably something more serious going on.

.biddle

I tryed to reproduce what causes the problem in my script on a basic example. The following script will kill the MacroRecorder in Max versions before 2011 as soon as you resize the form / the eventhandler will be triggered:

(
	Form = DotNetObject "MaxCustomControls.MaxForm"
  
	fn printTest = (print "when you read this, the macrorecorder is dead")
	
	DotNet.AddEventHandler Form "Resize" printTest
	
	Form.Show()
  )
  I also tryed the "Using DotNet Forms To Create MAXScript User Interfaces" example in the Maxscript Reference. It also kills the MacroRecorder as soon as the eventhandler will fire. I tryed to execute:
format "Hello, World!
" to:macrorecorder
   after the MacroRecorder was killed by my script. It worked and showed: "Hello, World!". I'm not familiar with the Max SDK but I can write .dll's and use them in Maxscript.
  
  Is there a way to write a .dll function to reactivate the MacroRecorder? (I wouldn't like to use .dlx since the script I'm writing is ment for portable use) Or is there a proof safe way to add eventhandlers to controls?

I experimented with what biddle mentioned and was able to enable and disable the MacroRecorder with a .dlx. I think it’s good to use “recorder->Cancel();” before calling “recorder->Enable();”, so the currently recorded macrostring will be aborted.

Then I tryed to reenable the MacroRecorder after showing a form and triggering a DotNet eventhandler, but no success.

I found a workaround for my problem. The following code should work. Instead of DotNet.addEventHandler, it uses a wrapper rollout so the eventhandlers can be added to the controls by using standard rollout methods.

(
       	rollout Roll "" (
       		
       		DotNetControl Form "MaxCustomControls.MaxForm"
       		
       		fn printTest = (print "when you read this, the macrorecorder is still alive")
       		
       		on Form resize do printTest()
       	)
       	
       	createDialog Roll
       	Roll.Form.Show()
       )
  Bad thing is you got the form also as rollout and the rollout has to stay open in order to keep the eventhandler alive. But you can just hide the rollout to an offscreen position and keep it there (not very nice, but should work). Good thing is the MacroRecorder stays alive.[b] [/b]All other controls that going to be added to the form have to be defined as DotNetControl in the rollout and can be added to the form in the event "on Roll open do (...)".