Powershell добавить тип в класс в PSM1

В PS1 это работает

class pxInitFailureMessage {
    static [void] Send ([int32]$processID, [String]$title, [string]$message) {
        Add-Type -AssemblyName:System.Windows.Forms
        Add-Type -AssemblyName:System.Drawing
        $balloonTip = New-Object System.Windows.Forms.NotifyIcon
        $balloonTip.icon = [system.drawing.icon]::ExtractAssociatedIcon($(Get-Process -id:$processID | Select-Object -expandProperty:Path))
        $balloonTip.balloonTipIcon = 'Error'
        $balloonTip.balloonTipTitle = $title
        $balloonTip.balloonTipText = $message
        $balloonTip.visible = $true 
        $balloonTip.ShowBalloonTip(0)
        $balloonTip.Dispose
    }
}
[pxInitFailureMessage]::Send($pid, 'Title', 'Message is just some extra text')

Но переместите этот класс в файл library.PSM1, а это в PS1.

Using module '\\Mac\iCloud Drive\Px Tools 4.#\Dev 4.0\#Spikes\Windows7\library.psm1'
[pxInitFailureMessage]::Send($pid, 'Title', 'Message is just some extra text')

И работает в ИСЕ, а не в консоли при запуске с ярлыка. я получаю Unable to find type [system.drawing.icon].

Очевидно, что первый Add-Type работает, я не получаю ошибок в New-Object. Так почему же второй тип нагрузки не работает? Я также попытался переместить две строки Add-Type из класса в корень файла модуля с теми же результатами. Что ДЕЙСТВИТЕЛЬНО работает, так это добавление этих строк в PS1 между using module (которая должна быть первой незамеченной строкой) и вызовом. Это работает, но тогда у вас нет автономного класса, что кажется немного отстойным. Что я здесь неправильно понимаю?

Как создать автономный класс, использующий типы .NET, и работать с ним из файла модуля?


person Gordon    schedule 01.06.2020    source источник
comment
Вы проверили библиотеку MSDN? docs.microsoft. com/de-de/powershell/module/ ? В частности, часть -RequiredAssemblies обрабатывает вашу проблему   -  person user3898488    schedule 01.06.2020
comment
@user3898488 user3898488 Исходя из этого, я попробовал Get-Module Microsoft.PowerShell.Diagnostics -List | Format-List -Property *, и он вернул ожидаемую информацию. Но Get-Module System.Drawing.Icon -List | Format-List -Property * и Get-Module System.Drawing -List | Format-List -Property * вообще ничего не возвращают. Тем не менее, я ожидаю, что это будет полезная ссылка, когда я буду углубляться в .NET через PS. Так вот!   -  person Gordon    schedule 01.06.2020
comment
я могу посмотреть на это позже, если никто не знает ответа   -  person user3898488    schedule 01.06.2020
comment
Это работает в ISE, потому что необходимые сборки уже загружены. Вставка определения класса в обычную консоль PS вызывает ту же ошибку (без фактического использования класса, только определение класса вызывает ошибку). Другими словами, это не проблема ps1/psm1. I also tried moving the two Add-Type lines out of the class, and into the root of the module file, with the same result Когда команды включают class, PowerShell сначала оценивает (анализирует) их. Итак, вам нужно сначала загрузить сборки каким-то образом...   -  person 7cc    schedule 01.06.2020
comment
Да, теперь я понимаю, что фундаментальная проблема заключается в том, что я прошу свой класс выйти за пределы самого себя и файла модуля, который его содержит, чтобы получить информацию о значке совершенно другого процесса. Тупой. Если я назначу значок переменной в основном скрипте, где он находится, и передам ЭТО классу, все будет работать как надо, и наличие using assembly System.Drawing имеет смысл, потому что именно там мне это нужно и я использую. Таким образом, даже если бы мой первоначальный подход сработал, это все равно было бы плохим решением.   -  person Gordon    schedule 01.06.2020


Ответы (1)


Кому интересно, решение, которое я придумал, выглядит следующим образом. В библиотеке.PSM1 у меня есть...

class pxInitFailureMessage {
    static [void] Send ([int32]$processID, [String]$title, [string]$message, [System.Drawing.Icon]$icon) {
        Add-Type -AssemblyName:System.Windows.Forms
        $balloonTip = New-Object System.Windows.Forms.NotifyIcon
        $balloonTip.icon = $icon
        $balloonTip.balloonTipIcon = 'Error'
        $balloonTip.balloonTipTitle = $title
        $balloonTip.balloonTipText = $message
        $balloonTip.visible = $true 
        $balloonTip.ShowBalloonTip(0)
        $balloonTip.Dispose
    }
}

И в моем сценарии есть...

using assembly System.Drawing
Using module '.\library.psm1'

$processIcon = [system.drawing.icon]::ExtractAssociatedIcon($(Get-Process -id:$pID | Select-Object -expandProperty:Path))

[pxInitFailureMessage]::Send($pid, 'Title', 'Message is just some extra text', $processIcon)

Суть в том, что класс теперь самодостаточен и следует хорошей практике предоставления классу всего, что ему нужно, поэтому ему не нужно искать что-то вне себя. Я мог бы так же легко использовать свой собственный файл ICO для значка, вот так...

$processIcon = [system.drawing.icon]::New('\\Mac\iCloud Drive\Px Tools 4.#\Dev 4.0\Px_Resources\PxIcon.ico')

Опять же с буквальным путем в этом примере.

Итак, сегодня я узнал кое-что. Ву.

person Gordon    schedule 01.06.2020