Quick and Dirty SCCM Application Deployment Reporting

, , , ,

For this blog, I’m going to go over a very basic script I wrote to quickly get application deployment statuses without having to use the Configuration Manager GUI console. I find the ReportingDeployments tab very slow to respond, and you still have to dig into each individual app if you want details.  What this function does is allow you to specify what you think is the name of the application and it will find anything like it, allow you to select the one you want, and then it will run a deployment summarization and output the results.

Examples:

Application Deployment
Function called with the correct name of the package

In this example, “Tanium Client” is the actual name of a software package, so it doesn’t need to pop up a prompt asking us which one we actually wanted.

Application Deployment
Function called with a keyword instead of the full package name
Application Deployment
After package was selected from the pop up
In the above two images, I didn’t remember the full name of my Tripwire deployments, so I just typed “Tripwire” and let it look for it for me.
The Code:
 
This is a fairly simple piece of code, but I wrote it to run quickly.  It first checks to see if the name you gave it when running already matches a software package. If not, it runs a WMI query (much faster than using Get-CMApplication with a where-object piped on) to look for anything like what you entered. It puts all results into an array which then selects the LocalizedDisplayName and filters out duplicates. Those unique values are then handed over to Out-GridView, which thanks to the -passthru flag assigns the selected result to our original $SoftwareName variable.  You’ll also see that I have to specify that I want the “.localizeddisplayname” NoteProperty. If you don’t do this, you’ll see the selected software name as “@LocalizedDisplayName={‘Whatever your name was’}”
After that selection process, everything proceeds as normal. It gets the CMDeployment object for that application and runs the Invoke-CMDeploymentSummarization cmdlet which refreshes the deployment status, gets you current numbers, etc.  After that, I have it get the deployment again and select what I found to be the relevant values for a list formatted report.  Because SummarizationTime is done in UTC, I have it convert to client local time for ease of reporting, and I also go ahead and do a quick math expression for the percent success, which is done with the Round function so we don’t get a dozen decimal places of needless precision.   The Query Time value was mostly tacked on at the end so the people I was getting this information for could see that the data was current.
Hopefully this is useful for someone out there. Thanks for reading!

WMI for Dummies

, , ,
WMI for Dummies
Part 1 – Basic Queries
To query WMI, you need to use the Get-WmiObject cmdlet.  An example is below:
No special formatting, filtering, output, etc.   A call to WMI like this will only query your local machine. If you’re trying to get information from a remote computer, then you need  to use the –ComputerName flag.  Be warned, that the credentials that work for your computer might be completely worthless on another machine.  If that happens, you’ll see an error like this:
You have some options when this happens, you can either open a new PowerShell window with the “RunAs” right click option and enter your credentials at that point, or you can use the –Credential flag to enter them on the fly.
That should be enough to give you a basic understanding of how to query WMI on your computer and remote machines.
Part 2 – Filtering Results
Sometimes when you query WMI, you’ll get a ton of results back. Easy examples of that are the Win32_Product class (a list of everything in Add/Remove programs), or our example, the Win32_NetworkAdapter class.
There are three typical ways of filtering WMI results. The first is with a pipe to the where-objectcommand, usually aliased to where or just ?
Here’s what the wherecommand looks like in action:
The downside to using whereto filter your results is that the first command will complete before the filtering is performed. This means that if you’re filtering against a giant list, that entire list has to be generated before it can even start filtering.   For things like our Win32_NetworkAdapter class, that isn’t a big deal, but if you’re filtering a few machines out of your entire SCCM SMS_R_Device database, it’s highly inefficient.  When you have giant datasets to filter against, you’re usually better off filtering the list as it’s being generated. The first example of this is the –filter flag.
Notice that when we use the where command, the filtering is done with “-like” and the “*” symbol , while WMI filtering has no “-“ and uses “%” instead.  We can also use the –query flag to construct the entire command as a WQL query statement.
That should give you a basic idea of how to filter your WMI search results.
Part 3 – Selecting Output
Up until now, we’ve just taken our output however WMI decided to give it to us, which was usually List format.  When looking for a lot of detail about one or two specific results, List is a great format, but when you’re getting data about more than a couple items, you usually want them as a Table.   If you just want to select one data point about your results, there are three main ways of doing this. The first is to pipe your output to the select-object or select command.
Now, we just have the Name value.  You can also do your selection from within a WQL query statement.
What you’ll notice with both of those options is that there’s some header information that comes along with the value you wanted. Personally, I like to use this method of calling out one specific value:
As you can see, that just returns the value we requested with no other information coming along for the ride.
Part 4 – Formatting and Exporting
Now, we’ve done some basic formatting by only selecting values we needed, but let’s say your SCCM architect really wants a nice report to show off and has come to you about it.  For this example, let’s say he wants a list of all the network adapters on your computer that actually have physical addresses.  Here’s what that statement looks like.
That gives us our dataset to work with, but it’s unformatted.  To format it in a report-friendly way, we pipe it to the format-tablecommand.
Note that we can use the –propertyflag to specify which values from the dataset we want to display. Now, if you want to export this as a CSV, you can’t just pipe your format-table command to the export-csvcommand.   Instead, we use the select command from earlier to pick out the values we want, and pipe that to the export-csvcommand.
You’ll get no output on your screen (assuming you typed it all in correctly), but when you open the CSV you created, you’ll see your data.
You may be wondering about the –notypeinformation flag. That’s to stop your CSV file from having weird header information in the first row like this:

 

Hopefully, that gives you some basic information to start with. WMI is one of those commands that just don’t have great documentation within the Get-Help command because each class has its own quirks, values, etc.  Microsoft does have excellent documentation for each class if you have a basic understanding of how WMI works, so just go to Google® and type in the exact name of the class you’re querying to see it.
Any further questions, just let me know!