Wednesday, March 10, 2010

Using RevitPythonShell to dynamically load plugins for debugging

Ever since I read Jeremy Tammiks blog post Reload an Add-In to Debug, where he
describes about John Morse's technique for dynamically loading plugins without
having to restart Revit, I have been itching to get this working in
RevitPythonShell!

Finally, with revision 55 and the loadplugin script, I can rapidly iterate
working on my C# projects - no more waiting for Autodesk Revit to restart after
fixing a small mistake!

Here is a little sampe session from the project page:

>>>import loadplugin
>>># use actual path here... (if you don't already have RvtMgdDbg.dll installed, you probably want to go and do so 
>>># right now - check ADN!)
>>>assembly = loadplugin.loadAssembly(r'C:\...\Visual Studio 2008\Projects\RvtMgdDbg\bin\RvtMgdDbg.dll')
>>># result is an assembly object
>>>assembly

<Assembly RvtMgdDbg, Version=1.0.3671.26458, Culture=neutral, PublicKeyToken=null>

>>># pretty cool: IronPython lets you use the assembly like a namespace
>>># also note the use of the special predefined variables for executing plugins!
>>>assembly.RvtMgdDbg.CmdSnoopDb().Execute(__commandData__, __message__, __elements__)

(<Autodesk.Revit.IExternalCommand+Result object at 0x000000000000002D [Succeeded]>, '')
>>>


So how dows it work? Basically, you load an assembly as a byte array and then
use Assembly.Load to load the assembly from the byte array. Dynamically loading
assemblies this way does not lock them on the hard disk, allowing Visual Studio
to overwrite the DLLs at build time.

I suggest you write a test script for your plugin, that you can then save as a
canned command in RevitPythonShell, that loads it via loadplugin.loadAssembly and
does some exercising: Instantiate some types, execute IExternalCommand instances etc.

To make interaction with plugins easier, RevitPythonShell now supports some predefined variables, that give you more access to the context in which the plugin itself was loaded.
This lets you simulate the user clicking on PushButtons in the Ribbon.

Also, I have included a fork of the IronPythonTextBox control, to make plain interactive
use of RevitPythonShell smoother.

Please let me know, if this is of any use to you. Also, I would really appreciate some help, especially in getting the system more user friendly (e.g. script repository etc.).

No comments:

Post a Comment