【问题标题】:How to cause Install-Module to also install any required modules?如何使 Install-Module 也安装任何必需的模块?
【发布时间】:2019-04-13 17:23:18
【问题描述】:

我正在开发一个依赖于 SqlServer 的 PS 模块。

这是模块清单文件:

@{
    ModuleVersion = "1.0.19103.11"
    GUID = "59bc8fa6-b480-4226-9bcc-ec243102f3cc"
    Author = "..."
    CompanyName = "..."
    Copyright = "..."
    Description = "..."
    RequiredModules = ""
    ScriptsToProcess = "vsts\config.ps1"
    NestedModules = @( ... )
    PrivateData = @{
        PSData = @{
            ExternalModuleDependencies = @(
                "SqlServer"
            )
        }
    }
}

这里是我用来发布模块的命令:

if (Get-PSRepository $PSRepositoryName -ErrorAction SilentlyContinue)
{
    Unregister-PSRepository $PSRepositoryName
}
Register-PSRepository $PSRepositoryName `
    -SourceLocation $NuGetRepoUrl `
    -PublishLocation $NuGetRepoUrl `
    -InstallationPolicy Trusted `
    -PackageManagementProvider nuget

Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force

问题是,当我安装此模块时,我收到以下警告:

WARNING: The externally managed, dependent module 'SqlServer' is not installed on this computer. To use the current module 'xyz.PS.Core', ensure that its dependent
module 'SqlServer' is installed.

如何在安装此包时自动安装 SqlServer 而没有任何警告。

我尝试设置 RequiredModules 属性,但如果构建机器没有安装模块 SqlServer,则首先无法发布模块。我可以在那里安装它,但是有没有更好的方法而不强制我们在构建代理上安装包?

编辑 1

所以,我在构建代理上安装了 SqlServer 模块并添加了RequiredModules 属性。显示相同的警告。但现在我什至无法导入模块:

Import-Module : The required module 'SqlServer' is not loaded. Load the module or remove the module from 'RequiredModules' in the file

编辑 2

我仍然无法使其工作。让我展示所有的组合。在所有情况下,测试机器上都没有安装了 SqlServer 模块。

尝试 1

RequiredModules = @(
    @{
        ModuleName = "SqlServer"
        ModuleVersion = "21.1.18068"
    }
)
PrivateData = @{
    PSData = @{
        ExternalModuleDependencies = "SqlServer"
    }
}

产量

C:\> Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force
PowerShellGet cannot resolve the module dependency 'SqlServer' of the module 'xyz.PS.Core' on the repository 'xyz-QA'. Verify that the dependent module 'SqlServer' is available in the repository 'xyz-QA'. If this dependent module 'SqlServer' is managed externally, add it to the ExternalModuleDependencies entry in the PSData section of the module manifest.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1227 char:17
+                 Publish-PSArtifactUtility -PSModuleInfo $moduleInfo `
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Publish-PSArtifactUtility], InvalidOperationException
    + FullyQualifiedErrorId : UnableToResolveModuleDependency,Publish-PSArtifactUtility
C:\>

尝试 2

RequiredModules = @("SqlServer")
PrivateData = @{
    PSData = @{
        ExternalModuleDependencies = "SqlServer"
    }
}

产量

C:\> Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force
PowerShellGet cannot resolve the module dependency 'SqlServer' of the module 'xyz.PS.Core' on the repository 'xyz-QA'. Verify that the dependent module 'SqlServer' is available in the repository 'xyz-QA'. If this dependent module 'SqlServer' is managed externally, add it to the ExternalModuleDependencies entry in the PSData section of the module manifest.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1227 char:17
+                 Publish-PSArtifactUtility -PSModuleInfo $moduleInfo `
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Publish-PSArtifactUtility], InvalidOperationException
    + FullyQualifiedErrorId : UnableToResolveModuleDependency,Publish-PSArtifactUtility
C:\>

尝试 3

PrivateData = @{
    PSData = @{
        ExternalModuleDependencies = "SqlServer"
    }
}

(没有RequiredModules)产量:

