从 Powershell ISE 中的加载项菜单调用自定义函数

call custom functions from Add-ons menu in 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] }
}

All good so far, when the profile is loaded, a submenu is created named "Company Modules" and each function is displayed within that menu - however when the function is selected, instead of 运行ning函数,它只是扩展 $cmd 的值,它始终只是第一个函数名称的字符串值。

我知道这是由于 -Script 值及其要求将其值包含在花括号中造成的。但我终究无法想出如何克服这个问题。

有没有什么方法可以让插件菜单中的功能 运行 完全像您手动将它们输入控制台一样?

提前致谢。

$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

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