我正在研究一个生成 CSharp 代码的 PoSh 项目,然后 Add-Type 将它放入内存中。新类型使用磁盘 DLL 中的现有类型,该类型通过 Add-Type 加载。一切都很好,直到我实际尝试调用新类型的方法。这是我正在做的一个例子:$PWD = "."rm -Force $PWD\TestClassOne*$code = "namespace TEST{public class TestClassOne{ public int DoNothing() { return 1; }}}"$code | Out-File tcone.csAdd-Type -OutputAssembly $PWD\TestClassOne.dll -OutputType Library -Path $PWD\tcone.csAdd-Type -Path $PWD\TestClassOne.dll$a = New-Object TEST.TestClassOne"Using TestClassOne"$a.DoNothing()"Compiling TestClassTwo"Add-Type -Language CSharpVersion3 -TypeDefinition "namespace TEST{public class TestClassTwo{ public int CallTestClassOne() { var a = new TEST.TestClassOne(); return a.DoNothing(); }}}" -ReferencedAssemblies $PWD\TestClassOne.dll"OK"$b = New-Object TEST.TestClassTwo"Using TestClassTwo"$b.CallTestClassOne()运行上述脚本在最后一行出现以下错误:使用“0”参数调用“CallTestClassOne”的异常:“无法加载文件或程序集 'TestClassOne,...'或其依赖项之一。该系统找不到指定的文件。”在 AddTypeTest.ps1:39 字符:20+ $b.CallTestClassOne + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullQualifiedErrorId:DotNetMethodException我究竟做错了什么? 最佳答案 发生这种情况是因为 CLR 加载程序在应用程序 (PowerShell) 的基目录中查找任何程序集。当然,它不会在那里找到您的程序集。解决这个问题的最好方法是像 stej 提到的那样 Hook AssemblyResolve 事件,但用它来告诉 CLR 程序集在哪里。您不能使用 PowerShell 2.0 的 Register-ObjectEvent 执行此操作,因为它不适用于需要返回值的事件(即程序集)。在这种情况下,让我们通过 Add-Type 使用更多的 C# 来为我们完成这项工作。这段代码有效:ri .\TestClassOne.dll -for -ea 0$resolver = @'using System;using System.Collections.Generic;using System.IO;using System.Reflection;namespace Utils{ public static class AssemblyResolver { private static Dictionary<string, string> _assemblies; static AssemblyResolver() { var comparer = StringComparer.CurrentCultureIgnoreCase; _assemblies = new Dictionary<string,string>(comparer); AppDomain.CurrentDomain.AssemblyResolve += ResolveHandler; } public static void AddAssemblyLocation(string path) { // This should be made threadsafe for production use string name = Path.GetFileNameWithoutExtension(path); _assemblies.Add(name, path); } private static Assembly ResolveHandler(object sender, ResolveEventArgs args) { var assemblyName = new AssemblyName(args.Name); if (_assemblies.ContainsKey(assemblyName.Name)) { return Assembly.LoadFrom(_assemblies[assemblyName.Name]); } return null; } }}'@Add-Type -TypeDefinition $resolver -Language CSharpVersion3$code = @'namespace TEST { public class TestClassOne { public int DoNothing() { return 1; } }}'@$code | Out-File tcone.csAdd-Type -OutputAssembly TestClassOne.dll -OutputType Library -Path tcone.cs# This is the key, register this assembly's location with our resolver utility[Utils.AssemblyResolver]::AddAssemblyLocation("$pwd\TestClassOne.dll")Add-Type -Language CSharpVersion3 ` -ReferencedAssemblies "$pwd\TestClassOne.dll" ` -TypeDefinition @'namespace TEST { public class TestClassTwo { public int CallTestClassOne() { var a = new TEST.TestClassOne(); return a.DoNothing(); } }}'@$b = new-object Test.TestClassTwo$b.CallTestClassOne()关于powershell - 如何获得 PowerShell 附加类型以使用附加类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2664028/ 10-13 06:41