Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell 3.0 to compare modern app installation on two computers.

Hey, Scripting Guy! QuestionHey, Scripting Guy! We have a small cadre of rogue users at work. They work in engineering, and they seem to act like they are beyond the realm of normal IT control. In fact, when they were told that they could not get new computers last year, they went to a computer store with their corporate AMX card, and they bought cases, power supplies, motherboards, memory chips, video cards, and solid-state drives as “spares” for their systems. I reviewed the invoice so I know that they built a couple of super systems to play with.

All that is history and “water off a beagle” as they might say, but here is the dilemma…

They are completely unreliable. They have been “evaluating” Windows 8 for some reason, and I fear they are violating company policy by downloading applications that are not approved by our standard computer use policy. I want to know what they have been installing, so I can compare it to my Windows 8 system because I am in-policy, so to speak. I know that System Center Configuration Manager would be ideal for this, but they have kicked all management tools from their realm—although, I do have admin rights over there in engineer land.

—JJ

Hey, Scripting Guy! Answer Hello JJ,

Microsoft Scripting Guy, Ed Wilson, is here. Thank you for bringing up bad memories. When I was a net admin there were two guys—one named Casey, and the other I want to call Dwight, but I am not sure of that one). I remember Casey because of a poem my father used to read to me when I was a little guy. It was called Casey at the Bat, and it was written by a poet named Ernest Lawrence Thayer. Casey was an overconfident ball player, and he ended up striking out and losing the game for the home team.

You don’t want these two guys letting the good old Mudvillle Nine down. Luckily, because they are using Windows 8, and you have admin rights to the boxes, you will not have any problems checking up on these users.

Don’t use the Win32_Product WMI class to query legacy software

In the past, I might have used the WMI class Win32_Product cmdlet. A most excellent guest blog written by Mark Carter, Use PowerShell to Quickly Find Installed Software, points out the dangers of using that WMI class due to the reindexing that it triggers. A better way is to use Windows PowerShell to read the uninstall keys from the registry. This provides a more complete list of software (and it ends up being the technique that is recommended by Marc in his blog).

In Windows 8 and Windows Server 2012, if you are interested in classic applications, you can still use the Win32_Product cmdlet. Just realize that it is slow and it reconfigures each application as it progresses. This is shown here where I used the Get-EventLog cmdlet to retrieve the 1035 events occurring on a specific day.

Get-EventLog application -InstanceId 1035 -After 9/24/12

Index Time          EntryType   Source                 InstanceID Message

 ----- ----          ---------   ------                 ---------- -------

   669 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

   668 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

   667 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

   666 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

   665 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

   664 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

   663 Sep 24 10:42  Information MsiInstaller                 1035 Windows Inst..

Knowing that I am retrieving information from September 24, that the messages come from the MSiInstaller, and that they are Event 1035, I can now dig into the text of the message. I do this with the command that follows.

PS C:\> Get-EventLog application -InstanceId 1035 -After 9/24/12 | select message

 

Message

-------

Windows Installer reconfigured the product. Product Name: Microsoft Silverlight. ...

Windows Installer reconfigured the product. Product Name: Microsoft Office Proofi...

Windows Installer reconfigured the product. Product Name: Microsoft Office Proofi...

Windows Installer reconfigured the product. Product Name: Microsoft Office Proofi...

Windows Installer reconfigured the product. Product Name: Microsoft Shared MUI (E...

Windows Installer reconfigured the product. Product Name: Microsoft Proofing (Eng...

Windows Installer reconfigured the product. Product Name: Microsoft Lync MUI (Eng...

Windows Installer reconfigured the product. Product Name: Microsoft Word MUI (Eng...

Windows Installer reconfigured the product. Product Name: Microsoft Groove MUI (E...

Windows Installer reconfigured the product. Product Name: Microsoft Outlook MUI (...

Windows Installer reconfigured the product. Product Name: Microsoft Publisher MUI...

Windows Installer reconfigured the product. Product Name: Microsoft PowerPoint MU...

Windows Installer reconfigured the product. Product Name: Microsoft Access Setup ...

Windows Installer reconfigured the product. Product Name: Microsoft Excel MUI (En...

Windows Installer reconfigured the product. Product Name: Microsoft Shared Setup ...

Windows Installer reconfigured the product. Product Name: Microsoft Access MUI (E...

Windows Installer reconfigured the product. Product Name: Microsoft InfoPath MUI ...

Windows Installer reconfigured the product. Product Name: Microsoft OSM UX MUI (E...

Windows Installer reconfigured the product. Product Name: Microsoft OSM MUI (Engl...

Windows Installer reconfigured the product. Product Name: Microsoft Shared 32-bit...

Windows Installer reconfigured the product. Product Name: Microsoft Office 32-bit...

Windows Installer reconfigured the product. Product Name: Microsoft OneNote MUI (...

Windows Installer reconfigured the product. Product Name: Microsoft Professional ...

Windows Installer reconfigured the product. Product Name: Microsoft DCF MUI (Engl...

Unfortunately, this sort of reconfiguration occurs every single time you query with the Win32_Product WMI class. This can take a toll on a heavily loaded server. But JJ, you are interested in examining what modern applications your dynamic duo installed on their rogue systems. This is easy…

Use the Get-AppxPackage cmdlet for modern apps

The cool thing about modern apps is that they have modern Windows PowerShell cmdlets to help us work with them. For example, if I want to see what modern apps I installed on my machine, I use the Get-AppxPackage cmdlet. If I want to see all the packages installed by all users of the machine (for example, from other profiles), I need to start Windows PowerShell as an administrator, but then I only need to use the AllUsers switch as shown here.

Get-AppxPackage  -allusers

The command and the associated output are shown in the image that follows. Notice that in the PackageUserInformation property, you can find user names and SIDS of users that have that package installed. Pretty cool huh?

Image of command output

Compare modern app installations on two computers

When working with remote machines, the first thing I do is store the credentials I will use in a variable. Normally the variable name is $cred because it is close enough to credential to not be confusing, yet short enough to not take up too much space on the command line. The command shown here stores the credentials.

$cred = Get-Credential nwtraders\administrator

Now I use the Invoke-Command cmdlet to run the Get-AppxPackage command on the two remote computers. I use the alias icm for Invoke-Command, and I supply the stored credentials. Because I am only running one command, I store the results in a local variable. This command is shown here.

$apps = icm {Get-AppxPackage} –cn c1,c2 –cred $cred

Now I filter out the apps that are stored on each computer, and I put the returned objects in a variable. The two commands are exactly the same; therefore, I am repeating only one of the commands.

$c1apps = $apps | where pscomputername –eq cq

Now I use the Compare-Object cmdlet to compare the two objects. The first attempt seems to work, but not really well. So I repeat the command a second time to reference the specific property I want to compare. The command is shown here.

Compare-Object –property name –referenceobject $c1apps –difference $c2apps

The image that follows shows the commands and the associated output. Note the direction of the arrows under the side indicator. This tells me that the BingSports and the ZuneMusic modern apps are present on C1, but they are not present on C2.

Image of command output

JJ, that is all there is to using the Get-AppxPackage cmdlet , Invoke-Command, and Compare-Object to compare systems.

Join me tomorrow when I kick off an excellent series of blogs written by Microsoft PowerShell MVP, Sean Kearney, about writing cmdlets. It is good stuff, and you do not want to miss it.

Until tomorrow, I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy