Tuesday, July 18, 2017

ProcDOT plugin writing. Part 4 - Context Menu and CanBeVerified

Throughout this tutorial, we learned how to write a plugin for the the Main Menu. Writing a plugin for the context menu isn't any different. There are a couple of options available for the context menu I would like to touch on though to help make your plugin a little more professional.

Context Menu plugins allow us to get more granular with the data we are after. Let's say we want a context menu item that is only available when we right click on a server node. The plugin engine offers this feature though the CanBeVerified switch.

Before we continue, lets alter our  cmd_line plugin so it becomes a Context Menu Item instead of being in the Main Menu. Open the cmd_line.pdp file in an editor and change the type from MainMenuItem to ContextMenuItemForGraph. Your pdp file should now look like this:

Name = cmd
Author = <your name>
Description = Open cmd prompt from ProcDOT's Main Menu
Version = 1
Type = ContextMenuItemForGraph
Architecture = WindowsBatchScript
File = cmd_line.bat
Priority = 9
RunHidden = 1
RunExclusively = 1
CanOverrideOtherPlugins = 0
CanOverrideProcdot = 0

Restart ProcDOT and load your graph again. If we right click anywhere on the graph, we should see cmd in the context menu. What we are trying to accomplish though is having a plugin show up if we right click on a server node. Lets right click on a server node an see what we need to do to have this happen.


In the command prompt enter the following:

 set | find /i "procdot"

You will notice that there are a lot more variables to choose from. Remember, this type of plugin allows us to get granular with what we are doing.


Looking through our list of options, it looks like PROCDOTPLUGIN_CurrentNode_name would be a good candidate for what we are doing. Notice it is telling us that this is a server node. With this information, we can try to get our  plugin to only show up if we right click on a server node.

To do this, we first have to set the CanBeVerified switch to 1 in our pdp file (add CanBeVerified = 1 to the end of the file). Lets stop ProcDOT and create our verify plugin. We'll start by creating a new pdp file called verify.pdp with the following content (Notice it has the CanBeVerified switch).

Name = Verify
Author = <your name>
Description = verify test
Version = 1
Type = ContextMenuItemForGraph
Architecture = WindowsBatchScript
File = verify.bat
Priority = 9
RunHidden = 0
RunExclusively = 1
CanOverrideOtherPlugins = 0
CanOverrideProcdot = 0
CanBeVerified = 1

RunHidden has also been set to 0 so we can see additional output. We can clean this up after our plugin is complete. When we set the CanBeVerified switch, a new ProcDOT variable called PROCDOTPLUGIN_VerificationRun is created and its initial value is set to 1. If the criteria for the verification passes, (in our case, is it a server node), this value will be set to 0 indicating the verification passed. If not, the value will remain 1. This will be a little easier to explain if I give you the code for the plugin and go through each part. Create a file called verify.bat with the following content:

 @setlocal enabledelayedexpansion && python -x "%~f0" %* & exit /b !ERRORLEVEL!

import os
import sys
verify = os.getenv('PROCDOTPLUGIN_VerificationRun')
   
if os.getenv('PROCDOTPLUGIN_VerificationRun') == '0':
    pass
   
else:   
    if os.getenv('PROCDOTPLUGIN_CurrentNode_name')[:6] == 'SERVER':
        print 'PROCDOTPLUGIN_VerificationRun = ' + verify
        raw_input('Yes. This is a server node.')
        sys.exit(1)
    else:
        print 'PROCDOTPLUGIN_VerificationRun = ' + verify
        raw_input('No. This is not a server node')
        sys.exit(0)

def main():
    print 'PROCDOTPLUGIN_VerificationRun = ' + verify
    raw_input('Verification complete.')

if __name__ == '__main__':
    main()

Lets take a closer look at what is going on.

if os.getenv('PROCDOTPLUGIN_VerificationRun') == '0':
    pass

This part of the code is telling the plugin, that if everything is verified, to skip or "pass" everything else and go to the main function. Remember, PROCDOTPLUGIN_VerificationRun is initially set to 1, so we are going to have to create a condition to set it to 0. this is were the next part o f the code comes into play.

else:   
    if os.getenv('PROCDOTPLUGIN_CurrentNode_name')[:6] == 'SERVER':
        print 'PROCDOTPLUGIN_VerificationRun = ' + verify
        raw_input('Yes. This is a server node.')
        sys.exit(1)
    else:
        print 'PROCDOTPLUGIN_VerificationRun = ' + verify
        raw_input('No. This is not a server node')
        sys.exit(0)

This  part of the code is responsible for verifying a condition for our plugin. In the if statement, we are using  the PROCDOTPLUGIN_CurrentNode_name variable to check if we are right clicking on a server node. If this is true, the plugin sets the exit code to 1. This will tell ProcDOT to change PROCDOTPLUGIN_VerificationRun to 0. If it is not a server node, the plugin will run the else statement and set the exit code to 0, leaving PROCDOTPLUGIN_VerificationRun set to 1. The print and raw_input statements are there for our debugging purposes so we can see what the plugin is doing.

After doing this check, if it is a server node, ProcDOT will set  PROCDOTPLUGIN_VerificationRun to 0 and initialize our plugin. Our plugin can now run the rest of its code under main. Lets continue and see it in action. Start ProcDOT and  refresh your graph.

The first thing we are going to do is right click on a server node. When we do this, you should see the following command prompt come up:


This is the place in the code we are at now:

    if os.getenv('PROCDOTPLUGIN_CurrentNode_name')[:6] == 'SERVER':
        print 'PROCDOTPLUGIN_VerificationRun = ' + verify
        raw_input('Yes. This is a server node.')
        sys.exit(1)

From here, hit enter. You will see the same command prompt come up again (ProcDOT does a double check for some reason). Hit enter one more time and then you should see the verify entry in the context menu.


If we left click on Verify, we should be presented with the following command prompt:


This is the place in the code we are at now:

def main():
    print 'PROCDOTPLUGIN_VerificationRun = ' + verify
    raw_input('Verification complete.')

if __name__ == '__main__':
    main()

Hit enter to clear the command prompt. So far it seems to be working. Lets do one more test to make sure it only shows up when we click on a server node. Now, right click anywhere except for on a server node. You should see the following command prompt:





This is the place in the code we are now:

else:
        print 'PROCDOTPLUGIN_VerificationRun = ' + verify
        raw_input('No. This is not a server node')
        sys.exit(0)

Hit enter, and then hit enter again. If everything worked, Verify should not show up in the context menu:
As you can see, you can set conditions for when your plugin will show up in the context menu. This is not just for a server node, this can be applied to any conditions you want met. All that you need to do to give it some function is to add your code to the main function. I hope I did a good job of explaining how this works. It can seem a little confusing at first.