PowerShell sınıflarında .NET türleri
PowerShell Sınıfı en iyi uygulamalarına kafa yormaya çalışıyorum ve Balon İpuçları ile başa çıkmak için basit bir sınıfla bazı karışıklıklarla karşılaşıyorum.
Add-Type -assemblyName:System.Drawing
Add-Type -assemblyName:System.Windows.Forms
class PxMessage {
static [PxMessage] $instance static $balloon
static $defaultIcon static [PxMessage] GetInstance($processIcon) {
if ([PxMessage]::instance -eq $null) { [PxMessage]::instance = [PxMessage]::new() #[PxMessage]::balloon = [Windows.Forms.NotifyIcon]::new() [PxMessage]::balloon = New-Object Windows.Forms.NotifyIcon [PxMessage]::defaultIcon = $processIcon
}
return [PxMessage]::instance
}
[Void] SendMessage ([String]$title, [String]$message, [String]$messageIcon) { [PxMessage]::balloon.icon = [PxMessage]::defaultIcon [PxMessage]::balloon.balloonTipTitle = $title
[PxMessage]::balloon.balloonTipText = $message [PxMessage]::balloon.balloonTipIcon = $messageIcon
[PxMessage]::balloon.visible = $true [PxMessage]::balloon.ShowBalloonTip(0) [PxMessage]::balloon.Dispose } } $processIcon = [System.Drawing.Icon]::ExtractAssociatedIcon($(Get-Process -id:$PID | Select-Object -expandProperty:path))
$message = [PxMessage]::GetInstance($processIcon)
$message.SendMessage('Title', "$(Get-Date)", 'Info')
İki sorum var:
1: Neden [PxMessage]::balloon = New-Object Windows.Forms.NotifyIconçalışıyor ama [PxMessage]::balloon = [Windows.Forms.NotifyIcon]::new()çalışmıyor ( Unable to find typehata)? Ve bu [Type]::new(), kullanımın henüz tam olarak desteklenmediğini ve tutarlılık adına New-Object'i her yerde kullanmamın daha iyi olduğunu gösteriyor mu? Ya da en azından kendi Sınıflarımdaki her yerde?
2: Özelliklerimi ve parametrelerimi yazmak istiyorum, ancak & özelliklerini yazdığımda veya parametreyi yöntemde yazdığımda da Unable to find typehata alıyorum .$balloon$defaultIcon$processIconGetInstance
Açıkçası, türüm tanımlanmış olsa bile Özellikler yazabilirim. Öyleyse ikisi [System.Drawing]& ile ilgili farklı olan nedir [System.Windows.Forms]ve bu bir hata mı yoksa özellik mi? Ve benzer şekilde davranan başka türler var mı?
Yanıtlar
Bu esasen bir yarış durumu!
PowerShell bir betik dosyasını yürütmeye başladığında, 3 aşamadan geçer:
- Ayrıştırma
- Derleme
- Yürütme
İlk şey olarak işlenir derleme aşamasında, (böylece önceki yürütme bile başlar) aşağıdaki gibidir:
usingKomut dosyasının üst kısmındaki tüm ifadeler- Herhangi bir tür tanımı - herhangi biri
classveyaenumanahtar sözcük - ayrı olarak derlenir
Dolayısıyla, [Windows.Forms.NotifyIcon]sınıf tanımının içindeki değişmez tipin çözümlenmesiyle ilgili hatalar , herhangi bir çalışma şansı yakalanmadan önce atılır Add-Type -AssemblyName:System.Windows.Forms!
Birkaç seçenek:
İç içe geçmiş komut dosyaları
Bağımlılığı yükleyen ayrı bir yükleyici komut dosyası yazın:
# loader.ps1
Add-Type -AssemblyName System.Windows.Forms,System.Drawing
. .\scriptWithTypes.ps1
# scriptWithTypes.ps1
class ClassDependentOnForms
{
[Windows.Forms.NotifyIcon]$BalloonTipIcon
}
Modülleri ile
Modüllerle, özel tür tanımlarını derlemeden önce bağımlılıkları yönetmek biraz daha kolaydır - RequiredAssembliesmodül bildirimine göre montaj adlarını eklemeniz yeterlidir:
New-ModuleManifest ... -RootModule moduleWithTypes.psm1 -RequiredAssemblies System.Windows.Forms,System.Drawing
Diskten yükle using assembly ...
Gerekli derlemenin yolu biliniyorsa, onu ayrıştırma zamanında bir deyimle yükleyebilirsiniz using assembly:
using assembly '.\path\to\System.Drawing.dll'
using assembly '.\path\to\System.Windows.Forms.dll'
class FormsDependentClass
{
[Windows.Forms.NotifyIcon]$BallonTipIcon
}
Kullanım durumunuz için, bu sonuncusu pek çekici değildir çünkü montajı GAC'den adıyla yüklemek yerine kodlamanız gerekir.
Bu neden ilk etapta oluyor?
Bu davranış biraz kafa karıştırıcı olabilir, çünkü PowerShell'deki diğer her şey basit "bir seferde bir ifade" yorumudur.
Bu istisnanın nedeni, komut dosyalarının ve işlevlerin özel parametre türlerini sarmalamasına izin vermektir:
param(
[CustomEnumType]$Option ) begin { enum CustomEnumType { None Option1 Option2 } } end { # do something based on $Option
}
CustomEnumTypeAyrıştırma zamanında bu önleyici derleme olmadan , PowerShell -Optionparametre bağımsız değişkeni için otomatik tamamlama ve giriş doğrulaması sunamaz - çünkü türü mevcut olmaz