From NuGet Package create Visual Studio menu entry

Nov 30, 2010 at 4:37 PM

I would like to implment the following scenario:

From a nuget package I want to add a Visual Studio menu entry on solution load. When this menu entry is clicked (event) I want to executed the a script block connected to the menu item even that is executed in the context of the nuget console.

Some of the following steps should be executed:

  1. In Init.ps1 a menu entry should be added
  2. A callback function should be defined in PowerShell
  3. the callback function must be hooked to the press menu item event

Any ideas on this scenario? Maybe even some example code? :-)

 

 

Coordinator
Nov 30, 2010 at 4:43 PM

No objection.

Phil

From: svdoever [mailto:notifications@codeplex.com]
Sent: Tuesday, November 30, 2010 8:38 AM
To: Phil Haack
Subject: From NuGet Package create Visual Studio menu entry [nuget:236539]

From: svdoever

I would like to implment the following scenario:

From a nuget package I want to add a Visual Studio menu entry on solution load. When this menu entry is clicked (event) I want to executed the a script block connected to the menu item even that is executed in the context of the nuget console.

Some of the following steps should be executed:

1. In Init.ps1 a menu entry should be added

2. A callback function should be defined in PowerShell

3. the callback function must be hooked to the press menu item event

Any ideas on this scenario? Maybe even some example code? :-)

Read the full discussion online.

To add a post to this discussion, reply to this email (nuget@discussions.codeplex.com@discussions.codeplex.com)

To start a new discussion for this project, email nuget@discussions.codeplex.com@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Nov 30, 2010 at 11:30 PM
Edited Nov 30, 2010 at 11:35 PM

I got somewhere, but not far enough... The menu entry appears (right-click on solution), but I can't get the event handler connected...

PM> $sol = $DTE.CommandBars | Where-Object { $_.Name -like 'Solution' }
PM> $menuitem = $sol.Controls.Add([Microsoft.VisualStudio.CommandBars.MsoControlType]::msoControlButton, 1, "", 1, $true)
PM> $menuitem.Caption = "Action From NuGet"
PM> $menuItemHandler = $DTE.Events.CommandBarEvents($menuitem)
PM> $commandBarEvents = Get-Interface $menuItemHandler ([EnvDTE._dispCommandBarControlEvents_Event])
PM> $commandBarEvents.add_Click([EnvDTE._dispCommandBarControlEvents_ClickEventHandler]{Write-Host “Clicked”})
Cannot convert value "Write-Host “Clicked”" to type "EnvDTE._dispCommandBarControlEvents_ClickEventHandler". Error: "The type 'System.Boolean&' may not be used as a type argument."
At line:1 char:84
+ $commandBarEvents.add_Click([EnvDTE._dispCommandBarControlEvents_ClickEventHandler] <<<< {Write-Host “Clicked”})
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
 
PM>

The last line gives the trouble...

 

I patterned this after code executed by nuget itself in nuget.psm1:

# Hook up Solution events

$solutionEvents = Get-Interface $dte.Events.SolutionEvents ([EnvDTE._dispSolutionEvents_Event])

$solutionEvents.add_Opened([EnvDTE._dispSolutionEvents_OpenedEventHandler]{
    ExecuteInitScripts
    UpdateWorkingDirectory
})

$solutionEvents.add_AfterClosing([EnvDTE._dispSolutionEvents_AfterClosingEventHandler]{
    UpdateWorkingDirectory
})

Any ideas on how to get the eventhandler connected?

Nov 30, 2010 at 11:45 PM

I have found it is way easier to write this code in c# and then load then hand a reference for a dte object in your init.ps1 script

sent from my mobile

On Nov 30, 2010 5:30 PM, "svdoever" <notifications@codeplex.com> wrote:
Nov 30, 2010 at 11:55 PM

I have no problem in writing the menu entry code in c# as long as I can execute PowerShell code from this menu entry in the context of the nuget console.

We have ten-thousands of lines in PowerShell in a Factory, I would like to distribute functionality through nuget packages, and be able to execute functions in these packages through menu items.

Would you write the menu entries with c# in VSIX packages? That would be a no-go for us. Only required installation may be a nuget package.

Or is it possible to have c# classes in your PowerShell script and make classes from them with Add-Type? How could then a PowerShell script block be called from the c# event handler in the context of the nuget PowerShell host? Using a custom PowerShell host this would be no problem... but that is what we have now, I want to use the nuget host.

 

Dec 1, 2010 at 3:15 AM
You do not need to use a vsix.. here is an example of loading up the assemblies from the init.ps1
The callbacks into powershell might be tricky but I bet you can make it work with a dynamic type inside of the library. You could probably make some helper functions in your library so that you can just add the menu name and hand a reference to a delegate that would execute the proper commandlet.
Dec 2, 2010 at 11:53 AM
Edited Dec 2, 2010 at 12:05 PM

Found the loading of the assemblies. Could have a library with a generic function to generate menu items based on an xml structure containing name, tooltip and action in PowerShell script. We do that now in our factory. Problem is the part of executing a PowerShell string in the context of the nuget console from this library. Can you be more specific about the dynamic type approach?

I have been looking at variables I have in PowerShell that I could pass to this library function for execution of PowerShell. For example $host.runspace, but that one has the value $null. I could create an additional runspace from PowerShell, copy over all variables and functions from the powershell, an provide that runspace to the library, problem is that we then have a snapshot of the nuget console state, and don't execute in the same runspace as the interactive runspace (could also be an advantage...). I could even execute the same nuget load scripts that call Init.ps on all packages, but then new package installs will not be picked up.

Dec 2, 2010 at 1:50 PM
When you register the menu items you would need to pass in a reference to the host. or store it in a static of the assembly that loads the menu items. That is why you would load the assembly from the init.ps1. So that you can load it into the powershell console and pass the reference to your call back functions.
On Thu, Dec 2, 2010 at 5:53 AM, svdoever <notifications@codeplex.com> wrote:

From: svdoever

Found the loading of the assemblies. Could have a library with a generic function to generate menu items based on an xml structure containing name, tooltip and action in PowerShell script. We do that now in our factory. Problem is the part of executing a PowerShell string in the context of the nuget console from this library. Can you be more specific about the dynamic type approach?

Read the full discussion online.

To add a post to this discussion, reply to this email (nuget@discussions.codeplex.com@discussions.codeplex.com)

To start a new discussion for this project, email nuget@discussions.codeplex.com@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com