在 Powershell (V5) 类中使用 .NET 对象 [英] Using .NET objects within a Powershell (V5) class
问题描述
以下是我遇到问题的确切代码.
Below is the exact code that I am having trouble with.
简要说明:
我正在尝试设置一个 PowerShell 类,该类将包含不同类型的对象以便于访问.我已经在 C# 中多次这样做了,所以我认为它会相当简单.需要的类型是 [System.Printing] 和 WMI-Objects.
I am trying to set up a PowerShell class that will hold objects of different types for easy access. I've done this numerous times in C#, so I thought it would be fairly straight forward. The types wanted are [System.Printing] and WMI-Objects.
最初我曾尝试将类直接写入我的 PowerShell 配置文件以方便使用,但是当我必须在其中对代码进行分类时,我的配置文件无法加载.说它找不到类型名称System.Printing.PrintServer",或任何其他明确列出的类型.
Originally I had tried to write the class directly to my PowerShell profile for easy usage, but my profile fails to load when I have to class code in it. Saying that it can’t find the type name "System.Printing.PrintServer", or any other explicitly listed types.
失败后,我将其移至其自己的特定模块,然后将我的配置文件设置为在打开时导入模块.但是,即使存储在它自己的模块中,如果我为任何属性明确列出 .NET 类型,整个模块也无法加载.无论我是否添加或导入了类型/dll.
After that failed, I moved it to its own specific module and then set my profile to import the module on open. However, even when stored in its own module, if I explicitly list a .NET type for any of the properties, the entire module fails to load. Regardless of whether I have added or imported the type / dll.
具体的问题区域是这样的:
The specific problem area is this:
[string]$Name
[System.Printing.PrintServer]$Server
[System.Printing.PrintQueue]$Queue
[System.Printing.PrintTicket]$Ticket
[System.Management.ManagementObject]$Unit
[bool]$IsDefault
当我把它设置为这个时,一切都有点"有效,但是我所有的属性都具有 _Object 类型,这没有帮助.
When I have it set to this, everything "kind of" works, but then all my properties have the _Object type, which is not helpful.
[string]$Name
$Server
$Queue
$Ticket
$Unit
$IsDefault
Add-Type -AssemblyName System.Printing
Add-Type -AssemblyName ReachFramework
Class PrinterObject
{
[string]$Name
[System.Printing.PrintServer]$Server
[System.Printing.PrintQueue]$Queue
[System.Printing.PrintTicket]$Ticket
[System.Management.ManagementObject]$Unit
[bool]$IsDefault
PrinterObject([string]$Name)
{
#Add-Type -AssemblyName System.Printing
#Add-Type -AssemblyName ReachFramework
$this.Server = New-Object System.Printing.PrintServer -ArgumentList [System.Printing.PrintSystemDesiredAccess]::AdministrateServer
$this.Queue = New-Object System.Printing.PrintQueue (($this.Server), ($this.Server.GetPrintQueues() |
Where-Object {$_.Name -match $Name} | Select-Object -ExpandProperty Name))
$this.Ticket = $this.Queue.UserPrintTicket
$this.Unit = Get-WmiObject -Query "SELECT * FROM Win32_Printer WHERE Name LIKE `"%$Name%`""
}
PrinterObject([string]$Name, [bool]$IsNetwork)
{
#Add-Type -AssemblyName System.Printing
#Add-Type -AssemblyName ReachFramework
if($IsNetwork -eq $true) {
$this.Server = New-Object System.Printing.PrintServer ("\Server")
$this.Queue = New-Object System.Printing.PrintQueue (($this.Server), ($this.Server.GetPrintQueues() |
Where-Object {$_.Name -match $Name} | Select-Object -ExpandProperty Name))
$this.Ticket = $this.Queue.UserPrintTicket
$this.Unit = Get-WmiObject -Query "SELECT * FROM Win32_Printer WHERE Name LIKE `"%$Name%`""
}
else {
$This.Server = New-Object System.Printing.PrintServer -argumentList [System.Printing.PrintSystemDesiredAccess]::AdministrateServer
$this.Queue = New-Object System.Printing.PrintQueue (($this.Server), ($this.Server.GetPrintQueues() |
Where-Object {$_.Name -match $Name} | Select-Object -ExpandProperty Name))
$this.Ticket = $this.Queue.UserPrintTicket
$this.Unit = Get-WmiObject -Query "SELECT * FROM Win32_Printer WHERE Name LIKE `"%$Name%`"" }
}
[void]SetPrintTicket([int]$Copies, [string]$Collation, [string]$Duplex)
{
$this.Ticket.CopyCount = $Copies
$this.Ticket.Collation = $Collation
$this.Ticket.Duplexing = $Duplex
$this.Queue.Commit()
}
[Object]GetJobs($Option)
{
if($Option -eq 1) { return $this.Queue.GetPrintJobInfoCollection() | Sort-Object -Property JobIdentifier | Select-Object -First 1}
else { return $this.Queue.GetPrintJobInfoCollection() }
}
static [Object]ShowAllPrinters()
{
Return Get-WmiObject -Class Win32_Printer | Select-Object -Property Name, SystemName
}
}
推荐答案
在执行脚本中的第一条语句之前,每个 PowerShell 脚本都会被完全解析.类定义中无法解析的类型名称标记被视为解析错误.要解决您的问题,您必须在解析类定义之前加载您的类型,因此类定义必须位于单独的文件中.例如:
Every PowerShell script is completely parsed before the first statement in the script is executed. An unresolvable type name token inside a class definition is considered a parse error. To solve your problem, you have to load your types before the class definition is parsed, so the class definition has to be in a separate file. For example:
Main.ps1:
Add-Type -AssemblyName System.Printing
Add-Type -AssemblyName ReachFramework
. $PSScriptRootClass.ps1
Class.ps1:
using namespace System.Management
using namespace System.Printing
Class PrinterObject
{
[string]$Name
[PrintServer]$Server
[PrintQueue]$Queue
[PrintTicket]$Ticket
[ManagementObject]$Unit
[bool]$IsDefault
}
另一种可能性是将 Class.ps1
作为字符串嵌入并使用 Invoke-Expression
来执行它.这会将类定义的解析延迟到类型可用的时间.
The other possibility would be embed Class.ps1
as a string and use Invoke-Expression
to execute it. This will delay parsing of class definition to time where types is available.
Add-Type -AssemblyName System.Printing
Add-Type -AssemblyName ReachFramework
Invoke-Expression @‘
using namespace System.Management
using namespace System.Printing
Class PrinterObject
{
[string]$Name
[PrintServer]$Server
[PrintQueue]$Queue
[PrintTicket]$Ticket
[ManagementObject]$Unit
[bool]$IsDefault
}
’@
这篇关于在 Powershell (V5) 类中使用 .NET 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!