Как принудительно перезагрузить определение функции модуля без запуска нового сеанса Powershell?

#powershell #module #powershell-module

#powershell #модуль #powershell-модуль

Вопрос:

У меня есть модуль, позвольте мне назвать его xyz.ps.core . Он экспортирует функцию — Get-PullRequestsFromCommitIds

Я исправил ошибку в функции, переиздал модуль, переустановил и повторно импортировал его, и все же функция по-прежнему ссылается на старую версию модуля.

Пожалуйста, соблюдайте:

 C:xyztip [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:xyztip [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:xyztip [master ≡]> get-module xyz.ps.core -ListAvailable | ft -AutoSize


    Directory: C:UsersmkharitonovDocumentsWindowsPowerShellModules


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:xyztip [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:xyztip [master ≡]> use-module xyz.ps.core
Using the latest version of xyz.ps.core ... 1.0.19107.7
 

Давайте проверим источник функции:

 C:xyztip [master ≡]> Get-Command Get-PullRequestsFromCommitIds | ft -AutoSize

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

Все тот же старый. Обратите внимание, что в новом окне Powershell функция берется из текущей версии модуля.

Можно ли обновить функцию, не закрывая powershell?

Комментарии:

1. Вы имеете в виду Import-Module modulename -Force ?

2. Я уже делаю это — обратите Import-Module $Name -Force внимание в теле функции Use-Module , которую я использую для обновления модуля.

Ответ №1:

Все дело в поведении, связанном с областями действия. ДВУ:

Сеансы, модули и вложенные приглашения являются автономными средами, но они не являются дочерними областями глобальной области в сеансе.

По сути, поскольку модули являются автономными средами, а не дочерней областью, они не могут импортировать модули в «родительскую» область сценария. Даже если вы используете -Force .

Давайте протестируем области внутри модуля:

Модуль выборки.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 like:

 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}      
 

Успех!