Utilizzo di oggetti .Net all’interno di una class PowerShell (V5)

Questa è una modifica importante fatta per scopi di chiarezza. Sembra che ho bisogno di lavorare sulla formazione di pensieri. Di seguito è riportato il codice esatto con cui ho problemi. Una breve descrizione: sto cercando di impostare una class PowerShell che possa contenere oggetti di diverso tipo per un facile accesso. L’ho fatto numerose volte in C #, quindi ho pensato che sarebbe stato abbastanza semplice. I tipi richiesti sono [System.Printing] e WMI-Objects.

Inizialmente avevo provato a scrivere la class direttamente sul mio profilo Powershell per un facile utilizzo, ma il mio profilo non si carica quando ho il codice di class. Dicendo che non può trovare il nome di tipo “System.Printing.PrintServer”, o qualsiasi altro tipo elencato esplicitamente. Dopo averlo fallito, l’ho spostato nel suo modulo specifico e poi ho impostato il mio profilo per importare il modulo all’apertura. Tuttavia, anche se memorizzato nel proprio modulo, se elenco esplicitamente un tipo .Net per una qualsiasi delle proprietà, l’intero modulo non riesce a caricare. Indipendentemente dal fatto che io abbia aggiunto o importato il tipo / dll. L’area del problema specifico è questa: [stringa] $ Nome [System.Printing.PrintServer] $ Server [System.Printing.PrintQueue] $ Queue [System.Printing.PrintTicket] $ Ticket [System.Management.ManagementObject] $ Unit [bool ] $ IsDefault

Quando ho impostato su questo, tutto “tipo di” funziona, ma tutte le mie proprietà hanno il tipo _Object, che non è utile. [stringa] $ Nome $ Server $ Coda $ Biglietto $ 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 } } 

Ogni script PowerShell viene completamente analizzato prima dell’esecuzione della prima istruzione nello script. Un token di nome di tipo non risolvibile all’interno di una definizione di class è considerato un errore di analisi. Per risolvere il tuo problema, devi caricare i tuoi tipi prima che la definizione della class venga analizzata, quindi la definizione della class deve essere in un file separato. Per esempio:

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 } 

L’altra possibilità sarebbe incorporare Class.ps1 come stringa e usare Invoke-Expression per eseguirlo. Ciò ritarderà l’analisi della definizione della class nel momento in cui i tipi sono disponibili.

 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 } '@ 

Per completare la risposta utile di PetSerAl :

using assembly dovrebbe essere la soluzione giusta, ma il suo utilizzo in fase di analisi non è ancora stato implementato a partire da Windows PowerShell v5.1 / PowerShell Core v6.1, perché richiede un lavoro extra per evitare il potenziale di esecuzione indesiderata di codice arbitrario quando viene caricato un assieme.

L’implementazione di questo aspetto è stata risolta in questo problema di GitHub e il lavoro necessario è stato tracciato come parte di questo problema .