Last active
June 15, 2016 22:40
-
-
Save guitarrapc/7dc6c33854028345ee6d to your computer and use it in GitHub Desktop.
PowerShell WebPlatformInstaller Module (rough)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Initializer | |
function New-WebPlatformInstaller | |
{ | |
[OutputType([Void])] | |
[CmdletBinding()] | |
param() | |
try | |
{ | |
[reflection.assembly]::LoadWithPartialName("Microsoft.Web.PlatformInstaller") > $null | |
} | |
catch | |
{ | |
} | |
$script:WebPI = @{} | |
} | |
New-WebPlatformInstaller | |
#endregion | |
#region Constructor | |
function New-WebPlatformInstallerProductManager | |
{ | |
[OutputType([Void])] | |
[CmdletBinding()] | |
param() | |
if ($null -eq $WebPI){ New-WebPlatformInstaller } | |
$productManager = New-Object Microsoft.Web.PlatformInstaller.ProductManager | |
$productManager.Load() | |
$WebPI.productManager = $productManager | |
Write-Verbose "Remove Blank Keywords Products / IIS Components (Windows Feature)" | |
$WebPI.productManagerProducts = $WebPI.productManager.Products | where Keywords | where Title -notlike 'IIS:*' | |
$WebPI.productManagerProductsIISComponent = $WebPI.productManager.Products | where Keywords | where Title -like 'IIS:*' | |
} | |
function New-WebPlatformInstallerInstallManager | |
{ | |
[OutputType([Void])] | |
[CmdletBinding()] | |
param() | |
if ($null -eq $WebPI){ New-WebPlatformInstaller } | |
$WebPI.installManager = New-Object Microsoft.Web.PlatformInstaller.InstallManager | |
} | |
#endregion | |
#region Product | |
function Get-WebPlatformInstallerProduct | |
{ | |
<# | |
.Synopsis | |
Get WebPlatformInstaller Packages. | |
.DESCRIPTION | |
This function will return Product information for WebPlatform Installer. | |
You can select 2 mode. | |
1. -ProductId will give you availability to filter package. | |
2. Omit -ProductId will return all packages. | |
Make sure No keyword items and IIS Components (Windows Feature) will never checked. | |
.EXAMPLE | |
Get-WebPlatformInstallerProduct -ProductId WDeploy | |
# Returns WDeploy Product information | |
.EXAMPLE | |
Get-WebPlatformInstallerProduct | |
# Returns All Product information | |
#> | |
[OutputType([Microsoft.Web.PlatformInstaller.Product[]])] | |
[CmdletBinding(DefaultParameterSetName = "Any")] | |
param | |
( | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)] | |
[string[]]$ProductId, | |
[switch]$Force | |
) | |
begin | |
{ | |
if (($null -eq $WebPI.productManagerProducts) -or $Force){ New-WebPlatformInstallerProductManager } | |
# Initialize | |
if ($PSBoundParameters.ContainsKey('ProductId')) | |
{ | |
$result = $null | |
$private:productManagerDic = New-Object 'System.Collections.Generic.Dictionary[[string], [Microsoft.Web.PlatformInstaller.Product]]' ([StringComparer]::OrdinalIgnoreCase) | |
$WebPI.productManagerProducts | %{$productManagerDic.Add($_.ProductId, $_)} | |
} | |
} | |
process | |
{ | |
if (-not $PSBoundParameters.ContainsKey('ProductId')) | |
{ | |
Write-Verbose ("Searching All Products.") | |
return $WebPI.productManagerProducts | sort ProductId | |
} | |
foreach ($id in $ProductId) | |
{ | |
# Search product by ProductId | |
Write-Verbose ("Searching ProductId : '{0}'" -f $id) | |
$isSuccess = $productManagerDic.TryGetValue($id, [ref]$result) | |
if ($isSuccess){ $result; continue; } | |
if ($id -in $WebPI.productManagerProductsIISComponent.ProductId){ [Console]::WriteLine("ProductId '{0}' will skip as it detected IIS Component." -f $id); continue; } | |
throw New-Object System.InvalidOperationException ("WebPlatform Installation could not found package '{0}' as valid ProductId. Please select from '{1}'" -f $id, (($WebPI.productManagerProducts.ProductId | sort) -join "', '")) | |
} | |
} | |
} | |
function Test-WebPlatformInstallerProductIsInstalled | |
{ | |
<# | |
.Synopsis | |
Test target Package is already installed or not. | |
.DESCRIPTION | |
This function will check desired Package is already installed or not yet by Boolean. | |
$true : Means already installed. | |
$false : Means not yet installed. | |
Pass ProductId which you want to check. | |
.EXAMPLE | |
Test-WebPlatformInstallerProductIsInstalled -ProductId WDeploy | |
# Check WDeploy is installed or not. | |
#> | |
[OutputType([bool])] | |
[CmdletBinding(DefaultParameterSetName = "Any")] | |
param | |
( | |
[parameter(Mandatory = 1, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)] | |
[string[]]$ProductId | |
) | |
# Not use Cached Value | |
$result = Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($false)} | |
Write-Verbose $result | |
return $result | |
} | |
#endregion | |
#region Install | |
function Install-WebPlatformInstallerProgram | |
{ | |
<# | |
.Synopsis | |
Install target Package. | |
.DESCRIPTION | |
This function will install desired Package. | |
If Package is already installed, then skip it. | |
.EXAMPLE | |
Install-WebPlatformInstallerProgram -ProductId WDeploy | |
# Install WDeploy | |
#> | |
[OutputType([void])] | |
[CmdletBinding()] | |
param | |
( | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)] | |
[string[]]$ProductId, | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)] | |
[ValidateSet('en', 'fr', 'es', 'de', 'it', 'ja', 'ko', 'ru', 'zh-cn', 'zh-tw', 'cs', 'pl', 'tr', 'pt-br', 'he', 'zh-hk', 'pt-pt')] | |
[string]$LanguageCode = 'en' | |
) | |
process | |
{ | |
Write-Verbose "Checking Product is already installed." | |
$ProductId ` | |
| % { | |
if(Test-WebPlatformInstallerProductIsInstalled -ProductId $_){ [Console]::WriteLine("Package '{0}' already installed. Skip installation." -f $_); return; } | |
$productIdList.Add($_) | |
} | |
} | |
end | |
{ | |
if (($productIdList | measure).count -eq 0){ return; } | |
try | |
{ | |
# Prerequisites | |
Write-Verbose "Get Product" | |
[Microsoft.Web.PlatformInstaller.Product[]]$product = Get-WebPlatformInstallerProduct -ProductId $productIdList | |
if ($null -eq $product){ throw New-Object System.NullReferenceException } | |
# Install | |
# InstallByNET -LanguageCode $LanguageCode -product $product | |
InstallByWebPICmd -Name $ProductId | |
} | |
catch | |
{ | |
throw $_ | |
} | |
finally | |
{ | |
if ($null -ne $WebPI.installManager){ $WebPI.installManager.Dispose() } | |
} | |
} | |
begin | |
{ | |
# Initialize | |
if ($null -eq $WebPI.productManager){ New-WebPlatformInstallerProductManager } | |
$productIdList = New-Object 'System.Collections.Generic.List[string]' | |
function ShowInstallerContextStatus | |
{ | |
if ($null -ne $WebPI.installManager.InstallerContexts){ $WebPI.installManager.InstallerContexts | Out-String -Stream | Write-Verbose } | |
} | |
function WatchInstallationStatus | |
{ | |
[OutputType([bool])] | |
[CmdletBinding()] | |
param | |
( | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)] | |
[string]$ProductId, | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)] | |
[Microsoft.Web.PlatformInstaller.InstallationState]$PreStatus, | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)] | |
[Microsoft.Web.PlatformInstaller.InstallationState]$PostStatus | |
) | |
# Skip | |
if ($postStatus -eq $preStatus) | |
{ | |
Write-Verbose "Installation not begin" | |
return $false | |
} | |
# Monitor | |
ShowInstallerContextStatus | |
while($postStatus -ne [Microsoft.Web.PlatformInstaller.InstallationState]::InstallCompleted) | |
{ | |
Start-Sleep -Milliseconds 100 | |
$postStatus = $WebPI.installManager.InstallerContexts.InstallationState | |
} | |
ShowInstallerContextStatus | |
$logfiles = $WebPI.installManager.InstallerContexts.Installer.LogFiles | |
$latestLog = ($logfiles | select -Last 1) | |
[Console]::WriteLine(("'{0}' Installation completed. Check Log file at '{1}'" -f ($ProductId -join "', '"), $latestLog)) | |
Write-Verbose ("Latest Log file is '{0}'." -f (Get-Content -Path $latestLog -Encoding UTF8 -Raw)) | |
return $true | |
} | |
function InstallByNET | |
{ | |
[OutputType([void])] | |
[CmdletBinding()] | |
param | |
( | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)] | |
[string]$LanguageCode, | |
[parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)] | |
[Microsoft.Web.PlatformInstaller.Product[]]$product | |
) | |
# Initialize | |
New-WebPlatformInstallerInstallManager | |
$installer = New-Object 'System.Collections.Generic.List[Microsoft.Web.PlatformInstaller.Installer]' | |
# Get Language | |
[Microsoft.Web.PlatformInstaller.Language]$language = $WebPI.productManager.GetLanguage($LanguageCode) | |
$product ` | |
| % { | |
Write-Verbose "Get Installer" | |
$x = $_.GetInstaller($language) | |
if ($null -eq $x.InstallerFile){ [Console]::WriteLine("Package '{0}' detected as no Installer to install. Skip Installation." -f $_.ProductId); return; } | |
$installer.Add($x) | |
$WebPI.InstallManager.Load($installer) | |
Write-Verbose "Donwload Installer" | |
ShowInstallerContextStatus | |
$failureReason = $null | |
$success = $WebPI.InstallManager.InstallerContexts | %{ $WebPI.installManager.DownloadInstallerFile($_, [ref]$failureReason) } | |
if ((-not $success) -and $failureReason){ throw New-Object System.InvalidOperationException ("Donwloading '{0}' Failed Exception!! Reason : {1}" -f ($ProductId -join "' ,'"), $failureReason ) } | |
Write-Verbose "Show Donwloaded Installer Status" | |
ShowInstallerContextStatus | |
# Get Status | |
[Microsoft.Web.PlatformInstaller.InstallationState]$preStatus = $WebPI.installManager.InstallerContexts.InstallationState | |
Write-Verbose "Start Installation with StartInstallation()" | |
$WebPI.installManager.StartInstallation() | |
if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; } | |
Write-Verbose "Start Installation with StartApplicationInstallation()" | |
$WebPI.installManager.StartApplicationInstallation() | |
if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; } | |
Write-Verbose "Start Installation with StartSynchronousInstallation()" | |
$installResult = $WebPI.installManager.StartSynchronousInstallation() | |
if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; } | |
} | |
} | |
function InstallByWebPICmd | |
{ | |
[OutputType([Void])] | |
[CmdletBinding()] | |
param | |
( | |
[parameter(Mandatory = $true)] | |
[System.String[]]$Name | |
) | |
end | |
{ | |
foreach ($x in $Name) | |
{ | |
Write-Verbose ("Installing package '{0}'" -f $x) | |
[string]$arguments = @( | |
"/Install", | |
"/Products:$x", | |
"/AcceptEula", | |
"/SuppressReboot" | |
) | |
Invoke-WebPICmd -Arguments $arguments | |
} | |
} | |
begin | |
{ | |
Write-Verbose "Start Installation with WebPICmd" | |
function Invoke-WebPICmd | |
{ | |
[OutputType([System.String])] | |
[CmdletBinding()] | |
param | |
( | |
[parameter(Mandatory = $true)] | |
[System.String]$Arguments | |
) | |
$fileName = "$env:ProgramFiles\Microsoft\Web Platform Installer\WebpiCmd-x64.exe" | |
if (!(Test-Path -Path $fileName)){ throw New-Object System.InvalidOperationException ("Web Platform Installer not installed exception!") } | |
try | |
{ | |
$psi = New-Object System.Diagnostics.ProcessStartInfo | |
$psi.CreateNoWindow = $true | |
$psi.UseShellExecute = $false | |
$psi.RedirectStandardOutput = $true | |
$psi.RedirectStandardError = $true | |
$psi.FileName = $fileName | |
$psi.Arguments = $Arguments | |
$process = New-Object System.Diagnostics.Process | |
$process.StartInfo = $psi | |
$process.Start() > $null | |
$output = $process.StandardOutput.ReadToEnd() | |
$process.StandardOutput.ReadLine() | |
$process.WaitForExit() | |
return $output | |
} | |
catch | |
{ | |
$outputError = $process.StandardError.ReadToEnd() | |
throw $_ + $outputError | |
} | |
finally | |
{ | |
if ($null -ne $psi){ $psi = $null} | |
if ($null -ne $process){ $process.Dispose() } | |
} | |
} | |
} | |
} | |
} | |
} | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Test-WebPlatformInstallerProductIsInstalled
Get-WebPlatformInstallerProduct
Install-WebPlatformInstallerProgram