Script OffCAT for use in an Enterprise
The Microsoft Office Configuration Analyzer Tool (OffCAT) is a powerful tool that detects several hundred known issues about Office programs and displays the results (in a scan report) with a solution link to for each detected issue. The report also includes a detailed tree-report display of several thousand configuration settings from the scanned machine as well as the results of a Calendar scan (using CalCheck) when Outlook is the scanned program. But, there are some important factors to consider when using OffCAT in a global enterprise with many subsidiaries/locations and users with varied technical backgrounds.
Not all users in the enterprise may have Internet access
You want to hide the detailed OffCAT scan results from the user
You want to minimize the administrative overhead when creating packages for each new OffCAT version
If any of these items are a concern for you, then one approach is to script the command-line version of OffCAT instead of installing the OffCAT program on Office clients. Then, Help Desk personnel can open the scan results in the full OffCAT client to determine the follow-up resolution/troubleshooting steps for the user. Briefly, the script can:
Copy the needed OffCAT files from a network share to the client on which the script is being run.
Start the OffCAT scan using the command-line executable OffCATcmd.exe.
Email the results to a Help Desk distribution group.
In this blog post, the different components of an example script (attached) are provided and discussed so that you follow along with the explanations provided below. Then, you can develop your own script based on these building blocks and ideas.
Example script solution
Use the following steps to implement a scripted solution for OffCAT.
Create a network share where all clients that may be scanned have Read access.
If done correctly, it should look like this:
To do this you need to download and install OffCAT. Use the installed files as a source for the files you copy to the share. After doing this, you should have created the above file and folder structure in the share.
- Determine the scope of the script.
But, before you code the script, a few decisions have to be made:
-
- Decide what applications you want to scan.
It is possible to scan just one Office program, all Office programs, or every possible subset of Office programs . In our script example it is possible to scan one Office program or all Office programs.
-
- Determine the Office Version you need to scan.
Maybe you have a mixed environment where different Office versions are installed. In our example, we scan Office 2013 if it is installed. If not, Office 2010 is scanned.
-
- Know the Type of installation that has to be scanned.
You may mix C2R-Installations and MSI-Installations within your company, but it is not possible to mix it on one client. So, you may need to check for the Office installation Type on the machine. The command-line argument for OffCATcmd.exe requires that you specify the installation Type that's being scanned.
-
- Decide how to start the script and handle the completed scans.
Since you are proobably trying to limit the amount of effort required by end-users, you can start the script using a link provided to the user (by email?) and you can also email the scan results back to the Help Desk.
For our solution, we send an email message to the client with a link to the script. The script also includes the option to either automatically reply back with the scan file attached (as .zip) or not respond back at all (leaving the file(s) on the drive).
-
- Pick a scripting language you will use to build the solution.
We recommend PowerShell for maximum forward-compatibility. When you use PowerShell the access policy needs to be considered to secure the solution. For example, the script needs to be signed.
After you have decided on these things, you can start to code.
- Create the script
After the necessary OffCAT files are copied to a network share and you have decided the scope of the script, the next step is to create the script.
We start the sample script by defining an enum for the different Office applications we want to scan. In this case, we created the enum to be able to scan everything (All) or one single application.
Add-Type -TypeDefinition @"
public enum OfficeApp
{
All,
Access,
Excel,
InfoPath,
OneNote,
Outlook,
Powerpoint,
Publisher,
Word,
Visio
}
"@
Then, we create one enum for the Office Version. We need to scan either Office 2010 or 2013.
Add-Type -TypeDefinition @"
public enum OfficeVersion
{
O14 = 14,
O15 = 15
}
"@
The function to start the scan comes next:
function runoffcat{
To keep a large number of scans organized when the Help Desk is reviewing OffCAT scans using the full OffCAT client, there should be a uniquie “speaking name” for every scan. In the script, the scan filename includes the scanned Office Application (the function gets as an argument), the machine name and the timestamp when the scan was taken:
$resultfile = $args[0]+'_'+$machinename+'_'+(Get-Date -format dd-mm-yy)+'.xml'
OffCATcmd.exe requires several command-line arguments. The values are set in the management part of the script and result is used here.
- The Office version that will be scanned as argument by calling the function:
$args[0]
- Office version that will be scanned:
$OVersion.value__
- The type of the installation:
Installtype msi'
- A few needed Parameters(For detailed descriptions, see OffCAT v2.1 ReadMe.docx):
-AE -ND -NoRTS
- And the location to save the scans:
$resultpath and $resultfile
This all combines to one Parameter String, that can be passed to the commandlet (for -ArgumentList).
$offcatargs= '-cfg '+$args[0]+' -gs MajorVersion '+$OVersion.value__+' Installtype msi','-AE','-ND','-NoRTS','-dat "'+$resultpath+"\"+$resultfile+'"'
Use the Start-Process Commandlet to start the OffCATcmd, pass the Arguments and control the number of windows, that are opened.
Start-Process $localpath\Offcatcmd.exe -ArgumentList $offcatargs –NoNewWindow
Then, wait for the running OffCATcmd process until going on. (There is only one OffCATcmd.exe process that can be running at one time.)
$proc = Get-Process OffCATcmd
Wait-Process -InputObject $proc
}
This was the heart of the solution. Now the management part should be defined.
The first step are the Parameters we need. These you can take from the decisions discussed previously:
param(
[Parameter(mandatory=$true, Position = 1)] [OfficeApp]$toScan,
[Parameter(Position = 2)] [boolean]$Mail = $false,
[Parameter(Position=3)] [OfficeVersion]$OVersion = [OfficeVersion]::O14
)
At the beginning of the script development we wanted to start the script from an email message sent to the user and and then a replying email to the sender would include the scan result. After a time using the script we decided to include the option to use it without email. Otherwise, it is only possible to run a scan when Outlook is working!
" UseOffcat for Office Apps:"+$toScan +" Office Version="+$OVersion+" and send a Mail:"+$Mail.ToString()
#Check only for outlook if a Mail should be sent
if ($Mail -eq $true)
{
#Create Outlook Object - Mail is opened becaus clicking the link initiates the Process
$outlook = New-Object -ComObject Outlook.Application
#Ticketnumber and Sender read from Mail with Link - Should be active Mail in Explorer no matter if the Mail is opened in Inspector or not
$Exp = $outlook.ActiveExplorer()
$prev = $Exp.Selection.Item(1)
if ($prev.MessageClass.ToString() -eq "IPM.Note"){
$sender = $prev.SentOnBehalfOfName
$TicketNo = $prev.Subject
}
}
That’s why the part for sending the email message is included in a condition.
The check for the installed Office version that is installed may be different depending on the version that is installed. At my customer we needed to check only for Office 2013 (15):
test-path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Office15.PROPLUS
After this, we defined the values for the network source location containing all of the OffCAT source files, and where to temporarily save the files locally on the client that will be scanned.
$srcdir = <Path of the rules files>
$cmddir = <Path of Programm and dll files including tools>
$localpath = (Get-Content env:LOCALAPPDATA) + "\Microsoft\offcat"
$resultzip = <Name of compressed resultlile>
Note, it is possible to use the files directly from the share to do the scan; however, we recommend copying the files to the client. In our tests we had various problems when we did not copy them locally. This is why we decided against using the files directly from the network share.
if (test-path $localpath){remove-item $localpath -Recurse -Force}
New-item -path $localpath\Tools\x86 -ItemType directory
New-item -path $localpath\en -ItemType directory
foreach ($item in (Get-ChildItem $srcdir)) {
Copy-Item $item.FullName $localpath\en
}
foreach ($cmditem in (Get-ChildItem $cmddir)) {
if ($cmditem.Extension){
Copy-Item $cmditem.FullName $localpath
}}
foreach ($cmditem in (Get-ChildItem $cmddir\Tools\x86)) {
Copy-Item $cmditem.FullName $localpath\Tools\x86
}
Before scanning Office there are a few variables we need to define and then we can check the Parameter for the Office Application that should be scanned. We create a condition if we need to scan everything or just one Application. If we need to scan everything we loop through the enum and scan for every Application in the enum.
If($toScan -eq [OfficeApp]::All)
{
Foreach ($Oitem in [OfficeApp].GetEnumValues())
{
if(-Not ($Oitem -eq "All"))
{
runoffcat($Oitem.ToString())
}
}
} else {
runoffcat ($toScan.ToString())
}
After the scans are complete we compress the results. To do this we use the assembly for creating zip files (System.IO.Compression.FileSystem)
If we do not email the results we copy the zip file to the temp folder (%temp%), and then we can delete the OffCAT-files at the end.
"Creating compressed file"
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
if ($Mail -eq $true)
{
[System.IO.Compression.ZipFile]::CreateFromDirectory($resultpath, $localpath+$resultzip)
} else {
"No Mail sent, so create the zip in temp directory"
(Get-Content env:temp)+$resultzip
if (Test-Path ((Get-Content env:temp)+$resultzip)) {remove-item ((Get-Content env:temp) + $resultzip) -Force}
[System.IO.Compression.ZipFile]::CreateFromDirectory($resultpath, ((Get-Content env:temp) + $resultzip))
}
The next step is to send the results by email (if this option is enabled).
if ($Mail -eq $true)
{
#Mail to sender including the Ticketnumber (in subject)
"Start sending mail"
$mail = $outlook.CreateItem(0)
$mail.To = $sender
$mail.Subject = $TicketNo
$mail.Body = "Das Offcat Ergebnis "
$mail.Attachments.Add($localpath+$resultzip)
#save the mail if anything happens during the send process
$mail.Save()
$mail.Send()
"Mail with offcat logs sent"
}
At the end, all files that were either copied down from the network share or created during the scan are deleted.
if (test-path $localpath){remove-item $localpath -Recurse -Force}
This way, there are no OffCAT files left on the client after the scan.
Maintenance items
There are two things to maintain when choosing this solution for your company:
Keep the rule files in the source directory up-to-date
Change the exe files and dll files if there is a new version of OffCAT available
You should run OffCAT at least a couple times each month to see if new rule files are available or if the application version has changed. Click the ‘About OffCAT’ control on the OPTIONS page to get the version numbers of the rule files and the OffCAT application.
In our environment, we use one installation of OffCAT that will be updated to get the actual rule files. Those files are copied to the share.
Joachim Fumy
Comments
- Anonymous
February 09, 2016
Awesome!!!!!
Post more articles. I would love to see more documentation on this tool out there. I want my team to jump on board with using this tool more.
Can we get a blog series basically splitting the read-me up into sections with some real-world (lab cough* lab* cough) examples??? :D :D