Uninstall & Re-Install O365

Open an Admin Powershell Window (win Key + X, Press "A")

Paste the Following:

 

 

Get-AppxPackage -name “Microsoft.Office.Desktop” | Remove-AppxPackage

Install-Module MSOnline

 

 

try {

Add-Type  -ErrorAction SilentlyContinue -TypeDefinition @"

   public enum OfficeCTRVersion

   {

      Office2013,

      Office2016

   }

"@

} catch {}

 

try {

$enum = "

using System;

 

namespace Microsoft.Office

{

     [FlagsAttribute]

     public enum Products

     {

         Unknown = 0,

         O365ProPlusRetail = 1,

         O365BusinessRetail = 2,

         VisioProRetail = 4,

         ProjectProRetail = 8,

         SPDRetail = 16,

         VisioProXVolume = 32,

         VisioStdXVolume = 64,

         ProjectProXVolume = 128,

         ProjectStdXVolume = 256,

         InfoPathRetail = 512,

         SkypeforBusinessEntryRetail = 1024,

         LyncEntryRetail = 2048,

     }

}

"

Add-Type -TypeDefinition $enum -ErrorAction SilentlyContinue

} catch {}

 

try {

$enum2 = "

using System;

 

    [FlagsAttribute]

    public enum LogLevel

    {

        None=0,

        Full=1

    }

"

Add-Type -TypeDefinition $enum2 -ErrorAction SilentlyContinue

} catch {}

 

try {

Add-Type  -ErrorAction SilentlyContinue -TypeDefinition @"

   public enum PinAction

   {

      PinToStartMenu,

      PinToTaskbar,

      UnpinFromStartMenu,

      UnpinFromTaskbar

   }

"@

} catch {}

 

