try { Add-Type -ErrorAction SilentlyContinue -TypeDefinition @" public enum OfficeLanguages { CurrentOfficeLanguages, OSLanguage, OSandUserLanguages, AllInUseLanguages } "@ } catch {} Function Generate-ODTConfigurationXml { <# .Synopsis Generates the Office Deployment Tool (ODT) Configuration XML from the current configuration of the target computer .DESCRIPTION This function will query the local or a remote computer and Generate the ODT configuration xml based on the local Office install and the local languages that are used on the local computer. If Office isn't installed then it will utilize a DefaultConfiguration file .NOTES Name: Generate-ODTConfigurationXml Version: 1.0.3 DateCreated: 2015-08-24 DateUpdated: 2017-03-03 .LINK https://github.com/OfficeDev/Office-IT-Pro-Deployment-Scripts .PARAMETER ComputerName The computer or list of computers from which to query .PARAMETER Languages Will expand the output to include all installed Office products .PARAMETER TargetFilePath The path and file name of the file to save the Configuration xml .PARAMETER IncludeUpdatePathAsSourcePath If this parameter is set to $true then the SourcePath in the Configuration xml will be set to the current UpdatePath on the local computer. This assumes that the UpdatePath location has the required files needed to run the installation. .PARAMETER DefaultConfigurationXml This parameter sets the path to the Default Configuration XML file. If Office is not installed on the computer that this script is run against it will default to this file in order to generate the ODT Configuration XML. The default file should have the products that you would want installed on a workstation if Office isn't currently installed. If this parameter is set to $NULL then it will not generate configuration XML if Office is not installed. By default the script looks for a file called "DefaultConfiguration.xml" in the same directory as the script. .EXAMPLE Generate-ODTConfigurationXml | fl Will generate the Office Deployment Tool (ODT) configuration XML based on the local computer .EXAMPLE Generate-ODTConfigurationXml -ComputerName client01,client02 | fl Will generate the Office Deployment Tool (ODT) configuration XML based on the configuration of the remote computers client01 and client02 .EXAMPLE Generate-ODTConfigurationXml -Languages OSandUserLanguages Will generate the Office Deployment Tool (ODT) configuration XML based on the local computer and add the languages that the Operating System and the local users are currently using. .EXAMPLE Generate-ODTConfigurationXml -Languages OSLanguage Will generate the Office Deployment Tool (ODT) configuration XML based on the local computer and add the Current UI Culture language of the Operating System .EXAMPLE Generate-ODTConfigurationXml -Languages CurrentOfficeLanguages Will generate the Office Deployment Tool (ODT) configuration XML based on the local computer and add only add the Languages currently in use by the current Office installation #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(ValueFromPipelineByPropertyName=$true, Position=0)] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName=$true)] [OfficeLanguages]$Languages = "AllInUseLanguages", [Parameter(ValueFromPipelineByPropertyName=$true)] [String]$TargetFilePath = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [bool]$IncludeUpdatePathAsSourcePath = $false, [Parameter(ValueFromPipelineByPropertyName=$true)] [String]$DownloadPath = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string]$DefaultConfigurationXml = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [System.Boolean]$KeepExcludedApps = $true, [Parameter()] [string]$LogFilePath ) begin { $HKLM = [UInt32] "0x80000002" $HKCR = [UInt32] "0x80000000" $HKU = [UInt32] "0x80000003" $installKeys = 'SOFTWARE\Microsoft\Windows\CurrentVersionninstall', 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersionninstall' $defaultDisplaySet = 'DisplayName','Version', 'ComputerName' $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet) $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet) [string]$tempStr = $MyInvocation.MyCommand.Path $scriptPath = GetScriptPath if (!($DefaultConfigurationXml)) { $DefaultConfigurationXml = (Join-Path $scriptPath "DefaultConfiguration.xml") } Set-Alias -name LINENUM -value Get-CurrentLineNumber $currentFileName = Get-CurrentFileName } process { try{ if ($TargetFilePath) { $folderPath = Split-Path -Path $TargetFilePath -Parent $fileName = Split-Path -Path $TargetFilePath -Leaf if ($folderPath) { [system.io.directory]::CreateDirectory($folderPath) | Out-Null } } $results = new-object PSObject[] 0; foreach ($computer in $ComputerName) { try { if ($Credentials) { $os=Get-WMIObject win32_operatingsystem -computername $computer -Credential $Credentials -ErrorAction Stop } else { $os=Get-WMIObject win32_operatingsystem -computername $computer -ErrorAction Stop } if ($Credentials) { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -Credential $Credentials -ErrorAction Stop } else { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -ErrorAction Stop } if ($TargetFilePath) { if ($ComputerName.Length -gt 1) { $NewFileName = $computer + "-" + $fileName $TargetFilePath = Join-Path $folderPath $NewFileName } } [System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument $productReleaseIds = ""; $productPlatform = "32"; $officeConfig = getCTRConfig -regProv $regProv $mainOfficeProduct = Get-OfficeVersion -ComputerName $ComputerName $officeProducts = Get-OfficeVersion -ComputerName $ComputerName -ShowAllInstalledProducts if (!($officeConfig.ClickToRunInstalled)) { $officeConfig = getOfficeConfig -regProv $regProv -mainOfficeProduct $mainOfficeProduct -officeProducts $officeProducts if ($officeConfig -and $officeConfig.OfficeKeyPath) { $officeLangs = officeGetLanguages -regProv $regProv -OfficeKeyPath $officeConfig.OfficeKeyPath } if ($officeConfig -and $officeConfig.Platform) { $productPlatform = $officeConfig.Platform } } else { $productPlatform = $officeConfig.Platform $otherProducts = $officeConfig.ProductReleaseIds $otherProducts = generateProductReleaseIds -OfficeProducts $officeProducts -MainOfficeProduct $mainOfficeProduct } if ($officeConfig.ProductReleaseIds) { $productReleaseIds = $officeConfig.ProductReleaseIds } if ($otherProducts) { if ($productReleaseIds) { $productReleaseIds += ",$otherProducts" } else { $productReleaseIds += $otherProducts } } [bool]$officeExists = $true if (!($officeProducts)) { $officeExists = $false if ($DefaultConfigurationXml) { if (Test-Path -Path $DefaultConfigurationXml) { $ConfigFile.Load($DefaultConfigurationXml) $products = $ConfigFile.SelectNodes("/Configuration/Add/Product") if ($products) { foreach ($product in $products) { if ($productReleaseIds.Length -gt 0) { $productReleaseIds += "," } $productReleaseIds += $product.ID } } $addNode = $ConfigFile.SelectSingleNode("/Configuration/Add"); if ($addNode) { $productPlatform = $addNode.OfficeClientEdition } } } } if ($productReleaseIds) { $splitProducts = $productReleaseIds.Split(','); $newSplitProducts = @() foreach ($productId in $splitProducts) { if($productId.ToUpper() -notlike "SPD*") { if (!($newSplitProducts -Contains $productId)) { $newSplitProducts += $productId } } } $splitProducts = $newSplitProducts } $osArchitecture = $os.OSArchitecture $osLanguage = $os.OSLanguage $machinelangId = "en-us" $machineCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $osLanguage} if ($machineCulture) { $machinelangId = $machineCulture.IetfLanguageTag } $primaryLanguage = checkForLanguage -langId $machinelangId $additionalLanguages = @() [String[]]$allLanguages = @() switch ($Languages) { "CurrentOfficeLanguages" { if ($officeConfig) { $primaryLanguage = $officeConfig.ClientCulture } if (!($primaryLanguage)) { $msiPrimaryLanguage = msiGetOfficeUILanguage -regProv $regProv if ($msiPrimaryLanguage) { $primaryLanguage = $msiPrimaryLanguage } $primaryLanguage = checkForLanguage -langId $machinelangId } } "OSLanguage" { $primaryLanguage = checkForLanguage -langId $machinelangId } "OSandUserLanguages" { $primaryLanguage = checkForLanguage -langId $machinelangId $additionalLanguages = getLanguages -regProv $regProv } "AllInUseLanguages" { $primaryLanguage = checkForLanguage -langId $machinelangId $returnLangs = getLanguages -regProv $regProv foreach ($returnLang in $returnLangs) { $additionalLanguages += $returnLang } } } if ($primaryLanguage) { $allLanguages += $primaryLanguage.ToLower() } foreach ($lang in $additionalLanguages) { if ($lang.GetType().Name.ToLower().Contains("string")) { if ($lang.Contains("-")) { [bool]$addLang = $true foreach ($language in $allLanguages) { if ($language.ToLower() -eq $lang.ToLower()) { $addLang = $false } } if ($addLang) { $allLanguages += $lang.ToLower() } } } } if (!($primaryLanguage)) { WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Cannot find matching Office language for: $primaryLanguage" -LogFilePath $LogFilePath throw "Cannot find matching Office language for: $primaryLanguage" } $languageIDs = @() $msiLangPacks = GetLanguagePacks if($splitProducts.GetType().Name -eq "Object[]"){ $splitProducts = $splitProducts | Sort-Object } foreach ($productId in $splitProducts) { if($msiLangPacks){ if($Languages -eq "CurrentOfficeLanguages") { $officeLangs = $null if($productId -match "Visio" -or $productId -match "Project"){ $languageIDs = @() } if($productId -match "O365"){ if($mainOfficeProduct.GetType().Name -eq "Object[]"){ $OfficeProduct = $mainOfficeProduct[0].DisplayName } else { $OfficeProduct = $mainOfficeProduct.DisplayName } if($OfficeProduct -notmatch "ProPlus"){ $product = "Office" } } if($productId -match "Visio"){ $product = "Visio" } if($productId -match "Project"){ $product = "Project" } if($product){ if($product -eq "Office"){ $languagePacks = GetLanguagePacks | ? {$_.DisplayName -match $product ` -and $_.DisplayName -notmatch "Visio" ` -and $_.DisplayName -notmatch "Project"} } else { $languagePacks = GetLanguagePacks | ? {$_.DisplayName -match $product} } foreach($lang in $languagePacks){ $languageIDs += $lang.LanguageID } } } } $excludeApps = $NULL if ($Languages -eq "CurrentOfficeLanguages") { $additionalLanguages = New-Object System.Collections.ArrayList $additionalLanguages += $languageIDs } if ($officeConfig.ClickToRunInstalled) { $officeKeyPath = $officeConfig.OfficeKeyPath if($KeepExcludedApps){ if ($productId.ToLower().StartsWith("o365")) { $excludeApps = odtGetExcludedApps -ConfigDoc $ConfigFile -OfficeKeyPath $officeConfig.OfficeKeyPath -ProductId $productId } } if($Languages -eq 'AllInUseLanguages'){ foreach($product in $splitProducts){ $languagePacks = GetLanguagePacks foreach($pack in $languagePacks){ $additionalLanguages += $pack.LanguageID } foreach($product in $splitProducts){ $officeAddLangs = odtGetOfficeLanguages -ConfigDoc $ConfigFile -OfficeKeyPath $officeConfig.OfficeKeyPath -ProductId $product $additionalLanguages += $officeAddLangs } } } else { $officeAddLangs = odtGetOfficeLanguages -ConfigDoc $ConfigFile -OfficeKeyPath $officeConfig.OfficeKeyPath -ProductId $productId } } else { #if ($officeExists) { # if($KeepExcludedApps){ # if($productId.ToLower().StartsWith("o365")) { # $excludeApps = officeGetExcludedApps -OfficeProducts $officeProducts -computer $computer -Credentials $Credentials # } # } #} $msiLanguages = msiGetOfficeLanguages -regProv $regProv foreach ($msiLanguage in $msiLanguages) { $additionalLanguages += $msiLanguage } foreach ($officeLang in $officeLangs) { if(!($additionalLanguages -contains $officeLang)){ $additionalLanguages += $officeLang } } } if ($officeAddLangs) { if (($Languages -eq "CurrentOfficeLanguages") -or ($Languages -eq "AllInUseLanguages")) { $additionalLanguages += $officeAddLangs } } if ($additionalLanguages) { $additionalLanguages = Get-Unique -InputObject $additionalLanguages -OnType [bool]$containsLang = $false foreach ($additionalLanguage in $additionalLanguages) { if ($primaryLanguage) { if ($additionalLanguage) { if ($primaryLanguage.ToLower() -eq $additionalLanguage.ToLower()) { $containsLang = $true } } } } if ($containsLang) { $tempLanguages = $additionalLanguages $additionalLanguages = New-Object System.Collections.ArrayList foreach($tempL in $tempLanguages){ if($tempL -ne $primaryLanguage){ $additionalLanguages.Add($tempL) | Out-Null } #$additionalLanguages.Remove($primaryLanguage) } } } $ChannelName = $NULL $ChannelDetect = Detect-Channel if ($ChannelDetect) { $ChannelName = $ChannelDetect.branch } if ($officeConfig.ClickToRunInstalled) { if ($Languages -eq "CurrentOfficeLanguages") { $officeAddLangs = odtGetOfficeLanguages -ConfigDoc $ConfigFile -OfficeKeyPath $officeConfig.OfficeKeyPath -ProductId $productId if ($officeAddLangs) { $additionalLanguages = New-Object System.Collections.ArrayList foreach($language in $officeAddLangs){ if(!($language.ToLower() -eq $primaryLanguage)){ $additionalLanguages += $language } } } } } odtAddProduct -ConfigDoc $ConfigFile -ProductId $productId -ExcludeApps $excludeApps -Version $officeConfig.Version ` -Platform $productPlatform -ClientCulture $primaryLanguage -AdditionalLanguages $additionalLanguages -Channel $ChannelName if ($officeConfig) { if (($officeConfig.UpdatesEnabled) -or ($officeConfig.UpdateUrl) -or ($officeConfig.UpdateDeadline)) { odtAddUpdates -ConfigDoc $ConfigFile -Enabled $officeConfig.UpdatesEnabled -UpdatePath $officeConfig.UpdateUrl -Deadline $officeConfig.UpdateDeadline } } } $clickToRunKeys = 'SOFTWARE\Microsoft\Office\ClickToRun', 'SOFTWARE\Microsoft\Office\15.0\ClickToRun' foreach($key in $clickToRunKeys){ $configKeys = $regProv.EnumKey($HKLM, $key) $clickToRunList = $configKeys.snames foreach($list in $clickToRunList){ if($list -match 'Configuration'){ $configPath = Join-Path $key "Configuration" $sharedLicense = $regProv.GetStringValue($HKLM, $configPath, "SharedComputerLicensing").sValue if($sharedLicense -eq '1'){ Set-ODTConfigProperties -SharedComputerLicensing $true -ConfigDoc $ConfigFile } } } } if ($IncludeUpdatePathAsSourcePath) { if ($officeConfig.UpdateUrl) { odtSetAdd -ConfigDoc $ConfigFile -SourcePath $officeConfig.UpdateUrl } } if ($DownloadPath) { odtSetAdd -ConfigDoc $ConfigFile -DownloadPath $DownloadPath } $formattedXml = Format-XML ([xml]($ConfigFile)) -indent 4 if (($PSCmdlet.MyInvocation.PipelineLength -eq 1) -or ` ($PSCmdlet.MyInvocation.PipelineLength -eq $PSCmdlet.MyInvocation.PipelinePosition)) { $results = new-object PSObject[] 0; $Result = New-Object -TypeName PSObject Add-Member -InputObject $Result -MemberType NoteProperty -Name "ConfigurationXML" -Value $formattedXml if ($ComputerName.Length -gt 1) { Add-Member -InputObject $Result -MemberType NoteProperty -Name "LanguageIds" -Value $allLanguages Add-Member -InputObject $Result -MemberType NoteProperty -Name "ComputerName" -Value $computer } if ($TargetFilePath) { $formattedXml | Out-File -FilePath $TargetFilePath $formattedXml | Out-File -FilePath C:\Windows\Temp\OfficeAutoScriptConfigFile.xml if ($ComputerName.Length -eq 1) { $Result = $formattedXml } } $Result } else { if ($TargetFilePath) { $formattedXml | Out-File -FilePath $TargetFilePath $formattedXml | Out-File -FilePath C:\Windows\Temp\OfficeAutoScriptConfigFile.xml } $allLanguages = Get-Unique -InputObject $allLanguages $results = new-object PSObject[] 0; $Result = New-Object -TypeName PSObject Add-Member -InputObject $Result -MemberType NoteProperty -Name "TargetFilePath" -Value $TargetFilePath Add-Member -InputObject $Result -MemberType NoteProperty -Name "LanguageIds" -Value $allLanguages Add-Member -InputObject $Result -MemberType NoteProperty -Name "ConfigurationXML" -Value $formattedXml $Result } #return $ConfigFile } catch { $errorMessage = $computer + ": " + $_ Write-Host $errorMessage WriteToLogFile -LNumber $_.InvocationInfo.ScriptLineNumber -FName $currentFileName -ActionError $_ -LogFilePath $LogFilePath throw; } } } catch [Exception] { $fileName = $_.InvocationInfo.ScriptName.Substring($_.InvocationInfo.ScriptName.LastIndexOf("\")+1) WriteToLogFile -LNumber $_.InvocationInfo.ScriptLineNumber -FName $currentFileName -ActionError $_ -LogFilePath $LogFilePath } } } Function Get-OfficeVersion { <# .Synopsis Gets the Office Version installed on the computer .DESCRIPTION This function will query the local or a remote computer and return the information about Office Products installed on the computer .NOTES Name: Get-OfficeVersion Version: 1.0.5 DateCreated: 2015-07-01 DateUpdated: 2016-10-14 .LINK https://github.com/OfficeDev/Office-IT-Pro-Deployment-Scripts .PARAMETER ComputerName The computer or list of computers from which to query .PARAMETER ShowAllInstalledProducts Will expand the output to include all installed Office products .EXAMPLE Get-OfficeVersion Will return the locally installed Office product .EXAMPLE Get-OfficeVersion -ComputerName client01,client02 Will return the installed Office product on the remote computers .EXAMPLE Get-OfficeVersion | select * Will return the locally installed Office product with all of the available properties #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)] [string[]]$ComputerName = $env:COMPUTERNAME, [switch]$ShowAllInstalledProducts, [System.Management.Automation.PSCredential]$Credentials ) begin { $HKLM = [UInt32] "0x80000002" $HKCR = [UInt32] "0x80000000" $excelKeyPath = "Excel\DefaultIcon" $wordKeyPath = "Word\DefaultIcon" $installKeys = 'SOFTWARE\Microsoft\Windows\CurrentVersionninstall', 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersionninstall' $officeKeys = 'SOFTWARE\Microsoft\Office', 'SOFTWARE\Wow6432Node\Microsoft\Office' $defaultDisplaySet = 'DisplayName','Version', 'ComputerName' $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet) $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet) } process { $results = new-object PSObject[] 0; $MSexceptionList = "mui","visio","project","proofing","visual" foreach ($computer in $ComputerName) { if ($Credentials) { $os=Get-WMIObject win32_operatingsystem -computername $computer -Credential $Credentials } else { $os=Get-WMIObject win32_operatingsystem -computername $computer } $osArchitecture = $os.OSArchitecture if ($Credentials) { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -Credential $Credentials } else { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer } [System.Collections.ArrayList]$VersionList = New-Object -TypeName System.Collections.ArrayList [System.Collections.ArrayList]$PathList = New-Object -TypeName System.Collections.ArrayList [System.Collections.ArrayList]$PackageList = New-Object -TypeName System.Collections.ArrayList [System.Collections.ArrayList]$ClickToRunPathList = New-Object -TypeName System.Collections.ArrayList [System.Collections.ArrayList]$ConfigItemList = New-Object -TypeName System.Collections.ArrayList $ClickToRunList = new-object PSObject[] 0; foreach ($regKey in $officeKeys) { $officeVersion = $regProv.EnumKey($HKLM, $regKey) foreach ($key in $officeVersion.sNames) { if ($key -match "\d{2}\.\d") { if (!$VersionList.Contains($key)) { $AddItem = $VersionList.Add($key) } $path = join-path $regKey $key $configPath = join-path $path "Common\Config" $configItems = $regProv.EnumKey($HKLM, $configPath) if ($configItems) { foreach ($configId in $configItems.sNames) { if ($configId) { $Add = $ConfigItemList.Add($configId.ToUpper()) } } } $cltr = New-Object -TypeName PSObject $cltr | Add-Member -MemberType NoteProperty -Name InstallPath -Value "" $cltr | Add-Member -MemberType NoteProperty -Name UpdatesEnabled -Value $false $cltr | Add-Member -MemberType NoteProperty -Name UpdateUrl -Value "" $cltr | Add-Member -MemberType NoteProperty -Name StreamingFinished -Value $false $cltr | Add-Member -MemberType NoteProperty -Name Platform -Value "" $cltr | Add-Member -MemberType NoteProperty -Name ClientCulture -Value "" $packagePath = join-path $path "Common\InstalledPackages" $clickToRunPath = join-path $path "ClickToRun\Configuration" $virtualInstallPath = $regProv.GetStringValue($HKLM, $clickToRunPath, "InstallationPath").sValue [string]$officeLangResourcePath = join-path $path "Common\LanguageResources" $mainLangId = $regProv.GetDWORDValue($HKLM, $officeLangResourcePath, "SKULanguage").uValue if ($mainLangId) { $mainlangCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $mainLangId} if ($mainlangCulture) { $cltr.ClientCulture = $mainlangCulture.Name } } [string]$officeLangPath = join-path $path "Common\LanguageResources\InstalledUIs" $langValues = $regProv.EnumValues($HKLM, $officeLangPath); if ($langValues) { foreach ($langValue in $langValues) { $langCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $langValue} } } if ($virtualInstallPath) { } else { $clickToRunPath = join-path $regKey "ClickToRun\Configuration" $virtualInstallPath = $regProv.GetStringValue($HKLM, $clickToRunPath, "InstallationPath").sValue } if ($virtualInstallPath) { if (!$ClickToRunPathList.Contains($virtualInstallPath.ToUpper())) { $AddItem = $ClickToRunPathList.Add($virtualInstallPath.ToUpper()) } $cltr.InstallPath = $virtualInstallPath $cltr.StreamingFinished = $regProv.GetStringValue($HKLM, $clickToRunPath, "StreamingFinished").sValue $cltr.UpdatesEnabled = $regProv.GetStringValue($HKLM, $clickToRunPath, "UpdatesEnabled").sValue $cltr.UpdateUrl = $regProv.GetStringValue($HKLM, $clickToRunPath, "UpdateUrl").sValue $cltr.Platform = $regProv.GetStringValue($HKLM, $clickToRunPath, "Platform").sValue $cltr.ClientCulture = $regProv.GetStringValue($HKLM, $clickToRunPath, "ClientCulture").sValue $ClickToRunList += $cltr } $packageItems = $regProv.EnumKey($HKLM, $packagePath) $officeItems = $regProv.EnumKey($HKLM, $path) foreach ($itemKey in $officeItems.sNames) { $itemPath = join-path $path $itemKey $installRootPath = join-path $itemPath "InstallRoot" $filePath = $regProv.GetStringValue($HKLM, $installRootPath, "Path").sValue if (!$PathList.Contains($filePath)) { $AddItem = $PathList.Add($filePath) } } foreach ($packageGuid in $packageItems.sNames) { $packageItemPath = join-path $packagePath $packageGuid $packageName = $regProv.GetStringValue($HKLM, $packageItemPath, "").sValue if (!$PackageList.Contains($packageName)) { if ($packageName) { $AddItem = $PackageList.Add($packageName.Replace(' ', '').ToLower()) } } } } } } foreach ($regKey in $installKeys) { $keyList = new-object System.Collections.ArrayList $keys = $regProv.EnumKey($HKLM, $regKey) foreach ($key in $keys.sNames) { $path = join-path $regKey $key $installPath = $regProv.GetStringValue($HKLM, $path, "InstallLocation").sValue if (!($installPath)) { continue } if ($installPath.Length -eq 0) { continue } $buildType = "64-Bit" if ($osArchitecture -eq "32-bit") { $buildType = "32-Bit" } if ($regKey.ToUpper().Contains("Wow6432Node".ToUpper())) { $buildType = "32-Bit" } if ($key -match "{.{8}-.{4}-.{4}-1000-0000000FF1CE}") { $buildType = "64-Bit" } if ($key -match "{.{8}-.{4}-.{4}-0000-0000000FF1CE}") { $buildType = "32-Bit" } if ($modifyPath) { if ($modifyPath.ToLower().Contains("platform=x86")) { $buildType = "32-Bit" } if ($modifyPath.ToLower().Contains("platform=x64")) { $buildType = "64-Bit" } } $primaryOfficeProduct = $false $officeProduct = $false foreach ($officeInstallPath in $PathList) { if ($officeInstallPath) { try{ $installReg = "^" + $installPath.Replace('\', '\') $installReg = $installReg.Replace('(', '\(') $installReg = $installReg.Replace(')', '\)') if ($officeInstallPath -match $installReg) { $officeProduct = $true } } catch {} } } if (!$officeProduct) { continue }; $name = $regProv.GetStringValue($HKLM, $path, "DisplayName").sValue $primaryOfficeProduct = $true if ($ConfigItemList.Contains($key.ToUpper()) -and $name.ToUpper().Contains("MICROSOFT OFFICE")) { foreach($exception in $MSexceptionList){ if($name.ToLower() -match $exception.ToLower()){ $primaryOfficeProduct = $false } } } else { $primaryOfficeProduct = $false } $clickToRunComponent = $regProv.GetDWORDValue($HKLM, $path, "ClickToRunComponent").uValue $uninstallString = $regProv.GetStringValue($HKLM, $path, "UninstallString").sValue if (!($clickToRunComponent)) { if ($uninstallString) { if ($uninstallString.Contains("OfficeClickToRun")) { $clickToRunComponent = $true } } } $modifyPath = $regProv.GetStringValue($HKLM, $path, "ModifyPath").sValue $version = $regProv.GetStringValue($HKLM, $path, "DisplayVersion").sValue $cltrUpdatedEnabled = $NULL $cltrUpdateUrl = $NULL $clientCulture = $NULL; [string]$clickToRun = $false if ($clickToRunComponent) { $clickToRun = $true if ($name.ToUpper().Contains("MICROSOFT OFFICE")) { $primaryOfficeProduct = $true } foreach ($cltr in $ClickToRunList) { if ($cltr.InstallPath) { if ($cltr.InstallPath.ToUpper() -eq $installPath.ToUpper()) { $cltrUpdatedEnabled = $cltr.UpdatesEnabled $cltrUpdateUrl = $cltr.UpdateUrl if ($cltr.Platform -eq 'x64') { $buildType = "64-Bit" } if ($cltr.Platform -eq 'x86') { $buildType = "32-Bit" } $clientCulture = $cltr.ClientCulture } } } } if (!$primaryOfficeProduct) { if (!$ShowAllInstalledProducts) { continue } } $object = New-Object PSObject -Property @{DisplayName = $name; Version = $version; InstallPath = $installPath; ClickToRun = $clickToRun; Bitness=$buildType; ComputerName=$computer; ClickToRunUpdatesEnabled=$cltrUpdatedEnabled; ClickToRunUpdateUrl=$cltrUpdateUrl; ClientCulture=$clientCulture } $object | Add-Member MemberSet PSStandardMembers $PSStandardMembers $results += $object } } } $results = Get-Unique -InputObject $results return $results; } } function getCTRConfig() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] $regProv = $NULL ) $HKLM = [UInt32] "0x80000002" $computerName = $env:COMPUTERNAME if (!($regProv)) { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computerName -ErrorAction Stop } $officeCTRKeys = 'SOFTWARE\Microsoft\Office\15.0\ClickToRun', 'SOFTWARE\Wow6432Node\Microsoft\Office\15.0\ClickToRun', 'SOFTWARE\Microsoft\Office\ClickToRun', 'SOFTWARE\Wow6432Node\Microsoft\Office\ClickToRun' $Object = New-Object PSObject $Object | add-member Noteproperty ClickToRunInstalled $false [string]$officeKeyPath = ""; foreach ($regPath in $officeCTRKeys) { [string]$installPath = $regProv.GetStringValue($HKLM, $regPath, "InstallPath").sValue if ($installPath) { if ($installPath.Length -gt 0) { $officeKeyPath = $regPath; break; } } } if ($officeKeyPath.Length -gt 0) { $Object.ClickToRunInstalled = $true $configurationPath = join-path $officeKeyPath "Configuration" [string]$platform = $regProv.GetStringValue($HKLM, $configurationPath, "Platform").sValue [string]$clientCulture = $regProv.GetStringValue($HKLM, $configurationPath, "ClientCulture").sValue [string]$productIds = $regProv.GetStringValue($HKLM, $configurationPath, "ProductReleaseIds").sValue [string]$versionToReport = $regProv.GetStringValue($HKLM, $configurationPath, "VersionToReport").sValue [string]$updatesEnabled = $regProv.GetStringValue($HKLM, $configurationPath, "UpdatesEnabled").sValue [string]$updateUrl = $regProv.GetStringValue($HKLM, $configurationPath, "UpdateUrl").sValue [string]$updateDeadline = $regProv.GetStringValue($HKLM, $configurationPath, "UpdateDeadline").sValue if (!($productIds)) { $productIds = "" $officeActivePath = Join-Path $officeKeyPath "ProductReleaseIDs\Active" $officeProducts = $regProv.EnumKey($HKLM, $officeActivePath) foreach ($productName in $officeProducts.sNames) { if ($productName.ToLower() -eq "stream") { continue } if ($productName.ToLower() -eq "culture") { continue } if ($productIds.Length -gt 0) { $productIds += "," } $productIds += "$productName" } } $splitProducts = $productIds.Split(','); if ($platform.ToLower() -eq "x86") { $platform = "32" } else { $platform = "64" } $Object | add-member Noteproperty Platform $platform $Object | add-member Noteproperty ClientCulture $clientCulture $Object | add-member Noteproperty ProductReleaseIds $productIds $Object | add-member Noteproperty Version $versionToReport $Object | add-member Noteproperty UpdatesEnabled $updatesEnabled $Object | add-member Noteproperty UpdateUrl $updateUrl $Object | add-member Noteproperty UpdateDeadline $updateDeadline $Object | add-member Noteproperty OfficeKeyPath $officeKeyPath } return $Object } function getOfficeConfig() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] $regProv = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(ValueFromPipelineByPropertyName=$true)] [PSObject]$mainOfficeProduct = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [PSObject[]]$officeProducts = $NULL ) #HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\14.0\Common\InstallRoot $officeCTRKeys = 'SOFTWARE\Microsoft\Office', 'SOFTWARE\Wow6432Node\Microsoft\Office' $Object = New-Object PSObject $Object | add-member Noteproperty ClickToRunInstalled $false [string]$officeKeyPath = ""; foreach ($regPath in $officeCTRKeys) { $officeVersionNums = $regProv.EnumKey($HKLM, $regPath) foreach ($officeVersionNum in $officeVersionNums.sNames) { [string]$officePath = join-path $regPath "$officeVersionNum\Common\InstallRoot" [string]$installPath = $regProv.GetStringValue($HKLM, $officePath, "Path").sValue if ($installPath) { if ($installPath.Length -gt 0) { $officeKeyPath = join-path $regPath $officeVersionNum break; } } } } if ($officeKeyPath.Length -gt 0) { $Object.ClickToRunInstalled = $false $productIds = generateProductReleaseIds -OfficeProducts $officeProducts $productDisplayName = "" $productBitness = "" $productVersion = "" if ($officeInstall.Bitness) { if ($officeInstall.Bitness.ToLower() -eq "32-bit") { $officeInstall.Bitness = "32" } else { $officeInstall.Bitness = "64" } $productBitness = $officeInstall.Bitness $productDisplayName = $officeInstall.DisplayName $productVersion = $officeInstall.Version } else { if ($mainOfficeProduct) { if ($mainOfficeProduct -is [System.Array]) { $firstProduct = $mainOfficeProduct[0] } else{ $firstProduct = $mainOfficeProduct } if ($firstProduct.Bitness.ToLower() -eq "32-bit") { $firstProduct.Bitness = "32" } else { $firstProduct.Bitness = "64" } $productBitness = $firstProduct.Bitness $productDisplayName = $firstProduct.DisplayName $productVersion = $firstProduct.Version } } $Object | add-member Noteproperty Platform $productBitness $Object | add-member Noteproperty DisplayName $productDisplayName $Object | add-member Noteproperty Version $productVersion $Object | add-member Noteproperty OfficeKeyPath $officeKeyPath $Object | add-member Noteproperty ProductReleaseIds $productIds } return $Object } function generateProductReleaseIds() { param( [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)] [PSObject[]]$MainOfficeProduct = $NULL, [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)] [PSObject[]]$OfficeProducts = $NULL ) $productReleaseIds = "" if (!($MainOfficeProduct)) { $productReleaseIds += "O365ProPlusRetail" } foreach ($OfficeProduct in $OfficeProducts) { if ($OfficeProduct.DisplayName.ToLower().Contains("microsoft") -and $OfficeProduct.DisplayName.ToLower().Contains("visio")) { if ($productReleaseIds.IndexOf("VisioProRetail") -eq -1) { if ($productReleaseIds.Length -gt 0) { $productReleaseIds += "," } $productReleaseIds += "VisioProRetail" } } if ($OfficeProduct.DisplayName.ToLower().Contains("microsoft") -and $OfficeProduct.DisplayName.ToLower().Contains("project")) { if ($productReleaseIds.IndexOf("ProjectProRetail") -eq -1) { if ($productReleaseIds.Length -gt 0) { $productReleaseIds += "," } $productReleaseIds += "ProjectProRetail" } } if ($OfficeProduct.DisplayName.ToLower().Contains("microsoft") -and $OfficeProduct.DisplayName.ToLower().Contains("sharepoint designer")) { if ($productReleaseIds.IndexOf("SPDRetail") -eq -1) { if ($productReleaseIds.Length -gt 0) { $productReleaseIds += "," } $productReleaseIds += "SPDRetail" } } } $productReleaseIds = Get-Unique -InputObject $productReleaseIds return $productReleaseIds } function odtGetOfficeLanguages() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] [System.XML.XMLDocument]$ConfigDoc = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$OfficeKeyPath = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$ProductId = $NULL ) begin { $HKLM = [UInt32] "0x80000002" $HKCR = [UInt32] "0x80000000" } process { [System.Collections.ArrayList]$appLanguages1 = New-Object System.Collections.ArrayList #SOFTWARE\Wow6432Node\Microsoft\Office\14.0\Common\LanguageResources\InstalledUIs $productsPath = join-path $officeKeyPath "ProductReleaseIDs\Active\$ProductId" $installedCultures = $regProv.EnumKey($HKLM, $productsPath) foreach ($installedCulture in $installedCultures.sNames) { if($installedCulture){ if ($installedCulture.Contains("-") -and !($installedCulture.ToLower() -eq "x-none")) { $addItem = $appLanguages1.Add($installedCulture) } } } if ($appLanguages1.Count) { $productsPath = join-path $officeKeyPath "ProductReleaseIDs\Active\$ProductId" } else { $productReleasePath = Join-Path $officeKeyPath "ProductReleaseIDs" $guids= $regProv.EnumKey($HKLM, $productReleasePath) foreach ($guid in $guids.sNames) { $productsPath = Join-Path $officeKeyPath "ProductReleaseIDs\$guid\$ProductId.16" $installedCultures = $regProv.EnumKey($HKLM, $productsPath) foreach ($installedCulture in $installedCultures.sNames) { if($installedCulture){ if ($installedCulture.Contains("-") -and !($installedCulture.ToLower() -eq "x-none")) { $addItem = $appLanguages1.Add($installedCulture) } } } if ($appLanguages1.Count) { $productsPath = Join-Path $officeKeyPath "ProductReleaseIDs\Culture\$ProductId" } } } return $appLanguages1; } } function msiGetOfficeUILanguage() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] $regProv = $NULL ) begin { $HKU = [UInt32] "0x80000003" } process { $computer = "." $msiUILanguages = @() $localUsers = $regProv.EnumKey($HKU, "") foreach ($localUser in $localUsers.sNames) { $regPathLangResource = "$localUser\SOFTWARE\Microsoft\Office\15.0\Common\LanguageResources" $UILanguage = $regProv.GetDWordValue($HKU, $regPathLangResource, "UILanguage").uValue if ($UILanguage) { $langCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $UILanguage} $convertLang = checkForLanguage -langId $langCulture.Name if ($convertLang) { $msiUILanguages += $convertLang } } } $primaryLanguage = ($msiUILanguages | Group-Object | Sort-Object Count -descending | Select-Object -First 1).Name return $primaryLanguage } } function msiGetOfficeLanguages() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] $regProv = $NULL ) begin { $HKU = [UInt32] "0x80000003" } process { $computer = "." $msiLanguages = @() if (!($regProv)) { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -ErrorAction Stop } $localUsers = $regProv.EnumKey($HKU, "") foreach ($localUser in $localUsers.sNames) { $regPathLangResource = "$localUser\SOFTWARE\Microsoft\Office\15.0\Common\LanguageResources" $regPathEnabledLangs = "$localUser\SOFTWARE\Microsoft\Office\15.0\Common\LanguageResources\EnabledLanguages" $UILanguageNum = $regProv.GetDWordValue($HKU, $regPathLangResource, "UILanguage").uValue if ($UILanguageNum) { $langCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $UILanguageNum} $UILanguage = checkForLanguage -langId $langCulture } else { $UILanguage = "" } $enabledLanguages = $regProv.EnumValues($HKU, $regPathEnabledLangs) foreach ($enabledLanguage in $enabledLanguages.sNames) { $languageStatus = $regProv.GetStringValue($HKU, $regPathEnabledLangs, $enabledLanguage).sValue if($languageStatus){ if ($languageStatus.ToLower() -eq "on") { $langCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $enabledLanguage} $convertLang = checkForLanguage -langId $langCulture if ($convertLang) { $flgInclude = $true if ($convertLang) { if ($UILanguage) { if ($UILanguage.ToLower() -eq $convertLang.ToLower()) { $flgInclude = $false } } if ($flgInclude) { $msiLanguages += $convertLang } } } } } } } $msiLanguages = $msiLanguages | Get-Unique if (!($msiLanguages)) { $msiLanguages = @() } return $msiLanguages } } function getLanguages() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] $regProv = $NULL ) $returnLangs = @() $HKU = [UInt32] "0x80000003" $userKeys = $regProv.EnumKey($HKU, ""); foreach ($userKey in $userKeys.sNames) { if ($userKey.Length -gt 8 -and !($userKey.ToLower().EndsWith("_classes"))) { [string]$userProfilePath = join-path $userKey "Control Panel\Internationalser Profile" [string[]]$userLanguages = $regProv.GetMultiStringValue($HKU, $userProfilePath, "Languages").sValue foreach ($userLang in $userLanguages) { if($userLang){ $convertLang = checkForLanguage -langId $userLang } if ($convertLang) { $returnLangs += $convertLang.ToLower() } } } } $langPacks = $regProv.EnumKey($HKLM, "SYSTEM\CurrentControlSet\Control\MUIILanguages"); foreach ($langPackName in $langPacks.sNames) { [bool]$addReturnLang = $true foreach ($returnLang in $returnLangs) { if ($returnLang.ToLower() -eq $langPackName.ToLower()) { $addReturnLang = $false } } if ($addReturnLang) { $returnLangs += $langPackName.ToLower() } } #HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MUIILanguages if ($returnLangs.Count -gt 1) { $returnLangs = Get-Unique -InputObject $returnLangs } $validLangs = @() foreach($lang in $returnlangs){ $langExists = $false foreach ($tmpLang in $availablelangs) { if ($tmpLang) { if ($lang) { if ($tmpLang.ToLower() -eq $lang.ToLower()) { $langExists = $true } } } } if($langExists){ $validLangs += $lang } } $returnLangs = $validLangs return $returnLangs } function checkForLanguage() { param( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$langId = $NULL ) [bool]$langExists = $false foreach ($availableLang in $availableLangs) { if ($availableLang.ToLower() -eq $langId.Trim().ToLower()) { $langExists = $true } } if ($langExists) { return $langId } else { $langStart = $langId.Split('-')[0] $checkLang = $NULL foreach ($availabeLang in $availableLangs) { if ($availabeLang.ToLower().StartsWith($langStart.ToLower())) { $checkLang = $availabeLang break; } } return $checkLang } } function officeGetExcludedApps() { param( [Parameter(ValueFromPipelineByPropertyName=$true, Position=0)] [PSObject[]]$OfficeProducts = $NULL, [string]$Credentials, [string]$computer = $env:COMPUTERNAME ) begin { $HKLM = [UInt32] "0x80000002" $HKCR = [UInt32] "0x80000000" $allExcludeApps = 'Access','Excel','InfoPath','Outlook','PowerPoint','Publisher','Word' if ($Credentials) { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -Credential $Credentials -ErrorAction Stop $os = Get-WMIObject win32_operatingsystem -computername $computer -Credential $Credentials -ErrorAction Stop } else { $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -computername $computer -ErrorAction Stop $os = Get-WMIObject win32_operatingsystem -computername $computer -ErrorAction Stop } } process{ $OfficeVersion = Get-OfficeVersion -ComputerName $computer if($OfficeVersion -ne $null){ $OfficeVersion = $OfficeVersion.Version.Split(".")[0] switch($os.OSArchitecture){ "32-bit" { $osBitness = '32' $appKeyPath = 'SOFTWARE\Microsoft\Office' } "64-bit" { $osBitness = '64' $appKeyPath = 'SOFTWARE\WOW6432Node\Microsoft\Office' } } switch($OfficeVersion){ "11" { $bitPath = '11.0' } "12" { $bitPath = '12.0' } "14" { $bitPath = '14.0' } "15" { $bitPath = '15.0' } "16" { $bitPath = '16.0' } } $appKeyPath = Join-Path $appKeyPath $bitPath $appKeys = $regProv.EnumKey($HKLM, $appKeyPath) $appList = $appKeys.sNames $appsToExclude = @() foreach($appName in $allExcludeApps){ [bool]$appInstalled = $false foreach ($OfficeProduct in $appList){ if($OfficeProduct.ToLower() -like $appName.ToLower()){ $appInstalled = $true break; } } if(!($appInstalled)){ $appsToExclude += $appName } } } return $appsToExclude; } } function officeGetLanguages() { param( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] $regProv = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$OfficeKeyPath = $NULL ) $HKLM = [UInt32] "0x80000002" $HKCR = [UInt32] "0x80000000" [string]$officeLangPath = join-path $OfficeKeyPath "Common\LanguageResources\InstalledUIs" [System.Collections.ArrayList] $returnLangs = New-Object System.Collections.ArrayList $langValues = $regProv.EnumValues($HKLM, $officeLangPath); foreach ($langValue in $langValues.sNames) { $langCulture = [globalization.cultureinfo]::GetCultures("allCultures") | where {$_.LCID -eq $langValue} $convertLang = checkForLanguage -langId $langCulture if ($convertLang) { $returnLangs.Add($convertLang.ToLower()) | Out-Null } } if ($returnLangs.Count -gt 1) { $returnLangs = $returnLangs | Get-Unique } return $returnLangs } function GetLanguagePacks { Param( [Parameter(ValueFromPipelineByPropertyName=$true)] $regProv = $NULL ) $HKLM = [UInt32] "0x80000002" $ComputerName = $env:COMPUTERNAME $installKeys = 'SOFTWARE\Microsoft\Windows\CurrentVersionninstall', 'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersionninstall' $defaultDisplaySet = 'DisplayName','LanguageID' $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet) $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet) $results = New-Object PSObject[] 0; if (!($regProv)) { $regProv = Get-Wmiobject -List "StdRegProv" -Namespace root\default -ComputerName $ComputerName -ErrorAction Stop } $LanguagePackProducts = @() $LanguageIDs = @() foreach($installKey in $installKeys){ $uninstallKeys = $regProv.EnumKey($HKLM, $installKey).sNames foreach($uninstallKey in $uninstallKeys){ $path = Join-Path $installKey $uninstallKey $DisplayName = $regProv.GetStringValue($HKLM, $path, "DisplayName").sValue if($DisplayName -match "Language Pack" -and $DisplayName -notmatch "Service Pack" ` -and $DisplayName -notmatch "Portable Library" ` -and $DisplayName -notmatch "Visual Studio" ` -and $DisplayName -notmatch "Foundation Server" ){ $languageId = $regProv.GetStringValue($HKLM, $path, "ShellUITransformLanguage").sValue $object = New-Object PSObject -Property @{DisplayName = $DisplayName; LanguageID = $languageId.ToLower()} $object | Add-Member MemberSet PSStandardMembers $PSStandardMembers $results += $object } } } return $results } function odtGetExcludedApps() { param( [Parameter(ValueFromPipelineByPropertyName=$true)] [System.XML.XMLDocument]$ConfigDoc = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$OfficeKeyPath = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$ProductId = $NULL ) begin { $HKLM = [UInt32] "0x80000002" $HKCR = [UInt32] "0x80000000" $allExcludeApps = 'Access','Excel','Groove','InfoPath','Lync','OneDrive','OneNote','Outlook', 'PowerPoint','Publisher','Word' #"SharePointDesigner","Visio", 'Project' } process { $configPath = join-path $officeKeyPath "Configuration" $appsToExclude = @() $keyValues = $regProv.EnumValues($HKLM, $configPath) foreach ($keyValue in $keyValues.sNames) { $checkValue = $ProductId + ".ExcludedApps" if ($keyValue.ToLower() -eq $checkValue.ToLower()) { $excludeApps = $regProv.GetStringValue($HKLM, $configPath, $checkValue).sValue $appSplit = $excludeApps.Split(','); foreach ($app in $appSplit){ $app = (Get-Culture).textinfo.totitlecase($app) $appsToExclude += $app } } } return $appsToExclude; } } function odtAddProduct() { param( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [System.XML.XMLDocument]$ConfigDoc = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$ProductId = $NULL, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [string]$Platform = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string]$ClientCulture = "en-us", [Parameter(ValueFromPipelineByPropertyName=$true)] [string[]]$AdditionalLanguages, [Parameter(ValueFromPipelineByPropertyName=$true)] [string[]] $ExcludeApps, [Parameter(ValueFromPipelineByPropertyName=$true)] [string]$Version = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string]$Channel = $NULL ) [System.XML.XMLElement]$ConfigElement=$NULL if($ConfigDoc.Configuration -eq $null){ $ConfigElement=$ConfigDoc.CreateElement("Configuration") $ConfigDoc.appendChild($ConfigElement) | Out-Null } [System.XML.XMLElement]$AddElement=$NULL if($ConfigFile.Configuration.Add -eq $null){ $AddElement=$ConfigDoc.CreateElement("Add") $ConfigDoc.DocumentElement.appendChild($AddElement) | Out-Null } else { $AddElement = $ConfigDoc.Configuration.Add } if ($Version) { if ($Version.StartsWith("16.")) { $AddElement.SetAttribute("Version", $Version) | Out-Null } } if ($Channel) { $AddElement.SetAttribute("Channel", $Channel) | Out-Null } if ($Platform) { $AddElement.SetAttribute("OfficeClientEdition", $Platform) | Out-Null } [System.XML.XMLElement]$ProductElement = $ConfigDoc.Configuration.Add.Product | where { $_.ID -eq $ProductId } if($ProductId){ if($ProductElement -eq $null){ [System.XML.XMLElement]$ProductElement=$ConfigDoc.CreateElement("Product") $AddElement.appendChild($ProductElement) | Out-Null $ProductElement.SetAttribute("ID", $ProductId) | Out-Null } } $LanguageIds = @($ClientCulture) foreach ($addLang in $AdditionalLanguages) { $LanguageIds += $addLang } foreach($LanguageId in $LanguageIds){ if ($LanguageId) { if ($LanguageId.Length -gt 0) { [System.XML.XMLElement]$LanguageElement = $ProductElement.Language | where { $_.ID -eq $LanguageId } if($LanguageElement -eq $null){ [System.XML.XMLElement]$LanguageElement=$ConfigFile.CreateElement("Language") $ProductElement.appendChild($LanguageElement) | Out-Null $LanguageElement.SetAttribute("ID", $LanguageId.ToString().ToLower()) | Out-Null } } } } foreach($ExcludeApp in $ExcludeApps){ if($ExcludeApp){ [System.XML.XMLElement]$ExcludeAppElement = $ProductElement.ExcludeApp | where { $_.ID -eq $ExcludeApp } if($ExcludeAppElement -eq $null){ [System.XML.XMLElement]$ExcludeAppElement=$ConfigDoc.CreateElement("ExcludeApp") $ProductElement.appendChild($ExcludeAppElement) | Out-Null $ExcludeAppElement.SetAttribute("ID", $ExcludeApp) | Out-Null } } } } function odtAddUpdates{ [CmdletBinding()] Param( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [System.XML.XMLDocument]$ConfigDoc = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $Enabled, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $UpdatePath, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $TargetVersion, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $Deadline ) Process{ #Check to make sure the correct root element exists if($ConfigDoc.Configuration -eq $null){ #write log $lineNum = Get-CurrentLineNumber $filName = Get-CurrentFileName WriteToLogFile -LNumber $lineNum -FName $filName -ActionError "no configuration element" throw $NoConfigurationElement } [bool]$addUpdates = $false $hasEnabled = $false if($Enabled){$hasEnabled = $true}else{$hasEnabled = $false} $hasUpdatePath = $false if($UpdatePath){$hasUpdatePath = $true}else{$hasUpdatePath = $false} if(($hasEnabled -eq $true) -or ($hasUpdatePath -eq $true)){ $addUpdates = $true } if ($addUpdates) { #Get the Updates Element if it exists [System.XML.XMLElement]$UpdateElement = $ConfigDoc.Configuration.GetElementsByTagName("Updates").Item(0) if($ConfigDoc.Configuration.Updates -eq $null){ [System.XML.XMLElement]$UpdateElement=$ConfigDoc.CreateElement("Updates") $ConfigDoc.Configuration.appendChild($UpdateElement) | Out-Null } #Set the desired values if($Enabled){ $UpdateElement.SetAttribute("Enabled", $Enabled.ToString().ToUpper()) | Out-Null } else { if ($PSBoundParameters.ContainsKey('Enabled')) { if ($ConfigDoc.Configuration.Updates) { $ConfigDoc.Configuration.Updates.RemoveAttribute("Enabled") } } } if($UpdatePath){ $UpdateElement.SetAttribute("UpdatePath", $UpdatePath) | Out-Null } else { if ($PSBoundParameters.ContainsKey('UpdatePath')) { if ($ConfigDoc.Configuration.Updates) { $ConfigDoc.Configuration.Updates.RemoveAttribute("UpdatePath") } } } if($TargetVersion){ $UpdateElement.SetAttribute("TargetVersion", $TargetVersion) | Out-Null } else { if ($PSBoundParameters.ContainsKey('TargetVersion')) { if ($ConfigDoc.Configuration.Updates) { $ConfigDoc.Configuration.Updates.RemoveAttribute("TargetVersion") } } } if($Deadline){ $UpdateElement.SetAttribute("Deadline", $Deadline) | Out-Null } else { if ($PSBoundParameters.ContainsKey('Deadline')) { if ($ConfigDoc.Configuration.Updates) { $ConfigDoc.Configuration.Updates.RemoveAttribute("Deadline") } } } } } } Function odtSetAdd{ Param( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)] [System.XML.XMLDocument]$ConfigDoc = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $SourcePath = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $DownloadPath = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $Version, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $Bitness ) Process{ #Check for proper root element if($ConfigDoc.Configuration -eq $null){ #write log $lineNum = Get-CurrentLineNumber $filName = Get-CurrentFileName WriteToLogFile -LNumber $lineNum -FName $filName -ActionError "no configuration element" throw $NoConfigurationElement } #Get Add element if it exists if($ConfigDoc.Configuration.Add -eq $null){ [System.XML.XMLElement]$AddElement=$ConfigFile.CreateElement("Add") $ConfigDoc.Configuration.appendChild($AddElement) | Out-Null } #Set values as desired if($SourcePath){ $ConfigFile.Configuration.Add.SetAttribute("SourcePath", $SourcePath) | Out-Null } else { if ($PSBoundParameters.ContainsKey('SourcePath')) { $ConfigDoc.Configuration.Add.RemoveAttribute("SourcePath") } } if($DownloadPath){ $ConfigFile.Configuration.Add.SetAttribute("DownloadPath", $DownloadPath) | Out-Null } else { if ($PSBoundParameters.ContainsKey('DownloadPath')) { $ConfigDoc.Configuration.Add.RemoveAttribute("DownloadPath") } } if($Version){ $ConfigDoc.Configuration.Add.SetAttribute("Version", $Version) | Out-Null } else { if ($PSBoundParameters.ContainsKey('Version')) { $ConfigDoc.Configuration.Add.RemoveAttribute("Version") } } if($Bitness){ $ConfigDoc.Configuration.Add.SetAttribute("OfficeClientEdition", $Bitness) | Out-Null } else { if ($PSBoundParameters.ContainsKey('OfficeClientEdition')) { $ConfigDoc.Configuration.Add.RemoveAttribute("OfficeClientEdition") } } } } Function Set-ODTConfigProperties{ <# .SYNOPSIS Modifies an existing configuration xml file to set property values .PARAMETER AutoActivate If AUTOACTIVATE is set to 1, the specified products will attempt to activate automatically. If AUTOACTIVATE is not set, the user may see the Activation Wizard UI. You must not set AUTOACTIVATE for Office 365 Click-to-Run products. .PARAMETER ForceAppShutDown An installation or removal action may be blocked if Office applications are running. Normally, such cases would start a process killer UI. Administrators can set FORCEAPPSHUTDOWN value to TRUE to prevent dependence on user interaction. When FORCEAPPSHUTDOWN is set to TRUE, any applications that block the action will be shut down. Data loss may occur. When FORCEAPPSHUTDOWN is set to FALSE (default), the action may fail if Office applications are running. .PARAMETER PackageGUID Optional. By default, all Office 2013 App-V packages created by using the Office Deployment Tool share the same App-V Package ID. Administrators can use PACKAGEGUID to specify a different Package ID. Also, PACKAGEGUID needs to be at least 25 characters in length and be separated into 5 sections, with each section separated by a dash. The sections need to have the following number of characters: 8, 4, 4, 4, and 12. .PARAMETER SharedComputerLicensing Optional. Set SharedComputerLicensing to 1 if you deploy Office 365 ProPlus to shared computers by using Remote Desktop Services. .PARAMETER TargetFilePath Full file path for the file to be modified and be output to. .PARAMETER PinIconsToTaskbar Optional. Set PinIconsToTaskbar to $true to pin icons to taskbar and $false to not. Does not apply to Windows 10 .Example Set-ODTConfigProperties -AutoActivate "1" -TargetFilePath "$env:Public/Documents/config.xml" Sets config to automatically activate the products .Example Set-ODTConfigProperties -ForceAppShutDown "True" -PackageGUID "12345678-ABCD-1234-ABCD-1234567890AB" -TargetFilePath "$env:Public/Documents/config.xml" Sets the config so that apps are forced to shutdown during install and the package guid to "12345678-ABCD-1234-ABCD-1234567890AB" .Notes Here is what the portion of configuration file looks like when modified by this function: ... ... #> [CmdletBinding()] Param( [Parameter(ValueFromPipelineByPropertyName=$true)] [System.XML.XMLDocument]$ConfigDoc = $NULL, [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)] [string] $ConfigurationXML = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [System.Nullable[bool]] $AutoActivate, [Parameter(ValueFromPipelineByPropertyName=$true)] [System.Nullable[bool]] $ForceAppShutDown, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $PackageGUID = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [System.Nullable[bool]] $SharedComputerLicensing = $NULL, [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $TargetFilePath, [Parameter(ValueFromPipelineByPropertyName=$true)] [System.Nullable[bool]] $PinIconsToTaskbar = $NULL, [Parameter()] [string]$LogFilePath ) Process{ Set-Alias -name LINENUM -value Get-CurrentLineNumber $currentFileName = Get-CurrentFileName #Load file if($ConfigDoc){ [System.XML.XMLDocument]$ConfigFile = $ConfigDoc } else { [System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument } if($TargetFilePath){ $ConfigFile.Load($TargetFilePath) | Out-Null } else { if($ConfigurationXml){ $ConfigFile.LoadXml($ConfigurationXml) | Out-Null $global:saveLastConfigFile = $NULL $global:saveLastFilePath = $NULL } } $global:saveLastConfigFile = $ConfigFile.OuterXml #Check for proper root element if($ConfigFile.Configuration -eq $null){ throw $NoConfigurationElement } #Set each property as desired if($AutoActivate -ne $NULL){ [System.XML.XMLElement]$AutoActivateElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "AUTOACTIVATE" } if($AutoActivateElement -eq $null){ [System.XML.XMLElement]$AutoActivateElement=$ConfigFile.CreateElement("Property") WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "The Property element has been created" -LogFilePath $LogFilePath } $ConfigFile.Configuration.appendChild($AutoActivateElement) | Out-Null $AutoActivateElement.SetAttribute("Name", "AUTOACTIVATE") | Out-Null $AutoActivateElement.SetAttribute("Value", $AutoActivate.ToString().ToUpper()) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Setting the AUTOACTIVATE element to $AutoActivate.ToString().ToUpper()" -LogFilePath $LogFilePath } Else { [System.XML.XMLElement]$AutoActivateElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "AUTOACTIVATE" } if($AutoActivateElement -ne $null){ if ($PSBoundParameters.ContainsKey('AUTOACTIVATE')) { $ConfigFile.Configuration.removeChild($AutoActivateElement) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removed the AUTOACTIVATE element" -LogFilePath $LogFilePath } } } if($ForceAppShutDown -ne $NULL){ [System.XML.XMLElement]$ForceAppShutDownElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "FORCEAPPSHUTDOWN" } if($ForceAppShutDownElement -eq $null){ [System.XML.XMLElement]$ForceAppShutDownElement=$ConfigFile.CreateElement("Property") WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "The Property element has been created" -LogFilePath $LogFilePath } $ConfigFile.Configuration.appendChild($ForceAppShutDownElement) | Out-Null $ForceAppShutDownElement.SetAttribute("Name", "FORCEAPPSHUTDOWN") | Out-Null $ForceAppShutDownElement.SetAttribute("Value", $ForceAppShutDown.ToString().ToUpper()) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Setting the FORCEAPPSHUTDOWN element to $ForceAppShutDown.ToString().ToUpper()" -LogFilePath $LogFilePath } Else { [System.XML.XMLElement]$ForceAppShutDownElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "FORCEAPPSHUTDOWN" } if($ForceAppShutDownElement -ne $null){ if ($PSBoundParameters.ContainsKey('FORCEAPPSHUTDOWN')) { $ConfigFile.Configuration.removeChild($ForceAppShutDownElement) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removed the FORCEAPPSHUTDOWN element" -LogFilePath $LogFilePath } } } if($PackageGUID){ [System.XML.XMLElement]$PackageGUIDElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "PACKAGEGUID" } if($PackageGUIDElement -eq $null){ [System.XML.XMLElement]$PackageGUIDElement=$ConfigFile.CreateElement("Property") WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "The Property element has been created" -LogFilePath $LogFilePath } $ConfigFile.Configuration.appendChild($PackageGUIDElement) | Out-Null $PackageGUIDElement.SetAttribute("Name", "PACKAGEGUID") | Out-Null $PackageGUIDElement.SetAttribute("Value", $PackageGUID) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Setting the PACKAGEGUID element to $PackageGUID" -LogFilePath $LogFilePath } Else { [System.XML.XMLElement]$PackageGUIDElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "PACKAGEGUID" } if($PackageGUIDElement -ne $null){ if ($PSBoundParameters.ContainsKey('PACKAGEGUID')) { $ConfigFile.Configuration.removeChild($PackageGUIDElement) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removed the PACKAGEGUID element" -LogFilePath $LogFilePath } } } if($SharedComputerLicensing -eq $true){ [System.XML.XMLElement]$SharedComputerLicensingElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "SharedComputerLicensing" } if($SharedComputerLicensingElement -eq $null){ [System.XML.XMLElement]$SharedComputerLicensingElement=$ConfigFile.CreateElement("Property") WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "The Property element has been created" -LogFilePath $LogFilePath } $ConfigFile.Configuration.appendChild($SharedComputerLicensingElement) | Out-Null $SharedComputerLicensingElement.SetAttribute("Name", "SharedComputerLicensing") | Out-Null $SharedComputerLicensingElement.SetAttribute("Value", "1") | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Setting the SharedComputerLicensing element to $SharedComputerLicensing.ToString().ToUpper()" -LogFilePath $LogFilePath } Else { [System.XML.XMLElement]$SharedComputerLicensingElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "SharedComputerLicensing" } if($SharedComputerLicensingElement -ne $null){ if ($PSBoundParameters.ContainsKey('SharedComputerLicensing')) { $ConfigFile.Configuration.removeChild($SharedComputerLicensingElement) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removed the SharedComputerLicensing element" -LogFilePath $LogFilePath } } } if ($PinIconsToTaskbar -ne $NULL) { [System.XML.XMLElement]$PinIconsToTaskbarElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "PinIconsToTaskbar" } if($PinIconsToTaskbarElement -eq $null){ [System.XML.XMLElement]$PinIconsToTaskbarElement=$ConfigFile.CreateElement("Property") WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "The Property element has been created" -LogFilePath $LogFilePath } $ConfigFile.Configuration.appendChild($PinIconsToTaskbarElement) | Out-Null $PinIconsToTaskbarElement.SetAttribute("Name", "PinIconsToTaskbar") | Out-Null $PinIconsToTaskbarElement.SetAttribute("Value", $PinIconsToTaskbar.ToString().ToUpper()) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Setting the PinIconsToTaskbar element to $PinIconsToTaskbar.ToString().ToUpper()" -LogFilePath $LogFilePath } Else { [System.XML.XMLElement]$PinIconsToTaskbarElement = $ConfigFile.Configuration.Property | Where { $_.Name -eq "PinIconsToTaskbar" } if($PinIconsToTaskbarElement -ne $null){ if ($PSBoundParameters.ContainsKey('PinIconsToTaskbar')) { $ConfigFile.Configuration.removeChild($PinIconsToTaskbarElement) | Out-Null WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removed the PinIconsToTaskbar element" -LogFilePath $LogFilePath } } } if($TargetFilePath){ $ConfigFile.Save($TargetFilePath) | Out-Null $global:saveLastFilePath = $TargetFilePath if (($PSCmdlet.MyInvocation.PipelineLength -eq 1) -or ` ($PSCmdlet.MyInvocation.PipelineLength -eq $PSCmdlet.MyInvocation.PipelinePosition)) { Write-Host Format-XML ([xml](cat $TargetFilePath)) -indent 4 Write-Host Write-Host "The Office XML Configuration file has been saved to: $TargetFilePath" WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "The Office XML Configuration file has been saved to: $TargetFilePath" -LogFilePath $LogFilePath } else { $results = new-object PSObject[] 0; $Result = New-Object –TypeName PSObject Add-Member -InputObject $Result -MemberType NoteProperty -Name "TargetFilePath" -Value $TargetFilePath Add-Member -InputObject $Result -MemberType NoteProperty -Name "SharedComputerLicensing" -Value $SharedComputerLicensing Add-Member -InputObject $Result -MemberType NoteProperty -Name "PackageGUID" -Value $PackageGUID Add-Member -InputObject $Result -MemberType NoteProperty -Name "ForceAppShutDown" -Value $ForceAppShutDown Add-Member -InputObject $Result -MemberType NoteProperty -Name "AutoActivate" -Value $AutoActivate $Result } } } } Function GetFilePath() { Param( [Parameter(ValueFromPipelineByPropertyName=$true)] [string] $TargetFilePath ) if (!($TargetFilePath)) { $TargetFilePath = $global:saveLastFilePath } if (!($TargetFilePath)) { Write-Host "Enter the path to the XML Configuration File: " -NoNewline $TargetFilePath = Read-Host } else { #Write-Host "Target XML Configuration File: $TargetFilePath" } return $TargetFilePath } Function GetScriptPath() { process { [string]$scriptPath = "." if ($PSScriptRoot) { $scriptPath = $PSScriptRoot } else { $scriptPath = (Get-Item -Path ".\").FullName } return $scriptPath } } function Format-XML ([xml]$xml, $indent=2) { $StringWriter = New-Object System.IO.StringWriter $XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter $xmlWriter.Formatting = "indented" $xmlWriter.Indentation = $Indent $xml.WriteContentTo($XmlWriter) $XmlWriter.Flush() $StringWriter.Flush() Write-Output $StringWriter.ToString() } function Win7Join([string]$st1, [string]$st2){ [string]$tempStr = $st1 + "\" + $st2 return $tempStr } function Detect-Channel { param( [Parameter()] [string]$LogFilePath ) Process { $currentFileName = Get-CurrentFileName Set-Alias -name LINENUM -value Get-CurrentLineNumber $channelXml = Get-ChannelXml $UpdateChannel = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration -Name UpdateChannel -ErrorAction SilentlyContinue).UpdateChannel $GPOUpdatePath = (Get-ItemProperty HKLM:\SOFTWARE\Policies\Microsoft\office\16.0