it-swarm.com.de

Können Sie einen zusätzlichen Typ in PowerShell erneut entfernen?

Ich schreibe gerade eine Bibliothek in C # und habe PowerShell verwendet, um sie in einigen Fällen schnell zu testen. Dies hindert mich jedoch daran, das Projekt neu zu erstellen, da in PowerShell offensichtlich noch die DLL geöffnet ist.

Gibt es eine Möglichkeit, die DLL nach dem Hinzufügen mit Add-Type erneut zu entladen? Die Dokumentation scheint keine Hinweise darauf zu haben, und der offensichtliche Kandidat wäre Remove-Type (was nicht existiert - es gibt nur einen Befehl mit Type als Substantiv). Es wird umständlich, PowerShell zu schließen und alles zu tun, um zum Build-Verzeichnis zu navigieren und den Typ jedes Mal wieder hinzuzufügen, wenn ich neu erstellen möchte.

57
Joey

Wie die anderen sagen, handelt es sich hierbei um ein .NET-Verhalten. In eine AppDomain geladene Baugruppen können nicht entladen werden. Nur die AppDomain kann entladen werden, und Powershell verwendet eine einzelne Domäne. Vor einigen Jahren habe ich darüber ein Blog geschrieben: http://www.nivot.org/2007/12/07/WhyAppDomainsAreNotAMagicBullet.aspx

Wenn ich so teste, halte ich normalerweise eine Shell offen und verwende eine verschachtelte Shell, um Tests durchzuführen. Starten Sie Powershell, cd in den Ablageort. Führen Sie dann "Powershell" aus, um die verschachtelte Shell (neuer Prozess) zu starten. "Beenden", um erneut zu starten, und "Powershell" erneut ausführen.

53
x0n

Der einfachste Weg, dieses Problem zu umgehen, besteht darin, den Add-Type und den Testcode in ein Start-Job zu packen. Start-Job erstellt einen Hintergrundprozess und der Typ wird dort geladen. Sobald Sie fertig sind, wird der Vorgang abgebrochen und Sie können es erneut versuchen.

Hier ist ein Beispiel wie es aussieht:

$job = Start-Job -ScriptBlock {

    Add-Type -path 'my.dll'
    $myObj = new-object My.MyTestClassName

    $result = $myObj.TestMethod
    $result
}
Wait-Job $job
Receive-Job $job

Die Ausgabe der Testmethode wird an die Konsole gesendet.

35

Wenn Ihre Assembly keinen bindenden Kontext erfordert können Sie dies tun:

$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
21
George Howarth

Hier ist ein vollständiges Beispiel, mit dem Sie den Befehl Add-Type als Hintergrundjob ausführen können, damit die Assembly nach dem Abschluss entladen wird:

# Start-Job will not preserve the working directory, so do it manually
# Other arguments can also be passed to the job this way
$cd = Split-Path $MyInvocation.MyCommand.Path
$jobParams = @{
    'cd' = $cd
}

Start-Job -InputObject $jobParams -ScriptBlock {
    cd $Input.cd
    Add-Type -Path Assembly.dll
} | Receive-Job -Wait -AutoRemoveJob

Receive-Job -Wait sorgt dafür, dass die Ausgabe des Jobs empfangen wird, da sie sonst verloren geht.

3
Knaģis

Ich war mit einem ähnlichen Problem konfrontiert. Es ist nicht möglich, einen Typ/eine Assembly zu entladen (da dies für .NET Framework gilt). 

In .NET können Sie es lösen, wenn Sie eine neue Anwendungsdomäne (System.AppDomain) erstellen und die Assembly in diese Domäne laden. Es ist möglich, die App-Domäne zu entladen, und dabei werden auch alle DLLs entladen.

Ich habe es noch nicht ausprobiert, weil es für mich viel einfacher ist, einen Tab in Console zu schließen und einen neuen zu öffnen.

0
stej