77

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

有没有办法在添加 DLL 后再次卸载 DLL Add-Type?文档似乎没有这方面的线索,而明显的候选者将是Remove-Type(它不存在——反正只有一个命令Type作为它的名词)。每次我想重建时,关闭 PowerShell 并执行导航到构建目录并再次添加类型的所有工作都变得很麻烦。

4

6 回答 6

65

就像其他人说的那样,这是一种 .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(新进程)“exit”重新开始,然后再次运行“powershell”。

于 2010-07-30T14:55:12.180 回答
51

我发现解决此问题的最简单方法是将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

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

于 2010-07-30T19:19:21.300 回答
27

如果您的程序集不需要绑定上下文,您可以这样做:

$bytes = [System.IO.File]::ReadAllBytes("Path_To_Your_Dll.dll")
[System.Reflection.Assembly]::Load($bytes)
于 2010-07-30T09:30:22.120 回答
6

这是一个完整的示例,它允许将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将确保收到作业的输出,否则它将丢失。

于 2017-01-10T14:25:34.350 回答
1

这个问题有一个简单的解决方法。只需在类名中添加随机后缀即可。

$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

于 2021-05-07T09:09:11.103 回答
0

我一直面临着类似的问题。无法卸载类型/程序集(这是因为它适用于 .NET 框架)。

在 .NET 中,如果您创建一个新的应用程序域 ( System.AppDomain) 并将程序集加载到该域中,您就可以解决它。可以卸载应用程序域并卸载所有 dll。

我还没有尝试过,因为对我来说,关闭控制台中的选项卡并打开新选项卡要简单得多。

于 2010-07-30T08:58:04.437 回答