Loading

Office 365 ProPlus (Microsoft 365 Apps) hantering i SCCM (MECM)

Ledsen, men denna bloggning blir på svenska (in English, by Google).

Jag har upplevt att en del företag har svårt att få till en bra hantering av Office 365 ProPlus, Visio och Project när det gäller installation och uppdateringar via SCCM/MECM (System Center Configuration Manager, eller som det numera heter Microsoft Endpoint Configuration Manager).
För att säkerställa att samtliga Applikationspaket för Office 365 ProPlus, Visio Pro for Office 365, och Project Online Desktop Client alltid är av senast verifierad (godkänd för installation) version är detta lösning som jag förespråkar.

Bakgrund
I SCCM/MECM skapas det statiska installationspaket (Application packages) för så väl Office 365 ProPlus som Visio och Project. Där Office 365 ProPlus oftast installeras under OS-installationen (via Task Sequence). När Office 365 ProPlus är installerat på klienterna blir de uppdaterade (patchade) via sedvanlig uppdaterings-rutin till nyare ”build” och ibland till ny version.
De statiska installationspaketen (Application packages) ligger fortfarande kvar på samma version och build som när de skapades.

Problemet
Användare A har sin dator installerad med Office 365 ProPlus sedan en tid, och fått både säkerhetsuppdateringar och ny version av Office 365 ProPlus. Nu behöver användare A även ha Visio installerat. Men eftersom den packade Visio-versionen i SCCM/MECM är äldre än den Office 365 ProPlus som användare A har installerat så kommer installationen att misslyckas.

Lösningen
På ett DFS-share som är åtkomligt från alla nät där klienter sitter (inkl. stagning-nät & VPN) skapar man en mapp för Office 365 filer (tex. Office365SetupFiles så att sökvägen ser ut ungefär så här: \dfs-share.organisationen.net\Office365SetupFiles$), i den skapar man två mappar, x86 och x64.
I mappen Office365SetupFiles lägger man sedan Office Deployment Tool (setup.exe) tillsammans med två XML-filer som man får skapa (en för x86 och en för x64) och som talar om vad som skall laddas ner (för exempel på XML-filer se längre ner i dokumentet).
I XML-filerna för nedladdning anger man alla produkter, språk och rättstavningsverktyg som kan tänkas behövas inom organisationen.
När mapparna och XML-filerna är skapade och på plats tillsammans med setup.exe (från Office Deployment Tool) kör man kommandot: setup.exe /download download_x86.xml för att ladda ner alla filerna för 32-bitars version, och sedan setup.exe /download download_x64.xml för 64-bitars version.

I rutinen för uppdateringar varje månad kör man setup.exe /download download_x32.xml (och setup.exe /download download_x64.xml) för att få de uppdaterade installationsfilerna (man tar sedan bort föregående version från nedladdningen). På detta sätt är alltid installationsfilerna uppdaterade, och givetvis kan man automatisera detta.
För installation skapar man sina statiska installationspaket (Application packages), enbart med filen setup.exe (från Office Deployment Tool) och den konfigurations-fil (XML-fil) som talar om vad som skall installeras. I XML-filen hänvisar man till DSF-sharet där nedladdningen finns, och installeras därifrån (exempel på XML-filer se längre ner i inlägget). Jag rekommenderar att använda PSADT (PowerShell App Deployment Toolkit) för att paketera installationen.

Sammanfattning
Nu i denna lösning när användare A med sin dator installerad med Office 365 ProPlus sedan en tid, med både ny version och säkerhetsuppdateringar nu behöver Visio så kommer installationen fungera, då installationsfilerna är i samma version som användare A redan har sitt Office 365 ProPlus på.

Office Deployment Tool (setup.exe) behöver uppdateras när man går upp i version för att stödja nya funktioner, på samma sätt som man kan behöva se över XML-filerna för att de nya funktionerna/produkter ska komma med, eller förhindras (använd Office Office Customization Tool).
Office Deployment Tool, https://go.microsoft.com/fwlink/p/?LinkID=626065
Office Customization Tool, https://config.office.com/deploymentsettings (skapa/importera/exportera konfigurationsfiler)

Exempel på konfigurationsfiler
Exempel på download_x64.xml

