PowerShell是一个命令行工具,但是您知道吗,它也可以用作图形界面的基础?有时,命令行不是特定实例的最佳界面。为您的服务台构建PowerShell GUI是一个很好的例子。这是更适合构建图形工具的时候之一。
PowerShell可以使用和公开.NET功能。可以为您创建的脚本编写GUI前端。构建PowerShell GUI可能看起来很复杂,特别是如果您是初学者。但是,如果您具有PowerShell脚本编写的基本经验,那么您就没有理由不学习和适应为脚本创建GUI的做法。
在本文中,您将学习如何使用Windows Presentation Framework(WPF)创建PowerShell GUI。
先决条件
潜水之前,请确保您满足以下要求:
- Visual Studio 2017或更高版本–您将使用它来使用WPF创建图形用户界面。您可以下载免费/社区版本。
- 脚本编辑器–我使用Visual Studio Code,但是您也可以使用其他选择的文本编辑器。其他一些选项是Notepad ++和内置的PowerShell ISE
- 装有Windows PowerShell v5.1的Windows 10计算机。
构建脚本
在本文中,您将创建一个名为Main.ps1的简单脚本。该脚本将通过查询Win32_LogicalDisk WMI类从本地或远程系统提取磁盘信息。
您首先需要一个脚本来包装GUI。我选择使用一个脚本,该脚本允许您提供计算机名称和查询磁盘信息。但是,这绝对不是构建GUI所必需的。使用您在本文中学到的技术使GUI适应您自己的脚本。
作为示例脚本,我将创建一个执行以下操作的函数:
- 接受输入要查询的计算机名称
- 查询计算机并将固定磁盘信息存储到变量
- 返回结果
功能
以下是您将用于此项目的函数,恰当地命名为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
然后添加代码以执行以下操作:
- 导入并读取表单的XAML代码。
- 动态创建分配给每个命名控件的变量
- 显示表格
以下是脚本中的更新代码。
注意:确保修改该行$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显示结果
- ..等等
您可以根据自己的要求修改和添加功能。