解析 Powershell 模块位置

huangapple go评论72阅读模式
英文:

Resolving Powershell Module Location

问题

我想获取包含类定义的psm1模块的文件或文件夹路径。
直到最新的Windows更新,我多年来都使用类的TypeInfo的AssemblyQualifiedName来解决此问题。

$type = [MyType]
$path = $type.AssemblyQualifiedName.Split(",")[1].Trim()

以前的AssemblyQualifiedName如下所示:
{类名}, {文件路径}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

但是,最新的更新将AssemblyQualifiedName更改为:
{类名}, PowerShell类库, Version=1.0.0.36, Culture=neutral, PublicKeyToken=null

似乎与PowerShell版本无关,因为我可以在5.1.19041.3031和5.1.22621.1778上复制新的不希望的行为,但也有一个VM(未安装Windows更新)上的版本为5.1.20348.1366,它仍然有效。

有没有人有办法恢复原始行为或以动态方式解析文件位置的替代解决方案?

唯一可能的解决方法是在每个类中创建一个提供ModuleLocation的方法:

static hidden [string]GetModuleLocation() {
    return $PSScriptRoot
}

但这是一个相当混乱的解决方案。

英文:

I want to get the file or folder path of the psm1 module in which a class is defined.
Until the latest windows update I had stable solution for this for many years using the AssemblyQualifiedName of the TypeInfo of the class.

$type = [MyType]
$path = $type.AssemblyQualifiedName.Split(",")[1].Trim()

Previously the AssemblyQualifiedName looked like this:
{ClassName}, {PathToFile}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

With the newest update the Assembly Qualifiedname changed to this:
{ClassName}, PowerShell Class Assembly, Version=1.0.0.36, Culture=neutral, PublicKeyToken=null

It doesn't seem to be related to the Powershell Version since i can reproduce the new unwanted behavior on 5.1.19041.3031 and 5.1.22621.1778 but also have a VM (windows update not installed) with version 5.1.20348.1366 where it still works.

Does anyone an idea how to get the original behavior back or an alternative solution to dynamically resolve the file location?

The only somewhat possible workaround would be to create a Method in each class which provides the ModuleLocation:

  static hidden [string]GetModuleLocation() {
    return $PSScriptRoot
  }

But thats a pretty messy solution.

答案1

得分: 1

[int].Assembly.Location

还有CodeBase属性。

编辑:
上面的解决方法过去适用于在模块中定义的类型。但我刚刚测试了,在我的机器上,它仍然适用于PowerShell 5.1,但在7.3中不再适用。

我找到了一个不同的解决方法,但它要求您首先导入可能定义类型的所有模块(-ListAvailable不会帮助)。它列出了模块定义的所有类型,然后您可以进行筛选。在ps 5.1和7.3上都有效。

(Get-Module | ? ImplementingAssembly)|%{
[pscustomobject]@{
模块 = $.Name
类型 = $
.ImplementingAssembly.DefinedTypes
}
}

结果:

模块 类型


TestModule {MyType, MyType_<staticHelpers>, MyEnum}
TestModulx {xType, xType_<staticHelpers>}

当然,如果同一类型可以在许多不同的模块中实现,并且您需要在运行时找到已加载的类型来自哪里,那么这并没有太大帮助。

英文:

Wouldn't this work?

[int].Assembly.Location

There's also CodeBase property.

EDIT:
Solution above used to work even for types defined in a module. But I just tested, and on my machine it still works in powershell 5.1, but not anymore in 7.3.

I found a different solution, but it requires that you first import all modules that may define the types (-ListAvailable won't help). It lists all types defined by the modules, then you can filter. Works both on ps 5.1 and 7.3

(Get-Module | ? ImplementingAssembly) | % {
  [pscustomobject]@{
    Module = $_.Name
    Types = $_.ImplementingAssembly.DefinedTypes
  }
}

Result:

Module     Types                                             
------     -----                                             
TestModule {MyType, MyType_&lt;staticHelpers&gt;, MyEnum}
TestModulx {xType, xType_&lt;staticHelpers&gt;}

Ofcourse it's not much help if same type can be implemented in many different modules, and you need to find where did already loaded type came from during runtime.

huangapple
  • 本文由 发表于 2023年6月19日 18:44:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76505872.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定