您可以再次在PowerShell中删除Add-ed Type吗?

Joe*_*oey 58 dll powershell add-type

我目前正在用C#编写一个库,并且正在使用PowerShell在某些情况下快速测试它.但是,这使我无法重新构建项目,因为PowerShell显然仍然打开了DLL.

有没有办法在添加后再次卸载DLL Add-Type?文档似乎没有关于这一点的线索,而明显的候选者将是Remove-Type(它不存在 - 无论如何只有一个命令Type作为其名词).关闭PowerShell并执行导航到构建目录的所有内容并在每次要重建时再次添加类型都很麻烦.

x0n*_*x0n 54

像其他人说的那样,这是一种.NET行为.无法卸载加载到AppDomain中的程序集.只能卸载AppDomain,而powershell使用单个appdomain.几年前我在博客上写了一篇博文:http://www.nivot.org/2007/12/07/WhyAppDomainsAreNotAMagicBullet.aspx

当我像这样测试时,我通常会打开一个shell并使用嵌套的shell来进行测试.启动powershell,cd到bin位置,然后运行"powershell"启动嵌套shell(新进程.)"exit"重新开始,再次运行"powershell".


Sta*_*ing 37

我发现解决这个问题的最简单方法是Add-Type将测试代码包装在一个内部Start-Job. Start-Job将创建一个后台进程,并在那里加载类型.一旦完成,该过程就会消失,您可以自由重试.

以下是它的外观示例:

$job = Start-Job -ScriptBlock {

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

    $result = $myObj.TestMethod
    $result
}
Wait-Job $job
Receive-Job $job
Run Code Online (Sandbox Code Playgroud)

测试方法的输出将回显到控制台.

  • 我喜欢这种方法,尽管就我而言,我需要后台作业中设置的变量的结果。如果不将其写入文件,我不确定如何获取该信息。尽管如此,我认为它值得+1 (2认同)
  • @SlogmeisterExtraordinaire 在工作中,回显结果。在主脚本中,调用“Receive-Job”来获取它。 (2认同)
  • 我添加了一个如何执行此操作的示例。示例中的任何拼写错误或错误都是我自己造成的,而不是 @Start-Automating 的。 (2认同)

Geo*_*rth 23

如果程序集不需要绑定上下文,则可以执行以下操作:

$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
Run Code Online (Sandbox Code Playgroud)

  • 您将无法卸载,但OTOH DLL将不会保持打开和锁定,因为读取独立于负载("ReadAllBytes"不保持文件打开或锁定).所以它取决于OP想要的东西; 这将解决"我无法构建"的问题,这似乎是想要卸载的驱动因素. (6认同)
  • 我欠你一品脱. (2认同)

Kna*_*ģis 5

这是一个完整的示例,它允许将Add-Type命令作为后台作业运行,以便在完成后卸载程序集:

# 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
Run Code Online (Sandbox Code Playgroud)

Receive-Job -Wait 将确保收到作业的输出,否则它将丢失。