johann.z

Powershell. Laden einer Assembly aus einer selbstdefinierten Klasse heraus

Hallo zusammen,

ich habe zur Schulungszwecken angefangen mich mit Klassen (Class) in Powershell zu beschäftigen.
Es klappt auch so weit, allerdings bin ich auf eine sonderbare Sache gestoßen, zu der ich online nicht so richtig was gefunden habe.
Es geht, ums Laden einer Assembly aus einer selbstdefinierten Klasse heraus.

Ziel ist es per Methoden-Aufruf (Klassenmethode, aus eigener Klasse) eine MessageBox aus system.windows.forms aufzurufen.
Aber schon bei Laden der Klasse kommt eine Fehlermeldung:
#############################################
[System.Windows.Forms.MessageBox]::Show("jkdhfgjkfdhg ...      
Der Typ [System.Windows.Forms.MessageBox] wurde nicht        
gefunden.
    + CategoryInfo          : ParserError: (:) , ParentCo  
   ntainsErrorRecordException
    + FullyQualifiedErrorId : TypeNotFound
#############################################

Ich muss die Assembly voher mit:
[void][System.Reflection.Assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
oder
[void][System.Reflection.Assembly]::LoadWithPartialName("system.windows.forms")
laden, um die Klasse Laden zu können.
Ist Laden einer Assembly aus einer selbstdefinierten Klasse so nicht möglich?
Muss man dafür mit " : base " arbeiten?

Für einen Hinweis wäre ich sehr dankbar.
Hier wurde das Thema schon so ähnlich behandelt aber leider ohne Erfolg.

https://stackoverflow.com/questions/59242764/powershell-unable-to-find-t ...

mein Testcode:
# [void][System.Reflection.Assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'); 
class test {
    # Parameter
    [string]$server
    [string]$OldBeschlagPfad
    [string]$SQLAbfrage

    test() {
        $this.server = 'leer'  
        $this.OldBeschlagPfad = 'leer'  
        $this.SQLAbfrage = 'leer'  
    }

    test(
        [string]$server_Konstruktor,
        [string]$OldBeschlagPfad_Konstruktor,
        [string]$SQLAbfrage_Konstruktor
    ) {
        $this.server = $server_Konstruktor
        $this.OldBeschlagPfad = $OldBeschlagPfad_Konstruktor
        $this.SQLAbfrage = $SQLAbfrage_Konstruktor
    }
 
    [string]SQLAbfrage_Run() {
        # TEst
        $test = "Hu Hu bin ich blöd"  
        return $test
    }
    # Eine Message fürs Debuggen
    [string]Message() {
        # [void][System.Reflection.Assembly]::LoadWithPartialName("system.windows.forms") 
        [void][System.Reflection.Assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089');  
       # [System.Windows.Forms.MessageBox]::Show("jkdhfgjkfdhgjk") 
        return  [System.Windows.Forms.MessageBox]::Show("jkdhfgjkfdhgjk")  
    } 
}

# Class Fertig
Auf Facebook teilen
Auf X (Twitter) teilen
Auf Reddit teilen
Auf Linkedin teilen

Content-ID: 1327821162

Url: https://administrator.de/forum/powershell-laden-einer-assembly-aus-einer-selbstdefinierten-klasse-heraus-1327821162.html

Ausgedruckt am: 19.05.2025 um 11:05 Uhr

149569
149569 30.09.2021 aktualisiert um 16:30:54 Uhr
Goto Top
Powershell Klassen sind da noch in den Kinderschuhen.

Das Problem ist das eigene Powershell Klassendefinitionen noch vor dem Laden jeglicher Assembilies und vor dem Ausführen des Scripts geparsed werden und zu dem Zeitpunkt gibt es die System.Windows.Forms Klasse nicht, und der Parser beschwert sich dann natürlich darüber.

https://github.com/PowerShell/PowerShell/issues/3641
The issue is that PS class definitions are parsed before script execution begins, which means that any types referenced in class definitions must currently already be loaded in the context of the caller.

In other words: your script breaks in the parsing stage, and no statements are ever executed.

Würdest du das Skript aus einer Konsole aus starten in der du das Assembly schon vorgeladen hast wird es laufen weil die Klassen dann schon in der Session existieren.

Ein möglicher Workaround wäre z.B. dieser hier (damit versteckt man die Klasse erst mal hinter einem String, lädt die nötigen Assemblies vor, und führt erst dann den Code des Strings aus
$code = @'  
class test {
    myfunction ($par1){
        [System.Windows.Forms.MessageBox]::Show($par1)
    }
}
'@  
Add-Type -A System.Windows.Forms
Invoke-Expression $code

$c = [test]::new()
$c.myfunction("Hallo das ist ein Test")  
Damit umgeht man das Problem das der Compiler sich schon über die fehlenden Assemblies beschwert.

Gibt noch mehr Issues mit benutzerdefinierten Klassen in der Powershell.
https://github.com/PowerShell/PowerShell/issues/6652
Johann.Z
Johann.Z 04.10.2021 um 17:05:45 Uhr
Goto Top
Vielen Dank für den Hinweis.
Ich brauche eine Weile, um das zu verinnerlichen/verstehen und testen zu können.