OWASP O2 Platform Blog

Adding an O2 Menu to Notepad++ and ‘listen’ to menu selections

When working on the TeamMentor 3.0 project, I started using Notepad++ to edit its *.HTML and *.cs files. Naturally, after a while, I wanted to access the TeamMentor development automation capabilities that I had already created using O2, so my solution was to add top-level menu to Notepad++ 🙂

Using O2’s Gui automation APIs (including its new API_InjectMenu_AnotherProcess.cs capability) I was able to add a new menu to Notepad++, which is ‘watched’ by a running instance of O2 (who responds to the selected O2 menu items).

Here is what the menu looks like:

Here is what the O2 Script that ‘listen’ to the commands from Notepad++ looks like:

And here is the source code that makes this possible:

var currentScript = PublicDI.CurrentScript;
var currentDirectory = currentScript.directoryName();
API_GuiAutomation guiAutomation = null;
Window mainWindow = null;
var injectedMenu = new API_InjectMenu_AnotherProcess();
injectedMenu.ProcessToInject = "notepad++";
injectedMenu.InjectedProcess_WindowTitle = "Notepad++ (TeamMentor version)";

var teamMentor = new API_TeamMentor();

var commands = new Dictionary<string,Action>();
Action<string> executeH2Script_TM =
O2Thread.mtaThread(()=> currentDirectory.pathCombine(scriptToExecute).executeH2Script());

Action<string> executeH2Script_O2 =
O2Thread.mtaThread(()=> scriptToExecute.local().executeH2Script());

var lastFileResolved = "";

Func<string> getCurrentFilePath =
if (lastFileResolved.valid() && lastFileResolved.fileName() == mainWindow.tabs()[0].SelectedTab.name())
"found previously resolve path whose filename matchs the current selected tab text".info();
return lastFileResolved;
catch(Exception ex) { "in getCurrentFilePath :{0}".error(ex.Message); }
mainWindow.menu("Edit").mouse();//.click(); // this is a issue/bug here which blocks the execution thread when clicking directly on the UIAutomation element
.menu("Copy to Clipboard").mouse();
.menu("Copy to Clipboard")
.menu("Current Full File path to Clipboard").mouse();
var filePath = "".clipboardText_Get();
if (filePath.valid())
lastFileResolved = filePath;
return filePath;
"could not get current filepath".error();
return null;

Action<string> compileScript =
"scriptToCompile: {0}".info(scriptToCompile);
if (scriptToCompile.extension(".h2"))
new CompileEngine().compileSourceFile(scriptToCompile);

Action<string> executeScript =
if (scriptToCompile.extension(".h2"))
new CompileEngine().compileSourceFile(scriptToCompile).executeFirstMethod();

commands.add( "Compile current script file", ()=> compileScript(getCurrentFilePath()))
.add( "Build TM Web Project (MsBuild)", ()=> teamMentor.website_CSProj().runMsBuild())
.add( "Build TM OnlineStorage (MsBuild)", ()=> teamMentor.webServices_Sln().runMsBuild("/t:Rebuild"))
.add( "Start WebServers", ()=> teamMentor.start_WebService().start_WebSite() )
.add( "Open v3.0 TeamMentor Website (new window)" , ()=> teamMentor.view_3_0_WebSite_InNewWindow())
.add( "Open v2.5 TeamMentor Website (new window)" , ()=> teamMentor.view_WebSite_InNewWindow())
.add( "View TeamMentor ContentViewer (via webservices)", ()=> executeH2Script_TM("Tool - TeamMentor - ContentViewer (via webservices).h2"))
.add( "Editing TM asp.net pages", ()=> executeH2Script_TM(@"Tools\Util - Editing TM asp.net pages .h2"))
.add( "TeamMentor- Custom O2", ()=> executeH2Script_TM("TeamMentor- Custom O2.h2"))
.add( "TeamMentor- IE Automation", ()=> executeH2Script_TM("TeamMentor- IE Automation.h2"))
.add( "Execute current script file", ()=> executeScript(getCurrentFilePath()))
.add( "open current script file in SourceCodeEditor", ()=> getCurrentFilePath().showInCodeEditor())
.add( "Close notepad++ Process" , ()=> injectedMenu.InjectedProcess.stop())
.add( "Write and Execute Unit Tests;", ()=> executeH2Script_O2("Write and Execute Unit Tests.h2"));

injectedMenu.MenuTitle = "O2 Menu (for TeamMentor)";
var initialId = 02000;
foreach(var command in commands)
injectedMenu.MenuCommands.add(initialId++, command.Key);
injectedMenu.CommandSelected =
(id, commandKey)=>{
"[InjectedMenu] Command Received: {0}".debug(commandKey);
O2Thread.mtaThread(()=> commands[commandKey]());;

"now using GuiAutomation".info();
guiAutomation = new API_GuiAutomation(injectedMenu.InjectedProcess);
mainWindow = guiAutomation.window(injectedMenu.InjectedProcess_WindowTitle);

var menu = mainWindow.menu(injectedMenu.MenuTitle)
return "here";

//      .menu("Exit").mouse().click();

//using White.Core.UIItems.WindowItems
//using O2.SecurityInnovation.TeamMentor

June 30, 2011 - Posted by | .NET, Interoperability

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: