我目前正在用 C# 编写一个库,并在某些情况下使用 PowerShell 快速测试它。然而,这阻止了我重新构建项目,因为 PowerShell 显然仍然打开了 DLL。
有没有办法在使用Add-Type
添加DLL后再次卸载它?文档似乎没有关于这一点的线索,明显的候选者是 Remove-Type
(它不存在 - 无论如何只有一个命令,其中 Type
作为它的名词)。每次我想要重建时,关闭 PowerShell 并执行导航到构建目录并再次添加类型的所有操作会变得很麻烦。
I'm currently writing a library in C# and was using PowerShell to quickly test it on some occasions. However, this prevents me from re-building the project as PowerShell obviously still has the DLL open.
Is there a way of unloading the DLL again after adding it with Add-Type
? The documentation doesn't seem to have clues on that and the obvious candidate would be Remove-Type
(which doesn't exist – there is only one command anyway with Type
as its noun). It gets cumbersome to close PowerShell and do all the stuff of navigating to the build directory and adding the type again each time I want to rebuild.
发布评论
评论(6)
正如其他人所说,这是一种 .NET 行为。无法卸载加载到 AppDomain 中的程序集。只能卸载AppDomain,并且powershell使用单个appdomain。几年前我在博客上写过一些关于这个问题的文章:
https://web.archive.org/web/20170707034334/http://www.nivot.org/blog/post/2007/12/07/WhyAppDomainsAreNotAMagicBullet
当我测试时为此,我通常保持 shell 打开并使用嵌套 shell 进行测试。启动 powershell,cd 到 bin 位置,然后运行“powershell”启动嵌套 shell(新进程)。“退出”重新开始,然后再次运行“powershell”。
Like the others say, this is a .NET behavior. Assemblies loaded into an AppDomain cannot be unloaded. Only the AppDomain can be unloaded, and powershell uses a single appdomain. I blogged a bit about this some years ago:
https://web.archive.org/web/20170707034334/http://www.nivot.org/blog/post/2007/12/07/WhyAppDomainsAreNotAMagicBullet
When I test like this, I usually keep a shell open and use a nested shell to do tests. start powershell, cd to bin location then run "powershell" to start nested shell (new process.) "exit" to start over, and run "powershell" again.
我发现解决此问题的最简单方法是将
Add-Type
和测试代码包装在开始作业
。Start-Job
将创建一个后台进程,并且类型将在那里加载。完成后,该过程就会消失,您可以重试。下面是它的外观示例:
测试方法的输出将回显到控制台。
I find the simplest way to get around this problem is to wrap the
Add-Type
and the test code inside of aStart-Job
.Start-Job
will create a background process, and the type will be loaded there. Once you are done, the process goes away and you're free to retry.Here's an example of how it looks:
The output from the test method will be echoed to the console.
如果您的程序集不需要 绑定上下文 你可以这样做:
If your assembly doesn't require a binding context you can do this:
下面是一个完整的示例,允许将
Add-Type
命令作为后台作业运行,以便在完成后卸载程序集:Receive-Job -Wait
将确保作业的输出已被接收,否则它将丢失。Here is a complete example that allows to run the
Add-Type
command as a background job so that the assembly is unloaded once it finishes:Receive-Job -Wait
will make sure that the output of the job is received since otherwise it will be lost.Visual Studio Code:
设置 ->扩展-> PowerShell->调试:创建临时集成控制台
选中复选框:“为每个调试会话创建临时 PowerShell 扩展终端。这对于调试 PowerShell 类和二进制模块非常有用。”
这会导致每次按F5都会延迟几秒钟,这很烦人。我经常通过将焦点转移到终端窗口(鼠标单击它),按向上箭头,验证命令提示符中现在是否有正确的脚本,然后按 Enter 来解决此问题。对我来说,这比等待稍微不那么烦人,但当我知道我需要一个新的 PowerShell 实例时,我仍然可以选择重新加载终端(按 F5)。
Visual Studio Code:
Settings -> Extensions -> PowerShell -> Debugging: Create Temporary Integrated Console
Check checkbox: "Creates a temporary PowerShell Extension Terminal for each debugging session. This is useful for debugging PowerShell classes and binary modules."
This results in a delay of several seconds every time you press F5, which is annoying. I often work around this by shifting focus to the terminal window (mouse clicking it), pressing up arrow, verifying the correct script is now in the command prompt, and pressing Enter. To me, this is a little less annoying than waiting, but still gives me the option to reload the terminal (pressing F5) when I know I need a new instance PowerShell.
我也遇到过类似的问题。无法卸载类型/程序集(这是因为它适用于 .NET 框架)。
在 .NET 中,如果创建一个新的应用程序域 (
System.AppDomain
) 并将程序集加载到该域中,就可以解决这个问题。可以卸载应用程序域并卸载所有 dll。我还没有尝试过,因为对我来说,在 Console 中关闭选项卡要简单得多并打开新的。
I have been facing to similar problem. It is not possible to unload a type/assembly (that's because it applies to .NET framework).
In .NET you can solve it if you crate a new application domain (
System.AppDomain
) and load the assembly into that domain. It is possible to unload the app domain and that unloads all the dlls as well.I haven't tried it yet, because for me it is much simpler to close a tab in Console and open new one.