【发布时间】:2021-06-18 21:33:00
【问题描述】:
由于 PowerShell 构建在 .NET 框架之上,我可以使用 PowerShell 编写自己的自定义类吗?
我不是在谈论实例化 .NET 类……那部分很简单。我想使用 PowerShell 脚本编写自己的自定义类。可能吗?到目前为止,我的研究表明这是不可能的。
我还在学习 PowerShell,尽管搜索了几次,但到目前为止我还没有在这个网站上找到答案。
【问题讨论】:
标签: powershell
由于 PowerShell 构建在 .NET 框架之上,我可以使用 PowerShell 编写自己的自定义类吗?
我不是在谈论实例化 .NET 类……那部分很简单。我想使用 PowerShell 脚本编写自己的自定义类。可能吗?到目前为止,我的研究表明这是不可能的。
我还在学习 PowerShell,尽管搜索了几次,但到目前为止我还没有在这个网站上找到答案。
【问题讨论】:
标签: powershell
查看Add-Type cmdlet。它允许您在 PowerShell 中编写 C# 和其他代码。 例如(来自上面的链接),在 PowerShell 窗口中,
$source = @"
public class BasicTest
{
public static int Add(int a, int b)
{
return (a + b);
}
public int Multiply(int a, int b)
{
return (a * b);
}
}
"@
Add-Type -TypeDefinition $source
[BasicTest]::Add(4, 3)
$basicTestObject = New-Object BasicTest
$basicTestObject.Multiply(5, 2)
【讨论】:
我怀疑您正在寻找的解决方案是PowerShell Modules。它们执行类通常在其他语言中执行的角色。它们为您提供了一种非常简单但结构化的方式来重用您的代码。
这里是如何使用模块在 PowerShell 中获取类的功能。在命令行你可以这样做:
New-Module -ScriptBlock {function add($a,$b){return $a + $b}; function multiply($a,$b){return $a * $b}; function supersecret($a,$b){return multiply $a $b}; export-modulemember -function add, supersecret}
那么你就可以:
PS C:\> add 2 4
6
PS C:\> multiply 2 4
The term 'multiply' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:9
+ multiply <<<< 2 4
+ CategoryInfo : ObjectNotFound: (multiply:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS C:\> supersecret 2 4
8
正如你所见,multiply 在模块中是私有的。更传统地,您将实例化一个作为模块实例的对象。这是通过 -AsCustomObject 参数完成的:
$m = New-Module -ScriptBlock {function add($a,$b){return $a + $b}; function multiply($a,$b){return $a * $b}; function supersecret($a,$b){return multiply $a $b}; export-modulemember -function add, supersecret} -AsCustomObject
那么你可以:
PS C:\> $m.add(2,4)
6
PS C:\> $m.multiply(2,4)
Method invocation failed because [System.Management.Automation.PSCustomObject] doesn't contain a method named 'multiply'.
At line:1 char:12
+ $m.multiply <<<< (2,4)
+ CategoryInfo : InvalidOperation: (multiply:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
PS C:\> $m.supersecret(2,4)
8
这一切都展示了 dynamic 模块的使用,这意味着没有任何东西存储到磁盘以供重复使用。它适用于非常简单的功能。但是,如果您希望真正能够阅读代码并在以后的会话或脚本中重用它,您可能希望将其存储在 .psm1 文件中,然后将该文件存储在具有相同名称的文件夹中(减去扩展名)作为文件。然后,您可以在命令行或其他脚本中将模块导入会话。
作为一个例子,假设我使用了这段代码:
function Add{
param(
$a,
$b
)
return $a + $b
}
function Multiply{
param(
$a,
$b
)
return $a + $b
}
function SuperSecret{
param(
$a,
$b
)
return Multiply $a $b
}
Export-ModuleMember -Function Add, SuperSecret
并将其保存到文件夹中名为 TestModule.psm1 的文件中:C:\Windows\System32\WindowsPowerShell\v1.0\Modules\TestModule
PowerShell 安装文件夹中的 Modules 文件夹是一个神奇的文件夹,其中存储的任何模块都对 Import-Module cmdlet 可见,而无需指定路径。现在,如果我们在命令行中运行Get-Module -List,我们会看到:
ModuleType Name ExportedCommands
---------- ---- ----------------
Script DotNet {}
Manifest FileSystem {Get-FreeDiskSpace, New-Zip, Resolve-ShortcutFile, Mount-SpecialFolder...}
Manifest IsePack {Push-CurrentFileLocation, Select-CurrentTextAsVariable, ConvertTo-Short...
Manifest PowerShellPack {New-ByteAnimationUsingKeyFrames, New-TiffBitmapEncoder, New-Viewbox, Ne...
Manifest PSCodeGen {New-Enum, New-ScriptCmdlet, New-PInvoke}
Manifest PSImageTools {Add-CropFilter, Add-RotateFlipFilter, Add-OverlayFilter, Set-ImageFilte...
Manifest PSRss {Read-Article, New-Feed, Remove-Article, Remove-Feed...}
Manifest PSSystemTools {Test-32Bit, Get-USB, Get-OSVersion, Get-MultiTouchMaximum...}
Manifest PSUserTools {Start-ProcessAsAdministrator, Get-CurrentUser, Test-IsAdministrator, Ge...
Manifest TaskScheduler {Remove-Task, Get-ScheduledTask, Stop-Task, Add-TaskTrigger...}
Manifest WPK {Get-DependencyProperty, New-ModelVisual3D, New-DiscreteVector3DKeyFrame...
Manifest AppLocker {}
Manifest BitsTransfer {}
Manifest PSDiagnostics {}
Script **TestModule** {}
Manifest TroubleshootingPack {}
Manifest Citrix.XenApp.Commands... {}
我们可以看到我们的模块已准备好导入。我们可以将其导入会话并在原始使用中使用它:
Import-Module TestModule
或者我们可以再次实例化一个对象:
$m = Import-Module TestModule -AsCustomObject
【讨论】:
您可以使用PowerShell 5.0中引入的the class keyword
这是example by Trevor Sullivan。 (存档here。)
##################################################
####### WMF 5.0 November 2014 Preview ###########
##################################################
class Beer {
# Property: Holds the current size of the beer.
[Uint32] $Size;
# Property: Holds the name of the beer's owner.
[String] $Name;
# Constructor: Creates a new Beer object, with the specified
# size and name / owner.
Beer([UInt32] $NewSize, [String] $NewName) {
# Set the Beer size
$this.Size = $NewSize;
# Set the Beer name
$this.Name = $NewName;
}
# Method: Drink the specified amount of beer.
# Parameter: $Amount = The amount of beer to drink, as an
# unsigned 32-bit integer.
[void] Drink([UInt32] $Amount) {
try {
$this.Size = $this.Size - $Amount;
}
catch {
Write-Warning -Message 'You tried to drink more beer than was available!';
}
}
# Method: BreakGlass resets the beer size to 0.
[void] BreakGlass() {
Write-Warning -Message 'The beer glass has been broken. Resetting size to 0.';
$this.Size = 0;
}
}
这适用于 Windows 10 专业版。
像这样试驾:
# Create a new 33 centilitre beer, named 'Chimay'
$chimay = [Beer]::new(33, 'Chimay');
$chimay.Drink(10)
$chimay.Drink(10)
# Need more beer!
$chimay.Drink(200)
$chimay.BreakGlass()
【讨论】:
$chimay = [Beer]@{ Size=33; Name='Chimay'}。有点像 C# 的对象初始化器语法。但是,如果构造函数有参数,则会引发错误。