Notifications
Clear all

[Closed] Test plugin written on C# without reloading 3d MAX

something in the back of my mind says that dll error might be something to do with admin rights

I run max with the admin rights so it is unlikely to be the issue.

__declspec(dllexport) ULONG CanAutoDefer()
{
return 1;
}
__declspec(dllexport) ULONG CanAutoDefer()
{
return 0;
}

tried bothof these CanAutoDefer
doesn’t affect the error dialog

for some reason if I run this code after the unloadPlugin

(
fn pad val w:10 pc:"_" =
(
	if w > 0 then
	( 
		if isKindOf pc string and pc != "" then -- pad with char
		(
			(dotNetObject "system.string" (val as string)).padRight w pc
		)
		else
		(
			(dotNetObject "system.string" (val as string)).padRight w
		)
			
	)
	else
	if w < 0 then ( (dotNetObject "system.string" (val as string)).padLeft -w )
	else ( val as string )
)

dd = (dotNetClass "Autodesk.Max.GlobalInterface").Instance.dlldir.instance

for i=0 to dd.count-1 do
(
	plug = dd.item i 
	format "%: %loaded:%defferable:%\n" (pad i w:-3) (pad plug.FileName w:34 pc:"_") (pad plug.IsLoaded w:8) (try (plug.IsDeferrable) catch ("[ error ]"))

)

)

it clearly shows that max don’t really delete the class when we call UnloadPlugin

306: materialid_modifier.dlm___________loaded:false___defferable:[ error ]
307: partgrav.dlm______________________loaded:false___defferable:true
308: proteus.dlm_______________________loaded:false___defferable:true

upd…
nope, class is actually deleted from OSM modifiers list

next thing to try is to substitute timestamp of new dll with the old one.
upd2
it didn’t worked out either

I rediscovered my work around for the Deferred DLL error… in the post build script I get the Modification Date and Time from the Destination file, copy the file then set the new file to the saved Modification Date and TIme from the previous file

As I mentioned it didn’t work for me, for unknown reason
I did these three steps manually, without any errors, but after step 3 max becomes unusable…

-- Step 1. reset, save timestamps and unload
dll_path = @"path-to-dlm"
file = (dotNetClass "system.io.file")
created  = file.GetCreationTime   dll_path
accessed = file.GetLastAccessTime dll_path
modified = file.GetLastWriteTime  dll_path
unloadPlugin "materialid_modifier.dlm" -- returns true

-- Step 2.compile fresh dll in VS

-- Step 3. Update timestamps and reload dlm
file.SetCreationTime   dll_path created
file.SetLastAccessTime dll_path accessed
file.SetLastWriteTime  dll_path modified
LoadDllsFromDir (getdir #maxroot + "plugins\\") "materialid*.dlm" -- returns true, but DOESN'T load a thing

I had to remove my mod button from here. It was the reason why max become unusable on plugin reload
%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5

btw…
(dotNetClass “Autodesk.Max.GlobalInterface”).Instance.DllDir.instance.LoadADll “materialID_Modifier.dlm” true
still shows Deferred DLL error dialog

woohoo… it kinda works
LoadDllsFromDir is the one to blame
I have to load my plug manually through Customize > Plug-in Manager interface
Thanks, Klvnk. Without your help it wouldn’t be possible at all.

it’s always going to be a flakey process, but as it’s only for helping with dev so if it works 50% of the time it’s a win. Also try and keep your plugin out of the UI till it’s finished (specifically keep it off the command panel buttons) as it i’ll crash max for sure.

this my load plugin code btw

def_visible_primitive(loadPlugin, "loadPlugin");

Value* loadPlugin_cf(Value **arg_list, int count)
{
	check_arg_count(loadPlugin, 1, count);
	const TCHAR* name = arg_list[0]->to_string();

	DllDir *dd = MAXScript_interface->GetDllDirectory();

	TCHAR theDir[MAX_PATH];
	for(int q = 0; q < dd->Count(); q++)
	{	
#if MAX_VERSION_MAJOR > 13 
	DllDesc *dsc = const_cast<DllDesc *>(&(*dd)[q]);
#else
	DllDesc *dsc = &(*dd)[q];
#endif

#if MAX_VERSION_MAJOR > 13 
		if(_tcsicmp(dsc->GetFileName(), name)==0)
		{
			//_tcscpy(dsc->GetFileName(), name);
			_tcscpy(theDir, dsc->GetDirectoryName());
		}
#else
		if(_tcsicmp(dsc->fname, name)==0)
		{
			//_tcscpy(dsc->fname, name);
			_tcscpy(theDir, dsc->directory);
		}
#endif

		
	}
	
#ifdef _UNICODE
	bool loaded = dd->LoadADll(wcscat(theDir,name),TRUE);
#else
	bool loaded = dd->LoadADll(strcat(theDir,name),TRUE);
#endif
	if(loaded)
		DeepRefreshUI(MAXScript_interface);
 
	return bool_result(loaded);
}

Yep, placing it into the ui was reckless for sure.
Thanks for the code.

upd.
I’ve added postbuild event to hardcode the filetime attributes to keep them from change
nircmd.exe setfiletime “$(TargetDir)$(TargetFileName)” “01-01-2000 00:00:00” “01-01-2000 00:00:00”

Now it takes a couple of seconds to reload a modifier! Fantastic!

upd2
And what is even greater than that is that I can recompile it while debugging in Hybrid mode and my breakpoints are still there and working. Well, at least if I don’t change much code

Page 4 / 4