I demoed this at MMS Jazz 2019 Tip and Tricks. This is Part 1 of a 3-part series. Part 2 covers creating an Azure Function. Part 3 covers how to create a Power BI function to use an Azure Function.
If you have ever checked the logs in ConfigMgr, you’ve likely run across an error code in a format like 0x87D00664
or -2016410012
. If use the error lookup feature in CMTrace, you can generally convert the error to plain text. In the ConfigMgr console, if you are looking at deployment statuses or even SSRS reports, you will see the plain text listed, but that data doesn’t exist in the database.
When I started trying to build a Power BI report to provide detailed status messages for Windows 10 Feature Updates, I discovered that the plain text wasn’t in the database as I expected. I decided to see where the existing SSRS reports got the data so I opened the Troubleshooting 2 - Deployment Errors report from the ConfigMgr Console. Using the queries from that report, I began to build my Power BI report. However, whenever I got to the Error Description field, I realized that the query used by the dataset doesn’t actually include the text, just the error codes!
I discovered that the Error Description column in the SSRS report references a DLL using this expression =SrsResources.Localization.GetErrorMessage(Fields!ErrorCode.Value,User!Language)
.
The DLL is SrsResources.dll
and can be found in the bin
folder of you ConfigMgr console installation directory. I was intrigued. As I began searching the web for this DLL, I found several posts which used it in PowerShell, so I started testing with it. It turns out, this file has a lot of power. Not only can it look up error codes, but it can look up a number of items including Status Messages.
Using PowerShell to Return Error Messages
You can load the DLL into PowerShell and list the available methods. Some of them are for internal use of the DLL (or so it seems). Run this code block at the top of your script to load the dll into PowerShell.
You can load the DLL into PowerShell and list the available methods. Some of them are for internal use of the DLL (or so it seems).
|
|
The list of available methods:
|
|
To get the parameter options for each method, you can simply reference the Method name without () like: [SrsResources.Localization]::GetErrorMessage
|
|
The method this post will focus on mostly is GetErrorMessage
, but the GetStatusMessage
method is pretty sweet too. If you pass values to these two methods, you will get something like this:
A quick note about GetStatusMessages
. If you run it without it’s last parameter, you will get something like this:
The % values are expecting values from the status message Insertion Strings. Run this SQL query SELECT * FROM v_StatMsgWithInsStrings
and you will see the columns InsString4 through InsString10. The values in this view all can be passed to the GetStatusMessages method to populate the placeholder % values like this:
|
|
Sourcing the Files
I want to use this on machines where I don’t have the ConfigMgr console installed but I discovered that SrsResources.dll doesn’t work on it’s own. It references a number of other files and these files must be present with the DLL anywhere you want to run it that doesn’t have the ConfigMgr Reporting Services role or ConfigMgr admin console installed. Copy all of the files from these locations to the same location as your PowerShell script. I am using a C:\Temp
. Be sure to retain the folder structures for the source files.
It’s also worth noting that if you don’t need multiple languages, you can just grab the folders corresponding to your language code. It may take some trial and error to find the right ones, so I just grabbed them all. I also noticed that in my env, Some language codes didn’t work with the DLL. Your results may vary.
Copy the following files/folders to C:\Temp\Bin
E:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\SRSResources.dll
E:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\AdminUI.UIResources.dll
This folder i386
and subfolders with folder contents (don’t grab anything in the root of this folder)E:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\i386
This should be a directory on your Reporting Services server.
This folder and all contentsE:\Program Files\SMS_SRSRP\Resources
E:\Program Files\SMS_SRSRP\resources\DatabaseResources.dll
C:\Windows\system32\wbem\wmiutils.dll
The final folder structure should look like this:C:\Temp\Bin\
C:\Temp\Bin\i386
C:\Temp\Bin\i386\00000404
C:\Temp\Bin\i386\00000405
C:\Temp\Bin\i386\00000407
C:\Temp\Bin\i386\00000409
C:\Temp\Bin\i386\0000040C
C:\Temp\Bin\i386\0000040E
C:\Temp\Bin\i386\00000410
C:\Temp\Bin\i386\00000411
C:\Temp\Bin\i386\00000412
C:\Temp\Bin\i386\00000413
C:\Temp\Bin\i386\00000415
C:\Temp\Bin\i386\00000416
C:\Temp\Bin\i386\00000419
C:\Temp\Bin\i386\0000041d
C:\Temp\Bin\i386\0000041f
C:\Temp\Bin\i386\00000804
C:\Temp\Bin\i386\00000816
C:\Temp\Bin\i386\00000c0a
C:\Temp\Bin\resources
C:\Temp\Bin\resources\115
C:\Temp\Bin\resources\2000
C:\Temp\Bin\resources\2000\00000409
C:\Temp\Bin\resources\2001
C:\Temp\Bin\resources\2002
C:\Temp\Bin\resources\2002\00000409
C:\Temp\Bin\resources\36
C:\Temp\Bin\resources\StatusMessages
C:\Temp\Bin\resources\StatusMessages\00000409
Custom Error Lookup Script
Now that we have all of the files, we just need an easy to call script that will give us the error message text. This script will be the basis for the Azure Function in my next post.
|
|
Save the file into the root of the directory where your source files are and call it from the PowerShell command line.
.\Get-ErrorMessage.ps1 -ExitCode '0x87D00664' -Language 'en-US'
Summary
This post has ended up much longer than I expected and has been ‘in progress’ for a few months now. I’m going to stop here on this one.