function Install-OfficeClickToRun {

<#

.SYNOPSIS

    Installs Office Click-To-Run

.DESCRIPTION

    Installs Office Click-To-Run using a specified configuration file or targetfilepath.

.PARAMETER ConfigurationXML

    The path to a pre-configured configuration.xml file used for installation.

.PARAMETER TargetFilePath

    If no ConfigurationXML is specified, this is the path where the generated configuration.xml will be saved.

.PARAMETER PinToStart 

    If $true, all Office apps will be pinned to the Start Menu in Windows 10.

.PARAMETER OfficeVersion

    The version of Office Click-To-Run to install. Available options are Office2013 and Office2016. 

.PARAMETER WaitForInstallToFinish

    If $true, the PowerShell console will remain open and provide status updates until Office is finished installing.

.PARAMETER PinToStartMenu

    Choose one or multiple Office applications to pin to the Start Menu after the installation is finished. 

.PARAMETER PinToTaskbar

    Choose one or multiple Office applications to pin to the Taskbar after the installation is finished. Pinning applications

    to the Taskbar in Windows 10 is not natively supported.

.EXAMPLE

    Install-OfficeClickToRun -ConfigurationXML C:\OfficeDeployment\configuration.xml

    Office 2016 Click-To-Run will be installed using the settings in the specified configuration.xml.

.EXAMPLE

    Install-OfficeClickToRun -TargetFilePath $env:temp\configuration.xml

    Office 2016 Click-To-Run will be installed using an auto-generated configuration file that will be saved to the temp directory.

.EXAMPLE

    Install-OfficeClickToRun -TargetFilePath $env:temp\configuration.xml -PinToStartMenu Word,Excel,Outlook -WaitForInstallToFinish $false

    

    Office 2016 Click-To-Run will be installed using an auto-generated configuration file that will be saved to the temp directory. Microsoft

    Word, Excel, and Outlook will be pinned to the Start Menu. The PowerShell console will not provide status updates of the installation.

#>

    [CmdletBinding()]

    Param(

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        [string] $ConfigurationXML = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string] $TargetFilePath = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [OfficeCTRVersion] $OfficeVersion = "Office2016",

 

        [Parameter()]

        [bool] $WaitForInstallToFinish = $true,

 

        [Parameter()]

        [ValidateSet("AllOfficeApps","None","Word","Excel","PowerPoint","OneNote","Access","Publisher","Outlook","Skype for Business",

                     "OneDrive for Business","Project","Visio")]

        [string[]]$PinToStartMenu,

 

        [Parameter()]

        [ValidateSet("AllOfficeApps","None","Word","Excel","PowerPoint","OneNote","Access","Publisher","Outlook","Skype for Business",

                     "OneDrive for Business","Project","Visio")]

        [string[]]$PinToTaskbar,

 

        [Parameter()]

        [bool]$InstallProofingTools = $false,

 

        [Parameter()]

        [string]$LogFilePath

 

    )

   

    Set-Alias -name LINENUM -value Get-CurrentLineNumber

    $currentFileName = Get-CurrentFileName

 

    $scriptRoot = GetScriptRoot

 

    #Load the file

    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Loading the configuration xml file..." -LogFilePath $LogFilePath

    [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

            $TargetFilePath = $NULL

        }

    }

 

    [string]$officeCtrPath = ""

 

    if ($OfficeVersion -eq "Office2013") {

        $officeCtrPath = Join-Path $scriptRoot "Office2013Setup.exe"

        if (!(Test-Path -Path $officeCtrPath)) {

           WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Cannot find the Office 2013 Setup executable" -LogFilePath $LogFilePath

           throw "Cannot find the Office 2013 Setup executable"

        }

    }

 

    if ($OfficeVersion -eq "Office2016") {

        $officeCtrPath = $scriptRoot + "\Office2016Setup.exe"

        if (!(Test-Path -Path $officeCtrPath)) {

           WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Cannot find the Office 2016 Setup executable" -LogFilePath $LogFilePath

           throw "Cannot find the Office 2016 Setup executable"

        }

    }

    

    if (!($TargetFilePath)) {

      if ($ConfigurationXML) {

         $TargetFilePath = $scriptRoot + "\configuration.xml"

         New-Item -Path $TargetFilePath -ItemType "File" -Value $ConfigurationXML -Force | Out-Null

      }

    }

    

    if (!(Test-Path -Path $TargetFilePath)) {

       $TargetFilePath = $scriptRoot + "\configuration.xml"

    }

    

    $products = Get-ODTProductToAdd -TargetFilePath $TargetFilePath 

    $addNode = Get-ODTAdd -TargetFilePath $TargetFilePath 

 

    $sourcePath = $addNode.SourcePath

    $version = $addNode.Version

    $edition = $addNode.OfficeClientEdition

 

    foreach ($product in $products)

    {

        if ($product) {

          $languages = getProductLanguages -Product $product 

          $existingLangs = checkForLanguagesInSourceFiles -Languages $languages -SourcePath $sourcePath -Version $version -Edition $edition

          if ($product.ProductId) {

              Set-ODTProductToAdd -TargetFilePath $TargetFilePath -ProductId $product.ProductId -LanguageIds $existingLangs -LogFilePath $LogFilePath | Out-Null

          }

        }

    }

 

    $localPath = "$env:TEMP\setup.exe"

 

    Copy-Item -Path $officeCtrPath -Destination $localPath -Force

 

    $cmdLine = $localPath

    $cmdArgs = "/configure " + '"' + $TargetFilePath + '"'

 

    Write-Host "Installing Office Click-To-Run..."

    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Installing Office 365 ProPlus..." -LogFilePath $LogFilePath

 

    if ($WaitForInstallToFinish) {

        StartProcess -execFilePath $cmdLine -execParams $cmdArgs -WaitForExit $false

 

        Start-Sleep -Seconds 5

 

        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Waiting for Office to finish installing..." -LogFilePath $LogFilePath

        Wait-ForOfficeCTRInstall -OfficeVersion $OfficeVersion -LogFilePath $LogFilePath

    }else {

        StartProcess -execFilePath $cmdLine -execParams $cmdArgs -WaitForExit $true

    }

  

    if(($PinToStartMenu) -or ($PinToTaskbar)){

        Write-Host ""

 

        $ClickToRun = Get-OfficeVersion

        if($ClickToRun.GetType().Name -eq "Object[]"){

            $C2RVersion = $ClickToRun[0]

        } else {

            $C2RVersion = $ClickToRun

        }

            

        $ClickToRun = $true

        $InstallPath = $C2RVersion.InstallPath

        $officeVersionInt = $C2RVersion.Version.Split('.')[0]

      

        if($PinToStartMenu){

            if($PinToStartMenu -eq 'AllOfficeApps'){

                $OfficeAppPinnedStatus = GetOfficeAppVerbStatus

            } else {

                if($PinToStartMenu -ne "None"){

                    $OfficeAppPinnedStatus = GetOfficeAppVerbStatus -OfficeApps $PinToStartMenu

                }

            }

            

            if($OfficeAppPinnedStatus -ne $NULL){

                foreach($app in $OfficeAppPinnedStatus){

                    if($app.PinToStartMenuAvailable -eq $true){

                        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Pinning $app.name to the Start Menu" -LogFilePath $LogFilePath

                        Set-OfficePinnedApplication -Action PinToStartMenu -OfficeApps $app.Name -ClickToRun $ClickToRun -InstallPath $InstallPath -OfficeVersion $officeVersionInt -LogFilePath $LogFilePath

                    }   

                }

            }   

            

            $allPinnedApps = GetOfficeAppVerbStatus

 

            if($PinToStartMenu -ne 'AllOfficeApps'){

                foreach($app in $allPinnedApps){

                    if($PinToStartMenu -notcontains $app.Name){

                        if($app.PinToStartMenuAvailable -eq $false){

                            WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removing $app.name from the Start Menu" -LogFilePath $LogFilePath

                            Set-OfficePinnedApplication -Action UnpinFromStartMenu -OfficeApps $app.Name -ClickToRun $ClickToRun -InstallPath $InstallPath -OfficeVersion $officeVersionInt -LogFilePath $LogFilePath

                        }  

                    }

                } 

            }       

        } else {

            if([Environment]::OSVersion.Version.Major -ge 10){

                $OfficeAppPinnedStatus = GetOfficeAppVerbStatus | ? {$_.PinToStartMenuAvailable -eq $true}

                foreach($app in $PinnedStartMenuApps){

                    if($OfficeAppPinnedStatus.Name -contains $app.Name){

                        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Pinning $app.name to the Start Menu" -LogFilePath $LogFilePath -LogFilePath $LogFilePath

                        Set-OfficePinnedApplication -Action PinToStartMenu -OfficeApps $app.Name -ClickToRun $ClickToRun -InstallPath $InstallPath -OfficeVersion $officeVersionInt -LogFilePath $LogFilePath

                    }

                }   

            }

        }

 

        if(($PinToTaskbar) -and ([Environment]::OSVersion.Version.Major -lt 10)){

            if($PinToTaskbar -eq 'AllOfficeApps'){

                $OfficeAppPinnedStatus = GetOfficeAppVerbStatus

            } else {

                $OfficeAppPinnedStatus = GetOfficeAppVerbStatus -OfficeApps $PinToTaskbar

            }    

            

            foreach($app in $OfficeAppPinnedStatus){

                if($app.PinToTaskbarAvailable -eq $true){

                    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Pinning $app.name to the Taskbar" -LogFilePath $LogFilePath

                    Set-OfficePinnedApplication -Action PinToTaskbar -OfficeApps $app.Name -ClickToRun $ClickToRun -InstallPath $InstallPath -OfficeVersion $officeVersionInt -LogFilePath $LogFilePath

                    $pinnedApp += $app.Name

                }     

            }

            

            $allPinnedApps = GetOfficeAppVerbStatus

 

            if($PinToTaskbar -ne 'AllOfficeApps'){

                foreach($app in $allPinnedApps){

                    if($PinToTaskbar -notcontains $app.Name){

                        if($app.PinToTaskbarAvailable -eq $false){

                            WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removing $app.name from the Taskbar" -LogFilePath $LogFilePath

                            Set-OfficePinnedApplication -Action UnpinFromTaskbar -OfficeApps $app.Name -ClickToRun $ClickToRun -InstallPath $InstallPath -OfficeVersion $officeVersionInt -LogFilePath $LogFilePath

                        }  

                    }

                } 

            }             

        } else {

            if([Environment]::OSVersion.Version.Major -ge 10){

                $OfficeAppPinnedStatus = GetOfficeAppVerbStatus | ? {$_.PinToTaskbarAvailable -eq $true}

                foreach($app in $PinnedTaskbarApps){

                    if($OfficeAppPinnedStatus.Name -contains $app.Name){

                        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Pinning $app.name to the Taskbar" -LogFilePath $LogFilePath

                        Set-OfficePinnedApplication -Action PinToTaskbar -OfficeApps $app.Name -ClickToRun $ClickToRun -InstallPath $InstallPath -OfficeVersion $officeVersionInt -LogFilePath $LogFilePath

                    }

                }

            }

        }

    }

    

    if($InstallProofingTools -eq $true){

        Write-Host ""

        Write-Host "Installing Proofing Tools..."

        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Installing Proofing Tools..." -LogFilePath $LogFilePath

 

        if((Get-OfficeVersion).Bitness -eq "32-bit"){

            $proofingToolFileName = "proofingtools2016_en-us-x86.exe"

        } else {

            $proofingToolFileName = "proofingtools2016_en-us-x64.exe"

        }

 

        $clientCulture = (Get-OfficeVersion).ClientCulture

        $proofingLangLCID = ([globalization.cultureinfo]::GetCultures("allCultures") | where {$_.Name.ToLower() -match $clientCulture}).LCID

 

        $commandArgs = "/lang:$proofingLangLCID /quiet /passive /norestart"

 

        Start-Process -FilePath .\$proofingToolFileName -ArgumentList $commandArgs

          

     }    

}

 

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\CurrentVersion\Uninstall',

                   'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'

 

    $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 checkForLanguagesInSourceFiles() {

    [CmdletBinding()]

    Param(

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        $Languages = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string]$SourcePath = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string]$Version = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string]$Edition = $NULL

    )

 

    $scriptRoot = GetScriptRoot

 

    $returnLanguages = @()

 

    if (!($SourcePath)) {

      $localSource = $scriptRoot + "\Office\Data"

      if (Test-Path -Path $localSource) {

         $SourcePath = $scriptRoot

      }

    }

 

    if (!($Version)) {

       $localPath = $env:TEMP

       $cabPath = $scriptRoot + "\Office\Data\v$Edition.cab"

       $cabFolderPath = $scriptRoot + "\Office\Data"

       $vdXmlPath = $localPath + "\VersionDescriptor.xml"

       

       if (Test-Path -Path $cabPath) {

          Invoke-Expression -Command "Expand $cabPath -F:VersionDescriptor.xml $localPath" | Out-Null

          $Version = getVersionFromVersionDescriptor -vesionDescriptorPath $vdXmlPath

          Remove-Item -Path $vdXmlPath -Force

       }

    }

 

    $verionDir = $scriptRoot + "\Office\Data\$Version"

    

    if (Test-Path -Path $verionDir) {

       foreach ($lang in $Languages) {

          $fileName = "stream.x86.$lang.dat"

          if ($Edition -eq "64") {

             $fileName = "stream.x64.$lang.dat"

          }

          

          $langFile = $verionDir + "\" + $fileName 

          

          if (Test-Path -Path $langFile) {

             $returnLanguages += $lang

          }

       }

    }

 

    return $returnLanguages

}

 

Function getVersionFromVersionDescriptor() {

    [CmdletBinding()]

    Param(

        [Parameter(Mandatory=$true)]

        [string] $vesionDescriptorPath = $NULL

    )

 

    [System.XML.XMLDocument]$doc = New-Object System.XML.XMLDocument

 

    if ($vesionDescriptorPath) {

        $doc.Load($vesionDescriptorPath) | Out-Null

        return $doc.DocumentElement.Available.Build

    }

}

 

Function getProductLanguages() {

    [CmdletBinding()]

    Param(

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        $Product = $NULL

    )

 

    $languages = @()

 

    foreach ($language in $Product.Languages)

    {

      if (!($languages -contains ($language))) {

          $languages += $language

      }

    }

 

    return $languages

}

 

Function getUniqueLanguages() {

    [CmdletBinding()]

    Param(

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        $Products = $NULL

    )

 

    $languages = @()

    foreach ($product in $Products)

    {

       foreach ($language in $product.Languages)

       {

          if (!($languages -contains $language)) {

            $languages += $language

          }

       }

    }

 

    return $languages

}

 

Function Get-ODTProductToAdd{

<#

.SYNOPSIS

    Gets list of Products and the corresponding language and exlcudeapp values

    from the specified configuration file

.PARAMETER All

    Switch to return All Products

.PARAMETER ProductId

    Id of Product that you want to pull from the configuration file

.PARAMETER TargetFilePath

    Required. Full file path for the file.

.Example

    Get-ODTProductToAdd -All -TargetFilePath "$env:Public\Documents\config.xml"

    Returns all Products and their corresponding Language and Exclude values

    if they have them 

.Example

    Get-ODTProductToAdd -ProductId "O365ProPlusRetail" -TargetFilePath "$env:Public\Documents\config.xml"

    Returns the Product with the O365ProPlusRetail Id and its corresponding

    Language and Exclude values

#>

    [CmdletBinding()]

    Param(

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        [string] $ConfigurationXML = $NULL,

 

        [Microsoft.Office.Products] $ProductId = "Unknown",

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string] $TargetFilePath,

 

        [Parameter(ParameterSetName="All")]

        [switch] $All

    )

 

    Process{

        $TargetFilePath = GetFilePath -TargetFilePath $TargetFilePath

 

        #Load the file

        [System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument

 

        if ($TargetFilePath) {

           $content = Get-Content $TargetFilePath

           $ConfigFile.LoadXml($content) | Out-Null

        } else {

            if ($ConfigurationXml) 

            {

              $ConfigFile.LoadXml($ConfigurationXml) | Out-Null

              $global:saveLastConfigFile = $NULL

              $global:saveLastFilePath = $NULL

            }

        }

 

        #Check that the file is properly formatted

        if($ConfigFile.Configuration -eq $null){

            throw $NoConfigurationElement

        }

 

        if($ConfigFile.Configuration.Add -eq $null){

            throw $NoAddElement

        }

 

        if($PSCmdlet.ParameterSetName -eq "All"){

            foreach($ProductElement in $ConfigFile.Configuration.Add.Product){

                $Result = New-Object -TypeName PSObject 

 

                Add-Member -InputObject $Result -MemberType NoteProperty -Name "ProductId" -Value ($ProductElement.GetAttribute("ID"))

 

                if($ProductElement.Language -ne $null){

                    $ProductLangs = $configfile.Configuration.Add.Product.Language | % {$_.ID}

                    Add-Member -InputObject $Result -MemberType NoteProperty -Name "Languages" -Value $ProductLangs

                }

 

                if($ProductElement.ExcludeApp -ne $null){

                    $ProductExlApps = $configfile.Configuration.Add.Product.ExcludeApp | % {$_.ID}

                    Add-Member -InputObject $Result -MemberType NoteProperty -Name "ExcludedApps" -Value $ProductExlApps

                }

                $Result

            }

        }else{

            if ($ProductId) {

            

 

                [System.XML.XMLElement]$ProductElement = $ConfigFile.Configuration.Add.Product | where { $_.ID -eq $ProductId }

                if ($ProductElement) {

                $tempId = $ProductElement.GetAttribute("ID")

                

                

                $Result = New-Object -TypeName PSObject 

                Add-Member -InputObject $Result -MemberType NoteProperty -Name "ProductId" -Value $tempId 

                if($ProductElement.Language -ne $null){

                    $ProductLangs = $configfile.Configuration.Add.Product.Language | % {$_.ID}

                    Add-Member -InputObject $Result -MemberType NoteProperty -Name "Languages" -Value $ProductLangs

                }

 

                if($ProductElement.ExcludeApp -ne $null){

                    $ProductExlApps = $configfile.Configuration.Add.Product.ExcludeApp | % {$_.ID}

                    Add-Member -InputObject $Result -MemberType NoteProperty -Name "ExcludedApps" -Value $ProductExlApps

                }

                $Result

                }

            }

        }

    }

}

 

