我已经{。{1}}(我们称其为PowerShell Module
)在.psd1中的定义如下:
PSModule
将其添加到此处,以便仅包含# Script files (.ps1) that are run in the caller's environment prior to importing this module.
ScriptsToProcess = @('Enums\MessageType.ps1')
的文件MessageType.ps1
可以在多个文件中重复使用。
此文件如下所示:
Enums
enum MessageType {
None
Something
}
-https://github.com/EvotecIT/PSWriteWord模块就是一个例子。这应该将Enums保留在其自己的文件夹中,并在模块启动时仍加载它们。
这在大多数情况下都可以正常工作。我运行脚本没有问题。现在,我已经创建了一个奇怪的情况:script1.ps1-我称之为。
script1.ps1的内容
PSWriteWord
现在从我呼叫的PSOtherModule的Call-Me函数中
Import-Module PSModule -Force
Import-Module PSOtherModule -Force
Call-Me -Parameters <params> # part of PSOtherModule
在ISE或VSCode中运行时它将起作用...
现在,如果我从Do-Something
do-Something
Call-OtherFunction # function from PSModule
重新运行相同的脚本,它将不会加载Task Scheduler
,这实际上在某些时候会失败。似乎它只是跳过了MessageType
的处理。
现在,如果您这样做:
ScriptsToProcess
它仍然无法工作...但这会...
Do-Something
do-Something
Import-Module PSModule
Call-OtherFunction # function from PSModule
因此,现在我正在努力寻找一种方法,以将ENUMS作为单独的文件正确添加到我的模块中,并在调用PSModule之前,使用IMport-Module进行怪异的解决方法,以使其保持运行状态。
我发现了这一点:https://d-fens.ch/2014/11/26/bug-powershell-scripts-in-scriptstoprocess-attribute-appear-as-loaded-modules/可以按照它说的做得很好,但是不能解决我的问题。
有人知道解决方法吗?我试着将全路径放到ScriptsToProcess中,以为ScriptsToProcess中的枚举路径可能会以某种方式被覆盖……但是没有。
我的.psm1文件如下:
Do-Something
do-Something
Import-Module PSModule -Force
Call-OtherFunction # function from PSModule
我刚刚添加了Enums,但是它没有任何改变。Export-Module之后的事情是从模块中删除脚本(如链接中所示)。没关系,我的问题。
答案 0 :(得分:2)
注意:
如果您只是根据通过Add-Type
进行C#代码的按需编译而寻求一种有效的解决方案,请参见
MadBoy's own answer。
如果您想理解问题,包括为什么基于Add-Type
的解决方案有帮助,请继续阅读。
行为符合预期:
您在Import-Module PSModule -Force
范围内的script.ps1
点源Enums\MessageType.ps1
中的script.ps1
呼叫 。
因此,当模块Call-Me
中的PSOtherModule
运行时,它对您已加载到script.ps1
的枚举一无所知,因为PSOtherModule
有自己的范围(不继承自调用方)。
Import-Module PSModule -Force
中的Call-Me
有效的原因是您在PSOtherModule
重新加载模块 >,然后将其作为点源Enums\MessageType.ps1
,使enum
可用(而省略-Force
则是无操作的操作,因为PowerShell已经加载了模块(在全局会话中进行) ),因此不会再次处理模块清单及其ScriptsToProcess
条目)。
是,将Add-Type
与包含按需编译的C#代码的字符串一起使用即可解决问题(如the answer you've since posted所示),但是出于不相关的原因:<添加strong> Add-Type
的类型始终是 session-global ,而不管调用Add-Type
的范围是什么。
要使用 PowerShell enum
(或class
)定义来实现相同的效果-从而解决您的问题-您需要:< / p>
直接在您的enum
文件中包含PSModule.psm1
定义。
使用using module PSModule
指令而不是Import-Module PSModule
cmdlet调用来导入模块-只有using module
使基于PowerShell的enum
和{{1 }}定义可以在模块外部使用,然后也可以全局会话。
可选的背景信息:
class
和enum
定义是PowerShell(v5)的新增功能,它们不是模块导出机制的一部分。
在模块之外,class
和enum
的定义对于它们在/点源中定义的范围是本地的。
如果将class
和enum
定义作为模块(class
)的一部分,则使用*.psm1
导入该模块,这些定义的确可以使用,但它们中的全部总是可用,并且总是 session-globally (基于using module
的类型也一样,尽管它们甚至在Add-Type
。
Import-Module
而不是Import-Module
,则作为模块一部分的using module
和class
定义实际上是 private 。 / li>
自Windows PowerShell v5.1 / PowerShell Core v6.1.0起,对enum
和enum
定义的许多修复和增强尚在待解决中:
This meta GitHub issue跟踪所有这些内容。
让class
看到模块的Import-Module
和enum
的定义in this issue进行了讨论;尽管从根本上说可能,class
在 runtime 执行而Import-Module
在 parse time 执行的事实排除了using module
的某些用例(简而言之:Import-Module
个定义引用了其他class
个定义)。
另外,能够显式控制要导出的 class
和enum
定义-类似于如何有选择地导出函数,别名和变量-正在讨论in this issue。
答案 1 :(得分:1)
要解决此问题,我选择将Add-Type
与按需编译的C#代码一起使用,而不是PowerShell自己的enum
构造。有用。
<#
enum MessageType {
Alert
Cancel
Disable
Download
Minus
Check
Add
None
}
#>
Add-Type -TypeDefinition @"
public enum MessageType
{
Alert,
Cancel,
Disable,
Download,
Minus,
Check,
Add,
None
}
"@