2015-06-05 31 views
1

我开发了一组函数,供我们的桌面和服务台团队使用,并且已经为每个加载模块的工作人员部署了一个自定义PowerShell ISE配置文件包含所有功能的文件。从Powershell的附加组件菜单中调用自定义函数ISE

我被要求让他们更加用户友好,所以我下一个合乎逻辑的想法是在附加组件菜单项下的PSISE中创建一个自定义菜单。

知道我将不断向模块文件中添加新功能,我不想硬编码任何菜单项 - 我希望菜单项能够准确反映在配置文件加载时存在或可用的功能。

我的第一个想法是创建一个加载的当前函数列表,然后循环遍历每个函数并将项添加到加载项菜单中,如下所示。

env:PSModulePath = $env:PSModulePath + ";\\remotelocation\Modules" 
$CommandList = Get-Command -Module "CompanyModules" | Select-Object Name -ExpandProperty Name 

function Add-ISEMenuItem([String]$MenuName,[String]$Name,[ScriptBlock]$Script,[String]$Shortcut) 
{ 
    try{ 
     if ($Shortcut) { $Menus[$MenuName].Submenus.Add($Name, $Script, $Shortcut) | Out-Null } 
     else { $Menus[$MenuName].Submenus.Add($Name, $Script,$null) | Out-Null } 
    } 
    catch { 
     Write-Warning $_ 
    } 
} 

function Add-ISESubMenu([String]$MenuName,[String]$Name) 
{ 
    try 
    { 
     if (-not ($menus -contains $MenuName)) 
     { 
      $menus[$Name] = $menus[$MenuName].SubMenus.Add($Name,$null,$null) 
     } 
     else 
     { 
      throw "Menu name already used" 
     } 
    } 
    catch 
    { 
     Write-Warning $_ 
    } 
}  

############################################################################## 
# Setting up the PowerShell_ISE environment 
############################################################################# 

$menus = @{} 
$menus["AddOns"] = $psISE.CurrentPowerShellTab.AddOnsMenu 

Add-ISESubMenu -MenuName "AddOns" -Name "Company Modules" 

$count = $CommandList.count 

for ($i = 0; $i -lt $count; $i++) 
{ 
    $cmd = $CommandList[$i] 
    Add-ISEMenuItem -MenuName "Company Modules" -Name "$cmd" -Script { $cmd[0] } 
} 

所有好为止,当配置文件被加载时,会创建一个子菜单名为“企业模块”和各功能显示的菜单中 - 然而,当功能被选择,而不是运行功能,它只是扩展了$ cmd的值,它总是第一个函数名的字符串值。

我明白这是由于-Script的价值和它的要求,它的价值包含在大括号中..但我不能为我的生活弄清楚如何克服这一点。

有没有什么办法让功能从加载项菜单中运行,就像你手动输入控制台一样?

在此先感谢。

回答

0
$CommandList = Get-Command -Module "CompanyModules" | Select-Object Name -ExpandProperty Name 

什么你所做的是你只在$CommandList得到每个函数的名称。

因此,而不是让我们改成这样:

$CommandList = Get-Command -Module "CompanyModules" 

得到完整的命令对象。

然后,在脚本的底部:

$CommandList | ForEach-Object { 
    Add-ISEMenuItem -MenuName "Company Modules" -Name $_.Name -Script ([ScriptBlock]::Create($_.Definition)) 
} 

请注意,如果你愿意,你仍然可以使用你的for循环迭代的$CommandList,我只是觉得这是比较容易。

Get-Command返回的功能.Definition属性包含拼成的功能代码的[String]。您可以使用[ScriptBlock]::Create()将其转换为ScriptBlock。

你之前做的事情基本上只是传递一个打印出该函数名称的新脚本块。

+0

感谢@briantist 具有很多意义 - 我必须记住get-member的真正价值! 最后一件事 - 代码是肯定执行的,但有什么办法可以抑制函数定义被转储到屏幕上吗? – DangerBen

+0

我不确定,但我猜不。这与执行未保存的文件时的行为是相同的,所以我认为它在内部以相同的方式处理它。 – briantist