在Powershell(V5)类中使用.Net对象 [英] Using .Net Objects within a Powershell (V5) Class

查看:92
本文介绍了在Powershell(V5)类中使用.Net对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是为了清晰起见而进行的主要编辑。看来我需要努力形成思想。
下面是我遇到的确切代码。
简要说明:
我正在尝试设置一个Powershell类,该类将容纳不同类型的对象以便于访问。我在C#中已经做过很多次了,所以我认为这很简单。所需的类型为[System.Printing]和WMI对象。

This is a major edit done for clarity purposes. It appears I need to work on forming thoughts. Below is the exact code that I am having trouble with. A brief description: I am trying to setup 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或任何其他明确列出的类型。
失败之后,我将其移至其自己的特定模块,然后设置我的配置文件以在打开时导入该模块。但是,即使存储在其自己的模块中,如果我为任何属性明确列出.Net类型,整个模块也无法加载。不管我是否添加或导入了类型/ dll。
特定的问题区域是:
[string] $ Name
[System.Printing.PrintServer] $ Server
[System.Printing.PrintQueue] $ Queue
[System.Printing.PrintTicket] $ Ticket
[System.Management.ManagementObject] $ Unit
[bool] $ IsDefault

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 cant find the type name "System.Printing.PrintServer", or any other explicitly listed types. After that failed I moved it to it's 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类型,这没有帮助。
[string] $ Name
$ Server
$ Queue
$ Ticket
$ Unit
$ IsDefault

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

. $PSScriptRoot\Class.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