如何在Powershell中使用通过Add-Type定义的接口?

时间:2018-08-10 21:11:45

标签: powershell

我开发了一个PowerShell模块,该模块依赖于.NET程序集进行某些操作。
我将这个模块重构为不需要该Assembly,并注意到了一些奇怪的行为,这最终使我无法删除该类:

function getOrgUsers() {
  var orgUserEmails = [];
  smartsheet.users.listAllUsers(options)
                  .then(function(userList) {
                    userList.data.forEach(function(userEmail) {
                    orgUserEmails.push(userEmail.email);
                  })
  // console.log(orgUserEmails);  // This works and returns the array of emails that are pushed to orgUserEmails
  return orgUserEmails; // Trying to return the variable to the function to then call the results of the function elsewhere.  
  })
  .catch(function(error) {
      console.log(error);
  });
}
getOrgUsers(); // calling the function

如果以交互方式运行此命令,它将成功。 但是,一旦我在ISE中或从psm1文件中“全面”运行它,它将抛出一个错误,指出它无法找到Add-Type -TypeDefinition "public interface ICanTalk { string talk(); }" -Language CSharp class Talker : ICanTalk { [string] talk() { return "Well hello there"; } } 调用中定义的接口。

我可以在Windows-PowerShell和PowerShell Core(6.0.2)中重现该问题

行为不同的原因是什么,我该如何解决?

2 个答案:

答案 0 :(得分:1)

显然,PowerShell将在执行代码之前读取文件并处理类定义。

要解决此问题,需要将Add-Type放入一个自己的脚本文件,该脚本文件在模块加载之前运行(或者在ISE中,仅在运行类定义之前运行代码)。

这可以通过使用PSD1文件中的ScriptsToProcess完成。

对@ TheIncorrigible1表示敬意,让我踏上了轨道。

答案 1 :(得分:1)

补充your own answer

PowerShell classenum的定义在执行开始之前进行了解析,并且其中的所有类型被引用这样的定义必须是:

  • 已预先加载到当前会话中。

  • [从Windows PowerShell v5.1 / PowerShell Core 6.1.0开始仅部分实现]
    通过using module / using assembly语句加载 文件顶部。

    • using module已经有效,但是仅当引用的类型是自身 class / enum定义时。

    • 当前,尚未检测到从程序集加载的类型-是否通过包含用using moduleusing assembly导入的程序集的模块直接加载程序集-

      • 请参阅以下GitHub问题:
        • #3461using module)和#2074using assembly
        • #6652-跟踪所有与课程相关的问题的元问题。

与此同时,解决方法是通过使用模块清单的NestedModules条目,预先通过单独的脚本加载引用的类型 strong>。

  • 注意:ScriptsToProcess条目也可以使用,但是它引用的脚本是基于点的源代码(加载到调用者的当前作用域中),而不是封闭模块。 br /> 使用来自编译的代码的类型(包括带有Add-Type的临时编译的代码)也可以工作,因为此类类型始终在全局会话中可用,但是从概念上讲,使用{{ 1}},因为它在 module 范围内