C:\> Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force
C:\> Get-Module SqlServer -ListAvailable
C:\> Install-Module xyz.PS.Core -Scope CurrentUser -Force -AllowClobber
WARNING: The externally managed, dependent module 'SqlServer' is not installed on this computer. To use the current module 'xyz.PS.Core', ensure that its dependent module 'SqlServer' is installed.
C:\> Get-Module SqlServer -ListAvailable
C:\>

如您所见,发布成功,但安装模块输出警告。并且没有安装 SqlServer。

尝试 4

RequiredModules = @(
    @{
        ModuleName = "SqlServer"
        ModuleVersion = "21.1.18068"
    }
)

(没有 ExternalModuleDependencies)产量:

C:\> Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force
The specified RequiredModules entry 'SqlServer' in the module manifest 'C:\Users\mkharitonov\AppData\Local\Temp\2144858157\xyz.PS.Core\xyz.PS.Core.psd1' is invalid. Try again after updating this entry with valid values.At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1144 char:27+ ... oduleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $mani ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\mkhari...ce.PS.Core.psd1:String) [Test-ModuleManifest], DirectoryNotFoundException
    + FullyQualifiedErrorId : Modules_InvalidRequiredModulesinModuleManifest,Microsoft.PowerShell.Commands.TestModuleManifestCommand
C:\>

尝试 5

RequiredModules = @("SqlServer")

(没有 ExternalModuleDependencies)产量:

C:\> Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force
The specified RequiredModules entry 'SqlServer' in the module manifest 'C:\Users\mkharitonov\AppData\Local\Temp\1208648280\xyz.PS.Core\xyz.PS.Core.psd1' is invalid. Try again after updating this entry with valid values.At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1144 char:27+ ... oduleInfo = Microsoft.PowerShell.Core\Test-ModuleManifest -Path $mani ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\mkhari...ce.PS.Core.psd1:String) [Test-ModuleManifest], DirectoryNotFoundException
    + FullyQualifiedErrorId : Modules_InvalidRequiredModulesinModuleManifest,Microsoft.PowerShell.Commands.TestModuleManifestCommand
C:\>

所以,我所做的一切都不起作用。到目前为止,Powershell 似乎无法安装所需的模块。

我做错了什么?

编辑 3

即使我在构建机器上安装了 SqlServer,RequiredModules 属性也不起作用。观察:

RequiredModules = @(
    "SqlServer"
)
PrivateData = @{
    PSData = @{
        ExternalModuleDependencies = "SqlServer"
    }
}

结果是:

C:\> Get-Module SqlServer -ListAvailable


    Directory: C:\Users\mkharitonov\Documents\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     21.1.18102 SqlServer                           {Add-RoleMember, Add-SqlAvailabilityDatabase, Add-SqlAvailabilityGroupListenerStaticIp, Ad...


C:\> Publish-Module -Name $ModuleManifestFile -NuGetApiKey $NuGetApiKey -Repository $PSRepositoryName -Force
PowerShellGet cannot resolve the module dependency 'SqlServer' of the module 'xyz.PS.Core' on the repository 'xyz-QA'. Verify that the dependent module 'SqlServer' is available in the repository 'xyz-QA'. If this dependent module 'SqlServer' is managed externally, add it to the ExternalModuleDependencies entry in the PSData section of the module manifest.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1:1227 char:17
+                 Publish-PSArtifactUtility -PSModuleInfo $moduleInfo `
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Publish-PSArtifactUtility], InvalidOperationException
    + FullyQualifiedErrorId : UnableToResolveModuleDependency,Publish-PSArtifactUtility
C:\>

Powershell 似乎在我的存储库而不是 PSGallery 中寻找 SqlServer 模块。我不明白的方式。以下是机器上注册的PS仓库:

C:\> Get-PSRepository

Name                      InstallationPolicy   SourceLocation
----                      ------------------   --------------
PSGallery                 Trusted              https://www.powershellgallery.com/api/v2
xyz-QA                    Trusted             http://devstatic.xyz.com/nugetserver/nuget


C:\>

所以,我真的不明白我该怎么做?

【问题讨论】:

    标签: powershell module powershell-module


    【解决方案1】:

    注意:以下内容来自this discussion in the PackageManagement (OneGet) GitHub repo,尤其是来自团队成员的this comment

    Install-Module 适用于同一仓库中的依赖关系。
    对于托管在与要安装的模块不同的 repo 上的依赖模块,我建议您将它们发布到您的房屋 repo。
    如果您不想将它们发布到您的家庭仓库中,您可以将模块保存到您的公共文件共享中,Register-PSRepository -Name local -SourceLocation \server\commonshare,然后先从文件共享中安装这些模块。”

    截至PackageManagement module 1.3 版,我从您的症状中得出结论,上述仍然适用,即使评论来自 2017 年中期(我找不到任何官方文档)。

    总结一下:

    • 不支持自动安装跨存储库依赖项解决方法是将外部依赖项也发布到您的内部存储库中

    • 在调用 Publish-Module 时,RequiredModules 条目中列出的模块必须出现在同一个目标存储库中

      • 也就是说,仅在您的机器上存在此类模块是不够的。 (我不清楚他们是否需要在场 - 他们不应该在场。)
    • 为了支持自动安装 intra-repository 依赖项,PrivateData.PSData.ExternalModuleDependencies 条目也必须列出这些依赖项 - 除了 RequiredModules - 仅按名称 - 见下文。

    为自动依赖安装指定intra-repository模块依赖(未验证)

    # Specify what other modules this module requires to work, using a FQMN,
    # (a Fully Qualified Module Name), via a hashtable.
    # The 'ModuleVersion' entry version numbers specifies a *minimum* required version 
    # number; 'RequiredVersion' specifies an *exact* version, and  
    # 'MaximumVersion' specifies a maximum version.
    # IMPORTANT:
    #   If you publish a module whose manifest has a 'RequiredModules'
    #   entry to a repository with Publish-Module, all referenced modules
    #   seemingly *must exist in that repository.*
    RequiredModules = @( @{ModuleName = 'SqlServer'; ModuleVersion = '21.1.18068' } )
    
    
    PrivateData = @{
      PSData = @{
    
        # ... 
    
        # !! This field is *ancillary* to the more detailed 'RequiredModules' field and
        # !! must reference the *same modules*, but by *names only*,
        # !! in order to automatically install other modules
        # !! *from the same repository* that this module depends on.
        # !! To be safe, specify even a *single* name as an *array*
        # !! (While this is not a general requirement in manifests, 
        # !!  it may be necessary here due to a bug.)
        ExternalModuleDependencies = @('SqlServer')
    }
    

    顺便说一句:New-ModuleManifest 中的一个错误目前阻止直接创建 PrivateData.PSData.ExternalModuleDependencies 条目:

    # !! BROKEN as of Windows PowerShell v5.1 / PowerShell Core 6.2.0;
    # The inner hashtable ends up represented as 'System.Collections.Hashtable'
    New-ModuleManifest someManifest.psd1 -PrivateData @{ 
      PSData = @{
        ExternalModuleDependencies = @('SqlServer')
      }
    }
    

    this GitHub issue

    【讨论】:

      【解决方案2】:

      除了@mklement0 的全面回答之外,还可以避免将外部依赖项持续发布到您的内部存储库中,从而避免不必要的冗余和维护工作:

      因此,您可以使用 repository manager,例如提供 repository grouping 功能的 Sonatype 的 Nexus:

      它们 [存储库组] 允许您在单个存储库中组合多个存储库和其他存储库组。这反过来意味着您的用户可以依赖单个 URL 来满足他们的配置需求,而管理员可以添加更多的存储库,从而将组件添加到存储库组。

      因此,您必须创建一个 nuget-group,它结合了 nuget 格式的存储库(例如 nuget-hosted(您的 PowerShell 模块)和 powershellgallery.com-代理(外部依赖项))到单个存储库中。

      这样,您需要将外部依赖项(来自 powershellgallery.com)发布到您的内部存储库 (nuget-hosted),以便仅发布您开发的 PowerShell 模块 (Publish-Module -Repository nuget-hosted -Name ...)。之后,您可以从 nuget-hosted 中删除外部依赖项。

      对于已开发模块的 Install-Module 以及任意 PowerShell 机器上的依赖项,您必须仅注册并使用 nuget-group 存储库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-29
        • 2017-09-21
        • 2015-02-18
        • 2021-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-08
        相关资源
        最近更新 更多