<Configuration ID="11666593-c103-4fad-bc07-0951fdee1223">
  <Add OfficeClientEdition="64" Channel="Broad" SourcePath="\\DFSSHARE.ORGANISATION.ORG\Office365SetupFiles$\x64">
    <Product ID="O365ProPlusRetail">
      <Language ID="sv-se" />
      <Language ID="da-dk" />
      <Language ID="nl-nl" />
      <Language ID="en-us" />
      <Language ID="fi-fi" />
      <Language ID="fr-fr" />
      <Language ID="de-de" />
      <Language ID="nn-no" />
    </Product>
    <Product ID="VisioProRetail">
      <Language ID="sv-se" />
      <Language ID="da-dk" />
      <Language ID="nl-nl" />
      <Language ID="en-us" />
      <Language ID="fi-fi" />
      <Language ID="fr-fr" />
      <Language ID="de-de" />
      <Language ID="nn-no" />
    </Product>
    <Product ID="ProjectProRetail">
      <Language ID="sv-se" />
      <Language ID="da-dk" />
      <Language ID="nl-nl" />
      <Language ID="en-us" />
      <Language ID="fi-fi" />
      <Language ID="fr-fr" />
      <Language ID="de-de" />
      <Language ID="nn-no" />
    </Product>
    <Product ID="LanguagePack">
      <Language ID="sv-se" />
      <Language ID="da-dk" />
      <Language ID="nl-nl" />
      <Language ID="en-us" />
      <Language ID="fi-fi" />
      <Language ID="fr-fr" />
      <Language ID="de-de" />
      <Language ID="nn-no" />
    </Product>
    <Product ID="ProofingTools">
      <Language ID="da-dk" />
      <Language ID="nl-nl" />
      <Language ID="en-us" />
      <Language ID="fi-fi" />
      <Language ID="fr-fr" />
      <Language ID="de-de" />
      <Language ID="nn-no" />
      <Language ID="sv-se" />
    </Product>
  </Add>
  <Display Level="None" AcceptEULA="TRUE" />
</Configuration>

Exempel på configuration_x64.xml för Office 365 ProPlus

<Configuration ID="5140f541-3226-4067-84d0-c3e53ac6d29f">
  <Add OfficeClientEdition="64" Channel="Broad" SourcePath="\\DFSSHARE.ORGANISATION.ORG\Office365SetupFiles$\x64" OfficeMgmtCOM="TRUE" AllowCdnFallback="FALSE">
    <Product ID="O365ProPlusRetail">
      <Language ID=" en-us " />
      <ExcludeApp ID="Bing" />
      <ExcludeApp ID="Groove" />
      <ExcludeApp ID="OneNote" />
    </Product>
    <Product ID="LanguagePack">
      <Language ID="sv-se" />
      <ExcludeApp ID="Bing" />
      <ExcludeApp ID="Groove" />
      <ExcludeApp ID="OneNote" />
   </Product>
    <Product ID="ProofingTools">
      <Language ID="fr-fr" />
      <Language ID="de-de" />
     </Product>
  </Add>
  <Property Name="SharedComputerLicensing" Value="0" />
  <Property Name="PinIconsToTaskbar" Value="FALSE" />
  <Property Name="SCLCacheOverride" Value="0" />
  <Property Name="AUTOACTIVATE" Value="1" />
  <Property Name="FORCEAPPSHUTDOWN" Value="FALSE" />
  <Property Name="DeviceBasedLicensing" Value="0" />
  <Updates Enabled="TRUE" />
  <AppSettings>
    <User Key="software\microsoft\office\16.0\excel\options" Name="defaultformat" Value="51" Type="REG_DWORD" App="excel16" Id="L_SaveExcelfilesas" />
    <User Key="software\microsoft\office\16.0\powerpoint\options" Name="defaultformat" Value="27" Type="REG_DWORD" App="ppt16" Id="L_SavePowerPointfilesas" />
    <User Key="software\microsoft\office\16.0\word\options" Name="defaultformat" Value="" Type="REG_SZ" App="word16" Id="L_SaveWordfilesas" />
  </AppSettings>
  <Display Level="None" AcceptEULA="TRUE" />
  <Logging Level="Standard" Path="%windir%\Logs\Software\" />
</Configuration>

Exempel på configuration_x64.xml för Visio Pro for Office 365

<Configuration ID="986241dd-06ab-49ed-a5e0-5fb25297a666">
  <Add OfficeClientEdition="64" Channel="Broad" SourcePath="\\DFSSHARE.ORGANISATION.ORG\Office365SetupFiles$\x64" OfficeMgmtCOM="TRUE" AllowCdnFallback="FALSE">
    <Product ID="VisioProRetail">
      <Language ID="en-us" />
      <ExcludeApp ID="Bing" />
      <ExcludeApp ID="Groove" />
    </Product>
    <Product ID="LanguagePack">
      <Language ID="sv-se" />
      <ExcludeApp ID="Bing" />
      <ExcludeApp ID="Groove" />
    </Product>
  </Add>
  <Property Name="SharedComputerLicensing" Value="0" />
  <Property Name="PinIconsToTaskbar" Value="TRUE" />
  <Property Name="SCLCacheOverride" Value="0" />
  <Property Name="AUTOACTIVATE" Value="1" />
  <Property Name="FORCEAPPSHUTDOWN" Value="FALSE" />
  <Property Name="DeviceBasedLicensing" Value="0" />
  <Display Level="Full" AcceptEULA="TRUE" />
  <Logging Level="Standard" Path="%windir%\Logs\Software\" />
