回答powershell 如何加载自定义的带有引用的C#类?


白天上班比较忙,不能静下心来帮助网友解决问题,只等稍微提点一下。晚上回来得做饭洗碗,照顾孕妇,现在夜深人静,是时候仔细捉摸一下。
首先,我建立一个控制台应用程序,引用了Install-Package Newtonsoft.Json。
写的代码Program.cs为:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
namespace PStips.Net
{
    public class Program
    {
        public static void Main()
        {
            JObject obj = new JObject();
            Console.WriteLine(obj.ToString());
        }
    }
}

然后尝试在PowerShell中加载Program.cs文件:

$source=get-content .\Program.cs -Raw
Add-Type -TypeDefinition $source

此时出现编译错误:
Add-Type : c:\Users\非苔\AppData\Local\Temp\1joeop23.0.cs(5) : 未能找到类型或命名空间名称“Newtonsoft”(是否缺少 using
指令或程序集引用?)
c:\Users\非苔\AppData\Local\Temp\1joeop23.0.cs(4) : using System.Text;
c:\Users\非苔\AppData\Local\Temp\1joeop23.0.cs(5) : >>> using Newtonsoft.Json.Linq;
c:\Users\非苔\AppData\Local\Temp\1joeop23.0.cs(6) : namespace PStips.Net
所在位置 行:1 字符: 1
+ Add-Type -TypeDefinition $source
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (c:\Users\非苔\App…sing 指令或程序集引用?):CompilerError) [Add-Type],Exce
ption
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand
Add-Type : 无法添加类型。出现编译错误。
所在位置 行:1 字符: 1
+ Add-Type -TypeDefinition $source
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-Type],InvalidOperationException
+ FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand
关键是红色的一行说明Newtonsoft.Json.Linq加载失败,@Amanda的问题得到重现,这是个好消息,有问题比没问题好。
此时我把上面的PowerShell脚本改为:

$source=get-content .\Program.cs -Raw
$ref=@("C:\Users\非苔\Documents\Visual Studio 2013\Projects\ConsoleApp\packages\Newtonsoft.Json.6.0.8\lib\net40\Newtonsoft.Json.dll")
Add-Type -TypeDefinition $source -ReferencedAssemblies $ref

编译通过,这也是好消息。然后我再通过PowerShell调用我的Main方法:

[PStips.Net.Program]::Main()

此时出现调用错误:
使用“0”个参数调用“Main”时发生异常:“未能加载文件或程序集“Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”或它的某一个依赖项。系统找不
到指定的文件。”
所在位置 行:1 字符: 1
+ [PStips.Net.Program]::Main()
我们可以向希特勒主席起誓,Newtonsoft.Json一定加载过了,否则上面的编译不可能通过,利用排除法,那肯定是它的一个或着多个依赖项没有加载了。
此时我们把画面切换到visual studio 的解决方案管理器中,参看应用程序的引用,或着把工程文件用记事本打开:
有如下引用:

  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>

我不想追究哪个幕后黑手引用导致了这个问题,全部给它判处死刑,全部加载:

$source=get-content .\Program.cs -Raw
$frameworkRefRootDir="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
$ref=@(
"C:\Users\非苔\Documents\Visual Studio 2013\Projects\ConsoleApp\packages\Newtonsoft.Json.6.0.8\lib\net40\Newtonsoft.Json.dll",
"$frameworkRefRootDir\Microsoft.CSharp.dll",
"$frameworkRefRootDir\System.dll",
"$frameworkRefRootDir\System.Core.dll",
"$frameworkRefRootDir\System.Data.dll",
"$frameworkRefRootDir\System.Data.DataSetExtensions.dll",
"$frameworkRefRootDir\System.Xml.dll",
"$frameworkRefRootDir\System.Xml.Linq.dll"
)
 $ref | foreach {
    Add-Type -Path $_
 }
Add-Type -TypeDefinition $source -ReferencedAssemblies $ref
[PStips.Net.Program]::Main()

哇,问题迎刃而解。
总结:

  1. add-type c#代码如果编译不通过,可以将依赖放在-ReferencedAssemblies中。
  2. 上面只解决了编译依赖,没有解决运行依赖,如果在运行时还是出错,那需要使用add-type将这些依赖全部导入。

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。