我目前正在用 C# 编写一个库,并且在某些情况下使用 PowerShell 对其进行快速测试。但是,这阻止了我重新构建项目,因为 PowerShell 显然仍然打开了 DLL。
有没有办法在添加 DLL 后再次卸载 DLL Add-Type
?文档似乎没有这方面的线索,而明显的候选者将是Remove-Type
(它不存在——反正只有一个命令Type
作为它的名词)。每次我想重建时,关闭 PowerShell 并执行导航到构建目录并再次添加类型的所有工作都变得很麻烦。
我目前正在用 C# 编写一个库,并且在某些情况下使用 PowerShell 对其进行快速测试。但是,这阻止了我重新构建项目,因为 PowerShell 显然仍然打开了 DLL。
有没有办法在添加 DLL 后再次卸载 DLL Add-Type
?文档似乎没有这方面的线索,而明显的候选者将是Remove-Type
(它不存在——反正只有一个命令Type
作为它的名词)。每次我想重建时,关闭 PowerShell 并执行导航到构建目录并再次添加类型的所有工作都变得很麻烦。
就像其他人说的那样,这是一种 .NET 行为。无法卸载加载到 AppDomain 中的程序集。只能卸载 AppDomain,powershell 使用单个 appdomain。几年前我在博客上写了一点:
当我像这样进行测试时,我通常会打开一个 shell 并使用嵌套的 shell 来进行测试。启动powershell,cd到bin位置然后运行“powershell”启动嵌套shell(新进程)“exit”重新开始,然后再次运行“powershell”。
我发现解决此问题的最简单方法是将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
测试方法的输出将回显到控制台。
如果您的程序集不需要绑定上下文,您可以这样做:
$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
这是一个完整的示例,它允许将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
Receive-Job -Wait
将确保收到作业的输出,否则它将丢失。
这个问题有一个简单的解决方法。只需在类名中添加随机后缀即可。
$id = get-random
$code = @"
using System;
namespace HelloWorld {
public class Program$id
{
public static void Main(){
Console.WriteLine("Hello world!");
}
}
}"@
Add-Type -TypeDefinition $code -Language CSharp
iex "[HelloWorld.Program$id]::Main()"
(来自:使用 PowerShell 脚本执行 C# 代码 - 随机 IT 用具https://blog.adamfurmanek.pl/2016/03/19/executing-c-code-using-powershell-script)
我一直面临着类似的问题。无法卸载类型/程序集(这是因为它适用于 .NET 框架)。
在 .NET 中,如果您创建一个新的应用程序域 ( System.AppDomain
) 并将程序集加载到该域中,您就可以解决它。可以卸载应用程序域并卸载所有 dll。
我还没有尝试过,因为对我来说,关闭控制台中的选项卡并打开新选项卡要简单得多。