top of page

Run and Test Plug-In Scripts from Visual Studio

Testing Plug-in Scripts


Testing plug-in scripts in Eclipse is annoying at best. For one, any time you make a change to the script you need to re-start Eclipse, or it'll lock up your script DLL and won't even let you compile.


Another problem with running your script in Eclipse is that you can't use the debugger (easily). It would be nice if you could just press F5 in Visual Studio and run your script, set up breakpoints, or step through your code line by line.


PluginTester


To help with these problems, Eduardo Acosta (a former software developer at the University of Michigan, now at Varian) wrote PluginTester, available at the Varian Developers Forum.


PluginTester is a stand-alone app that creates an Eclipse Application object and calls your script's main method. If you add the PluginTester project to your solution, you can run it from Visual Studio and step through the code, including yours.


PluginTester is a great tool for running and debugging your scripts, but it has one drawback: it requires that you edit its code to specify the method to call in your script. And you need to do this for every new script you write.


EclipsePlugInRunner


To address this drawback, I wrote a new tool based on PluginTester, which I've creatively called EclipsePlugInRunner. You don't need to modify its code in order to run your script. Additionally, your script doesn't need to know about EclipsePlugInRunner. In other words, neither library references the other. After all, the tool is there only for running it from Visual Studio and won't be needed once your script is running in Eclipse.


I've made the source code available on GitHub: EclipsePlugInRunner. But the best way to start using it is through NuGet. First, open a plug-in script you'd like to run in Visual Studio. Add the following method to your Script class:


public void Run(
    User user,
    Patient patient,
    Image image,
    StructureSet structureSet,
    PlanSetup planSetup,
    IEnumerable<PlanSetup> planSetupsInScope,
    IEnumerable<PlanSum> planSumsInScope,
    Window mainWindow)
    {
        // Your main code now goes here
    }

This method is now your "main" method, so any code that used to be in the Execute method should go here. Notice that there's no ScriptContext anymore. EclipsePlugInRunner will call the Run method, but because it can't create a ScriptContext object, it needs to pass the context members individually. This means that you'll need to either (1) modify any code that uses the ScriptContext to use the member objects instead, or (2) create your own wrapper to contain the context members and use it instead.


The Execute method should now just call the Run method and pass the appropriate members:


public void Execute(ScriptContext scriptContext, Window mainWindow)
{
    Run(scriptContext.CurrentUser,
        scriptContext.Patient,
        scriptContext.Image,
        scriptContext.StructureSet,
        scriptContext.PlanSetup,
        scriptContext.PlansInScope,
        scriptContext.PlanSumsInScope,
        mainWindow);
}

Now, add a new WPF Application project to your solution. If your script's project is named MyScript, you can call the WPF project something like MyScript.Runner. Remove the MainWindow.xaml file, which will also remove the associated MainWindow.xaml.cs file.


Right-click on the WPF project and select "Manage NuGet Packages..." Search for "esapi" and you should see the EclipsePlugInRunner package. Install it. (Update: If you're using ESAPI 13.6, use version 1.0.0. If you're using ESAPI 15.5, use version 2.0.0.)


Right-click on the WPF project again and select "Add Reference..." Choose the "Projects" item on the left bar, and check the project that contains the main Script class.


Open the App.xaml file and replace the StartupUri line with the following:


Startup="App_OnStartup"

Open the App.xaml.cs file and add the following handler:


private void App_OnStartup(object sender, StartupEventArgs e)
{
    ScriptRunner.Run(new Script());
}

Make sure that you've added the correct using statements (in this case, EclipsePlugInRunner.Scripting and VMS.TPS). EclipsePlugInRunner uses the x64 ESAPI assemblies, so you'll need to set the WPF project's CPU to x64 as well. Also, set the project as the "Start Up" project.


Finally, reference the Varian assemblies VMS.TPS.Common.Model.API and VMS.TPS.Common.Model.Types. If you're using ESAPI 15.5 and above, you'll need to force the compiler to include the Varian assemblies (see post Fix UnauthorizedScriptingAPIAccessException). To do this, add the following method to App.xaml.cs:


// Fix UnauthorizedScriptingAPIAccessException
public void DoNothing(PlanSetup plan) { }

Running Your Script


When you start the application, you'll be prompted for your username as password. These are the same you use to log in to Eclipse. A window will show up, which looks somewhat similar to PluginTester:


(Image to be added.)


Enter the patient ID1, click Open, and choose the PlanSetup(s) or PlanSum(s) you'd like to be in scope. Then, choose the PlanSetup that you'd like to be active. Click on Run and your script will run with the context you've chosen (you can also double-click on the active PlanSetup in order to run your script).


Recent contexts will be displayed at the top, where you can double-click on one and quickly run your script with that context. If you click on Open for a recent context, you'll be able to modify the context and run the script with that. Recent contexts are automatically saved in the bin\Debug or bin\Release directory of the WPF Application in your project.


When you've run your script and then closed it, you'll go back to the Runner window. You may open another patient or context and run the script again. If you want the Runner window to automatically close when you close your script, choose the "Exit after plug-in script ends" option at the bottom.


Open Source


EclipsePlugInRunner is open source, so you can submit issues, fork it, or send pull requests. It's not a finished product and can use many improvements. Feel free to contribute!

Related Posts

See All

ESAPI Essentials 1.1 and 2.0

A few months ago, I introduced ESAPI Essentials—a toolkit for working with ESAPI (available via NuGet). I've recently added one major feature: asynchronous access to ESAPI for binary plugin scripts. Y

Announcement: ESAPI Subreddit

A few months ago, Matt Schmidt started the ESAPI subreddit. It's another useful resource for finding and discussing ESAPI-related topics. According to the description, This community is to post and di

Dump All Patient Data from ESAPI

If, for whatever reason, you need to dump out all of the data for a patient from ESAPI, there's a quick and dirty way to do it. Well, there are probably several ways to do it, but here's one I've foun

bottom of page