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

[玩转系统] 如何为脚本构建 PowerShell GUI

作者:精品下载站 日期:2024-12-14 20:50:46 浏览:16 分类:玩电脑

如何为脚本构建 PowerShell GUI


PowerShell 是一个命令行工具,但您知道它也可以用作图形界面的基础吗?有时,命令行并不是特定实例的最佳界面。为您的服务台构建 PowerShell GUI 就是一个很好的例子。这是构建图形工具更合适的时候之一。

在帮助台重置密码时强制执行最终用户验证。使用 Specops Secure Service Desk 减少您的社会工程漏洞。联系我们获取演示!

PowerShell 可以使用和公开 .NET 功能和特性。因此,可以为您创建的脚本编写 GUI 前端。构建 PowerShell GUI 可能看起来很复杂,特别是如果您是初学者。

但是,如果您有 PowerShell 脚本编写的基本经验,那么您没有理由不学习和适应为脚本创建 GUI 的实践。

在本文中,您将学习如何使用 Windows 演示框架 (WPF) 创建 PowerShell GUI。

先决条件

在您投入之前,请确保您满足以下要求:

  1. Visual Studio 2017 或更高版本 - 您将使用它来创建使用 WPF 的图形用户界面。您可以下载免费/社区版本。
  2. 脚本编辑器 - 我使用 Visual Studio Code,但您也可以使用您选择的其他文本编辑器。其他一些选项包括 Notepad++ 和内置 PowerShell ISE
  3. 装有 Windows PowerShell 5.1 的 Windows 10 计算机

构建脚本

在本文中,您将创建一个名为 Main.ps1 的简单脚本。 在脚本中,您将编写代码,通过查询 Win32_LogicalDisk WMI 类从本地或远程系统提取磁盘信息。

您首先需要一个脚本来封装 GUI。我选择使用一个脚本,该脚本允许您提供计算机名称并查询磁盘信息。但这绝不是构建 GUI 所必需的。使用您在本文中学到的技术使您的 GUI 适应您自己的脚本。

作为示例脚本,我将创建一个执行以下操作的函数:

  1. 接受输入要查询的计算机名称
  2. 查询计算机并将固定磁盘信息存储到变量中
  3. 返回结果

编写函数

下面是您将用于此项目的函数,恰当地命名为 Get-FixedDisk。该项目的目的是获取有关目标计算机上的不可移动或固定磁盘的信息。

虽然这段代码可以按原样使用,但如果您只想执行快速查询,而不必每次都对函数进行点源并手动键入命令,那么创建 GUI 将很有帮助。

Function Get-FixedDisk {
    [CmdletBinding()]
    # This param() block indicates the start of parameters declaration
    param (
        <# 
            This parameter accepts the name of the target computer.
            It is also set to mandatory so that the function does not execute without specifying the value.
        #>
        [Parameter(Mandatory)]
        [string]$Computer
    )
    <#
        WMI query command which gets the list of all logical disks and saves the results to a variable named $DiskInfo
    #>
    $DiskInfo = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter 'DriveType=3'
   $DiskInfo
}

您可以看到我在代码中添加了一个 param() 块。这是为了指示函数根据指示的数据类型接受输入。

在示例中,我添加了一个接受字符串值的 Computer 参数。此外,通过添加 Mandatory 参数属性,可以确保如果在运行时未指定 Computer 参数,则该函数不会运行。

接下来,第 18 行显示了实际的 WMI 查询命令,该命令获取所有逻辑磁盘的列表并将结果保存到名为 $DiskInfo 的变量中。我还添加了一个过滤器以仅获取带有 DriveType=3 的磁盘。此过滤器确保仅显示有关本地固定磁盘的信息。

导入代码(点源)

此时,您已经有了一个工作脚本并准备好对其进行测试。但在测试脚本之前,您需要将代码导入到 PowerShell 会话中。将代码加载到 PowerShell 会话中的一种方法是通过点采购

要对脚本进行点源,请在脚本路径前键入一个点 (.) 和一个空格。如果脚本位于 C:\PoshGUI-sample 文件夹中,您可以像下面这样点源它。

PS C:\PoshGUI-sample> . .\Main.ps1

如果不在当前工作目录中,您还可以指定完整路径。在下面的示例代码中,您可以看到脚本的完整路径。

PS C:>. C:\PoshGUI-sample\Main.ps1

现在我们已经将代码导入到内存中,我们可以继续测试我们创建的函数。在下面的示例中,它显示了 Get-FixedDisk 函数用于查询计算机 poshLabExc

PS51> Get-FixedDisk -Computer poshLabExc

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 53037772800
Size         : 135838822400
VolumeName   : Windows

DeviceID     : D:
DriveType    : 3
ProviderName :
FreeSpace    : 14872641536
Size         : 17178750976
VolumeName   : Temporary Storage

DeviceID     : E:
DriveType    : 3
ProviderName :
FreeSpace    : 488202240
Size         : 524283904
VolumeName   : System Reserved

构建 PowerShell GUI

此时,您已经创建了名为 Main.ps1 的脚本文件,并在脚本内创建了函数 Get-FixedDisk。您还可以测试并确认该功能正在运行。

现在您知道该脚本可以工作,您可以开始构建 GUI。

设计 PowerShell GUI 表单

首先规划您希望 GUI 的外观以及您想要使用的元素。对于这个简单的示例,我们的 GUI 将具有:

  • 可以输入计算机名称的文本框
  • 执行该功能的按钮
  • 我们可以在其中显示结果的文本框

接下来,您可以开始构建它!

要开始创建 GUI,请打开 Visual Studio 并创建一个新项目。

Visual Studio 打开后,单击文件 (1) -> 新建 (2) -> 项目 ( 3)。

在“新建项目”窗口下,选择“Visual C#”(1),选择“WPF 应用程序 (.NET Framework)”(2 ),将名称更改为PoshGUI-sample (3),然后单击确定

创建项目后,将显示一个空白表单,其名称为 MainWindow.xaml

您现在需要格式化此表单以满足我们的要求。以下是您需要添加的控件和格式。

  • 窗户

    • 标题:磁盘信息
  • 身高:326
  • 宽度:403
  • 控制 (4)

    • 标签

      • 内容:“计算机名称:”
  • 保证金:10, 10, 0, 0
  • 文本框

    • 名称:txt电脑
  • 文本: ””
  • 身高:23
  • 宽度:174
  • 按钮

    • 名称:btn查询
  • 内容:查询
  • 保证金:0, 13, 12, 0
  • 文本框

    • 名称:txt结果
  • 文本: ””
  • 是否只读:True
  • 保证金:10, 60, 0, 0
  • 身高:225
  • 宽度:373
  • 表单的最终外观应类似于下图所示。您可以以不同的方式重新排列窗口的布局。有创意!

    结合脚本和 PowerShell GUI

    一旦您对设计感到满意,您现在就可以开始将其与脚本集成。

    PowerShell 无法本机显示表单。为了能够显示表单,我们需要在脚本的最顶部添加一行代码以支持 WPF 表单的呈现。

    Add-Type -AssemblyName PresentationFramework

    然后添加代码来执行以下操作:

    1. 导入并读取表单的 XAML 代码。
    2. 动态创建分配给每个命名控件的变量
    3. 显示表格

    以下是脚本中更新的代码。

    注意:请确保修改 $xamlFile 行并将其指向 MainWindow.xaml 文件的完整路径。

    Add-Type -AssemblyName PresentationFramework
    
    Function Get-FixedDisk {
        [CmdletBinding()]
        # This param() block indicates the start of parameters declaration
        param (
            <# 
                This parameter accepts the name of the target computer.
                It is also set to mandatory so that the function does not execute without specifying the value.
            #>
            [Parameter(Mandatory)]
            [string]$Computer
        )
        <#
            WMI query command which gets the list of all logical disks and saves the results to a variable named $DiskInfo
        #>
        $DiskInfo = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter 'DriveType=3'
        $DiskInfo
    }
    
    # where is the XAML file?
    $xamlFile = "C:\PoshGUI-sample\MainWindow.xaml"
    
    #create window
    $inputXML = Get-Content $xamlFile -Raw
    $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
    [XML]$XAML = $inputXML
    
    #Read XAML
    $reader = (New-Object System.Xml.XmlNodeReader $xaml)
    try {
        $window = [Windows.Markup.XamlReader]::Load( $reader )
    } catch {
        Write-Warning $_.Exception
        throw
    }
    
    # Create variables based on form control names.
    # Variable will be named as 'var_<control name>'
    
    $xaml.SelectNodes("//*[@Name]") | ForEach-Object {
        #"trying item $($_.Name)"
        try {
            Set-Variable -Name "var_$($_.Name)" -Value $window.FindName($_.Name) -ErrorAction Stop
        } catch {
            throw
        }
    }
    Get-Variable var_*
    
    $Null = $window.ShowDialog()

    注意:$Null=$window.ShowDialog() 必须始终是脚本中的最后一行代码。

    当您通过执行 Main.ps1 脚本来运行此代码时,您应该看到下面的示例输出。

    正如您所看到的,三个命名控件都被分配了它们的变量。稍后当我们添加控制逻辑代码时,将在脚本中引用这些变量名称。

    • var_btn查询
    • var_btn计算机
    • var_txt结果

    请记住,此时的脚本只能显示表单,但控件是无用的,因为您还没有添加代码。

    添加按钮点击事件代码

    现在您已成功修改脚本以导入和显示 GUI,开始将代码添加到控件以检索和显示磁盘信息数据。

    在此项目中,只有 btnQuery 按钮将被分配一个操作。其他控件仅用作输入和输出/显示控件。这意味着我们只需要向btnQuery添加click事件代码即可。

    要将点击操作添加到btnQuery,请将以下代码分配给其相应的变量名称$var_btnQuery。复制下面的代码并将其插入脚本中的 Get-Variable var_*$Null=$window.ShowDialog() 代码引用之间。

    $var_btnQuery.Add_Click( {
       #clear the result box
       $var_txtResults.Text = ""
           if ($result = Get-FixedDisk -Computer $var_txtComputer.Text) {
               foreach ($item in $result) {
                   $var_txtResults.Text = $var_txtResults.Text + "DeviceID: $($item.DeviceID)`n"
                   $var_txtResults.Text = $var_txtResults.Text + "VolumeName: $($item.VolumeName)`n"
                   $var_txtResults.Text = $var_txtResults.Text + "FreeSpace: $($item.FreeSpace)`n"
                   $var_txtResults.Text = $var_txtResults.Text + "Size: $($item.Size)`n`n"
               }
           }       
       })
    
    $var_txtComputer.Text = $env:COMPUTERNAME

    测试完成的 PowerShell GUI

    涵盖所有部分后,下面是我们脚本的完整代码,其中包含我们设计的函数和 PowerShell GUI。

    Add-Type -AssemblyName PresentationFramework
    
    Function Get-FixedDisk {
        [CmdletBinding()]
        # This param() block indicates the start of parameters declaration
        param (
            <# 
                This parameter accepts the name of the target computer.
                It is also set to mandatory so that the function does not execute without specifying the value.
            #>
            [Parameter(Mandatory)]
            [string]$Computer
        )
        <#
            WMI query command which gets the list of all logical disks and saves the results to a variable named $DiskInfo
        #>
        $DiskInfo = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter 'DriveType=3'
       $DiskInfo
    }
    
    #where is the XAML file?
    $xamlFile = "C:\Users\june\source\repos\PoshGUI-sample\PoshGUI-sample\MainWindow.xaml"
    
    #create window
    $inputXML = Get-Content $xamlFile -Raw
    $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
    [xml]$XAML = $inputXML
    #Read XAML
    
    $reader = (New-Object System.Xml.XmlNodeReader $xaml)
    try {
        $window = [Windows.Markup.XamlReader]::Load( $reader )
    }
    catch {
        Write-Warning $_.Exception
        throw
    }
    
    #Create variables based on form control names.
    #Variable will be named as 'var_<control name>'
    
    $xaml.SelectNodes("//*[@Name]") | ForEach-Object {
        #"trying item $($_.Name)";
        try {
            Set-Variable -Name "var_$($_.Name)" -Value $window.FindName($_.Name) -ErrorAction Stop
        } catch {
            throw
       }
    }
    
    Get-Variable var_*
    
    $var_btnQuery.Add_Click( {
       #clear the result box
       $var_txtResults.Text = ""
           if ($result = Get-FixedDisk -Computer $var_txtComputer.Text) {
               foreach ($item in $result) {
                   $var_txtResults.Text = $var_txtResults.Text + "DeviceID: $($item.DeviceID)`n"
                   $var_txtResults.Text = $var_txtResults.Text + "VolumeName: $($item.VolumeName)`n"
                   $var_txtResults.Text = $var_txtResults.Text + "FreeSpace: $($item.FreeSpace)`n"
                   $var_txtResults.Text = $var_txtResults.Text + "Size: $($item.Size)`n`n"
               }
           }       
       })
    
    $var_txtComputer.Text = $env:COMPUTERNAME
    $Null = $window.ShowDialog()

    如下所示,在 PowerShell 中调用脚本后,出现了 PowerShell GUI 窗口。然后您就可以输入有效的计算机名称来测试功能。

    使用身份验证方法安全地验证调用者,消除用户模拟的机会。使用 Specops Secure Service Desk 阻止服务台黑客。免费试用!

    概括

    在本文中,您学习了如何创建一个接受输入并返回结果的简单函数。您还学习了如何创建基本的 WPF PowerShell GUI 以及如何导入它以充当您创建的 PowerShell 脚本的前端。

    这只是一个基本的脚本和 GUI 组合。可以进行许多改进,例如:

    • 设置大小和可用空间的格式以显示为 GB 值。
    • 更改显示的属性的名称。
    • 使用GridView而不是TextBox来显示结果。
    • 添加导入按钮以循环浏览 CSV 文件中的服务器列表

    您可以根据自己的要求修改和添加功能。

    进一步阅读

    • WMI Win32_LogicalDisk 类
    • PowerShell 点采购
    • Windows Presentation Foundation
    • 在 PowerShell 中使用 WMI

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

    取消回复欢迎 发表评论:

    关灯