Monday, March 27, 2017

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-object command, usually aliased to where or just ?
Here’s what the where command looks like in action:

The downside to using where to 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-table command.

Note that we can use the –property flag 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-csv command.   Instead, we use the select command from earlier to pick out the values we want, and pipe that to the export-csv command.

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! 

Thursday, March 2, 2017

Distribution Point Migration Tool-Kit

The toolkit can be downloaded from my Technet Gallery HERE
This post is a long time in coming, but creating something robust enough to work in most environments that's still user friendly (with associated documentation) can take a little bit of time.  In the course of one contract I've worked, we realized that we needed a way to convert old Secondary SCCM sites into Distribution Points, but we wouldn't be given any new servers to migrate to. We also knew that the WAN links connecting these remote sites back to our headquarters were severely lacking.  Our solution was to prestage all the content currently stored on the content libraries so we could strip off all the roles (which would clear the SCCM content library), remove unneeded programs and features, add the servers back as Distribution Points, and then reload the prestaged content so it wouldn't have to transfer over our unspeakably slow WAN connection. We got a peek at this work with my last post of the SCCM Universal Prestage script, but this post will give you the other pieces of the puzzle.  

The Core Functions


Initialize-Toolkit
                This is the first function you call if you’re running the Migration Kit from a PowerShell window you didn’t summon up from inside the Configuration Manager console.  This function will verify that you have Administrator rights, will seek out and import the Configuration Manager module, and will map your CMSite PSDrive if you don’t already have it mapped. This function is also called within every other function after a quick check to make sure that the CMSite drive is mapped.  If it isn't mapped, it calls the Initialize-Toolkit function and maps it. 
 Console run without admin rights
Console run without admin rights

After the drive has been created

Get-DPContent
                The second function in the toolkit will query our primary site server and return a list of all content that is assigned to the distribution point we provided.  There are multiple ways to get this information. I’ve seen it done with Get-CMDeploymentPackage cmdlet since that will also return package type information that we’ll need later.   However, I chose to do it via the SMS_DPContentInfo WMI class because I find that it returns the same level of information, but does so in roughly 1/3 the time.  It also means that you can run the command without needing to be connected to the CMSite drive if you don’t want to fully initialize everything. 
 A simple report of package ID's and names

An example of the data stored by SMS_DPContentInfo
Prestage-Content
                This is one of the ‘heavy lifters’ of the toolkit.  This function requires a package ID number, the Distribution Point containing the package, and the folder you want it dumped to after creation. What this creates is a PKGX file named with the package ID of whatever you prestaged.  The way it decides what to prestage is based on the PackageType value that comes from WMI’s SMS_PackageBaseClass. Again, you can get a package type identifier from Get-CMDeploymentPackage if you’d rather go that way, but I like WMI.  Once it’s pulled the PackageType value, it runs it through a SWITCH command and runs the appropriate Publish-CMPrestageContent command.  I don’t do any special logging with this function since Publish-CMPrestageContent already does a good job of it.
 Prestaging a single file

Prestaging multiple packages with a For Loop

Restage-Content
                This function is one of the main reasons I like to save my prestage files with the PackageID as the name.  You input the folder containing the prestage files as well as the name of the Distribution Point they need to be assigned to, and this will get the package type information for that package, run the same switch as Prestage-Content, and issue the Start-CMContentDistribution command with the appropriate flags.  Just to save time, it will also query the Get-DPContent function to make sure that it isn’t trying to reassign packages that are already assigned.
Packages were already assigned in SCCM

 Package distribution in progress

Extract-Content
                This function calls upon Microsoft’s ExtractContent.exe tool to run, and is designed to be run locally from whatever DP you’re importing the package to.  The only flag you need to specify is the location of the prestaged content folder.  It takes the hostname of the computer it’s running from and makes a WMI query to see any packages assigned to it that aren’t in State 0.  If the package shows as state 0, then there’s no further work to be done, and we can just work on the others.  There are multiple ways you can run the extractcontent.exe tool, but I’ve found some to work better than others.   Whether you run it specifying a single package to extract or you run it with an entire folder targeted, I’ve found that when I check the Distribution Point Configuration Status in the SCCM console, there’s always some that still show “waiting for prestage content.”  In almost every case where that’s happened, just re-prestaging the content cleared it up. I don’t know if this is a limitation of the extractcontent.exe tool, my impatience, or what, but it works for me.  Because of that, I actually have my Extract-Content function run through the Prestage content folder one item at a time, so you can re-run the function, it will re-query for unsuccessful packages, and only attempt to extract the packages that didn’t make it the first time.
 
ExtractContent running

Example

Stage-LocalDPContent
                I put this together for our SCCM architect who wanted something that he could quickly and easily run while logged into our Secondary Site Server that was being migrated.  What this does is query the local DP for all assigned content, export it with the Prestage-Content function, and give you a progress bar to show you how far along you are.