Pouvez-vous supprimer un type Add-ed dans PowerShell à nouveau?

j'écris actuellement une bibliothèque en C# et j'utilisais PowerShell pour la tester rapidement à certaines occasions. Cependant, cela m'empêche de reconstruire le projet car PowerShell a évidemment toujours la DLL ouverte.

y a-t-il un moyen de décharger la DLL à nouveau après l'avoir ajoutée avec Add-Type ? La documentation ne semble pas avoir d'indices à ce sujet et le candidat évident serait Remove-Type (qui n'existe pas – il n'y a qu'une seule commande de toute façon avec Type comme son nom). Il devient encombrant de fermer PowerShell et de faire tout le truc de naviguer dans le répertoire de compilation et d'ajouter le type de nouveau à chaque fois que je veux reconstruire.

57
demandé sur Joey 2010-07-30 12:06:06

5 réponses

comme disent les autres, c'est un comportement .NET. Les assemblages chargés dans un AppDomain ne peuvent pas être déchargés. Seul L'AppDomain peut être déchargé, et powershell utilise un seul appdomain. J'ai blogué sur ce sujet il y a quelques années: http://www.nivot.org/2007/12/07/WhyAppDomainsAreNotAMagicBullet.aspx

quand je teste comme ceci, je garde habituellement une coquille ouverte et utilise une coquille emboîtée pour faire des tests. démarrer powershell, cd à l'emplacement bin puis lancer "powershell" pour démarrer le shell imbriqué (nouveau processus.) "exit" pour recommencer, et exécuter "powershell".

53
répondu x0n 2010-07-30 14:55:12

je trouve que la façon la plus simple de contourner ce problème est d'envelopper le Add-Type et le code de test à l'intérieur d'un Start-Job . Start-Job va créer un processus de fond, et le type y sera chargé. Une fois que vous avez terminé, le processus disparaît et vous êtes libre de réessayer.

voici un exemple de comment il regarde:

$job = Start-Job -ScriptBlock {

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

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

la sortie de La méthode d'essai sera repris à la console.

34
répondu Start-Automating 2017-02-01 22:11:54

si votre assemblage ne nécessite pas un contexte de liaison vous pouvez faire ceci:

$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
21
répondu George Howarth 2010-07-30 09:30:22

voici un exemple complet qui permet d'exécuter la commande Add-Type comme tâche de fond pour que l'assemblage soit déchargé une fois qu'il est terminé:

# 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 assurez-vous que la sortie de l'emploi est reçu car sinon il sera perdu.

3
répondu Knaģis 2017-01-10 14:25:34

j'ai été confronté à un problème similaire. Il n'est pas possible de décharger un type/assemblage (c'est parce qu'il s'applique à .net framework).

dans .NET, vous pouvez le résoudre si vous créez un nouveau domaine d'application ( System.AppDomain ) et chargez l'assemblage dans ce domaine. Il est possible de décharger le domaine app et cela déchargera aussi tous les dlls.

Je ne l'ai pas encore essayé, parce que pour moi il est beaucoup plus simple de fermer un onglet dans la Console et d'ouvrir une nouvelle.

0
répondu stej 2010-07-30 08:58:04