web-dev-qa-db-fra.com

Pouvez-vous supprimer à nouveau un type ajouté dans PowerShell?

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

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

57
Joey

Comme le disent les autres, il s’agit d’un comportement .NET. Les assemblys chargés dans un AppDomain ne peuvent pas être déchargés. Seul AppDomain peut être déchargé et Powershell utilise un seul appdomain. J'ai blogué un peu à ce sujet il y a quelques années: http://www.nivot.org/2007/12/07/WhyAppDomainsAreNotAMagicBullet.aspx

Lorsque je teste de la sorte, je garde généralement un shell ouvert et l’utilise pour faire des tests. Lancez PowerShell, cd vers l'emplacement de la corbeille, puis exécutez "PowerShell" pour démarrer Shell imbriqué (nouveau processus.) "Exit" pour recommencer, puis exécutez "PowerShell" à nouveau.

53
x0n

Je trouve que le moyen le plus simple de contourner ce problème est d’envelopper le Add-Type et le code de test dans un Start-Job . Start-Job créera un processus en arrière-plan et le type y sera chargé. Une fois que vous avez terminé, le processus s'en va et vous êtes libre de réessayer.

Voici un exemple de quoi il ressemble:

$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 de test sera répercutée sur la console.

35
Start-Automating

Si votre Assemblée n'a pas besoin d'un contexte binding , vous pouvez le faire:

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

Voici un exemple complet qui permet d'exécuter la commande Add-Type en tant que tâche en arrière-plan afin de décharger l'assembly une fois celle-ci terminée:

# 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 s'assurera que la sortie du travail est reçue, sinon elle sera perdue.

3
Knaģis

J'ai été confronté à un problème similaire. Il n'est pas possible de décharger un type/Assembly (c'est parce que cela s'applique au framework .NET). 

Dans .NET, vous pouvez le résoudre si vous créez un nouveau domaine d’application (System.AppDomain) et chargez l’Assembly dans ce domaine. Il est possible de décharger le domaine d'application et cela décharge également toutes les dll.

Je ne l'ai pas encore essayé, car pour moi, il est beaucoup plus simple de fermer un onglet dans Console et d'en ouvrir un autre.

0
stej