Skip to content

Instantly share code, notes, and snippets.

@guitarrapc
Last active June 15, 2016 22:40
Show Gist options
  • Select an option

  • Save guitarrapc/7dc6c33854028345ee6d to your computer and use it in GitHub Desktop.

Select an option

Save guitarrapc/7dc6c33854028345ee6d to your computer and use it in GitHub Desktop.

Revisions

  1. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 85 additions and 8 deletions.
    93 changes: 85 additions & 8 deletions WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -136,7 +136,9 @@ function Test-WebPlatformInstallerProductIsInstalled
    [parameter(Mandatory = 1, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)]
    [string[]]$ProductId
    )
    $result = Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($null)}

    # Not use Cached Value
    $result = Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($false)}
    Write-Verbose $result
    return $result
    }
    @@ -191,7 +193,8 @@ function Install-WebPlatformInstallerProgram
    if ($null -eq $product){ throw New-Object System.NullReferenceException }

    # Install
    InstallByNET -Language $language -product $product
    # InstallByNET -LanguageCode $LanguageCode -product $product
    InstallByWebPICmd -Name $ProductId
    }
    catch
    {
    @@ -207,13 +210,8 @@ function Install-WebPlatformInstallerProgram
    {
    # Initialize
    if ($null -eq $WebPI.productManager){ New-WebPlatformInstallerProductManager }
    New-WebPlatformInstallerInstallManager
    $productIdList = New-Object 'System.Collections.Generic.List[string]'

    # Get Language
    [Microsoft.Web.PlatformInstaller.Language]$language = $WebPI.productManager.GetLanguage($LanguageCode)


    function ShowInstallerContextStatus
    {
    if ($null -ne $WebPI.installManager.InstallerContexts){ $WebPI.installManager.InstallerContexts | Out-String -Stream | Write-Verbose }
    @@ -264,14 +262,19 @@ function Install-WebPlatformInstallerProgram
    param
    (
    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)]
    [Microsoft.Web.PlatformInstaller.Language]$Language,
    [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"
    @@ -305,6 +308,80 @@ function Install-WebPlatformInstallerProgram
    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() }
    }
    }
    }
    }
    }
    }

  2. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 33 additions and 33 deletions.
    66 changes: 33 additions & 33 deletions WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -170,6 +170,39 @@ function Install-WebPlatformInstallerProgram
    [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 -Language $language -product $product
    }
    catch
    {
    throw $_
    }
    finally
    {
    if ($null -ne $WebPI.installManager){ $WebPI.installManager.Dispose() }
    }
    }

    begin
    {
    # Initialize
    @@ -273,39 +306,6 @@ function Install-WebPlatformInstallerProgram
    }
    }
    }

    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 -Language $language -product $product
    }
    catch
    {
    throw $_
    }
    finally
    {
    if ($null -ne $WebPI.installManager){ $WebPI.installManager.Dispose() }
    }
    }
    }

    #endregion
  3. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 44 additions and 24 deletions.
    68 changes: 44 additions & 24 deletions WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -8,7 +8,7 @@ function New-WebPlatformInstaller

    try
    {
    Add-Type -Path "C:\Program Files\Microsoft\Web Platform Installer\Microsoft.Web.PlatformInstaller.dll"
    [reflection.assembly]::LoadWithPartialName("Microsoft.Web.PlatformInstaller") > $null
    }
    catch
    {
    @@ -84,12 +84,10 @@ function Get-WebPlatformInstallerProduct
    begin
    {
    if (($null -eq $WebPI.productManagerProducts) -or $Force){ New-WebPlatformInstallerProductManager }
    Write-Verbose "Make sure IIS Components (Windows Feature) will never get result."

    # Initialize
    if ($PSBoundParameters.ContainsKey('ProductId'))
    {
    Write-Verbose ("ParameterSet 'ProductId' detected.")
    $result = $null
    $private:productManagerDic = New-Object 'System.Collections.Generic.Dictionary[[string], [Microsoft.Web.PlatformInstaller.Product]]' ([StringComparer]::OrdinalIgnoreCase)
    $WebPI.productManagerProducts | %{$productManagerDic.Add($_.ProductId, $_)}
    @@ -138,7 +136,9 @@ function Test-WebPlatformInstallerProductIsInstalled
    [parameter(Mandatory = 1, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)]
    [string[]]$ProductId
    )
    Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($null)}
    $result = Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($null)}
    Write-Verbose $result
    return $result
    }

    #endregion
    @@ -179,7 +179,7 @@ function Install-WebPlatformInstallerProgram

    # Get Language
    [Microsoft.Web.PlatformInstaller.Language]$language = $WebPI.productManager.GetLanguage($LanguageCode)
    $installer = New-Object 'System.Collections.Generic.List[Microsoft.Web.PlatformInstaller.Installer]'


    function ShowInstallerContextStatus
    {
    @@ -223,30 +223,25 @@ function Install-WebPlatformInstallerProgram
    Write-Verbose ("Latest Log file is '{0}'." -f (Get-Content -Path $latestLog -Encoding UTF8 -Raw))
    return $true
    }
    }

    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
    function InstallByNET
    {
    Write-Verbose "Get Product"
    [Microsoft.Web.PlatformInstaller.Product[]]$product = Get-WebPlatformInstallerProduct -ProductId $productIdList
    if ($null -eq $product){ throw New-Object System.NullReferenceException }
    [OutputType([void])]
    [CmdletBinding()]
    param
    (
    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)]
    [Microsoft.Web.PlatformInstaller.Language]$Language,

    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)]
    [Microsoft.Web.PlatformInstaller.Product[]]$product
    )

    $installer = New-Object 'System.Collections.Generic.List[Microsoft.Web.PlatformInstaller.Installer]'

    Write-Verbose "Get Installer"
    $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)
    @@ -277,6 +272,31 @@ function Install-WebPlatformInstallerProgram
    if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }
    }
    }
    }

    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 -Language $language -product $product
    }
    catch
    {
    throw $_
  4. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -158,7 +158,7 @@ function Install-WebPlatformInstallerProgram
    # Install WDeploy
    #>

    [OutputType([Microsoft.Web.PlatformInstaller.Product[]])]
    [OutputType([void])]
    [CmdletBinding()]
    param
    (
  5. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -17,6 +17,11 @@ function New-WebPlatformInstaller
    $script:WebPI = @{}
    }

    New-WebPlatformInstaller
    #endregion

    #region Constructor

    function New-WebPlatformInstallerProductManager
    {
    [OutputType([Void])]
  6. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 51 additions and 6 deletions.
    57 changes: 51 additions & 6 deletions WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -49,6 +49,23 @@ function New-WebPlatformInstallerInstallManager

    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
    @@ -62,11 +79,12 @@ function Get-WebPlatformInstallerProduct
    begin
    {
    if (($null -eq $WebPI.productManagerProducts) -or $Force){ New-WebPlatformInstallerProductManager }
    Write-Verbose "Make sure IIS Components (Windows Feature) will never get result."

    # Initialize
    if ($PSBoundParameters.ContainsKey('ProductId'))
    {
    Write-Verbose ("ParameterSet 'ProductId' detected. Make sure IIS Components (Windows Feature) will never get result.")
    Write-Verbose ("ParameterSet 'ProductId' detected.")
    $result = $null
    $private:productManagerDic = New-Object 'System.Collections.Generic.Dictionary[[string], [Microsoft.Web.PlatformInstaller.Product]]' ([StringComparer]::OrdinalIgnoreCase)
    $WebPI.productManagerProducts | %{$productManagerDic.Add($_.ProductId, $_)}
    @@ -96,6 +114,18 @@ function Get-WebPlatformInstallerProduct

    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
    @@ -112,6 +142,17 @@ function Test-WebPlatformInstallerProductIsInstalled

    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([Microsoft.Web.PlatformInstaller.Product[]])]
    [CmdletBinding()]
    param
    @@ -146,6 +187,9 @@ function Install-WebPlatformInstallerProgram
    [CmdletBinding()]
    param
    (
    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)]
    [string]$ProductId,

    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1)]
    [Microsoft.Web.PlatformInstaller.InstallationState]$PreStatus,

    @@ -169,8 +213,9 @@ function Install-WebPlatformInstallerProgram
    }
    ShowInstallerContextStatus
    $logfiles = $WebPI.installManager.InstallerContexts.Installer.LogFiles
    Write-Verbose ("'{0}' Installation completed. Check Log file at '{1}'." -f ($ProductId -join "', '"), ($logfiles -join "', '"))
    #Write-Verbose ("Latest Log file is '{0}'." -f (cat -Path ($logfiles) -Encoding UTF8 -Raw))
    $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
    }
    }
    @@ -216,15 +261,15 @@ function Install-WebPlatformInstallerProgram

    Write-Verbose "Start Installation with StartInstallation()"
    $WebPI.installManager.StartInstallation()
    if (WatchInstallationStatus -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }
    if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }

    Write-Verbose "Start Installation with StartApplicationInstallation()"
    $WebPI.installManager.StartApplicationInstallation()
    if (WatchInstallationStatus -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }
    if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }

    Write-Verbose "Start Installation with StartSynchronousInstallation()"
    $installResult = $WebPI.installManager.StartSynchronousInstallation()
    if (WatchInstallationStatus -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }
    if (WatchInstallationStatus -ProductId $_.ProductId -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }
    }
    }
    catch
  7. guitarrapc revised this gist Nov 12, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -100,7 +100,7 @@ function Test-WebPlatformInstallerProductIsInstalled
    [CmdletBinding(DefaultParameterSetName = "Any")]
    param
    (
    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)]
    [parameter(Mandatory = 1, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)]
    [string[]]$ProductId
    )
    Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($null)}
  8. guitarrapc created this gist Nov 12, 2014.
    241 changes: 241 additions & 0 deletions WebPlatformInstaller.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,241 @@
    #region Initializer

    function New-WebPlatformInstaller
    {
    [OutputType([Void])]
    [CmdletBinding()]
    param()

    try
    {
    Add-Type -Path "C:\Program Files\Microsoft\Web Platform Installer\Microsoft.Web.PlatformInstaller.dll"
    }
    catch
    {
    }

    $script:WebPI = @{}
    }

    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
    {
    [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'))
    {
    Write-Verbose ("ParameterSet 'ProductId' detected. Make sure IIS Components (Windows Feature) will never get result.")
    $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
    {
    [OutputType([bool])]
    [CmdletBinding(DefaultParameterSetName = "Any")]
    param
    (
    [parameter(Mandatory = 0, Position = 0, ValueFromPipelineByPropertyName = 1, ValueFromPipeline = 1)]
    [string[]]$ProductId
    )
    Get-WebPlatformInstallerProduct -ProductId $ProductId | % {$_.IsInstalled($null)}
    }

    #endregion

    #region Install

    function Install-WebPlatformInstallerProgram
    {
    [OutputType([Microsoft.Web.PlatformInstaller.Product[]])]
    [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'
    )

    begin
    {
    # Initialize
    if ($null -eq $WebPI.productManager){ New-WebPlatformInstallerProductManager }
    New-WebPlatformInstallerInstallManager
    $productIdList = New-Object 'System.Collections.Generic.List[string]'

    # Get Language
    [Microsoft.Web.PlatformInstaller.Language]$language = $WebPI.productManager.GetLanguage($LanguageCode)
    $installer = New-Object 'System.Collections.Generic.List[Microsoft.Web.PlatformInstaller.Installer]'

    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)]
    [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
    Write-Verbose ("'{0}' Installation completed. Check Log file at '{1}'." -f ($ProductId -join "', '"), ($logfiles -join "', '"))
    #Write-Verbose ("Latest Log file is '{0}'." -f (cat -Path ($logfiles) -Encoding UTF8 -Raw))
    return $true
    }
    }

    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
    {
    Write-Verbose "Get Product"
    [Microsoft.Web.PlatformInstaller.Product[]]$product = Get-WebPlatformInstallerProduct -ProductId $productIdList
    if ($null -eq $product){ throw New-Object System.NullReferenceException }

    Write-Verbose "Get Installer"
    $product `
    | % {
    $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 -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }

    Write-Verbose "Start Installation with StartApplicationInstallation()"
    $WebPI.installManager.StartApplicationInstallation()
    if (WatchInstallationStatus -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }

    Write-Verbose "Start Installation with StartSynchronousInstallation()"
    $installResult = $WebPI.installManager.StartSynchronousInstallation()
    if (WatchInstallationStatus -PreStatus $preStatus -PostStatus $WebPI.installManager.InstallerContexts.InstallationState){ return; }
    }
    }
    catch
    {
    throw $_
    }
    finally
    {
    if ($null -ne $WebPI.installManager){ $WebPI.installManager.Dispose() }
    }
    }
    }

    #endregion