当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 核心 Out-Gridview 解决方案

作者:精品下载站 日期:2024-12-14 07:54:15 浏览:11 分类:玩电脑

PowerShell 核心 Out-Gridview 解决方案


正如你们许多人所知,今年我已经转向 PowerShell Core 作为我的“日常驱动程序”。一个主要的驱动因素是发现局限性。当我们进入跨平台世界时,肯定有很多优势。但 PowerShell Core 基于 .NET Core,它并不包含我们在完整 Windows 桌面中习惯的所有内容。许多人担心的主要限制之一是失去对图形工具的支持。 PowerShell Core 不支持 Windows 窗体或 WPF。也许我听到的最大的哀叹是失去了 Out-Gridview。我得到它。该命令可能是一个有用的工具。现在,如果我告诉您,您可以在 PowerShell Core 中运行命令,并且仍然将结果发送到您熟悉和喜爱的 Out-Gridview 命令,该怎么办?

要求

我的解决方案实际上只不过是一种解决方法,假设您正在运行 Windows 桌面(例如 Windows 10),这意味着您可以访问 Windows PowerShell。我的解决方案背后的前提非常简单:获取 PowerShell Core 命令的输出并将其发送到运行 Out-Gridview 的 Windows PowerShell 实例。只要您可以在 Windows PowerShell 会话中使用 Out-Gridview,并且我无法想象为什么您不能,那么您就一切就绪了。

PowerShell Core 的 Out-Gridview 替代方案

我的解决方案的重要部分是运行 PowerShell.exe 命令来启动新实例。在提示符处,如果您键入 powershell /?,您将看到语法。我最初尝试将 PowerShell Core 输出作为脚本块的参数发送。但脚本块的大小有限制。所以我采取了我能想到的下一个最佳步骤。我获取 PowerShell 核心命令的输出,并使用 Export-Clixml 将其序列化为文件。在 PowerShell.exe 脚本块中,我使用 Import-Clixml 将其转换回来,并将结果通过管道传输到 Out-Gridview。

我想尽可能地复制 Out-Gridview 的功能。我希望能够显示结果或显示并选择。我遇到的挑战是,当仅显示 Out-Gridview 时,Windows PowerShell 窗口会在您看到任何内容之前打开和关闭。使用 -Passthru 可以提供您期望的体验。我的解决方案是在最后添加一个 Pause 语句。这将使 Windows PowerShell 窗口保持打开状态,直到您按 Enter 键。您仍然可以将对象传递回 PowerShell Core。

这个魔法的代码位于 Github 上。

Send-ToPSGridview.ps1:

#requires -version 6.1

Function Send-ToPSGridView {

 get-childitem c:\scripts\*.ps1 | Send-ToPSGridview -title "My Scripts"
Press Enter to continue...:

Display all ps1 files in Out-Gridview. You must press Enter to continue.
.EXAMPLE
PS C:\>  get-service | where status -eq 'running' | Send-ToPSGridView -Passthru | Restart-service -PassThru
Press Enter to continue...:

Status   Name               DisplayName
------   ----               -----------
Running  BluetoothUserSe... Bluetooth User Support Service_17b710
Running  Audiosrv           Windows Audio

Get all running services and pipe to Out-Gridview where you can select services which will be restarted.
.EXAMPLE
PS C:\> $val = 1..10 | Send-ToPSGridView -Title "Select some numbers" -Passthru
Press Enter to continue...:
PS C:\> $val
4
8
6
PS C:\> $val | Measure-Object -sum

Count             : 3
Average           :
Sum               : 18
Maximum           :
Minimum           :
StandardDeviation :
Property          :

Send the numbers 1 to 10 to Out-Gridview where you can select a few. The results are saved to a variable in the PowerShell Core session where you can use them.
.INPUTS
System.Object
.OUTPUTS
None, Deserialized.System.Object[]
.NOTES
Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/
#>

    [cmdletbinding()]
    [alias("ogv")]
    [OutputType("None", "Deserialized.System.Object[]")]

    Param(
        [Parameter(Position = 0, ValueFromPipeline, Mandatory)]
        [ValidateNotNullOrEmpty()]
        [object[]]$InputObject,
        [ValidateNotNullOrEmpty()]
        [string]$Title = "Out-GridView",
        [switch]$Passthru
    )
    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN  ] Starting $($myinvocation.mycommand)"
        #validate running on a Windows platform`
        if ($PSVersionTable.Platform -ne 'Win32NT') {
            Throw "This command requires a Windows platform with a graphical operating system like Windows 10."
        }
        #initialize an array to hold pipelined objects
        $data = @()

        #save foreground color
        $fg = $host.ui.RawUI.ForegroundColor

    } #begin

    Process {
        Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Adding object"
        $data += $InputObject
    } #process

    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Creating a temporary xml file with the data"
        $tempFile = Join-Path -path $env:temp -ChildPath ogvTemp.xml
        $data | Export-Clixml -Path $tempFile

        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Starting up a PowerShell.exe instance"
        PowerShell.exe -nologo -noprofile -command {
            param([string]$Path, [string]$Title = "Out-Gridview", [bool]$Passthru)
            Import-Clixml -Path $path | Out-Gridview -title $Title -passthru:$Passthru
            #a pause is required because if you don't use -Passthru the command will automatically complete and close
            $host.ui.RawUI.ForegroundColor = "yellow"
            Pause
        } -args $tempFile, $Title, ($passthru -as [bool])

        if (Test-Path -Path $tempFile) {
            Write-Verbose "[$((Get-Date).TimeofDay) END    ] Removing $tempFile"
            Remove-Item -Path $tempFile
        }

        #restore foreground color
        $host.ui.RawUI.ForegroundColor = $fg
        Write-Verbose "[$((Get-Date).TimeofDay) END    ] Ending $($myinvocation.mycommand)"
    } #end

} #close Send-ToPSGridView

我什至添加了 ogv 别名。

[玩转系统] PowerShell 核心 Out-Gridview 解决方案

您可以看到我正在 Windows 平台上运行 PowerShell Core。我将 Get-Process 的结果传递给 Out-Gridview,指定窗口标题并使用 -Passthru。这与 Out-Gridview 命令相同。

[玩转系统] PowerShell 核心 Out-Gridview 解决方案

我可以选择项目并单击“确定”。结果写回 PowerShell Core 管道并存储在 $P 中。您会注意到暂停消息。在该函数中,我暂时更改主机前景色以使其脱颖而出。我怀疑很多人都在运行黄色背景,但如果是这样,你就需要调整该功能。

局限性

我的解决方案并非没有一些缺点。因为我使用的是 Clixml cmdlet,所以序列化和反序列化会产生一些开销。添加磁盘时间和启动 Windows PowerShell 进程的时间,所有开销就会加起来。这不一定是无法忍受的,但你需要认识到这是要付出代价的。只要您不尝试将 10K 文件对象发送到 Out-Gridview,我认为您不会抱怨太多。当然,您始终可以有所选择。

[玩转系统] PowerShell 核心 Out-Gridview 解决方案

我希望你们中的一些人能够获取该函数的副本并让我知道您的想法。请在 Github 要点的评论部分报告任何问题、疑问或请求。如果这让您远离 PowerShell Core,我希望您现在重新考虑并与我一起迈出这一步。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