.NET Assembly Loader
 
 
 

A new plug-in loader has been created specifically for .NET plug-ins which makes it safer for 3ds Max to load and unload .NET and mixed-mode 3ds Max plug-ins. Assemblies (DLLs) which contain .NET or C++/CLI plug-ins should now be placed in the bin/assemblies subfolder of the 3ds Max installation, instead of the plugins folder. The AssemblyLoader class is contained in maxsdk/assemblies/AssemblyLoader.dll and the 64 bit version can be found in maxsdk/x64/assemblies/AssemblyLoader.dll.

Using the Assembly Loader

The assembly loader loads plug-ins from the bin/assemblies folder in the 3ds Max program folder. Each plug-in is given a chance to execute some initialization code. The assembly loading process happens in four phases:

  1. All assemblies in the bin/assembly and its subdirectories are loaded into memory.
  2. The loader executes the first entry point method that it finds in each assembly. An entry point method must exist on a public type and must match one of the following two signatures:
    • public static void AssemblyMain()
    • public static void AssemblyMain(AssemblyLoader.Loader loader)

    This second form is passed the current executing loader object. This form is useful if an assembly needs to examine types from other loaded classes during the next loading phase.

  3. The loader examines every publicly exported type from each loaded assembly and passes each type in turn to its TypeLoaded event handlers.
  4. When completed the loader executes the first clean up method that it finds in each assembly. As with AssemblyMain, this method must exist on a public type and must match one of the following two signatures for the Loader to recognize it:
    • public static void AssemblyInitializationCleanup()
    • public static void AssemblyInitializationCleanup(AssemblyLoader.Loader loader)

    Note that it is not necessary to remove the TypeLoaded event handlers. These are cleared automatically at the end of the clean-up phase.

When the application shuts down, the loader runs over all loaded assemblies and calls a shutdown method. For the Loader to recognize the method, the method must exist in a public type, and it must match one of the following two signatures:

These shutdown methods can be used to release any native resources and to delete any remaining native objects. Each hook indicated above is entirely optional. The plug-in designer may choose to use none, any, or all of these hooks: the AssemblyMain method, TypeLoaded event handlers, the AssemblyInitializationCleanup method, or the AssemblyShutdown method.

It is important that .NET assemblies avoid native global objects: objects allocated during DLL load, and released only during DLL shutdown. This includes every type other than basic primitives or arrays of primitives. Any actual object (class or struct) would have a constructor or destructor, even if it is generated by the compiler, and executing the constructor at load time or the destructor during application termination may cause the execution of managed code outside the CLR's lifetime. This can cause the application to crash, or to enter a deadlock. Instead of global objects, plug-ins should use dynamically allocated objects explicitly constructed during AssemblyMain(), and explicitly destructed during AssemblyShutdown().