Require.psm1
function Request-Module { [CmdletBinding()] param( [Parameter(Mandatory=$true)] $modules, $version = $null, $package = $null, [switch][bool] $reload, $source = "oneget", [switch][bool] $wait = $false, [Parameter()] [ValidateSet("AllUsers","CurrentUser","Auto")] [string] $scope = "CurrentUser", [switch][bool] $SkipPublisherCheck, [switch][bool] $AllowClobber = $true ) $original_version = $version if ($version -eq "latest") { $version = "999.999.999" } import-module process -Global -Verbose:$false if ($scope -eq "Auto") { $scope = "CurrentUser" if (test-IsAdmin) { $scope = "AllUsers" } } foreach($_ in $modules) { $name = $_ $currentversion = $null $mo = gmo $_ $loaded = $mo -ne $null $found = $loaded if ($loaded) { $currentversion = $mo.Version[0] } if ($loaded -and !$reload -and ($mo.Version[0] -ge $version -or $version -eq $null)) { write-verbose "module $_ is loaded with version $($mo.version). Nothing to do here" return } if (!$loaded) { try { write-verbose "module $_ is not loaded. trying to load." ipmo $_ -ErrorAction SilentlyContinue -Global -Verbose:$false $mo = gmo $_ $loaded = $mo -ne $null if ($loaded) { write-verbose "loaded" } $found = $loaded } catch { write-verbose "failed to load module $name : $($_.Exception.Message)" } } if(!$found) { $mo = gmo $_ -ListAvailable | sort version -Descending write-verbose "module $_ not found" } $found = $mo -ne $null -and $mo.Version[0] -ge $version if ($mo -ne $null) { write-verbose "found module $($mo.name) version $($mo.version). found=$found reload=$reload" } else { write-verbose "module $_ not found" } if(!$found -and $mo -ne $null) { $available = @(gmo $_ -ListAvailable | sort version -Descending) $mo = $available $matchingVers = @($available | ? { $_.Version -ge $version }) $found = ($matchingVers.Length -gt 0) write-verbose "found $($matchingVers.count) matching versions from total $($available.count)" #$found = $available -ne $null } if ($mo -ne $null) { write-verbose "version=$version mo=$mo mo.version=$($mo.Version[0]) requested version = $version" } if ($reload -or ($version -ne $null -and $loaded -and $currentversion -lt $version)) { write-verbose "removing module $_" if (gmo $_) { rmo $_ -Verbose:$false } } function init-psget { if ($global:psgetready) { return } write-verbose "initializing psget" if ((get-command Install-PackageProvider -module PackageManagement -ErrorAction Ignore) -ne $null) { import-module PackageManagement -Verbose:$false $nuget = get-packageprovider -Name Nuget -force -forcebootstrap if ($nuget -eq $null) { write-host "installing nuget package provider" # this isn't availalbe in the current official release of oneget (?) install-packageprovider -Name NuGet -Force -MinimumVersion 2.8.5.201 -verbose } } import-module powershellget -Verbose:$false if ((get-PSRepository -Name PSGallery).InstallationPolicy -ne "Trusted") { Set-PSRepository -Name PSGallery -InstallationPolicy Trusted } $global:psgetready = $true } function RequestPowershellModule($name) { $psrepository = $null if ($source.startswith("psgallery:")) { $psrepository = $source.substring("psgallery:".Length) } write-warning "trying powershellget package manager repository='$psrepository'" init-psget $islinked = $false if ($mo -eq $null) { $p = @{ Name = $name Verbose = $true Scope = $scope ErrorAction = "Stop" } if ($AllowClobber -and ((get-command install-module).Parameters.AllowClobber) -ne $null) { $p += @{ AllowClobber = $true } } if ($SkipPublisherCheck -and ((get-command install-module).Parameters.SkipPublisherCheck) -ne $null) { $p += @{ SkipPublisherCheck = $true } } if ($psrepository -ne $null) { $p += @{ Repository = $psrepository } } $cmd = "install-module" write-warning "$cmd [scope=$scope]" foreach($kvp in $p.GetEnumerator()) { $val = $kvp.value if ($val -eq $true) { $val = "`$true" } $cmd += " -$($kvp.key):$($val)" } if ($scope -eq "CurrentUser") { install-module @p } else { Invoke-AsAdmin -ArgumentList @("-Command", $cmd) -wait if ($LASTEXITCODE -ne 0) { write-error "install-module failed" } } } else { # remove module to avoid loading multiple versions rmo $name -erroraction Ignore $toupdate = $name $p = @{ Name = $toupdate Verbose = $true ErrorAction = "Stop" } if ($psrepository -ne $null) { # update-module has no repository parameter # $p += @{ Repository = $psrepository } } $cmd = "update-module" foreach($kvp in $p.GetEnumerator()) { $val = $kvp.value if ($val -eq $true) { $val = "`$true" } $cmd += " -$($kvp.key):$($val)" } write-warning "$cmd [scope=$scope]" if ($scope -eq "CurrentUser") { try { ipmo pathutils -Verbose:$false $path = $mo.path try { $target = pathutils\Get-JunctionTarget (split-path -parent $path) $islinked = $target -ne $null } catch { write-warning $_.Exception.message } if ($islinked) { write-verbose "module $toupdate is linked to path $target. updating from source control" pathutils\update-modulelink $toupdate -ErrorAction stop } else { write-verbose "updating module $toupdate" update-module @p } } catch { if ($_.Exception.Message.Contains("Install-Module")) { # "was not installed by using Install-Module" throw } elseif ($_.Exception.Message.Contains("Administrator")) { # "cannot be updated because Administrator rights are required" write-warning "need to update module as admin" # if module was installed as Admin, try to update as admin Invoke-AsAdmin -ArgumentList @("-Command", $cmd) -wait if ($LASTEXITCODE -ne 0) { write-error "update-module failed" } } else { throw } } } else { Invoke-AsAdmin -ArgumentList @("-Command", $cmd) -wait if ($LASTEXITCODE -ne 0) { write-error "update-module failed" } } } $mo = gmo $name -ListAvailable | sort version -Descending | select -first 1 if ($mo -ne $null -and $mo.Version[0] -lt $version -and !$islinked) { # ups, update-module did not succeed? # if module is already installed, oneget will try to update from same repositoty # if the repository has changed, we need to force install write-warning "requested module $name version $version, but found $($mo.Version[0])!" $p = @{ Name = $name Verbose = $true Scope = $scope ErrorAction = "Stop" Force = $true } if ($AllowClobber -and ((get-command install-module).Parameters.AllowClobber) -ne $null) { $p += @{ AllowClobber = $true } } if ($SkipPublisherCheck -and ((get-command install-module).Parameters.SkipPublisherCheck) -ne $null) { $p += @{ SkipPublisherCheck = $true } } if ($psrepository -ne $null) { $p += @{ Repository = $psrepository } } $cmd = "install-module" write-warning "trying again: $cmd [scope=$scope]" foreach($kvp in $p.GetEnumerator()) { $val = $kvp.value if ($val -eq $true) { $val = "`$true" } $cmd += " -$($kvp.key):$($val)" } if ($scope -eq "CurrentUser") { install-module @p } else { Invoke-AsAdmin -ArgumentList @("-Command", $cmd) -wait if ($LASTEXITCODE -ne 0) { write-error "update-module failed" } } $mo = gmo $name -ListAvailable | sort version -Descending | select -first 1 } if ($mo -eq $null) { Write-Warning "failed to install module $name through oneget" Write-Warning "available modules:" $list = find-module $name $list } elseif ($mo.Version[0] -lt $version -and $original_version -ne "latest") { Write-Warning "modules found:" $m = find-module $name $m | Format-Table | Out-String | Write-Warning Write-Warning "sources:" $s = Get-PackageSource $s | Format-Table | Out-String | Write-Warning } } function RequestChocoPackage($name) { if ($mo -eq $null) { # install $cmd = "Process\invoke choco install -y $package -verbose" if ($source.startswith("choco:")) { $customsource = $source.substring("choco:".length) $cmd = "Process\invoke choco install -y $package -source $customsource -verbose" } $processModulePath = split-path -parent (gmo Process).path # ensure choco is installed, then install package Invoke-AsAdmin -ArgumentList @("-Command", " try { `$env:PSModulePath = `$env:PSModulePath + ';$processModulePath' . '$PSScriptRoot\functions\helpers.ps1'; ipmo Require req Process write-host 'Ensuring chocolatey is installed'; _ensure-choco; write-host 'installing chocolatey package $package'; $cmd; } finally { if (`$$wait) { Read-Host 'press Enter to close this window and continue'; } } ") -wait if ($LASTEXITCODE -ne 0) { write-error "choco install failed" } #refresh PSModulePath # throw "Module $name not found. `r`nSearched paths: $($env:PSModulePath)" } elseif ($mo.Version[0] -lt $version) { # update write-warning "requested module $name version $version, but found $($mo.Version[0])!" # ensure choco is installed, then upgrade package $cmd = "Process\invoke choco upgrade -y $package -verbose" if ($source.startswith("choco:")) { $customsource = $source.substring("choco:".length) $cmd = "Process\invoke choco upgrade -y $package -source $customsource -verbose" } $processModulePath = split-path -parent ((gmo Process).path) Invoke-AsAdmin -ArgumentList @("-Command", " try { `$ex = `$null; `$env:PSModulePath = `$env:PSModulePath + ';$processModulePath' ipmo Require req Process . '$PSScriptRoot\functions\helpers.ps1'; write-host 'Ensuring chocolatey is installed'; _ensure-choco; write-host 'updating chocolatey package $package'; $cmd; if (`$$wait) { Read-Host 'press Enter to close this window and continue' } } catch { write-error `$_; `$ex = `$_; if (`$$wait) { Read-Host 'someting went wrong. press Enter to close this window and continue' } throw; } finally { } ") -wait if ($LASTEXITCODE -ne 0) { write-error "choco upgrade failed" } } refresh-modulepath if ($mo -ne $null) { rmo $name } ipmo $name -ErrorAction Ignore } if (!$found) { . "$PSScriptRoot\functions\helpers.ps1"; $verstring = "not found" if ($currentversion -ne $null) { $verstring = "is not satisfied by current version=$currentversion" } write-warning "module $_ version >= $version $verstring. installing from $source" if ($source -eq "choco" -or $source.startswith("choco:")) { requestchocopackage -name $_ } if ($source -in "oneget","psget","powershellget","psgallery" -or $source.startswith("psgallery:")) { RequestPowershellModule -name $_ } $mo = gmo $name -ListAvailable | sort version -Descending $found = $mo -ne $null -and $mo.Version[0] -ge $version } else { if (($matchingvers -ne $null) -and ($matchingvers.count -ge 0)) { ipmo $_ -MinimumVersion $version $mo = gmo $_ } } if (!($mo)) { throw "Module $_ not found. `r`nSearched paths: $($env:PSModulePath)" } if ($original_version -eq "latest") { Import-Module $_ -DisableNameChecking -Global -ErrorAction stop $mo = gmo $_ write-host "lastest version of module $_ : $($mo.version)" } else { if ($mo.Version[0] -lt $version) { throw "requested module $_ version $version, but found $($mo.Version[0])!" } Import-Module $_ -DisableNameChecking -MinimumVersion $version -Global -ErrorAction stop } } } if ((get-alias Require-Module -ErrorAction ignore) -eq $null) { new-alias Require-Module Request-Module } if ((get-alias req -ErrorAction ignore) -eq $null) { new-alias req Request-Module } Export-ModuleMember -Function "Request-Module" -Alias * |