如何使用Windows Presentation Framework(WPF)创建PowerShell GUI

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

PowerShell可以使用和公开.NET功能。可以为您创建的脚本编写GUI前端。构建PowerShell GUI可能看起来很复杂,特别是如果您是初学者。但是,如果您具有PowerShell脚本编写的基本经验,那么您就没有理由不学习和适应为脚本创建GUI的做法。

在本文中,您将学习如何使用Windows Presentation Framework(WPF)创建PowerShell GUI。

先决条件

潜水之前,请确保您满足以下要求:

  1. Visual Studio 2017或更高版本–您将使用它来使用WPF创建图形用户界面。您可以下载免费/社区版本
  2. 脚本编辑器–我使用Visual Studio Code,但是您也可以使用其他选择的文本编辑器。其他一些选项是Notepad ++和内置的PowerShell ISE
  3. 装有Windows PowerShell v5.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接受字符串值的参数。另外,通过添加Mandatoryparameter属性,可以确保如果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

建立GUI

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

现在,您可以开始构建GUI。

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

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

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

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

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

创建一个新的Visual Studio项目

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

选择一个Visual Studio项目

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

Visual Studio MainWindow.xaml

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

  • 窗口
    • 标题:磁盘信息
    • 高度:326
    • 宽度:403
  • 控制(4)
    • 标签
      • 内容:“计算机名称:”
      • 边距:10,10,0,0
    • 文本框
      • 名称:txtComputer
      • 文字:“”
      • 高度:23
      • 宽度:174
    • 纽扣
      • 名称:btnQuery
      • 内容:查询
      • 边距:0,13,12,0
    • 文本框
      • 名称:txtResults
      • 文字:“”
      • IsReadOnly:正确
      • 边距:10,60,0,0
      • 高度:225
      • 宽度:373

表单的最终外观应类似于下图所示。您可以不同地重新排列窗口的布局。有创造力!

PowerShell GUI模板

结合脚本和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脚本运行此代码时,应该看到下面的示例输出。

PowerShell GUI变量和字段映射

如您所见,三个命名控件被分配了变量。当我们添加控制逻辑代码时,这些变量名将在脚本的后面引用。

  • var_btnQuery
  • var_btnComputer
  • var_txtResults

请记住,此时脚本只能显示表单,但是控件尚未使用,因为您尚未添加代码。

添加按钮单击事件代码

现在,您已经成功修改了脚本以导入和显示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

成品代码

在涵盖所有部分的情况下,以下是我们脚本的完整代码,其中包含我们设计的功能和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\Administrator\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 GUI示例结果

概要

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

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

  • 格式化大小和可用空间以显示为GB值
  • 更改显示的属性的名称
  • 使用GridView而不是TextBox显示结果
  • ..等等

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

 

猜你喜欢

转载自blog.csdn.net/allway2/article/details/109556558