DSCResources/MSFT_SPInstallLanguagePack/MSFT_SPInstallLanguagePack.psm1
function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [parameter(Mandatory = $true)] [System.String] $BinaryDir, [parameter(Mandatory = $false)] [ValidateSet("mon","tue","wed","thu","fri","sat","sun")] [System.String[]] $BinaryInstallDays, [parameter(Mandatory = $false)] [System.String] $BinaryInstallTime, [parameter(Mandatory = $false)] [ValidateSet("Present","Absent")] [System.String] $Ensure = "Present", [parameter(Mandatory = $false)] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Getting install status of SharePoint Language Pack" # Check if Binary folder exists if (-not(Test-Path -Path $BinaryDir)) { throw "Specified path cannot be found." } $osrvFolder = Get-ChildItem -Path (Join-Path -Path $BinaryDir ` -ChildPath "\osrv*.*") if ($osrvFolder.Count -ne 1) { throw "Unknown folder structure" } $products = Invoke-SPDSCCommand -Credential $InstallAccount ` -ScriptBlock { return Get-SPDscRegProductsInfo } # Extract language from filename if ($osrvFolder.Name -match "\w*.(\w{2}-\w{2})") { $language = $matches[1] } else { throw "Update does not contain the language code in the correct format." } try { $cultureInfo = New-Object -TypeName System.Globalization.CultureInfo ` -ArgumentList $language } catch { throw "Error while converting language information: $language" } # try/catch is required for some versions of Windows, other version use the LCID value of 4096 if ($cultureInfo.LCID -eq 4096) { throw "Error while converting language information: $language" } # Extract English name of the language code if ($cultureInfo.EnglishName -match "(\w*,*\s*\w*) \(\w*\)") { $languageEnglish = $matches[1] if ($languageEnglish.contains(",")) { $languages = $languageEnglish.Split(",") $languageEnglish = $languages[0] } } # Extract Native name of the language code if ($cultureInfo.NativeName -match "(\w*,*\s*\w*) \(\w*\)") { $languageNative = $matches[1] if ($languageNative.contains(",")) { $languages = $languageNative.Split(",") $languageNative = $languages[0] } } # Build language string used in Language Pack names $languageString = "$languageEnglish/$languageNative" Write-Verbose -Message "Update is for the $languageEnglish language" # Find the product name for the specific language pack $productName = "" foreach ($product in $products) { if ($product -match $languageString) { $productName = $product } } if ($productName -eq "") { return @{ BinaryDir = $BinaryDir BinaryInstallDays = $BinaryInstallDays BinaryInstallTime = $BinaryInstallTime Ensure = "Absent" } } else { return @{ BinaryDir = $BinaryDir BinaryInstallDays = $BinaryInstallDays BinaryInstallTime = $BinaryInstallTime Ensure = "Present" } } } function Set-TargetResource { [CmdletBinding()] param ( [parameter(Mandatory = $true)] [System.String] $BinaryDir, [parameter(Mandatory = $false)] [ValidateSet("mon","tue","wed","thu","fri","sat","sun")] [System.String[]] $BinaryInstallDays, [parameter(Mandatory = $false)] [System.String] $BinaryInstallTime, [parameter(Mandatory = $false)] [ValidateSet("Present","Absent")] [System.String] $Ensure = "Present", [parameter(Mandatory = $false)] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Setting install status of SharePoint Language Pack" if ($Ensure -eq "Absent") { throw [Exception] ("SharePointDsc does not support uninstalling SharePoint " + ` "Language Packs. Please remove this manually.") return } # Check if Binary folder exists if (-not(Test-Path -Path $BinaryDir)) { throw "Specified path cannot be found." } $now = Get-Date if ($BinaryInstallDays) { # BinaryInstallDays parameter exists, check if current day is specified $currentDayOfWeek = $now.DayOfWeek.ToString().ToLower().Substring(0,3) if ($BinaryInstallDays -contains $currentDayOfWeek) { Write-Verbose -Message ("Current day is present in the parameter BinaryInstallDays. " + ` "Update can be run today.") } else { Write-Verbose -Message ("Current day is not present in the parameter BinaryInstallDays, " + ` "skipping the update") return } } else { Write-Verbose -Message "No BinaryInstallDays specified, Update can be ran on any day." } # Check if BinaryInstallTime parameter exists if ($BinaryInstallTime) { # Check if current time is inside of time window $upgradeTimes = $BinaryInstallTime.Split(" ") $starttime = 0 $endtime = 0 if ($upgradeTimes.Count -ne 3) { throw "Time window incorrectly formatted." } else { if ([datetime]::TryParse($upgradeTimes[0],[ref]$starttime) -ne $true) { throw "Error converting start time" } if ([datetime]::TryParse($upgradeTimes[2],[ref]$endtime) -ne $true) { throw "Error converting end time" } if ($starttime -gt $endtime) { throw "Error: Start time cannot be larger than end time" } } if (($starttime -lt $now) -and ($endtime -gt $now)) { Write-Verbose -Message ("Current time is inside of the window specified in " + ` "BinaryInstallTime. Starting update") } else { Write-Verbose -Message ("Current time is outside of the window specified in " + ` "BinaryInstallTime, skipping the update") return } } else { Write-Verbose -Message ("No BinaryInstallTime specified, Update can be ran at " + ` "any time. Starting update.") } # To prevent an endless loop: Check if an upgrade is required. if ((Get-SPDSCInstalledProductVersion).FileMajorPart -eq 15) { $wssRegKey ="hklm:SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\15.0\WSS" } else { $wssRegKey ="hklm:SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\16.0\WSS" } # Read LanguagePackInstalled and SetupType registry keys $languagePackInstalled = Get-SPDSCRegistryKey -Key $wssRegKey -Value "LanguagePackInstalled" $setupType = Get-SPDSCRegistryKey -Key $wssRegKey -Value "SetupType" # Determine if LanguagePackInstalled=1 or SetupType=B2B_Upgrade. # If so, the Config Wizard is required, so the installation will be skipped. if (($languagePackInstalled -eq 1) -or ($setupType -eq "B2B_UPGRADE")) { Write-Verbose -Message ("An upgrade is pending. " + ` "To prevent a possible loop, the install will be skipped") return } Write-Verbose -Message "Writing install config file" $configPath = "$env:temp\SPInstallLanguagePackConfig.xml" $configData = "<Configuration> <Setting Id=`"OSERVERLPK`" Value=`"1`"/> <Setting Id=`"USINGUIINSTALLMODE`" Value=`"0`"/> <Logging Type=`"verbose`" Path=`"%temp%`" Template=`"SharePoint " if ((Get-SPDSCInstalledProductVersion).FileMajorPart -eq 15) { $configData += "2013" } else { $configData += "2016" } $configData += " Products Language Pack Setup(*).log`"/> <Display Level=`"none`" CompletionNotice=`"no`" /> </Configuration>" $configData | Out-File -FilePath $configPath Write-Verbose -Message "Beginning installation of the SharePoint Language Pack" $setupExe = Join-Path -Path $BinaryDir -ChildPath "setup.exe" $setup = Start-Process -FilePath $setupExe ` -ArgumentList "/config `"$configPath`"" ` -Wait ` -PassThru switch ($setup.ExitCode) { 0 { Write-Verbose -Message "SharePoint Language Pack binary installation complete" } 17022 { Write-Verbose -Message "SharePoint Language Pack binary installation complete. Reboot required." $global:DSCMachineStatus = 1 } Default { throw "SharePoint Language Pack install failed, exit code was $($setup.ExitCode)" } } } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [parameter(Mandatory = $true)] [System.String] $BinaryDir, [parameter(Mandatory = $false)] [ValidateSet("mon","tue","wed","thu","fri","sat","sun")] [System.String[]] $BinaryInstallDays, [parameter(Mandatory = $false)] [System.String] $BinaryInstallTime, [parameter(Mandatory = $false)] [ValidateSet("Present","Absent")] [System.String] $Ensure = "Present", [parameter(Mandatory = $false)] [System.Management.Automation.PSCredential] $InstallAccount ) Write-Verbose -Message "Testing install status of SharePoint Language Pack" $PSBoundParameters.Ensure = $Ensure if ($Ensure -eq "Absent") { throw [Exception] ("SharePointDsc does not support uninstalling SharePoint " + ` "Language Packs. Please remove this manually.") return } $CurrentValues = Get-TargetResource @PSBoundParameters return Test-SPDscParameterState -CurrentValues $CurrentValues ` -DesiredValues $PSBoundParameters ` -ValuesToCheck @("Ensure") } Export-ModuleMember -Function *-TargetResource |