正在加载其他文件(ps1)以在PowerShell模块中使用
我有正在加载其他文件(ps1)以在PowerShell模块中使用,powershell,Powershell,我有PowerShell模块(我们称之为PSModule),其中我在.psd1中定义如下 # Script files (.ps1) that are run in the caller's environment prior to importing this module. ScriptsToProcess = @('Enums\MessageType.ps1') 这是在那里添加的,因此保存justenum的文件MessageType.ps1可以跨多个文件重用 此文件看起来像: enum
PowerShell模块
(我们称之为PSModule
),其中我在.psd1中定义如下
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
ScriptsToProcess = @('Enums\MessageType.ps1')
这是在那里添加的,因此保存justenum
的文件MessageType.ps1
可以跨多个文件重用
此文件看起来像:
enum MessageType {
None
Something
}
这方面的一个例子是PSWriteWord
-模块。这应该将枚举保存在它自己的文件夹中,并在模块启动时仍然加载它们
这在大多数情况下都很有效。我运行的脚本没有问题。现在我创建了一个奇怪的场景:script1.ps1——我调用它
script1.ps1的内容
Import-Module PSModule -Force
Import-Module PSOtherModule -Force
Call-Me -Parameters <params> # part of PSOtherModule
在ISE或VSCode中运行时,它将工作
现在,如果我从任务调度器
重新运行相同的脚本,它将不会加载消息类型
,这在某一点上基本上会失败。它似乎只是跳过了ScriptsToProcess
的处理
现在如果你这样做了:
Do-Something
do-Something
Import-Module PSModule
Call-OtherFunction # function from PSModule
还是不行。。。但这将
Do-Something
do-Something
Import-Module PSModule -Force
Call-OtherFunction # function from PSModule
所以现在我正在努力找到一种方法,在调用PSModule之前,正确地将枚举作为单独的文件添加到我的模块中,并在不使用IMport Module的奇怪解决方法的情况下保持运行
我发现:它言而有信,做得很好,但不能解决我的问题
有人知道解决这个问题的方法吗?我尝试将fullpath放入ScriptStopProcess,认为ScriptStopProcess中的枚举路径可能会被某种方式覆盖。。。但是没有
我的.psm1文件如下所示:
#Get public and private function definition files.
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue )
$Enums = @( Get-ChildItem -Path $PSScriptRoot\Enums\*.ps1 -ErrorAction SilentlyContinue )
#Dot source the files
Foreach ($import in @($Public + $Private + $Enums)) {
Try {
. $import.fullname
} Catch {
Write-Error -Message "Failed to import function $($import.fullname): $_"
}
}
Export-ModuleMember -Function '*'
[string] $ManifestFile = '{0}.psd1' -f (Get-Item $PSCommandPath).BaseName;
$ManifestPathAndFile = Join-Path -Path $PSScriptRoot -ChildPath $ManifestFile;
if ( Test-Path -Path $ManifestPathAndFile) {
$Manifest = (Get-Content -raw $ManifestPathAndFile) | iex;
foreach ( $ScriptToProcess in $Manifest.ScriptsToProcess) {
$ModuleToRemove = (Get-Item (Join-Path -Path $PSScriptRoot -ChildPath $ScriptToProcess)).BaseName;
if (Get-Module $ModuleToRemove) {
Remove-Module $ModuleToRemove;
}
}
}
我刚才添加了枚举,但它没有改变任何东西。。。导出模块之后的事情是从模块中删除脚本(如链接中所示)。这与我的问题无关
可以在这里看到:
为了解决这个问题,我选择将
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
}
"@
添加类型-类型定义@”
公共枚举消息类型
{
警觉的
取消
使残废
下载
减
检查
添加
没有一个
}
"@
为了解决这个问题,我选择将添加类型
与按需编译的C#代码一起使用,而不是PowerShell自己的枚举
构造。它起作用了
<#
enum MessageType {
Alert
Cancel
Disable
Download
Minus
Check
Add
None
}
#>
Add-Type -TypeDefinition @"
public enum MessageType
{
Alert,
Cancel,
Disable,
Download,
Minus,
Check,
Add,
None
}
"@
添加类型-类型定义@”
公共枚举消息类型
{
警觉的
取消
使残废
下载
减
检查
添加
没有一个
}
"@
注意:
- 如果您只是想通过
,基于C代码的按需编译,寻找一个有效的解决方案,请参阅Add Type
- 如果您想了解问题,包括为什么基于
添加类型的解决方案有帮助,请继续阅读
行为与预期一致: 您的
导入模块PSModule-Force
调用script.ps1
点源Enums\MessageType.ps1
仅在script.ps1
的范围内
因此,当运行模块PSOtherModule
中的Call Me
时,它对加载到script.ps1
中的枚举一无所知,因为PSOtherModule
有自己的作用域(不会从调用方继承)
Call Me
中的Import Module PSModule-Force
起作用的原因是,您在PSOtherModule
的上下文中强制重新加载模块,从而点源Enums\MessageType.ps1
,使enum
可用(忽略-Force
将是不可操作的,因为PowerShell已经加载了模块(在全局会话中发生),因此不会再次处理模块清单及其ScriptsToProcess
条目)
是的,使用添加类型
和包含按需编译的C代码的字符串可以解决问题(如中所示),但出于一个不相关的原因:添加类型
-添加的类型始终是会话全局的,而不管在什么范围内调用添加类型
要使用PowerShellenum
(或class
)定义实现相同的效果,从而解决您的问题,您需要:
- 直接在
文件中包含PSModule.psm1
定义enum
- 使用
指令而不是使用模块PSModule
cmdlet调用来导入您的模块-仅导入模块PSModule
使基于PowerShell的使用模块
和枚举
定义在模块外部可用,然后还可以全局会话类
可选背景信息:
和enum
定义是PowerShell(v5)最近添加的,它们不是模块导出机制的一部分class
- 在模块之外,
和enum
定义是它们在/dot中定义的范围的本地定义class
- 如果将
和enum
定义作为模块(class
)的一部分,并使用模块*.psm1
导入该模块,则这些定义确实变为可用,但始终是所有定义,并且始终是全局会话定义(与添加基于类型的类型一样,尽管它们即使在导入模块时也会这样做)
- 如果使用
而不是导入模块
,则属于模块一部分的使用模块
和类
定义实际上是私有的枚举
- 在模块之外,
- 自Windows PowerShell v5.1/PowerShell Core v6.1.0起,对
和enum
定义的许多修复和增强都处于挂起状态:class
- 跟踪他们所有人
- 制作
参见导入模块