引用PS类中的程序集会导致“无法找到类型”错误

时间:2017-09-18 20:02:06

标签: .net class powershell .net-assembly

我在Windows 7机器上使用PowerShell 5.1,并尝试从PowerShell类中引用.NET程序集中的类型,并且收到“无法找到类型”错误。

我的“主”程序是FooProg.ps1,我正在创建一个FooMod类的新实例

#Requires -Version 5.1
using module .\FooMod\FooMod.psm1
[FooMod]::new() | out-null

FooMod类位于FooMod子文件夹中的PowerShell模块(FooMod.psm1)中

#Requires -Version 5.1

using assembly .\Foo.dll
using namespace Foo

class FooMod {
   FooMod() {
      Write-Host "Start - Assembly access"
      [Bar] $bar = [Bar]::new()
      Write-Host $bar.Name
      Write-Host $bar.Greeting()
      Write-Host "Finish - Assembly access"
   }
}

我的Foo.dll是从以下Bar.cs构建的,并且与Module文件(FooMod.psm1)和Module Manifest文件(FooMod.psd1)一起位于FooMod子文件夹中

namespace Foo {
   public class Bar {
      public string Name;

      public Bar(string name) => this.Name = name;

      public Bar() : this("Bar") {
      }

      public string Greeting() {
         return System.String.Format("Hello! My name is {0}", Name);
      }
   }
}

我还在名为FooMod.psd1的FooMod子文件夹中有一个Module Manifest,其中包含这些相关条目

RootModule = 'FooMod.psm1'
RequiredAssemblies = 'Foo.dll'

还有什么我想念的吗?使用类外部的程序集工作正常,实例化PowerShell类(不引用程序集/外部类型)工作正常 - 但组合PowerShell类和程序集类型是不行的!

1 个答案:

答案 0 :(得分:1)

想出来!事实证明,在主脚本FooProg.ps1中,using语句需要引用Module Manifest和 NOT 模块脚本。

所以不要使用

#Requires -Version 5.1
using module .\FooMod\FooMod.psm1
[FooMod]::new() | out-null

我把它改成了

#Requires -Version 5.1
using module .\FooMod\FooManifest.psd1
[FooModule]::new() | out-null

因此,我还将我的Module Manifest文件从。\ FooMod \ FooMod.psd1 重命名为。\ FooMod \ FooManifest.psd1

此外,在Module Manifest文件中,我将条目 RootModule =&#39; FooMod.psm1&#39; 更改为 RootModule =&#39; FooModule.psm1&#39; < / strong>即可。这不是必需的更改,但有助于理解不同文件的结构。

这显然导致将模块脚本从 FooMod.psm1 重命名为 FooModule.psm1 ,并且还从 FooMod <更改模块脚本中的类名称/ strong>到 FooModule 。同样不是必需的更改,但它与命名类一致,与包含它们的文件名相同。

整个练习让我相信需要首先处理主脚本中命名的Module Manifest文件,以便在 RequiredAssemblies 中命名的程序集在<解析strong> RootModule 。这使得外部.NET程序集中的类型在解析模块时可用,并防止&#34;无法找到类型&#34;错误。

现在配备了新的FooModule.psm1文件

#Requires -Version 5.1

using assembly .\Foo.dll
using namespace Foo

class FooModule {
   FooModule() {
      Write-Host "Start - Assembly access"
      Write-Host

      [Bar] $bar1 = [Bar]::new("Romeo")

      Write-Host $bar1.Name
      Write-Host $bar1.Greeting()

      Write-Host

      [Bar] $bar2 = [Bar]::new("Juliet")

      Write-Host $bar2.Name
      Write-Host $bar2.Greeting()

      Write-Host
      Write-Host "Finish - Assembly access"
   }
}

我得到的输出如下

Start - Assembly access

Romeo
Hello! My name is Romeo

Juliet
Hello! My name is Juliet

Finish - Assembly access

关键是使用Module Manifest,正确设置RequiredAssemblies键,并在主脚本中引用Module Manifest而不是Module Script本身。