如何获取定义PowerShell类的psm1模块路径?原方案因更新失效
我需要获取定义某类的psm1模块的文件或文件夹路径。此前多年来,一直通过类TypeInfo的AssemblyQualifiedName实现该需求,使用的代码如下:
$type = [MyType] $path = $type.AssemblyQualifiedName.Split(",")[1].Trim()
之前AssemblyQualifiedName的格式为:{ClassName}, {PathToFile}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
但在最新Windows更新后,AssemblyQualifiedName格式变为:{ClassName}, PowerShell Class Assembly, Version=1.0.0.36, Culture=neutral, PublicKeyToken=null
该问题与PowerShell版本无关,在5.1.19041.3031和5.1.22621.1778版本中可复现此异常,但未安装更新的5.1.20348.1366版本仍正常工作。
目前唯一可行的临时方案是在每个类中添加如下静态隐藏方法来返回模块位置,但该方案十分繁琐:
static hidden [string]GetModuleLocation() { return $PSScriptRoot }
求恢复原有行为的方法,或动态解析模块路径的替代方案。
方法1:通过已加载模块反向匹配程序集
PowerShell模块导出的类型会关联到模块的程序集,遍历已加载模块,匹配类型所属的程序集就能拿到模块路径:
function Get-TypeModulePath([Type]$type) { $targetAssembly = $type.Assembly foreach ($module in Get-Module) { if ($module.Assembly -eq $targetAssembly) { return $module.Path } # 检查模块的嵌套程序集 foreach ($nestedAssembly in $module.NestedAssemblies) { if ($nestedAssembly -eq $targetAssembly) { return $module.Path } } } return $null } # 使用示例 $type = [MyType] $modulePath = Get-TypeModulePath $type $folderPath = Split-Path $modulePath -Parent
方法2:解析类型的自定义属性获取模块路径
PowerShell类自带的ModuleAttribute里包含模块路径信息,直接解析这个属性即可:
function Get-TypeModulePath([Type]$type) { $moduleAttr = $type.CustomAttributes | Where-Object { $_.AttributeType.Name -eq 'ModuleAttribute' } if ($moduleAttr) { return $moduleAttr.ConstructorArguments[0].Value } return $null } # 使用示例 $type = [MyType] $modulePath = Get-TypeModulePath $type
方法3:模块内主动建立类型-路径映射
在psm1模块里,定义类后主动记录类型到模块路径的映射,后续直接查询这个映射表:
# 在psm1开头初始化映射表 $script:TypeToModuleMap = @{} # 定义类后添加映射 class MyType {} $script:TypeToModuleMap[[MyType]] = $PSScriptRoot # 导出映射表供外部访问 Export-ModuleMember -Variable TypeToModuleMap # 外部查询方式 $type = [MyType] $moduleFolder = (Get-Module YourModuleName).TypeToModuleMap[$type]
目前这个变化是Windows更新导致的PowerShell类程序集命名逻辑变更,没有官方的恢复开关或配置项。建议直接用上面的替代方案——毕竟AssemblyQualifiedName的格式属于未公开的实现细节,本来就不适合作为可靠的路径提取依据。
内容的提问来源于stack exchange,提问作者lolsharp