Function Get-ODTAdd{

<#

.SYNOPSIS

    Gets the value of the Add section in the configuration file

.PARAMETER TargetFilePath

    Required. Full file path for the file.

.Example

    Get-ODTAdd -TargetFilePath "$env:Public\Documents\config.xml"

    Returns the value of the Add section if it exists in the specified file.

#>

    Param(

 

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        [string] $ConfigurationXML = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string] $TargetFilePath

 

    )

 

    Process{

        $TargetFilePath = GetFilePath -TargetFilePath $TargetFilePath

 

        #Load the file

        [System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument

 

        if ($TargetFilePath) {

           $content = Get-Content $TargetFilePath

           $ConfigFile.LoadXml($content) | Out-Null

        } else {

            if ($ConfigurationXml) 

            {

              $ConfigFile.LoadXml($ConfigurationXml) | Out-Null

              $global:saveLastConfigFile = $NULL

              $global:saveLastFilePath = $NULL

            }

        }

 

        #Check that the file is properly formatted

        if($ConfigFile.Configuration -eq $null){

            throw $NoConfigurationElement

        }

        

        $ConfigFile.Configuration.GetElementsByTagName("Add") | Select OfficeClientEdition, SourcePath, Version, Channel, Branch

    }

 

}

 

Function Set-ODTDisplay{

<#

.SYNOPSIS

    Modifies an existing configuration xml file to set display level and acceptance of the EULA

.PARAMETER Level

    Optional. Determines the user interface that the user sees when the 

    operation is performed. If Level is set to None, the user sees no UI. 

    No progress UI, completion screen, error dialog boxes, or first run 

    automatic start UI are displayed. If Level is set to Full, the user 

    sees the normal Click-to-Run user interface: Automatic start, 

    application splash screen, and error dialog boxes.

.PARAMETER AcceptEULA

    If this attribute is set to TRUE, the user does not see a Microsoft 

    Software License Terms dialog box. If this attribute is set to FALSE 

    or is not set, the user may see a Microsoft Software License Terms dialog box.

.PARAMETER TargetFilePath

    Full file path for the file to be modified and be output to.

.Example

    Set-ODTLogging -Level "Full" -TargetFilePath "$env:Public/Documents/config.xml"

    

    Sets config show the UI during install

.Example

    Set-ODTDisplay -Level "none" -AcceptEULA "True" -TargetFilePath "$env:Public/Documents/config.xml"

    

    Sets config to hide UI and automatically accept EULA during install

.Notes

    Here is what the portion of configuration file looks like when modified by this function:

    <Configuration>

      ...

      <Display Level="None" AcceptEULA="TRUE" />

      ...

    </Configuration>

#>

    Param(

 

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        [string] $ConfigurationXML = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [LogLevel] $Level,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [bool] $AcceptEULA = $true,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string] $TargetFilePath

 

    )

 

    Process{

        $TargetFilePath = GetFilePath -TargetFilePath $TargetFilePath

 

        #Load file

        [System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument

 

        if ($TargetFilePath) {

           $content = Get-Content $TargetFilePath

           $ConfigFile.LoadXml($content) | 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

        }

 

        #Get display element if it exists

        [System.XML.XMLElement]$DisplayElement = $ConfigFile.Configuration.GetElementsByTagName("Display").Item(0)

        if($ConfigFile.Configuration.Display -eq $null){

            [System.XML.XMLElement]$DisplayElement=$ConfigFile.CreateElement("Display")

            $ConfigFile.Configuration.appendChild($DisplayElement) | Out-Null

        }

 

        #Set values

        if($Level -ne $null){

            $DisplayElement.SetAttribute("Level", $Level) | Out-Null

        } else {

            if ($PSBoundParameters.ContainsKey('Level')) {

                $ConfigFile.Configuration.Add.RemoveAttribute("Level")

            }

        }

 

        if($AcceptEULA -ne $null){

            $DisplayElement.SetAttribute("AcceptEULA", $AcceptEULA.ToString().ToUpper()) | Out-Null

        } else {

            if ($PSBoundParameters.ContainsKey('AcceptEULA')) {

                $ConfigFile.Configuration.Add.RemoveAttribute("AcceptEULA")

            }

        }

 

        $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"

        } 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 "Level" -Value $Level

            Add-Member -InputObject $Result -MemberType NoteProperty -Name "AcceptEULA" -Value $AcceptEULA

            $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"

    }

    

   $locationPath = (Get-Location).Path

    

    if (!($TargetFilePath.IndexOf('\') -gt -1)) {

      $TargetFilePath = $locationPath + "\" + $TargetFilePath

    }

 

    return $TargetFilePath

}

 

Function Get-OfficeCTRRegPath() {

    $path15 = 'SOFTWARE\Microsoft\Office\15.0\ClickToRun'

    $path16 = 'SOFTWARE\Microsoft\Office\ClickToRun'

 

    if (Test-Path "HKLM:\$path15") {

      return $path15

    } else {

      if (Test-Path "HKLM:\$path16") {

         return $path16

      }

    }

}

 

Function Set-ODTProductToAdd{

<#

.SYNOPSIS

    Modifies an existing configuration xml file to modify a existing product item.

.PARAMETER ExcludeApps

    Array of IDs of Apps to exclude from install

.PARAMETER ProductId

    Required. ID must be set to a valid ProductRelease ID.

    See https://support.microsoft.com/en-us/kb/2842297 for valid ids.

.PARAMETER LanguageIds

    Possible values match 'll-cc' pattern (Microsoft Language ids)

    The ID value can be set to a valid Office culture language (such as en-us 

    for English US or ja-jp for Japanese). The ll-cc value is the language 

    identifier.

.PARAMETER TargetFilePath

    Full file path for the file to be modified and be output to.

.Example

    Add-ODTProductToAdd -ProductId "O365ProPlusRetail" -LanguageId ("en-US", "es-es") -TargetFilePath "$env:Public/Documents/config.xml" -ExcludeApps ("Access", "InfoPath")

    Sets config to add the English and Spanish version of office 365 ProPlus

    excluding Access and InfoPath

.Example

    Add-ODTProductToAdd -ProductId "O365ProPlusRetail" -LanguageId ("en-US", "es-es) -TargetFilePath "$env:Public/Documents/config.xml"

    

    Sets config to add the English and Spanish version of office 365 ProPlus

.Notes

    Here is what the portion of configuration file looks like when modified by this function:

    <Configuration>

      <Add OfficeClientEdition="64" >

        <Product ID="O365ProPlusRetail">

          <Language ID="en-US" />

          <Language ID="es-es" />

          <ExcludeApp ID="Access">

          <ExcludeApp ID="InfoPath">

        </Product>

      </Add>

      ...

    </Configuration>

#>

    [CmdletBinding()]

    Param(

        [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]

        [string] $ConfigurationXML = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string] $TargetFilePath = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [Microsoft.Office.Products] $ProductId = "Unknown",

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [Alias("LanguageId")]

        [string[]] $LanguageIds = $NULL,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [string[]] $ExcludeApps = $NULL,

 

        [Parameter()]

        [string]$LogFilePath

 

    )

 

    Process{

        $currentFileName = Get-CurrentFileName

        Set-Alias -name LINENUM -value Get-CurrentLineNumber

 

        $TargetFilePath = GetFilePath -TargetFilePath $TargetFilePath

        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "TargetFilePath set to $TargetFilePath" -LogFilePath $LogFilePath

 

        if ($ProductId -eq "Unknown") {

           $ProductId = SelectProductId

        }

 

        $ProductId = IsValidProductId -ProductId $ProductId

        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "ProductId set to $ProductId" -LogFilePath $LogFilePath

        

        $langCount = $LanguageIds.Count

 

        if ($langCount -gt 0) {

           foreach ($language in $LanguageIds) {

              $language = IsSupportedLanguage -Language $language

           }

        }

 

        #Load the file

        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Loading the configuration file" -LogFilePath $LogFilePath

        [System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument

        

        if ($TargetFilePath) {

           $content = Get-Content $TargetFilePath

           $ConfigFile.LoadXml($content) | Out-Null

        } else {

            if ($ConfigurationXml) 

            {

              $ConfigFile.LoadXml($ConfigurationXml) | Out-Null

              $global:saveLastConfigFile = $NULL

              $global:saveLastFilePath = $NULL

              $TargetFilePath = $NULL

            }

        }

 

        $global:saveLastConfigFile = $ConfigFile.OuterXml

 

        #Check that the file is properly formatted

        if($ConfigFile.Configuration -eq $null){

            WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "$NoConfigurationElement" -LogFilePath $LogFilePath

            throw $NoConfigurationElement

        }

 

        [System.XML.XMLElement]$AddElement=$NULL

        if($ConfigFile.Configuration.Add -eq $null){

            WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Cannot find 'Add' element" -LogFilePath $LogFilePath

            throw "Cannot find 'Add' element"

        }

 

        $AddElement = $ConfigFile.Configuration.Add 

 

        #Set the desired values

        [System.XML.XMLElement]$ProductElement = $ConfigFile.Configuration.Add.Product | Where { $_.ID -eq $ProductId }

        if($ProductElement -eq $null){

            WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Cannot find Product with Id '$ProductId'" -LogFilePath $LogFilePath

            throw "Cannot find Product with Id '$ProductId'"

        }

 

        if ($LanguageIds) {

            $existingLangs = $ProductElement.selectnodes("./Language")

            if ($existingLangs.count -gt 0) {

                foreach ($lang in $existingLangs) {

                  $ProductElement.removeChild($lang) | Out-Null

                }

 

                foreach($LanguageId in $LanguageIds){

                    [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) | Out-Null

                    }

                }

            }

        }

 

        if ($ExcludeApps) {

            $existingExcludes = $ProductElement.selectnodes("./ExcludeApp")

            if ($existingExcludes.count -gt 0) {

                foreach ($exclude in $existingLangs) {

                  $ProductElement.removeChild($exclude) | Out-Null

                }

            }

 

            foreach($ExcludeApp in $ExcludeApps){

                [System.XML.XMLElement]$ExcludeAppElement = $ProductElement.ExcludeApp | Where { $_.ID -eq $ExcludeApp }

                if($ExcludeAppElement -eq $null){

                    [System.XML.XMLElement]$ExcludeAppElement=$ConfigFile.CreateElement("ExcludeApp")

                    $ProductElement.appendChild($ExcludeAppElement) | Out-Null

                    $ExcludeAppElement.SetAttribute("ID", $ExcludeApp) | Out-Null

                }

            }

        }

 

        $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 "ProductId" -Value $ProductId

            Add-Member -InputObject $Result -MemberType NoteProperty -Name "LanguageIds" -Value $LanguageIds

            $Result

        }

    }

}

 

Function Wait-ForOfficeCTRInstall() {

    [CmdletBinding()]

    Param(

        [Parameter()]

        [int] $TimeOutInMinutes = 120,

 

        [Parameter(ValueFromPipelineByPropertyName=$true)]

        [OfficeCTRVersion] $OfficeVersion = "Office2016",

 

        [Parameter()]

        [string]$LogFilePath

    )

 

    begin {

        $HKLM = [UInt32] "0x80000002"

        $HKCR = [UInt32] "0x80000000"

    }

 

    process {

        $currentFileName = Get-CurrentFileName

        Set-Alias -name LINENUM -value Get-CurrentLineNumber

 

        Write-Host "Waiting for Install to Begin..."

        WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Waiting for Install to Begin..." -LogFilePath $LogFilePath

 

        #Start-Sleep -Seconds 25

 

        if($OfficeVersion -eq 'Office2016'){

            $mainRegPath = 'SOFTWARE\Microsoft\Office\ClickToRun'

        } else {

            $mainRegPath = Get-OfficeCTRRegPath

        } 

 

        $scenarioPath = $mainRegPath + "\scenario"

 

        $regProv = Get-Wmiobject -list "StdRegProv" -namespace root\default -ErrorAction Stop

 

        [DateTime]$startTime = Get-Date

 

        [string]$executingScenario = ""

        $failure = $false

        $updateRunning=$false

        [string[]]$trackProgress = @()

        [string[]]$trackComplete = @()

        

        $timeout = New-TimeSpan -Minutes 2

        $sw = [diagnostics.stopwatch]::StartNew()

        while ($sw.elapsed -lt $timeout){

            try {

                $exScenario = $regProv.GetStringValue($HKLM, $mainRegPath, "ExecutingScenario")

                if($exScenario.sValue){ break; }

            } catch {}

 

            Start-Sleep -Seconds 5

        }

       

        if ($exScenario) {

            $executingScenario = $exScenario.sValue

        }

         

        do {

            $allComplete = $true

            $scenarioKeys = $regProv.EnumKey($HKLM, $scenarioPath)

            foreach ($scenarioKey in $scenarioKeys.sNames) {

                if (!($executingScenario)) { continue }

                if ($scenarioKey.ToLower() -eq $executingScenario.ToLower()) {

                    $taskKeyPath = $scenarioPath + "\$scenarioKey\TasksState"

                    $taskValues = $regProv.EnumValues($HKLM, $taskKeyPath).sNames

 

                    foreach ($taskValue in $taskValues) {

                        [string]$status = $regProv.GetStringValue($HKLM, $taskKeyPath, $taskValue).sValue

                        $operation = $taskValue.Split(':')[0]

                        $keyValue = $taskValue

 

                        if ($status.ToUpper() -eq "TASKSTATE_FAILED") {

                            $failure = $true

                        }

 

                        $displayValue = showTaskStatus -Operation $operation -Status $status -DateTime (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')

 

                        if (($status.ToUpper() -eq "TASKSTATE_COMPLETED") -or`

                            ($status.ToUpper() -eq "TASKSTATE_CANCELLED") -or`

                            ($status.ToUpper() -eq "TASKSTATE_FAILED")) {

                                if (($trackProgress -contains $keyValue) -and !($trackComplete -contains $keyValue)) {

                                    $displayValue

                                    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError $displayValue -LogFilePath $LogFilePath

                                    $trackComplete += $keyValue

                                    Start-Sleep -Seconds 1

                                }

                        } else {

                            $allComplete = $false

                            $updateRunning = $true

 

                            if ($trackProgress -notcontains $keyValue) {

                                $displayValue

                                WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError $displayValue -LogFilePath $LogFilePath

                                $trackProgress += $keyValue                                

                                Start-Sleep -Seconds 1

                            }

                        }

                    }

                }

            }

 

            if ($startTime -lt (Get-Date).AddHours(-$TimeOutInMinutes)) {

                WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Waiting for Update Timed-Out" -LogFilePath $LogFilePath

                throw "Waiting for Update Timed-Out"

                break;

            }

 

            if($allComplete){

                $updateRunning = $false

            }

 

            Start-Sleep -Seconds 5

 

        } while($updateRunning -eq $true)

    

        if($failure){

            Write-Host ""

            Write-Host 'Update failed'

            WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError 'Update failed' -LogFilePath $LogFilePath

        } else {

            if($trackProgress.Count -gt 0){

                Write-Host ""

                Write-Host 'Update complete'

                WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError 'Update complete' -LogFilePath $LogFilePath

            } else {

                Write-Host ""

                Write-Host 'Update not running'

                WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError 'Update not running' -LogFilePath $LogFilePath

            }

        } 

    }

}

 

function showTaskStatus() {

    [CmdletBinding()]

    Param(

        [Parameter()]

        [string] $Operation = "",

 

        [Parameter()]

        [string] $Status = "",

 

        [Parameter()]

        [string] $DateTime = ""

    )

 

    $Result = New-Object -TypeName PSObject 

    Add-Member -InputObject $Result -MemberType NoteProperty -Name "Operation" -Value $Operation

    Add-Member -InputObject $Result -MemberType NoteProperty -Name "Status" -Value $Status

    Add-Member -InputObject $Result -MemberType NoteProperty -Name "DateTime" -Value $DateTime

    return $Result

}

 

Function StartProcess {

Param

(

        [Parameter()]

[String]$execFilePath,

 

        [Parameter()]

        [String]$execParams,

 

        [Parameter()]

        [bool]$WaitForExit = $false

 

 

)

 

    Try

    {

        $startExe = new-object System.Diagnostics.ProcessStartInfo

        $startExe.FileName = $execFilePath

        $startExe.Arguments = $execParams

        $startExe.CreateNoWindow = $false

        $startExe.UseShellExecute = $false

 

        $execStatement = [System.Diagnostics.Process]::Start($startExe) 

        if ($WaitForExit) {

           $execStatement.WaitForExit()

        }

    }

    Catch

    {

        Write-Log -Message $_.Exception.Message -severity 1 -component "Office 365 Update Anywhere"

    }

}

 

Function GetScriptRoot() {

 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 Set-OfficePinnedApplication { 

<#  

.SYNOPSIS  

    Automate the process for pinning or unpinning Office apps

.DESCRIPTION  

    Pin or unpin Office apps from the Start Menu or Taskbarb setting the action

.EXAMPLE 

    Set-PinnedApplication -Action PinToTaskbar

#>  

    [CmdletBinding()] 

    param( 

        [Parameter(Mandatory=$true)]

        [PinAction]$Action,

 

        [Parameter()]

        [ValidateSet("Word","Excel","PowerPoint","OneNote","Access","Publisher","Outlook","Skype for Business",

                     "OneDrive for Business","Project","Visio")]

        [string[]]$OfficeApps = $null,

 

        [Parameter()]

        [string]$ClickToRun,

 

        [Parameter()]

        [string]$InstallPath,

 

        [Parameter()]

        [string]$OfficeVersion,

 

        [Parameter()]

        [string]$LogFilePath

    )

    $currentFileName = Get-CurrentFileName

    Set-Alias -name LINENUM -value Get-CurrentLineNumber

 

    if(!$ClickToRun){

        $ctr = Get-OfficeVersion

        if($ctr.GetType().Name -eq "Object[]"){

            $ClickToRun = $ctr[0].ClickToRun

        } else {

            $ClickToRun = (Get-OfficeVersion).ClickToRun

        }

    }

    

    if(!$InstallPath){

        $ctr = Get-OfficeVersion

        if($ctr.GetType().Name -eq "Object[]"){

            $InstallPath = $ctr[0].InstallPath

        } else {

            $InstallPath = (Get-OfficeVersion).InstallPath

        }   

    }

    

    if(!$officeVersion){

        $ctr = Get-OfficeVersion

        if($ctr.GetType().Name -eq "Object[]"){

            $officeVersion = $ctr[0].Version.Split('.')[0]

        } else {

            $officeVersion = (Get-OfficeVersion).Version.Split('.')[0]

        }             

    }

 

    if($InstallPath.GetType().Name -eq "Object[]"){

        $InstallPath = $InstallPath[0]

    }

 

    if($ClickToRun -eq $true) {

        $officeAppPath = $InstallPath + "\root\Office" + $officeVersion

    } else {

        $officeAppPath = $InstallPath + "Office" + $officeVersion

    }

 

    $officeAppList = @()

 

    if(!$OfficeApps){

        $officeAppList = @("WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE", "ONENOTE.EXE", "MSACCESS.EXE", "MSPUB.EXE", "OUTLOOK.EXE",

                           "lync.exe", "GROOVE.EXE", "WINPROJ.EXE", "VISIO.EXE")

    } else {

        foreach($app in $OfficeApps){

            switch($app){

                "Word" {

                    $officeAppList += "WINWORD.EXE"

                }

                "Excel" {

                    $officeAppList += "EXCEL.EXE"

                }

                "PowerPoint" {

                    $officeAppList += "POWERPNT.EXE"

                }

                "OneNote" {

                    $officeAppList += "ONENOTE.EXE"

                }

                "Access" {

                    $officeAppList += "MSACCESS.EXE"

                }

                "Publisher" {

                    $officeAppList += "MSPUB.EXE"

                }

                "Outlook" {

                    $officeAppList += "OUTLOOK.EXE"

                }

                "Skype for Business" {

                    $officeAppList += "lync.exe"

                }

                "OneDrive for Business" {

                    $officeAppList += "GROOVE.EXE"

                }

                "Project" {

                    $officeAppList += "WINPROJ.EXE"

                }

                "Visio" {

                    $officeAppList += "VISIO.EXE"

                }

            }

        }

    }

 

    foreach($app in $officeAppList){

        if(Test-Path ($officeAppPath + "\$app")){

            switch($Action) {

                "PinToStartMenu" {

                    Write-Host "Pinning $app to the Start Menu..."

                    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Pinning $app to the Start Menu..." -LogFilePath $LogFilePath

                    if([Environment]::OSVersion.Version.Major -ge 10){

                        $actionId = '51201'

                    } else { 

                        $actionId = '5381'

                    }

                }

                "UnpinFromStartMenu" {

                    Write-Host "Removing $app from the Start Menu..."

                    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removing $app from the Start Menu..." -LogFilePath $LogFilePath

                    if([Environment]::OSVersion.Version.Major -ge 10){

                        $actionId = '51394'

                    } else { 

                        $actionId = '5382'

                    } 

                }

                "PinToTaskbar" {

                    Write-Host "Pinning $app to the TaskBar..."

                    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Pinning $app to the TaskBar..." -LogFilePath $LogFilePath

                    if([Environment]::OSVersion.Version.Major -ge 10){

                        throw "Unable to pin items to the taskbar in Windows 10"

                    }

            

                    $actionId = '5386'

                }

                "UnpinFromTaskbar" {

                    Write-Host "Removing $app from the TaskBar..."

                    WriteToLogFile -LNumber $(LINENUM) -FName $currentFileName -ActionError "Removing $app from the TaskBar..." -LogFilePath $LogFilePath

                    $actionId = '5387'

                }

            }

 

            InvokeVerb -FilePath ($officeAppPath + "\$app") -Verb $(GetVerb -VerbId $actionId) -officeVersion $officeVersion

        }

    } 

 

function GetVerb { 

    param(

        [int]$verbId

    ) 

 

    try { 

        $t = [type]"CosmosKey.Util.MuiHelper" 

    } catch { 

        $def = [Text.StringBuilder]"" 

        [void]$def.AppendLine('[DllImport("user32.dll")]') 

        [void]$def.AppendLine('public static extern int LoadString(IntPtr h,uint id, System.Text.StringBuilder sb,int maxBuffer);') 

        [void]$def.AppendLine('[DllImport("kernel32.dll")]') 

        [void]$def.AppendLine('public static extern IntPtr LoadLibrary(string s);') 

        Add-Type -MemberDefinition $def.ToString() -name MuiHelper -namespace CosmosKey.Util             

    } 

    if($global:CosmosKey_Utils_MuiHelper_Shell32 -eq $null){         

        $global:CosmosKey_Utils_MuiHelper_Shell32 = [CosmosKey.Util.MuiHelper]::LoadLibrary("shell32.dll") 

    } 

    $maxVerbLength=255 

    $verbBuilder = new-object Text.StringBuilder "",$maxVerbLength 

    [void][CosmosKey.Util.MuiHelper]::LoadString($CosmosKey_Utils_MuiHelper_Shell32,$verbId,$verbBuilder,$maxVerbLength) 

    

    return $verbBuilder.ToString() 

 

function InvokeVerb { 

    param([string]$FilePath,$verb,$officeVersion) 

 

    $verb = $verb.Replace("&","") 

    $path= split-path $FilePath 

    $shell=new-object -com "Shell.Application"  

    $folder=$shell.Namespace($path)    

    $item = $folder.Parsename((split-path $FilePath -leaf)) 

    $itemVerb = $item.Verbs() | ? {$_.Name.Replace("&","") -eq $verb} 

   

    try{

        if(([Environment]::OSVersion.Version.Major -ge 10) -and ($verb -eq 'Unpin from taskbar')){

            Remove-PinnedOfficeAppsForWindows10 -OfficeApp $item.Name -officeVersion $officeVersion

        }else { 

            $itemVerb.DoIt() 

        }

    }catch{}

     

}

 

function Remove-PinnedOfficeAppsForWindows10() {

    [CmdletBinding()]

    param(

        [Parameter()]

        [string]$OfficeApp,

 

        [Parameter()]

        [string]$officeVersion

    )

 

    $Action = 'Unpin from taskbar'

 

    switch($OfficeApp){

        "WINWORD" {

            $officeAppName = "Word"  

        }

        "EXCEL" {

            $officeAppName = "Excel"

        }

        "POWERPNT" {

            $officeAppName = "PowerPoint"

        }

        "ONENOTE" {

            $officeAppName = "OneNote"

        }

        "MSACCESS" {

            $officeAppName = "Access"

        }

        "MSPUB" { 

            $officeAppName = "Publisher"

        }

        "OUTLOOK" {

            $officeAppName = "Outlook"

        }

        "lync" {

            $officeAppName = "Skype for Business"

        }

        "GROOVE" {

            $officeAppName = "OneDrive for Business"

        }

        "WINPROJ" {

            $officeAppName = "Project"

        }

        "VISIO" {

            $officeAppName = "Visio"

        }

    }

 

        switch($officeVersion){

        "11" {

            $officeAppVersion = "Microsoft Office " + $officeAppName + " 2003"

        }

        "12" {

            $officeAppVersion = "Microsoft Office " + $officeAppName + " 2007"

        }

        "14" {

            $officeAppVersion = "Microsoft " + $officeAppName + " 2010"

        }

        "15" {

            $officeAppVersion = $officeAppName + " 2013"

        }

        "16" {

            $officeAppVersion = $officeAppName + " 2016"

        }

    }

 

    ((New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items() | ? {$_.Name -like $officeAppVersion}).Verbs() | ? {$_.Name.replace('&','') -match $Action} | % {$_.DoIt()}

       

}

 

function GetOfficeAppVerbStatus{

    [CmdletBinding()]

    param(

        [Parameter()]

        [ValidateSet("Word","Excel","PowerPoint","OneNote","Access","Publisher","Outlook","Skype for Business",

                     "OneDrive for Business","Project","Visio")]

        [string[]]$OfficeApps

    )

 

    Begin{

        $defaultDisplaySet = 'Name','PinToStartMenuAvailable', 'PinToTaskbarAvailable'

        $defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet)

        $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)

    }

 

    Process{

        $results = new-object PSObject[] 0;

 

        $ctr = Get-OfficeVersion 

                     

        if($ctr -ne $null){

            if($ctr.GetType().Name -eq "Object[]"){

                $ctr = $ctr[0]

                $officeversion = $ctr.Version.Split('.')[0]                      

            } else {

                $officeVersion = (Get-OfficeVersion).Version.Split('.')[0]

            }

        }

        

        $InstallPath = $ctr.InstallPath 

        $ctr = $ctr.ClickToRun

 

        if($ctr -eq $true) {

            $officeAppPath = $InstallPath + "\root\Office" + $officeVersion

        } else {

            $officeAppPath = $InstallPath + "Office" + $officeVersion

        }

 

        $availableApps = @()

        $officeAppList = @()

 

        if(!$OfficeApps){

            $officeAppList += @("WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE", "ONENOTE.EXE", "MSACCESS.EXE", "MSPUB.EXE", "OUTLOOK.EXE",

                            "lync.exe", "GROOVE.EXE", "WINPROJ.EXE", "VISIO.EXE")

        } else {

            foreach($app in $OfficeApps){

                switch($app){

                    "Word" {

                        $officeAppList += "WINWORD.EXE"

                    }

                    "Excel" {

                        $officeAppList += "EXCEL.EXE"

                    }

                    "PowerPoint" {

                        $officeAppList += "POWERPNT.EXE"

                    }

                    "OneNote" {

                        $officeAppList += "ONENOTE.EXE"

                    }

                    "Access" {

                        $officeAppList += "MSACCESS.EXE"

                    }

                    "Publisher" {

                        $officeAppList += "MSPUB.EXE"

                    }

                    "Outlook" {

                        $officeAppList += "OUTLOOK.EXE"

                    }

                    "Lync" {

                        $officeAppList += "lync.exe"

                    }

                    "OneDriveForBusiness" {

                        $officeAppList += "GROOVE.EXE"

                    }

                    "Project" {

                        $officeAppList += "WINPROJ.EXE"

                    }

                    "Visio" {

                        $officeAppList += "VISIO.EXE"

                    }

                }

            }

        }

 

        foreach($app in $OfficeAppList){

            if(Test-Path ($officeAppPath + "\$app")){

                $availableApps += $app

            }

        }

 

        foreach($app in $availableApps){

            switch($app){

                "WINWORD.EXE" {

                    $officeAppName = "Word"  

                }

                "EXCEL.EXE" {

                    $officeAppName = "Excel"

                }

                "POWERPNT.EXE" {

                    $officeAppName = "PowerPoint"

                }

                "ONENOTE.EXE" {

                    $officeAppName = "OneNote"

                }

                "MSACCESS.EXE" {

                    $officeAppName = "Access"

                }

                "MSPUB.EXE" { 

                    $officeAppName = "Publisher"

                }

                "OUTLOOK.EXE" {

                    $officeAppName = "Outlook"

                }

                "lync.exe" {

                    $officeAppName = "Skype for Business"

                }

                "GROOVE.EXE" {

                    $officeAppName = "OneDrive for Business"

                }

                "WINPROJ.EXE" {

                    $officeAppName = "Project"

                }

                "VISIO.EXE" {

                    $officeAppName = "Visio"

                }

            }

 

            if(!($officeAppName -eq "OneDrive for Business")){

                switch($officeVersion){

                    "11" {

                        $officeAppVersion = "Microsoft Office " + $officeAppName + " 2003"

                    }

                    "12" {

                        $officeAppVersion = "Microsoft Office " + $officeAppName + " 2007"

                    }

                    "14" {

                        $officeAppVersion = "Microsoft " + $officeAppName + " 2010"

                    }

                    "15" {

                        $officeAppVersion = $officeAppName + " 2013"

                    }

                    "16" {

                        $officeAppVersion = $officeAppName + " 2016"

                    }

                }

            }

            

            [bool]$availablePinToStartMenu = $false

            [bool]$availablePinToTaskbar = $false

            

            if([Environment]::OSVersion.Version.Major -ge 10){

                $verbs = ((New-Object -Com Shell.Application).NameSpace('shell:::{4234d49b-0245-4df3-b780-3893943456e1}').Items() | ? {$_.Name -like $officeAppVersion}).Verbs() | select Name

                

                foreach($verb in $verbs.name){

                    switch($verb.Replace('&','')){

                        "Pin to Start" {

                            $availablePinToStartMenu = $true

                        }

                        "Pin to Taskbar" {

                            $availablePinToTaskbar = $true

                        }

                    }

                }

            } else {

                $pinActions = @("5381","5386")

                

                foreach($action in $pinActions){

                    $verb = GetVerb -verbId $action

                    $verb = $verb.Replace("&","")

                    $FilePath = $officeAppPath + "\" + $app

                    $path = Split-Path $FilePath

                    $shell = New-Object -ComObject "Shell.Application"

                    $folder = $shell.Namespace($path)

                    $item = $folder.Parsename((Split-Path $filepath -Leaf))

                    $itemverb = $item.Verbs() | ? {$_.Name.Replace("&","") -eq $verb}

                    

                    if($itemverb){

                        switch($verb){

                            "Pin to Start Menu" {

                                $availablePinToStartMenu = $true

                            }

                            "Pin to Taskbar" {

                                $availablePinToTaskbar = $true

                            }

                        }

                    }

                }         

            }

            

            $object = New-Object PSObject -Property @{Name = $officeAppName; PinToStartMenuAvailable = $availablePinToStartMenu; PinToTaskbarAvailable = $availablePinToTaskbar;}

                                                      

            $object | Add-Member MemberSet PSStandardMembers $PSStandardMembers

            $results += $object 

        }

 

        return $results

    }

}

 

function Get-CurrentLineNumber {

    $MyInvocation.ScriptLineNumber

}

 

function Get-CurrentFileName{

    $MyInvocation.ScriptName.Substring($MyInvocation.ScriptName.LastIndexOf("\")+1)

}

 

Function WriteToLogFile() {

    param( 

        [Parameter(Mandatory=$true)]

        [string]$LNumber,

 

        [Parameter(Mandatory=$true)]

        [string]$FName,

 

        [Parameter(Mandatory=$true)]

        [string]$ActionError,

 

        [Parameter()]

        [string]$LogFilePath

    )

 

    try{

        $headerString = "Time".PadRight(30, ' ') + "Line Number".PadRight(15,' ') + "FileName".PadRight(60,' ') + "Action"

        $stringToWrite = $(Get-Date -Format G).PadRight(30, ' ') + $($LNumber).PadRight(15, ' ') + $($FName).PadRight(60,' ') + $ActionError

 

        if(!$LogFilePath){

            $LogFilePath = "$env:windir\Temp\" + (Get-Date -Format u).Substring(0,10)+"_OfficeDeploymentLog.txt"

        }

        if(Test-Path $LogFilePath){

             Add-Content $LogFilePath $stringToWrite

        }

        else{#if not exists, create new

             Add-Content $LogFilePath $headerString

             Add-Content $LogFilePath $stringToWrite

        }

    } catch [Exception]{

        Write-Host $_

    Press Enter. Follow the prompt as they display for any dropdowns chose "semi".

Article Details

Article ID:
4
Category:
Date added:
2021-06-26 11:45:00
Rating :