</Configuration>

Exempel på configuration_x64.xml för Project Online Desktop Client

<Configuration ID="2755de1d-24bf-4299-b3a0-70ce31c8941b">
  <Add OfficeClientEdition="64" Channel="Broad" SourcePath="\\DFSSHARE.ORGANISATION.ORG\Office365SetupFiles$\x64" OfficeMgmtCOM="TRUE" AllowCdnFallback="FALSE">
    <Product ID="ProjectProRetail">
      <Language ID="en-us" />
      <ExcludeApp ID="Bing" />
      <ExcludeApp ID="Groove" />
	</Product>
    <Product ID="LanguagePack">
      <Language ID="sv-se" />
      <ExcludeApp ID="Bing" />
      <ExcludeApp ID="Groove" />
    </Product>
  </Add>
  <Property Name="SharedComputerLicensing" Value="0" />
  <Property Name="PinIconsToTaskbar" Value="TRUE" />
  <Property Name="SCLCacheOverride" Value="0" />
  <Property Name="AUTOACTIVATE" Value="1" />
  <Property Name="FORCEAPPSHUTDOWN" Value="FALSE" />
  <Property Name="DeviceBasedLicensing" Value="0" />
  <Display Level="None" AcceptEULA="TRUE" />
  <Logging Level="Standard" Path="%windir%\Logs\Software\" />
</Configuration>

Diskpart to the rescue

In my work, I recently heard that more often new devices (desktop’s/laptop’s) fails in the beginning of the OSD (OS deploy) because of something is wrong with the partitions on the hard drive. The Boot-image can’t download policys or files to the disk, so it fails. Often the IT-person needs to boot the device and re-partition the disk, and after that start the OSD again, and it will work. I have not done some examination on why it fails. The OEM’s OS works on the device/disk. But I have a workaround, or it’s not mine workaround. I did find it on the Internet for a few years ago, so I don’t remember whos to credit (I’m sorry).

But this is the workaround I have.

Begin by creating a txt-file with the content of commands for diskpart we will be using later (this is for UEFI-disks).
sel disk 0 clean convert gpt cre par efi size=200 assign letter=s format quick fs=FAT32 cre par msr size=128 cre par pri assign letter=c format quick fs=NTFS exit
Save the file (I have named my file uefi_disk.txt ), and put it on your SCCM Package-share. Then you will need to create a Package in your SCCM-console, where you will point out the source files (where you saved your new .txt-file). You don’t need to create a program, just select “Do not create a program” and click next, and just go on and finish the wizard. Here is two ways to use this. The first one, if you boot your PC’s from a boot-media (CD/USB), you can create a new boot-media and put in a prestart command to run diskpart. So go one and create a new Task Sequence Media if you choose this way. Mark Boot media, and Next Continue the wizard, entering your “SCCM-info” till you come to Customize the task sequence media. Here you will need to tick the Enable prestart command checkbox, and also enter Command line: cmd.exe /c diskpart /s uefi_disk.txt <– or the name you gave your .txt-file You must also select the Diskpart package you created earlier, and point out your Distribution point. After that, finish the wizard, and you are now ready to boot using your new boot-media.
The other one is to put this in your boot-image (if you PXE-boot your devices, choose this). Using this way the prestart command will always run (when using TS using this boot-image), and you don’t need to create a new boot-image with this prestart command. Go to your Boot-image in the SCCM-console, and right-click it and choose Properties. Go to the Customization tab, and tick the Enable prestart command checkbox, and also enter Command line: cmd.exe /c diskpart /s uefi_disk.txt <– or the name you gave your .txt-file Klick Ok, to save and re-distribute your boot-image, and after that your done.
When you are here, click Next And diskpart will run After diskpart is finished, you can choose your TS, and continue your installation

Paus i jobbhelgen

jobbhelgHelgjobb står på tapeten denna helg.
Började gårdagen med att ominstallera 15 RDS:er. På dagens agenda står det patchning av servrar för min del, men just nu väntar jag på att kollegorna ska bli klara med brandväggsjobb så att nätverket åter blir tillgängligt och jag kan fortsätta patchningen.

Under tiden så tar jag och bläddrar lite i Deployment Fundamentals, Vol. 6: Deploying Windows 10 Using Microsoft Deployment Toolkit som damp ner i brevlådan igår. Det får gärna ta ett tag med brandväggsjobbet känner jag 🙂 .

Krasslig idag, beställde en bok

dfv6Förkyld, utslagen allmänt gnäll. Men en bok köptes in, Deployment Fundamentals, Vol. 6: Deploying Windows 10 Using Microsoft Deployment Toolkit.
Hoppas på snabb leverans. På något sjukt sätt så tycker jag sådant här är kul, samt att jag råkar kunna använda det i jobbet…

Hoppas nu bara att jag lyckas skrapa ihop hårdvara för att kunna få till lämplig labbmiljö.

 

Uppdatera Configmgr Content, där det behövs

Återigen, Rikard Rönnkvist spar mig massor av tid med sina PowerShell-script, tack!

PARAM (
    $sccmServer = "configmgr.snowland.se",
    $sccmSiteCode = "ABC",
    $failStates = "2, 3, 5, 6", # Retrying and Failed (Both Install and Removal)
    $packageTypes = "0, 3, 4, 8, 257, 258" # Not checking 5 (SUP) due to automatic deployments
)
 
Write-Host "Searching for failed content distributions"
ForEach ($FailedDist in (Get-WmiObject -ComputerName $sccmServer -Namespace "ROOT\SMS\Site_$($sccmSiteCode)" -Query "SELECT * FROM SMS_PackageStatusDistPointsSummarizer WHERE State IN ($($failStates)) AND PackageType IN ($($packageTypes))" | Sort-Object PackageID)) {
     
    # Figure out servername from NalPath
    $failedServer = $FailedDist.ServerNALPath.Substring($FailedDist.ServerNALPath.LastIndexOf("]")+3).Trim("\")
 
    # Get the distribution points that content wouldn't distribute to
    ForEach ($FailedDPDist in (Get-WmiObject -ComputerName $sccmServer -Namespace "ROOT\SMS\Site_$($sccmSiteCode)" -Query "SELECT * FROM SMS_DistributionPoint WHERE SiteCode='$($FailedDist.SiteCode)' AND PackageID='$($FailedDist.PackageID)' AND ServerNALPath LIKE '%$($failedServer)%'") ) {
        # Refresh content on the selected DP
        Write-Host "Refreshing $($FailedDPDist.PackageID), type $($FailedDist.PackageType) in state $($FailedDist.State) on $($failedServer)"
        $FailedDPDist.RefreshNow = $true
        $FailedDPDist.Put() | Out-Null
    }
}
 
Write-Host "Done!"

Tack till Rikard Rönnkvist, källa: SnowLand

Exportera / Importera Boot-image drivrutiner till ny Boot-image

Återigen, ett mycket bra PowerShell-script som besparar massa tid.

Function Export-BootImageDrivers {
    PARAM (
        [String] $ImageId,
        [String] $ExportXml
    )
  
    $drivers = @{}
    (Get-CMBootImage -Id $ImageId).ReferencedDrivers | ForEach-Object {
        Write-Verbose "Found driver ID - $($_.Id)"
 
        $drivers.Add($_.Id, $_.SourcePath)
    }
 
    $drivers | Export-Clixml -Path $ExportXml
}
 
Function Import-BootImageDrivers {
    PARAM (
        [String] $ImageId,
        [String] $ExportXml
    )
 
    $BootImage = Get-CMBootImage -Id $ImageId
    $drivers = Import-Clixml -Path $ExportXml
    $drivers.GetEnumerator() | ForEach-Object {
        Write-Verbose "Adding driver ID - $($_.Name)"
        Set-CMDriver -Id $_.Name -AddBootImagePackage $BootImage -UpdateDistributionPointsforBootImagePackage $false -Force
    }
}

Exportera först drivrutinerna

Export-BootImageDrivers -ImageId “ABC00123” -ExportXml “D:\Script\PS\drivers.xml”

Uppgradera Boot-imagen

Sedan importera drivrutinerna

Import-BootImageDrivers -ImageId “ABC00345” -ExportXml “D:\Script\PS\drivers.xml”

Tack till Rikard Rönnkvist, källa: SnowLand

Kopiera drivrutiner från en boot-image till en annan

Lifesaver. Eller med andra ord, en grym tidsbesparare.

Function Copy-BootImageDrivers {
    PARAM (
        $from, $to
    )
 
    $boot = Get-CMBootImage -ID $to
 
    (Get-CMBootImage -Id $from).ReferencedDrivers | ForEach-Object {
        Write-Verbose "Copying $($_.Id) to $($to)"
        Set-CMDriver -Id $_.Id -AddBootImagePackage $boot -UpdateDistributionPointsforBootImagePackage $false
    }
 
}
 
#Example use
Copy-BootImageDrivers -from "ABC00123" -to "ABC00456"

Tack till Rikard Rönnkvist, källa SnowLand