如何在不启动新的Powershell会话的情况下强制重新加载模块功能定义?

时间:2019-04-17 22:05:05

标签: powershell module powershell-module

我有一个模块,我称之为xyz.ps.core。它导出一个函数-Get-PullRequestsFromCommitIds

我修复了该功能中的一个错误,重新发布了该模块,重新安装并重新导入了该功能,但该功能仍引用该模块的旧版本。

请注意:

C:\xyz\tip [master ≡]> Get-Command Get-PullRequestsFromCommitIds | ft -AutoSize

CommandType Name                          Version     Source
----------- ----                          -------     ------
Function    Get-PullRequestsFromCommitIds 1.0.19107.4 xyz.ps.core

如您所见,该函数来自1.0.19107.4

C:\xyz\tip [master ≡]> get-module xyz.ps.core | ft -AutoSize

ModuleType Version     Name             ExportedCommands
---------- -------     ----             ----------------
Manifest   1.0.19107.7 xyz.ps.core {Assert-ExtractionDestFolder, Assert-PullRequestMatchesFolder, Backup-Database, Connect-OctopusToTfs...}


C:\xyz\tip [master ≡]> get-module xyz.ps.core -ListAvailable | ft -AutoSize


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


ModuleType Version     Name             ExportedCommands
---------- -------     ----             ----------------
Manifest   1.0.19107.7 xyz.PS.Core {Assert-ExtractionDestFolder, Assert-PullRequestMatchesFolder, Backup-Database, Connect-OctopusToTfs...}

但是模块版本已经在1.0.19107.7上。但是,好的,我有一个刷新模块的功能,即使它已经安装到相同的版本:

C:\xyz\tip [master ≡]> (get-command Use-Module).ScriptBlock
param([Parameter(Mandatory)]$Name)

    if ($VerbosePreference -ne 'Continue')
    {
        Write-Host -ForegroundColor Cyan -NoNewline "Using the latest version of $Name ... "
    }

    Write-Verbose "Uninstalling all the versions of $Name ..."
    Uninstall-Module $Name -AllVersions -Force -ErrorAction SilentlyContinue
    Remove-Module $Name -Force -ErrorAction SilentlyContinue

    Write-Verbose "Installing the latest version of $Name ..."
    Install-Module $Name -Scope CurrentUser -Force

    Write-Verbose "Importing $Name into the current session ..."
    Import-Module $Name -Force

    if ($VerbosePreference -ne 'Continue')
    {
        Write-Host -ForegroundColor Cyan (Get-Module $Name).Version
    }

让我们现在使用它:

C:\xyz\tip [master ≡]> use-module xyz.ps.core
Using the latest version of xyz.ps.core ... 1.0.19107.7

让我们检查函数源:

C:\xyz\tip [master ≡]> Get-Command Get-PullRequestsFromCommitIds | ft -AutoSize

CommandType Name                          Version     Source
----------- ----                          -------     ------
Function    Get-PullRequestsFromCommitIds 1.0.19107.4 xyz.ps.core

还是旧的。请注意,在新的Powershell窗口中,该功能取自模块的当前版本。

是否可以在不关闭powershell的情况下刷新功能?

1 个答案:

答案 0 :(得分:2)

行为全部为about scopes。 TLDR:

  

会话,模块和嵌套提示是独立的环境,   但它们不是会话中全局作用域的子作用域。

基本上,由于模块是独立的环境,而不是子作用域,因此它们无法将模块导入“父”脚本作用域。 即使使用了-Force

让我们在模块内测试范围:

sampleModule.psm1

Function Test-Import { 
param([Parameter(Mandatory)]$Name)
    Write-Host "List Loaded modules before"
    Get-Module

    Write-Host "Importing $Name into the current session ..."
    Import-Module $Name -Force

    Write-Host "Module Version $((Get-Module $Name).Version)"

    Write-Host "Loaded Modules After"
    #List Loaded modules after
    Get-Module
}

#Only present desired functions
Export-ModuleMember -Function Test-Import

如果我们从简单的空白测试开始(为了简便起见,我删除了无关的模块):

PS C:> #Clean state - Nothing Loaded for demonstration
PS C:> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------

PS C:> Import-Module .\sampleModule.psm1
PS C:> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        Test-Module                         {Test-Import}

PS C:> Test-Import ActiveDirectory
List Loaded modules before

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        Test-Module                         {Test-Import}

Importing ActiveDirectory into the current session ...
Module Version 1.0.1.0

Loaded Modules After

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   1.0.1.0    ActiveDirectory                     {Add-ADCentralAccessPolicyMember, Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-ADFineGrainedPasswordPolicySubject...}
Script     0.0        Test-Module                         {Test-Import}      

在这里,我们注意到ActiveDirectory模块在该函数的开头不存在,但实际上是在该函数的末尾加载的,并报告了正确的版本。现在让我们看看它是否已加载:

PS C:> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        Test-Module                         {Test-Import}

我们可以看到,由于模块在自己的独立环境中运行,因此我们成功地将模块(在此示例中为ActiveDirectory)导入了模块作用域,但没有像您期望的那样导入到本地作用域。

解决此范围问题的唯一方法是将模块导入全局范围 通过添加-Global,例如:

Import-Module $Name -Force -Global

在示例脚本中更改这一行,然后重新导入:

PS C:> Import-Module .\sampleModule.psm1 -Force

PS C:> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        Test-Module                         {Test-Import}

PS C:> Test-Import ActiveDirectory
List Loaded modules before

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        Test-Module                         {Test-Import}

Importing ActiveDirectory into the current session ...
Module Version 1.0.1.0

Loaded Modules After

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   1.0.1.0    ActiveDirectory                     {Add-ADCentralAccessPolicyMember, Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-ADFineGrainedPasswordPolicySubject...}
Script     0.0        Test-Module                         {Test-Import}      

与以前相同...现在让我们检查它是否正确加载:

PS C:> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   1.0.1.0    ActiveDirectory                     {Add-ADCentralAccessPolicyMember, Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-ADFineGrainedPasswordPolicySubject...}
Script     0.0        Test-Module                         {Test-Import}      

成功!