点源文件中的PowerShell点源-导入类

Jon*_*man 4 powershell class powershell-module

我的项目的结构如下:

MyScript.ps1
classes\
    Car.ps1
    Tesla.ps1
Run Code Online (Sandbox Code Playgroud)

Car.ps1是Tesla.ps1的基类。我试图在Tesla.ps1中这样定义Tesla:

. "$PSScriptRoot\Car.ps1"

class Tesla : Car
{
}
Run Code Online (Sandbox Code Playgroud)

MyScript.ps1需要使用Tesla类,但不必知道它是从Car继承的。

. "$PSScriptRoot\classes\Tesla.ps1"

$tesla = [Tesla]::new()
Run Code Online (Sandbox Code Playgroud)

点采购classes\Tesla.ps1工作正常,但从Tesla文件中抛出此错误:

找不到类型[汽车]

如果我以正确的顺序将所有文件导入MyScript.ps1,则可以正常工作。例:

. "$PSScriptRoot\classes\Car.ps1"
. "$PSScriptRoot\classes\Tesla.ps1"

$tesla = [Tesla]::new()
Run Code Online (Sandbox Code Playgroud)

这很麻烦,尤其是随着复杂性的增长。我的网点采购不正确吗?有没有更好的方法可以使用PSModulePath中没有的相对路径导入自定义PowerShell类?

mkl*_*nt0 6

与以前无数次一样,PetSerAl在对该问题的简短评论中提供了关键的指针:

由于使用了,因此必须使用模块并将其与using module语句一起导入才能使用它们。

不幸的是,截至本文撰写时,using module)中仍未提及Get-Help about_Modules

具体来说,为了在class定义中引用类型(类),PowerShell 在解析时必须知道该类型。

在您的示例中,为了Tesla从class 派生,执行脚本之前,PowerShell在解析脚本之前必须知道Car类型,这就是为什么现在通过点源包含其脚本()尝试导入为时已晚CarCar. "$PSScriptRoot\Car.ps1"

PowerShell在解析时通过以下两种方式之一了解引用的类型:

  • 如果类型已经加载到当前的PowerShell会话中

  • 通过using module引用定义了类型(类)的模块的语句(请注意,还有一条using assembly语句用于从DLL加载类型,并using namespace允许仅使用类型名称引用类型)。

    • 请注意,相关Import-Modulecmdlet的不会没有在这种情况下工作,因为它执行的运行

因此,正如PetSerAl建议的那样:

  • 将类存储在模块文件中*.psm1最简单的情况是独立文件)

  • 然后使用using module相对于封闭脚本/模块的location的路径,使Tesla模块导入Car模块,MyScript.ps1脚本使Tesla模块导入模块。

    • 警告:从PowerShell Core 6.1.0-preview.4开始,存在一个错误,该错误要求您甚至在通常使用Unix的平台上,使用\相对路径中的路径分隔符。using module/
MyScript.ps1
classes\
    Car.psm1    # Note the .psm1 extension
    Tesla.psm1  # Ditto
Run Code Online (Sandbox Code Playgroud)

Car.psm1

class Car {}
Run Code Online (Sandbox Code Playgroud)

Tesla.psm1

using module .\Car.psm1

class Tesla : Car {}
Run Code Online (Sandbox Code Playgroud)

MyScript.ps1

using module .\classes\Tesla.psm1

$tesla = [Tesla]::new()
Run Code Online (Sandbox Code Playgroud)