如何使Install-Module也安装任何必需的模块?

时间:2019-04-13 17:23:18

标签: powershell module powershell-module

我正在开发一个依赖于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:\>

那么,我真的不明白我该怎么办?

2 个答案:

答案 0 :(得分:2)

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

  

Install-Module适用于同一仓库中的依赖项。
  如果依赖项模块托管在与要安装的模块不同的仓库中,建议您将其发布到内部仓库中。
  如果您不希望将它们发布到房屋回购中,则可以将模块保存到公用文件共享中,Register-PSRepository -Name local -SourceLocation \ server \ commonshare,然后从文件共享中首先安装这些模块。“

PackageManagement module版本1.3开始,即使您的评论来自2017年中(我找不到任何正式文档),我仍从您的症状得出结论,上述内容仍然适用。

总结:

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

  • 在调用 Publish-Module 时,似乎RequiredModules条目 中列出的模块必须存在于同一目标中回购

    • 也就是说,仅在您的计算机上仅存在这样的模块是 。 (我不清楚他们是否还需要存在-是否不必存在。)
  • 要支持自动安装库内依赖项,PrivateData.PSData.ExternalModuleDependencies条目还必须列出这些依赖项-除RequiredModules -仅按名称-参见下文。

为自动依赖项安装指定存储库内模块依赖项(未验证)

# 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

答案 1 :(得分:0)

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

因此,您可以使用repository manager之类的Sonatype Nexus,它提供repository grouping功能:

它们[存储库组]允许您将多个存储库和其他存储库组组合在一个存储库中。反过来,这意味着您的用户可以依靠单个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 存储库。