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


PowerShell交流中心分类: Powershell基础powershell 如何加载自定义的带有引用的C#类?
0
Amanda asked 9年 ago

自己写了一个c#类,想用powershell(4.0)创建一个自定义的.net对象,但是不知道怎么加载改类(引用了Newtonsoft.Json)
使用loadfile加载的时候错误如下


[void][System.Reflection.Assembly]::LoadFile("E:\1.dll")

使用“1”个参数调用“LoadFile”时发生异常:“该模块应包含一个程序集清单。
 
换用add-type加载

add-type -path e:\1.cs

报错:
未能找到类型或命名空间名称“Newtonsoft”(是否缺少 using 指令或程序集引用?)
未能找到类型或命名空间名称“JObject”(是否缺少 using 指令或程序集引用?)
add-type : 无法添加类型。出现编译错误。
 
c#类的引用如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Web;
using System.IO;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

新手,跪求大神指教如何加载该类~~~~(>_<)~~~~
 

2 Answers
1
Mooser Lee 管理员 answered 9年 ago

白天上班比较忙,不能静下心来帮助网友解决问题,只等稍微提点一下。晚上回来得做饭洗碗,照顾孕妇,现在夜深人静,是时候仔细捉摸一下。
首先,我建立一个控制台应用程序,引用了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将这些依赖全部导入。
Amanda replied 9年 ago

Oh,Yes!终于成功鸟~~感动哭了(~ ̄▽ ̄)~十分感谢您在百忙之中抽空对一个编程小白问题的耐心解答,祝您生活幸福,家庭美满O(∩_∩)O~~

0
Mooser Lee 管理员 answered 9年 ago

PowerShell出于安全不会自动加载某一程序集所引用的其它程序集。建议你先手动加载依赖程序集:(比如Newtonsoft.dll
比如你要加载A,结果A引用了B和C,
所以加载的顺序应当是:

  1. B
  2. C
  3. A
Amanda replied 9年 ago

嗯,好的。那么请问如何加载Newtonsoft.Json.dll呢?用如下方法<br>[void][System.Reflection.Assembly]::LoadFile("e:\Newtonsoft.Json.dll")<br>总是报错<br>使用“1”个参数调用“LoadFile”时发生异常:“尝试从一个网络位置加载程序集,在早期版本的 .NET Framework 中,这会导致对该程序集进行沙盒处理。此发行版的 .NET Framework 默认情况下不启用 CAS 策略,因此,此加载可能会很危险。如果此加载不是要对程序集进行沙盒处理,请启用 loadFromRemoteSources 开关。有关详细信息,请参见 http://go.microsoft.com/fwlink/?LinkId=155569。”<br>怎么启用loadFromRemoteSources 开关呢?或者有其他的加载方式吗?

Mooser Lee 管理员 replied 9年 ago

你的powershell 的.NET 运行时是2.0 还是4.0。可以通过这个查看:[environment]::Version

Mooser Lee 管理员 replied 9年 ago

你要保证你要加载的dll的运行时和当前的PowerShell版本一致,并且dll的依赖项已经加载进来了。

Mooser Lee 管理员 replied 9年 ago

直接使用Add-Type -Path ‘your.dll’ 进行加载。

Amanda replied 9年 ago

是4.0的 Newtonsoft.Json类库解压缩之后在如下目录下 \json\Source\Build 有install.ps1和build.ps1 这两个文件,是不是运行这两个文件就可以加载Newtonsoft.Json类库了呢?

Mooser Lee 管理员 replied 9年 ago

那两个文件是供visual studio 安装package 用的。你就用add-type -Path ‘dll的绝对路径’,安装,看是什么错误。

Amanda replied 9年 ago

错误是未能加载文件或程序集“file:///E:\Newtonsoft.Json.dll”或它的某一个依赖项。不支持操作。so 怎么看dll的依赖项啊?

Amanda replied 9年 ago

在网上找了Newtonsoft.Json的源码,添加引用的时候发现FShap.Core add-type 不进去Add-Type -AssemblyName “FSharp.Core”Add-Type : 无法添加类型。找不到程序集“FSharp.Core”。是不是因为powershell不支持F#啊?有木有解决方法呢?

Mooser Lee 管理员 replied 9年 ago

我这边测试是通过的。windows 8.1 ,powershell 是4.0:使用的是Newtonsoft.Json.5.0.8,用的是Newtonsoft.Json.5.0.8\lib\net40PS D:\packages\Newtonsoft.Json.5.0.8\lib\net40> Add-Type -Path Newtonsoft.Json.dl

Amanda replied 9年 ago

请问这个调用之前有没有add newtonsoft.json 的依赖集呢?我的json之前是6.0.8版本,现在又重新下载了5.0.8版本,还是不成Add-Type -Path ‘D:\C# workspace\Json50r8\Bin\Net40\Newtonsoft.Json.dll’Add-Type : 未能加载文件或程序集“file:///D:\C# workspace\Json50r8\Bin\Net40\Newtonsoft.Json.dll”或它的某一个依赖项。不支持操作。 (异常来自 HRESULT:0x80131515)所在位置 行:1 字符: 1+ Add-Type -Path ‘D:\C# workspace\Json50r8\Bin\Net40\Newtonsoft.Json.dll’+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Add-Type], FileLoadException + FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand我是window7 系统,是系统和powershell4.0不兼容吗?

0
Amanda answered 9年 ago

我用别人的电脑(windows8系统)加载了成功了 newtonsoft.json
使用 $a = New-Object Newtonsoft.Json.Linq.JObjcet 可以创建对象,
但是加载我自己的cs代码还是会报错,
未能找到类型或命名空间名称“Newtonsoft”(是否缺少 using 指令或程序集引用?)
未能找到类型或命名空间名称“JObject”(是否缺少 using 指令或程序集引用?)
add-type : 无法添加类型。出现编译错误。
 
请问是怎么回事呢?我是否需要修改我的C#代码呢?