简体   繁体   中英

How to install a Powershell module concurrently?

I have a Pull Request validation build running for different branches, ie several concurrent instances of the build is a very common thing.

One of the things the build does is install a module. Now I could modify the profile on the build agent and install module from there, but I want to avoid any extra build agent configuration. So, my build installs a module in the current user scope.

I noticed that Install-Module does not seem to be safe when invoked concurrently - it may fail with all kinds of different and weird error messages.

Now I solved this with a named mutex acquired before and released after, but this causes abysmal performance - the code sometimes waits for 30 seconds and more. So, how to solve this problem? How to install a powershell module concurrently, but safely and with good performance?

EDIT 1

It is frustrating. I am trying to trace the concurrent installs using Set-PSDebug -Trace 2 , but apparently Install-Module has a lot of Write-Debug invocations calling to functions which are themselves not safe for concurrent execution! So trying to trace actually worsens matters.

Apparently, Install-Module is totally NOT SAFE to run during a build where multiple builds run on the same agent. Looks like using a named Mutex is the safest approach.

EDIT 1

In a multi-threading environments invoking the following commands is not safe without explicit mutex:

  • Install-Module
  • Import-Module
  • Get-PSRepository without arguments

Maybe more. In my code I invoke all the three commands, and I discovered that all of them together must be in the same mutex, ie these combinations do not work:

Not working #1

$mtx.WaitOne()
try
{
    Install-Module ...
}
finally
{
    $mtx.ReleaseMutex()
}
Import-Module ...
Get-PSRepository ...

Not working #2

$mtx.WaitOne()
try
{
    Install-Module ...
    Import-Module ...
}
finally
{
    $mtx.ReleaseMutex()
}
Get-PSRepository

The only safe option appears to be this one:

$mtx.WaitOne()
try
{
    Install-Module ...
    Import-Module ...
    Get-PSRepository
}
finally
{
    $mtx.ReleaseMutex()
}

Which is surprising, because I do not expect Install-Module or Import-Module to affect Get-PSRepository , yet somehow they do:

   ParameterBindingException: A parameter cannot be found that matches parameter name 'Provider'.
   at Get-PSRepository<Process>, C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PSModule.psm1: line 4496
   at Use-ModuleFB22C60E, C:\Users\mkharitonov\AppData\Local\Temp\fb22c60e-a0c5-48b3-953a-0b580c6a2f5e\m_deadbeef_.ps1: line 167
   at <ScriptBlock>, <No file>: line 4

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM