Windows 10 Soup Sandwiches

Version 2.1 (I lost Version 1.0 somehow, from the old blog, but it was focused on Windows 7, 8.1 anyway)

An ad hoc collection of wine-infused recipes to help smoosh Windows 10 like a ball of clay, or like a soggy sandwich.

Disable Windows Firewall (MDT, SCCM)

Disable Windows Firewall (GPO)

Disable Windows Defender (GPO)

Deploy .NET Framework 3.5 with Feature on Demand (GPO)

Enable Controlled Folder Access (GPO)

Create Shortcuts on Desktop, Start Menu (GPO)

Disable IPv6 (GPO)

Configure, Start, Stop Windows Services (GPO)

Block and Disable Cortana (GPO)

Set default Web Browser (GPO)

Waste Time Customizing the Start Menu and Taskbar (GPO, Script, MDT, SCCM)

Configure OEM Support info and Company Logo on Support page (GPO)

Block Windows Store and Store Apps (GPO)

Remove Store Apps during Imaging (MDT, SCCM, etc.)

Remove OneDrive from File Explorer (GPO)

Show File Extensions in File Explorer (GPO)

Show Hidden Folders and Files in File Explorer (GPO)

Show File Explorer Menu Bar (GPO)

Expand to Current Folder in File Explorer (GPO)

Customize and Push BGInfo to Desktops (script)

Customize and Push BGInfo to Desktops (GPO)

Destroy and Annihilate SMBv1 by any means necessary

TLS Configuration Guidelines (hotfix, registry, GPO)

Create and Configure a Group Policy Central Store

Updates 2.1

Add Domain User to Local Administrators Group (GPO)

Add Domain Users to Remote Desktop Users on Servers (GPO)

Modify Registry Key Permissions on Domain Computers (GPO)

Create Scheduled Tasks using Group Policy (script, GPO)

Configure PowerShell Settings using Group Policy (GPO)

Prompt for Computer Name / OSD Variable in Task Sequence (script)

Mass Upgrade Windows 10 using PowerShell (script)

Replicate MDT Boot Images to multiple WDS/PXE servers (script)

Set Google Chrome as Default Browser (GPO)

More to be added (version will be updated too)

Advertisements

ConfigMgr Script Deployments

Introduction

The following caffeine-induced mess was the result of a quick demo session conducted with a customer about the use of the new “Scripts” feature in Configuration Manager 1710+.  There are other examples floating about the Internet which are equally good, if not better, but just finished unpacking, doing laundry, walking the dog, and needed something to do.

What is it?

The new “Scripts” feature allows you to perform “real-time” execution of PowerShell scripts against a Device Collection or individual members of a Device Collection.  It is worth noting that you cannot deploy to individual Devices from within the Devices node of the console, it only works from within, and beneath, the Device Collections node.  The script is executed on the client remotely, so the shell context is local to the remote client.  This means if you instruct the code to look at C:, it will be looking for C: on the remote device(s).

What Can You Use This For?

The answer to this question depends on your intentions and personality.  If you’re an eager workaholic, the sky is the limit.  If you’re a diabolical evil bastard with malicious thoughts, the sky is also the limit.  Is this potentially dangerous?  Yes.  But EVERYTHING in life is potentially dangerous, even brushing your teeth and going for a walk.  So weigh your risks and proceed accordingly.  I’ve provided a few examples below to illustrate some possible use cases.  Read the disclaimer before attempting to use any of them.

Preliminary Stuff

The first thing you need is to have Configuration Manager 1710 or later.  The second thing you need is to check the box to “Consent to use Pre-Release features” (Administration / Site Configuration / Sites / Hierarchy Settings / General tab).  The third thing you need (for testing anyway) is to un-check the box right below it that says “Do not allow script authors to approve their own scripts”.  If you do not un-check that option, you will be able to create script items, but you won’t be able to deploy them.

The next step is to enable the pre-release feature “Create and run scripts”:  Administration / Updates and Servicing / Features.  Right-click “Create and run scripts” and select “Turn on”. Once you’ve enabled the feature, the first time at least, you may need to close and re-open the console.  This is not always the case it seems, but I have seen this most of the time.

The Process

Create the Script

Once everything is enabled and ready to go, you should be ready to destroy, I mean, ready to begin.

  1. Select “Software Library”
  2. Select “Scripts”
  3. Select “Create Script” on the ribbon menu at top-left (or right-click and choose “Create Script”)
  4. Provide a Name
  5. Import or Paste the script code (only PowerShell is supported as of now)
  6. Tip: Make sure your script code returns an exit code of some sort to indicate success/fail to ConfigMgr (example: Write-Output 0)
  7. Click Next, Next, and Close

Approve the Script

  1. Right-click on the Script item
  2. Select Approve/Deny
  3. Click Next (I still don’t know why, but you have to, at least for now)
  4. Choose “Approve” or “Deny” and enter an “Approver comment”
    NOTE: Many organizations have procedures that require documenting approval authorization directly on the change items involved with a given change.  And to change that would require changing the way you manage change, which would require change management to effect the change and change the way you’re changing things.
  5. Click Next, Next and Close

Deploy the Script

  1. Select Assets and Compliance
  2. Select Device Collections
  3. Navigate to an appropriate device collection
    1. To deploy the script to all members, right-click on the Collection and select “Run Script”
    2. To deploy the script to individual members, select ‘Show Members’, right-click on each member (resource) and select “Run Script”
  4. Choose the approved Script from the library listbox, and click Next
  5. Click Next again (safety switch, good idea!)
  6. Watch the green bar thing slide across the progress banner a few times
  7. When it’s done, review the pretty Bar Chart.

    Select the “Bar Chart” drop-down to change reports to “Pie Chart” or “Data Table” display.
  8. Change the “Script Output” selection to “Script Exit Code” to view results by exit code values.

Parameters

You can include parameter inputs within a script by including the param(…) block at the very top.  As soon as you type in param ( and then enter a variable name, like $MyParam, you should notice the ‘Script Parameters’ node appear in the left-hand panel below “Script”.  Remember to close the parentheses on param ().  This adds a new set of options that you’ll see when you click Next in the Create Script form.

This allows you to make scripts more flexible at runtime, so you can provide specific inputs as needed, rather than making a bunch of duplicate scripts with only minor variations between them.

Examples

So, here are just a few basic examples for using this feature.  You can obviously apply more brain juice to this and concoct way-more amazing awesomeness than this stuff, but here’s a taste.  These are provided “as-is” without any warranty or guarantee of fitness or function for any purposes whatsoever.  The author assumes no liability or responsibility for use,  or derivative use, of any kind in any environment on any planet in any universe for any reason whatsoever, notwithstanding, hereinafter, forthwith, batteries not included, actual results may vary, void where prohibited or taxed, past results do not indicate future performance.

Collect Client Log Files

# Collect-ClientLogs.ps1
# Modify $TargetPath to suit your needs
$SourcePath = 'C:\Windows\CCM\Logs'
$TargetPath = '\\CM01.contoso.com\ClientLogs$\'+$($env:COMPUTERNAME)
if (!(Test-Path $TargetPath)) { mkdir $TargetPath }
robocopy $SourcePath $TargetPath *.log /R:2 /W:2 /XO /MT:16
if (Test-Path $TargetPath) {
  Write-Output 0
}
else {
  Write-Output -1
}

Refresh Group Policy

# Refresh-GroupPolicy.ps1
GPUPDATE /FORCE
Write-Output 0

Modify Folder Permissions

# Set-FolderPermissions.ps1
param (
  [parameter(Mandatory=$True)]
  [ValidateNotNullOrEmpty()]
  [string] $FolderPath
)
if (Test-Path $FolderPath) {
  ICACLS "$FolderPath" /grant 'USERS:(OI)(CI)(M)' /T /C /Q
  Write-Output 0
}
else {
  Write-Output -1
}

Summary

If you haven’t looked into this feature yet, I strongly recommend you give it a try IN A TESTING ENVIRONMENT.

How’s my driving?

Did I miss anything?  Did you find any bugs?  Let me know!

Thank you for reading!

Random Thoughts and Stuff

While packing for travel I was having a conversation around the “state of IT” with a friend. So I figured (A) it might be worth jotting down some of the key points, and (B) do it before I fly out, in case some underpaid mechanic forgets to tighten that one bolt that holds the engine onto the wing.  Actually, who am I kidding, that mechanic probably earns more than I do.  Anyhow…

this is rambling, so drink plenty of medication and smoke your wine before continuing.

(travel-packing sidenote: Oreo is 15 years old, and like most humans, used to hate my guts.  Eventually, as daughter number 3 moved out, and I became her sole source of attention and food, she has become my friend.  She follows me around all day.  Every time she sees my suitcase out the night before I travel, she does this.  I’ll need to go over that ball cap with a ball of tape in the morning.)

The Future of SCCM and MDT and EMS

This is admittedly a Microsoft-centric topic. The discussion mentioned above was about “how long” will SCCM and MDT be “of interest” to consumers?  Obviously, I do not own a real crystal ball.  I only have a Dollar Tree knock-off, and I don’t have access to real business data, therefore I rely upon what scientists often refer to as ‘shit talking‘.

I’ll admit, after day 1 at MS Ignite this year, I was feeling the angst.  For example, while riding the bus back from the conference center to the hotel, staring out the window, I kept thinking “why, why, why did I leave app-dev to move into this infrastructure rat race?!  wtf was I thinking?!” and “I hope my dog isn’t chewing up my last pair of flip flops right now.”  It really felt like the job market for anyone walking around a typical IT shop today, would be dried up to around 10% of that volume within 5 years.  And who really knows?  It could go in any direction.  I think everyone is in agreement that there is already a major tectonic shift in play, with traditional operations moving into software-defined operations.  The thought of learning things like JSON, Git, VSTS, on top of PowerShell and Azure, is adding wrinkles to quite a few faces I see.

The mere mention of “new certs” is probably having a measurable effect on the sales of alcohol, tobacco and firearms, which should keep these guys employed for a long time.  For many I’ve known over the years, the feeling is like being shoved onto a rollercoaster by your drunk buddies, against your will, and now you’re approaching the top of the first peak in the run.

After 3 more days, and soaking up session content, food, beer, and more importantly: engaging vendors in deep discussions out on the expo floor, my initial expectations of SCCM/MDT doom were relaxed quite a bit.  Mainly out of realizing the following points:

  • The majority of imaging work I see being done at most mid-sized and large customers is refresh of existing hardware.  The mix of new vs. reuse is cyclical at most larger shops, due to budget cycles and SLA’s about hardware refresh programs.  So at various times in a given year, there’s more new imaging, but for the remainder of the year it seems to be more refresh/reuse.
  • Most of the (above) people I’ve spoken with are very interested in AutoPilot, but quite a few hadn’t yet been allowed access to the preview at the time I spoke with them (I think most are now seeing it in their portals)
  • In-place upgrades are still a minority (far too low in my opinion)
  • The description of “automatic redeployment” got their attention, but most are still tied to the comfort of a “clean wipe and load” for various reasons.
  • Ultimately: Regardless of what anyone says, things which “work” have a very VERY tough time dying in the IT world.  Hence why so many machines still run XP.  I’d also wager my tombstone that Windows 7 will easy to find running on machines in 2027.  That’s because I’m planning to be cremated on a Walmart grill.  But that’s beside the point.

The weeks after Ignite I’ve made it a point to casually interview my customers to get a feel for where they see the biggest and most immediate changes coming.  It’s a delicate thing to ask, since it can easily smell like a sales pitch.  Sales pitches have a distinct odor that is often confused with bus station toilets or dead cows laying in the sun.  However, most of them are well aware of my dislike for sales people in general (some of my friends are in sales, so there are exceptions).

  • The biggest hurdles they have today are keeping up with device models and drivers, patching, moving to some new system for IT operations (ticketing, change mgt, etc.), and endless training of each new-hire who is replacing three who just left.  See what I did there?
  • The single biggest complaint about imaging in general revolves around drivers.
  • There’s still quite a bit of frustration and confusion I hear around Intune capabilities.  Some is related to Intune agent vs. agentless, management; Some is around app deployment capabilities; Some is inventory reporting.

Windows 10

I still spend way too much time explaining Windows 10 servicing models and the naming convention.  They were just starting to grasp CB, and CBB, but now “Semi-Annual” and “Semi-Annual Targeted” are leaving them in one of two modes: pissed off or chuckling.  The most common response I hear from the former is around the constant renaming of things in general.  “Active, Live, Visual, and now CBB, then Semi Annual Targeted, WUS, then WSUS”, and so on.  Their words, not mine.

I’m always surprised to find so many shops still heavily invested in MDT and doing very well with it.  The other interesting thing is that the majority of them assume they’re doing everything wrong and are panicked when I arrive that I’ll redline their papers.  In fact, most of them are doing very well.  They’ve read the blogs, the tweets, bought the books, watched the videos, done the TechNet labs, and so on.  A few have been lucky enough to attend training and/or conferences as well, but that’s a very small percentage.

The pace at which organizations are getting their Windows 10 rollouts moving is gaining speed and volume.  However, the Office aspect has thrown a wrench into quite a few (see below)

Office

This reminded me of a discussion I had at Ignite with the Office team on the expo floor.  It was around the issue of third-party extensions (add-ons) for Office, and how many are produced by small shops which do not stay current with Office versions.  The result I’ve continued to see is a fair amount of shops who can’t upgrade Office until the third-party vendor puts out an update or a new version.  Then there’s the cost factor (is it free or not?).  In many of those cases, the hold-up triggered the IT department to wait on other projects such as Windows 10.

The number of Access applications interfering with Office upgrades has dropped significantly for me in the past 3 years.  Not just the projects I’m working on, but also from reports I get from other engineers and customers.  That’s a good thing.

Controls vs. Controls

I’m still seeing a continued reliance on inefficient control mechanisms with regards to device and user configuration management.  Way too much effort put into the imaging side, and not enough on the environment side.  Way too much on the “nice to have” side, vs. the “gotta have” side.  Not enough attention is being paid to ‘baseline’ and ‘continuous’ control models, and when to use which one, and how best to apply tools for each.  For example, hours and hours spent on wallpaper, shortcuts, and folders in the imaging process, being manually adjusted with each update cycle, rather than letting Group Policy Preferences step in and mop that shit up with one hand.

I’ve had fairly good results convincing customers to drop the continuous meddling with reference images, instead, (at least trying to)…

  • Change the data storage process to keep users from storing anything valuable on their device
  • Remove as many non-critical configuration controls as possible
  • Move continuous controls to the environment (GPO)
  • Move baseline controls to the environment wherever possible (GPP)
  • Move remaining baseline controls to task sequence steps

There are obviously exceptions that require mucking with the install.wim to make a new .wim, but I’m finding that’s only REALLY necessary in a small percentage of the time.  The vast majority of controls I see are voluntary and serve little functional or operational benefit.  Things like hiding Edge, Forcing IE, hiding Cortana, forcing Start Menu and Taskbar items, etc.  Just educate users to avoid them.  Treat them like adults and who knows, maybe they’ll stop urinating on your office chair.  Try it and see.  The worst you’ll get is whining (you get that anyway), but the best (and most likely) outcome is less work for you and less risk of something breaking.

Role and Salary Compression

It not only continues to thrive, it seems to be accelerating its pace.  Almost every customer I meet tells me how they’re expected to do more with fewer people, less training, less budget, and shorter time constraints.  Most haven’t had a significant raise in a long time.  This seems more prevalent at companies which are publicly-traded than those which are not, but it affects both.  Personally, I see a correlation with public organizations and cost reduction priorities over innovation and revenue increase.  Then again, I have no formal training in such matters, so again, I’m probably talking shit.  Again.

Intune

Speaking of Intune.  I’ve been spending more time with it this past week, along with Azure AD, and AzureADPreview powershell module.  I’ve always like the concept of what Intune and EMS are aimed at. The mechanics are still frustrating to me however.  There are plenty of design quirks that drive me batshit crazy.  Like devices / all devices vs. Azure AD devices, and the differences in how provisioning an app for iOS or Android and Windows, from the Windows Store no less.  As Ricky Bobby would say, “it’s mind-bottling”.

Then again, I’m not at all a fan of the “blade” UI paradigm.  The Blade model is (in my humble, semi-professional, almost coherent opinion) marginally efficient for direct touchscreen use, but for mouse and keyboard it blows chunks of post-Chipotle residuals.  I’m sure that will infuriate some of you.  But that’s just how I feel.  Drop-down menus, panels, heck, even ribbons, are more efficient in terms of hand and finger interaction (mouse, touchpad) for operations involving closely related tasks (settings, options, etc.)  Ask yourself if moving ConfigMgr to a blade UI would make it better?  Or Office?  If you think so, try switching to another brand of model glue.

Back to Intune.  I would really look forward to seeing it mature.  Especially in areas like agent vs. agentless device management (it’s very confusing right now, and the differences are weird), AutoPilot, Redeployment/Reset, and expanding the features for deploying applications, remote management (TeamViewer, etc.), and GPO-to-MDM migration.  I’m thinking Windows desktops and laptops of course (if you hadn’t already figured that out).  Phones are great, but nobody, who isn’t masochistic, is going to write a major app using their phone most of the time.  Auto-correct and latent-rich touch screen typing, would cause most PowerShell, C# or Ruby code writers to massage their head with a running chainsaw.

I think I digressed a bit.  sorry about that.

Other Stuff

I’ve spent some after-hours time keeping my brain occupied with scripting and app-dev projects.  I’ve been doing Windows 10, Windows Server 2016, MDT and SCCM lab builds and demos for months, along with real implementation projects, and starting to burn out on it all.  I needed a break, so I’ve managed to get a few things done and few in the pipeline:

I ran across a couple of (seem to be) abandoned Git projects focused on DSC for building ConfigMgr sites, but none of them appear to be factored into a template construct.  Meaning?  That they’re still built on specific parameters, or require extensive customization for various roles, configurations, environments.  I’m still poking at them and forked one to see what I can make it do.  In the meantime, I’m moving ahead with CM_BUILD and CM_SITECONFIG being merged into a new CMBuild PowerShell module.  So far so good.  And when that’s done, I’ll go back to see what I can in that regard with DSC and applying that towards Azure VM extensions.

I’ve come to realize that there’s 4 basic types of southern dialect in America:  Fast, Slow, Twangy and Crooked Jaw.  Think about it, and you’ll see that’s true.

The shortest distance between two points is often the most expensive.

If you never fail, you’re not trying hard enough.

If you fail most of the time, you’re probably in the wrong career path.

I’m on travel next week.  Expect more of the same stupid tweets about mundane stuff.  If you tire of me, unfollow me.  I don’t mind.  It’s just Twitter after all.  I will do my best to keep my camera ready for anything interesting.  I need to watch some air crash documentaries now, to get my mind relaxed for tomorrow.

FudgePack

Pardon the headline and semi-questionable graphic, but it’s all I had to work with on short notice.

As a result of way too much caffeine, tempered with a sudden burst of alcohol and intense, yet clueless conversation with a colleague, the following hair-brained idea sprang up. This required immediate action, because, stupid ideas have to be enacted quickly in order to produce rapid failures and immediate lessons-learned…

Idea: What if you could manage remote, non-domain-joined, Windows 10 computers from a web page control mechanism, for “free”, where the local user has NO local admin rights, to do things like run scripts, deploy or remove applications, etc.?

What if? Aye?

So, Chocolatey came to mind. Partly because I was eating something with chocolate in it, but mostly because I love the Chocolatey PowerShell packaging paradigm potential, and that’s a heavy string of “P”‘s in one sentence.  Anyhow, it felt like one of those sudden Raspberry Pi project urges that I had to get out of my system, so I could move on to more important things, like figuring out what to eat.

Caveats:

  1. The machine would need to be configured at least once by someone with local admin rights.
  2. The machine would need to be connected to the Internet in order to receive updated instructions
  3. The admin needs a little knowledge of technical things, like proper coffee consumption, shit-talking and locating clean restrooms

Outline of Stupid Idea

  1. Drop the FudgePack script into a folder on the device (e.g. C:\ProgramData\FudgePack, file is Invoke-FudgePack.ps1)
  2. Create a Scheduled Task to run under the local NT Authority\SYSTEM account
    1. Task should only run if a network connection is active
    2. Task should only run as often as you would need for immediacy
    3. User (device owner) should be able to invoke Task interactively if needed.
  3. Host the control data somewhere on the Internet where the script can access it

Procedure for Stupid Idea

  1. Here’s the FudgePack app control XML file.  Make a copy and edit to suit your needs.
  2. Here’s the FudgePack PowerShell script.  Douse it in gasoline and set on fire if you want.
  3. Here’s an example Scheduled Task job file to edit, import, point at, and laugh.

Setting up and Testing the Stupid Idea

  1. Copy the appcontrol.xml file somewhere accessible to the device you wish to test it on (local drive, UNC share on the network, web location like GitHub, etc.)
  2. Edit the appcontrol.xml file to suit your needs (devicename, list of Chocolatey packages, runtime date/time values, etc.)
  3. Invoke the script under the SYSTEM account context (you can use PsExec.exe or a Scheduled Task to do this)
  4. Once you get it working as desired, create a scheduled task to run as often as you like
  5. Send me a box filled with cash – ok, just kidding.  but seriously, if you want to, that’s ok too.

More Stupid Caveats

  1. It’s quite possible in this day and age, that someone else has done this, and likely done a better job of it than I have.  That’s okay too.  I searched around and didn’t find anything like this, but my search abilities could quite possibly suck.  So, if someone else has already posted an idea identical to this, I will gladly set this aside to try theirs.  After all, it’s about solving a problem, not wasting a sunny, beautiful Saturday behind a keyboard.

Cheers!

Random Notes from This Week

Warning: Skattered thoughts ensue.

Checking Memory

Calculating total system memory within a virtual machine session might seem like a rather mundane task.  But during a recent troubleshooting call with a customer, I ran across something I had forgotten: Physical machine properties are stored in WMI differently depending upon the context.  Note that running these on an actual physical machine, a virtual machine with static memory allocation, and a virtual machine with dynamic memory allocation, will often yield different results.

Win32_ComputerSystem (TotalPhysicalMemory)

[math]::Round(((Get-WmiObject -Class Win32_ComputerSystem | 
  Select-Object -ExpandProperty TotalPhysicalMemory) | 
    Measure-Object -Sum).Sum/1GB,0)

This returned 4 (GB) from 4,319,100,928

Win32_PhysicalMemory (Capacity)

Using Win32_PhysicalMemory / Capacity returns a different result.

[math]::Round(((Get-WmiObject -Class Win32_PhysicalMemory | 
  Select-Object -ExpandProperty Capacity) | 
    Measure-Object -Sum).Sum/1GB,0)

This returned 16 (GB) from the sum of 17,179,869,184 (13,019,119,616 + 4,160,749,568).

 

PowerShell, CSV and sparse Label Names

Some of the biggest headaches in IT, besides people, are caused by imposing human habits on technical processes.  For example, insisting on embedded spaces in LDAP names, CSV column headings and SQL table columns.  Just stop it!  Say no to spaces.  The only space we need is the one between our ears, and usually when driving.  However, we don’t always have the luxury of dictating “best practices”, instead, we have to adapt.  So, I had a colleague suffering with a CSV file that a customer provided with column names like “Last Name”, “Dept Number”, and so on.  Why they couldn’t use “LastName”, “LName”, or even “LN”, who knows, but it was “Last Name”.

$csvdata = Import-Csv "C:\Program Files (x86)\Microsoft Visual Studio 14.0\DesignTools\SampleData\en\SampleStrings.csv"
PS C:\> $csvdata[0]
Name : Aaberg, Jesper
Phone Number : (111) 555-0100
Email Address : someone@example.com
Website URL : http://www.adatum.com/
Address : 4567 Main St., Buffalo, NY 98052
Company Name : A. Datum Corporation
Date : November 5, 2003
Time : 8:20:14 AM
Price : $100
Colors : #FF8DD3C7

PS C:\> $csvdata[0]."Email Address"
someone@example.com 

PS C:\> $csvdata | Where-Object {$_."Email Address" -like '*fabrikam*'} | 
  Select-Object -ExpandProperty "Email Address"

Thankfully, PowerShell is somewhat forgiving in this regard and allows you to adapt to such challenges easily.  A very small feature but very helpful as well.

Searching for Apps: Slow vs. Fast

Searching for installed software is usually pretty simple.  However, using WMI to query the class Win32_Product often becomes much slower due to overhead incurred by the Windows background refresh.  If you run a query for “SQL Server Management Studio” on a Windows server or client, regardless of the amount of memory, processor power, or disk performance, if these are all equal, WMI will be much slower than searching the registry or file system.  Case in point (using PowerShell for example purposes only):

Get-WmiObject -Class Win32_Product | 
  Where-Object {$_.Name -eq 'SQL Server Management Studio'}

When you run this, if you watch Task Manager at the same time, you may notice WmiPrvSE.exe and dwm.exe spin up more memory until the query is completed.  However, if you search the registry, which may not always be possible for every situation, the performance is typically much better (faster):

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ -Recurse | 
  Where-Object {$_.GetValue('DisplayName') -eq 'SQL Server Management Studio'}

Another option is to query the file system, which in this example is looking for a specific file and specific version:

$file = "C:\program files\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\Microsoft.SqlServer.Configuration.SString.dll"
if (Test-Path $file) { 
  (Get-Item -Path $file).VersionInfo.FileVersion 
}

Running these three statements on my HP Elitebook 9470m with 16 GB memory and a Samsung 500 GB 850 EVO SSD the results end up with the following average execution times:

  • WMI: 20 seconds
  • Registry: 0.98 seconds
  • File System: 0.13 seconds

The point here isn’t that you should avoid WMI, or anything like that.  It’s just that we should always consider other options to insure we’re choosing the right approach for each situation.  For example, if you really need to invoke the .Uninstall() method, then your options may narrow somewhat.

For a handful of targeted queries it may not matter to you which of these (or others) makes the most sense.  But when querying 5,000, 10,000 or 100,000 machines across a WAN, without the aid of a dedicated inventory product, the choice may have a significant impact.

If I had a Dollar for Every time…

Skype for Business client said “You can’t add or remove Favorites at this time. Try again later.”

Someone on a conference call said (late): “Sorry, I was walking to mute

A web site says it only works in Chrome, Firefox or Internet Explorer (but not Edge)

My smartphone says “you have 24 app updates pending

Microsoft Outlook client says “trying to connect”

I heard “that will be fixed in the next version

Our power company insists a new project will benefit customer costs, but it never does

Health, Dental and Vision insurance premiums increased, while overall coverage drops

I pass a hospital in the midst of major renovation or new construction

I hear Siri say “here’s what I found…”

I hear Google Assistant saying nothing whatsoever (it pantomimes)

I hear a corporate line manager get excited over a cloud migration while saying it will help reallocate staffing

I hear a corporate executive get excited over a cloud migration while saying it will help reduce staffing

Netflix adds another stand-up comedy special

I hear someone bashing foreign markets while they’re holding a Chinese-made phone

I hear someone complain about how stupid and unreliable human vehicle drivers are, but they’re dead against self-driving cars

My little terrier bark at the sound of an ant tip-toeing over the carpet at 2am

I hear Webex say “at the tone, please say your name and then press pound…

I see some idiot named Skatterbrainz post some stupid crap online

Top 10 Reasons Your Job Might be Automated

10. Machines don’t give a shit about your favorite sports team, movie, TV or streaming series, cars, food, drinks, types of women or men, tasteless jokes, what you did last night or over the weekend, or what programming language you think is the best.
9. Machines don’t need restroom, smoke, vape, or lunch breaks
8. Machines don’t need to get their kid from the school nurse
7. Machines don’t ask for a raise or better benefits
6. Machines don’t need to rest
5. Machines work faster than you
4. Machines can do the work of more than one of you
3. Machines are better at analytical processes than you’ll ever be
2. Machines don’t horde information about their job
1. Machines don’t sue their employer

Even funnier, is that most people are convinced that THEIR job could never be automated.  No matter what profession they’re in.  Let’s list off some of the folks who were convinced of this as well:

  • Telephone operators
  • Mail sorters
  • Grocery store clerks (in many places)
  • Surveillance aircraft pilots
  • Security guards
  • Punch card handlers
  • Carpet weavers
  • Stock market traders
  • Food and drink vendors
  • Waiters (in many places)
  • Newspaper deliverers
  • Gas station attendants (in most places)
  • Librarians (in most places)
  • Milk delivery (in most places)
  • Movie set demolition experts
  • Camera Film Developers
  • Data center rack engineers (I already hear that giant sucking sound Mr. Perot mentioned)