从Powershell ISE中的附加组件菜单调用自定义函数

时间:2015-06-05 01:24:08

标签: powershell menu powershell-v3.0 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,它始终只是第一个函数名的String值。

我明白这是因为-Script值及其要求将其值包含在花括号中...但我不能为我的生活找出如何克服这一点。

有没有办法让这些功能从附加组件菜单运行,就像你手动将它们输入控制台一样?

提前致谢。

1 个答案:

答案 0 :(得分: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,我认为这样更容易。

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

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