Office Readiness Toolkit per User – without MSI

Last updated: February 18, 2020 at 21:23 pm

So you might know the Office Readiness Toolkit already, which provides a great way to assess your Office Add-Ins before you migrate to Office 365/2019. One of the greatest catches is this: You need to run this on a Per-User basis, meaning every user has to run this, ideally over several weeks while you monitor the progress. This is because the tool scans the users recently used files. You can store the progress in a SQL database, or – since I didn’t have that many clients – use the file based approach with a local share. Needless to say, the share has to be

Secret Forest Path

You might already know, that if you have the tools required to build you own MSI that there’s a feature called Self-Heal, which lets you execute things per user with the help of registry magic (called ActiveSetup). This article isn’t about that. Instead we’re going to do the more dirty version, because I don’t have these tools available and I need the information from the Office Readiness Toolkit asap.

By the way, if you have MECM (former SCCM) at hand, great! Go ahead and use the Office 365 Readiness first option integrated. You might be surprised how compliant your environment already is. However, if you want more in-depth information, maybe on a per user scale, this approach should help you complete your picture.

The Installation .bat

Nothing out of the ordinary here – don’t forget to replace the MSI name wit the version you have.

msiexec /i "ReadinessToolkitForOffice_VERSION.msi" /qn
powershell -executionpolicy bypass -windowstyle hidden -file %~dp0\scan.ps1

The PowerShell

Again, nothing too special here. The first part is something I use to evaluate the current location in every situation (VScode, ISE or Shell). After that we create the .bat that is run in the scheduled task later on. Don’t forget to change the %TEMP% to whatever path you might need. I didn’t verify this with UNC paths though. At the end I use an exported task XML file to adjust the start time of the task. In the case shown below 2 weeks into the feature. Again, not the cleanest of solution. As of now this was the easier approach when held against creating a scheduled task with PowerShell. This leaves you with a task, that is never run again since it has no schedule to run again. Sure, users can run the task again and it will fail. If it’s really required you could use a GPO to delete this task when found.

if ($psISE) {
    $PathToScript = Split-Path -Path $psISE.CurrentFile.FullPath
}
else {
    if ($profile -match "VScode") {
        $PathToScript = split-path $psEditor.GetEditorContext().CurrentFile.Path
    }
    else {
        $PathToScript = $PSScriptRoot
    }
}
$ReadinessTestExe = '"C:\Program Files (x86)\Microsoft Readiness Toolkit for Office\ReadinessReportCreator.exe"'
$ReadinessTestArgs = "-addinscan -mru -silent -output %TEMP%"
$StartupPath = "$env:Programdata\Microsoft\Windows\Start Menu\Programs\Startup"

New-Item -Path $StartupPath -Name Readiness.bat -ItemType file -Force
Set-Content -Path $StartupPath\Readiness.bat -Value "
@echo off
$($ReadinessTestExe) $($ReadinessTestArgs)
rm $($StartupPath)\Readiness.bat
"

$DateInAWeek = (Get-Date).AddDays(14)
$DateToString = "<StartBoundary>"+ ($DateInAWeek | Get-Date -Format yyyy-MM-dd)

(Get-Content -Path ($PathToScript+"\DeleteReadinessStartupBat.xml") -Raw) -replace "<StartBoundary>2020-02-29",$DateToString | Set-Content ($PathToScript+"\DeleteReadinessStartupBat.xml") -Force
Register-ScheduledTask -xml (Get-Content ($PathToScript+"\DeleteReadinessStartupBat.xml") | Out-String) -TaskName "Delete Readiness Startup Bat" -Force
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2020-02-12T12:58:05.3085628</Date>
    <Author>Martin Himken</Author>
    <Description>Deletes C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\Readiness.bat</Description>
    <URI>\Delete Office Readiness Toolkit bat</URI>
  </RegistrationInfo>
  <Triggers>
    <TimeTrigger>
      <StartBoundary>2020-02-29T12:00:00</StartBoundary>
      <Enabled>true</Enabled>
    </TimeTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>S-1-5-18</UserId>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>cmd</Command>
      <Arguments>/c del "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\Readiness.bat"</Arguments>
    </Exec>
  </Actions>
</Task>