ConfigMgr – 2 Minute Microwave Style

Genesis – I posted a tweet about someone I know getting stressed at learning Configuration Manager in order to manage 50 Windows devices.  All desktops.  The background is basically that his company had planned on 1000 devices running Windows.  But the end-users, who wield more purchasing power, opted to buy mostly Macbooks.  So the total Windows device count was capped at 50, BUT…. they already approved the purchase of ConfigMgr.  It’s worth noting that the end-users also purchases JAMF (formerly Casper) and set it up in their own secret underground lab, complete with a diabolical German scientist in a white lab coat.  Ok.  That last part isn’t really true, but the JAMF part is true.

So, the “discussion” slid into “okay mr. smarty-pants skatter-turd-brainz, what would you want in a ‘perfect’ ConfigMgr world to address such a scenario?” (again, I’m paraphrasing a bit here)

MC DJam, aka DJammer, aka David the Master ConfigMaster Meister of ConfigMgr, popped some thermal verbals in front of the house and the room went Helen Keller (that means quiet and dark, but please don’t be offended, just stay with me I promise this will make sense soon…)

Yes, I’ve had a few beers.  Full disclosure.  I had to switch to water and allow time for the electric shock paddles to bring my puny brain back online.  That was followed by a brief gasp,”oh shit?! what have I started now?”  Then some breathing exercises and knuckle crackings and now, back to the program…

So, Ryan Ephgrave (aka @EphingPosh) stepped in and dropped some mic bombs of his own.

And just like having kids, the whole thing got out ahead of me way too quick.

So, I agree with Ryan, who also added a few other suggestions like IIS logs, Chocolatey package deployments (dammit – I was hoping to beat him to that one).

So the main thing about this was that this person (no names) is entirely new to ConfigMgr.  Never seen it before, and only gets to spend a small portion of their daily/weekly time with it, due to concurrent job functions.  This is becoming more and more common everywhere I go, and I’ve blogged ad nauseum about it many times (e.g. “role compression”)

What do most small shop admins complain about?

  1. Inventory reporting
  2. Remote management tools
  3. Deploy applications
  4. Deploy updates
  5. Imaging
  6. Customizable / Extendable

These are the top (6) regardless of being ConfigMgr, LANdesk, Kace, Altiris, Solarwinds, or any other product.  All of them seem to handle most of the first 4 pretty well, with varying levels of learning and effort.  But Imaging is entirely more flexible and capable with ConfigMgr (or MDT) than any of the others I’ve seen (Acronis, Ghost, etc. etc. etc.)

ConfigMgr does an outstanding job of all 6 (even though I might bitch about number 6 in private sometimes, it is improving).  ConfigMgr is also old as dirt and battle-tested.  It scales to very large demands, and has a strong community base to back it up in all kinds of ways.  In some respects it reminds me of the years I spent with AutoCAD and Autodesk communities and the ecosystems that developed around that, but that’s another story for another time.

The challenge tends to come from just a few areas:

  1. Cost and Licensing – ConfigMgr is still aimed at medium-to-large scale customers.  The EA folks with Software Assurance, are most often interested and courted into buying it.  Some would disagree, but I set my beer mug down and calmly say “Walk into any major corporate IT office and ask who knows about ConfigMgr.  Then walk into a dentist office, car dealership, or small school system and ask that same question.”  I bet you get a different response.
  2. Complexity – ConfigMgr makes no bones about what it aims to do.  The product sprung from years of “Microsoft never lets me do what I want to manage my devices” (say that with a nasally whiny tone for optimum effect).  Microsoft responded “Here you go bitch.  A million miles of rope to hang yourself.  Enjoy!”  It’s an adjustable wrench filled with adjustable wrenches, because it was designed to be the go-to toolset for almost any environment.  And it’s still evolving today (faster than ever by the way)
  3. Administration – Anyone who’s worked with ConfigMgr knows it’s not really a “part-time” job.  But that’s okay.  It’s part of the “complexity” side-effect.  And rarely are two environments identical enough to make it cookie cutter.  That’s okay too.  Microsoft didn’t try to shoehorn us into “one way”, but said “here’s fifty ways, you choose“.  The more devices you manage with it, the more time and staff it often demands in order to do it justice.  I know plenty of environments that have scaled to the point of having dedicated staff for parts of it like App deployments, Patch Management, Imaging and even Reporting.

None of these are noted with the intention of being negative.  They are realities.  It’s like saying an NHRA dragster is loud and fast.  It’s supposed to be.

Now, add those three areas up and it makes that small office budget person lose control of their bowels and start munching bottles of Xanax.  So they start searching Google for “deploy apps to small office computers” or “patching small office computers cheap as hell” and things like that.

So, ConfigMgr already does the top 6 functions pretty darn well.  So what could be done to spin off a new sitcom version of this hit TV show for the younger generation?

  1. Simpler – It needs to be stupid-simple to install/deploy and manage.  This reaches into the UI as well.  Let’s face it, as much as I love the product, the console needs a makeover.  Simplify age-old cumbersome tasks like making queries and Collections, ADRs and so on.
  2. Lightweight – Less on-prem infrastructure requirements: DPs, MPs, SUPs, RPs, etc.  Move that into cloud roles if possible.
  3. Integrate/Refactor – Move anything which is mature (and I mean really mature) in Intune, out of ConfigMgr.  Get rid of Packages AND Applications, make a hybrid out of both.  Consider splitting some features off as premium add-ons or extensions, like Compliance Rules (or move that to Intune), OSD, Custom Reporting, Endpoint Protection, Metering, etc.
  4. Cheaper – Offer a per-node pricing model that scales down as well as up.  Users should be able to get onboard within the cost range of Office 365 models, or lower.

Basically, this sounds like Intune 3.0, which I’ve also blabbered about like some Kevin Kelly wanna-be futurist guy, but without the real ability to predict anything.

Some of the other responses on Twitter focused on ways to streamline the current “enterprise” realm, with things like automating many of the (currently) manual tasks involved with installation and initial configuration (SQL, AD, service accounts, IIS, WSUS, dependencies, etc. etc.), all of which are extremely valid points.  I’m still trying to focus on this “small shop” challenge though.

It’s really easy to stare at the ConfigMgr console and start extrapolating “what would the most basic features I could live with really come down to?” and end up picking the entire feature set in the end.  But pragmatically, it’s built to go 500 mph and slow down to push a baby stroller.  That’s a lot of range for a small shop to deal with, and they really shouldn’t.  That would be like complaining that the Gravedigger 4×4 monster truck makes for a terrible family vehicle, but it’s not supposed to be that.  And ConfigMgr really isn’t supposed to be the go-to solution for a group of 10-20 machines on a small budget.  Intune COULD be, but it’s still not there yet.  And even it is already wandering off the mud trail of simplicity.  It needs to be designed with a different mindset, but borrowing from the engine parts under the ConfigMgr hood.

Maybe, like how App-V was boiled down and strained into a bowl of Windows 10 component insertions for Office 365 enablement, and dayam that was a weird string of nouns and verbs, they could do something similar with a baked-in “device management client” in a future build of Windows 10.  Why not?  Why have to deploy anything?  They have the target product AND the management tool under the same umbrella (sort of, but I heard someone unnamed recently moved from the MDT world into the Windows 10 dev world, so I’m not that far off).

Does any of this make sense?  Let me know.

 

Advertisements

The IT Professional’s PlayBook

cant_crash

So, you’re growing tired of trying to convince clueless managers about approving your requests to improve IT operations.  Maybe you’ve been doing it like this…

You: “Good morning sir/ma’am.  If we spend some money on upgrading our WAN links, we can get ahead of our backlog of projects by moving all our deployment processes out of the slow lane.”

Them: “I don’t know who WAN links is, but it sounds like Chinese food.  Go away.”

Maybe you should try rehearsing these tried-and-tested proven methods:

You: “Good morning sir/ma’am.  I ran the numbers and found we could save money by upgrading our WAN links.  A one-time cost of $14k would eliminate our need for additional infrastructure, license upgrades, controlled spaces, and lower power and cooling costs at all our remote facilities.  That alone would reduce our infrastructure costs by $5,000 per year, and cut our deployment times from weeks to hours.  The cost could be a tax deduction and we’d recoup that in less than three years.  And, are you losing weight?”

Them: “Yes, I’ve been working on my chip shot all weekend and I think it’s getting me in shape again.  I like you Bob….”

You: “It’s Ben.  Sir.”

Them: “Right, Bill, anyhow, it sounds like you think this WAN links guy is really that good?  Ok. I’ll approve him, if you think he can help with our taxes.”

Another example…

You: “Good morning sir/ma’am. I ran the numbers and it turns out we’re spending 150 hours per week installing apps by hand.  That’s 5 technicians over 150 hours at $7.50 per hour, oops, I mean $5.50 per hour.  That comes to $8,250 per week, and a backlog on other support requests in the queue.  We could spend a quarter of that packaging or wrapping the installers and procuring a product to help deploy them remotely.”

Them: “I like that idea.  We can then cut 3 of those technician’s jobs and reduce our burden rate at the same time!  Great work Bill!  You can call me Mike.”

You: “Actually, uh, no disrespect, but I don’t think we should cut…”

Them: “Consider it done Bobby!” (strong pat on the back)

And another…

You: “Good morning Ma’am.  I would like to request approval to replace Acronis and Ghost and all our other imaging tools with Microsoft Deployment Toolkit.  It’s free.  It’s very customizable.  It would allow us to reduce our image library from 43 individual images to 1 with a task sequence.  And it’s been around for years and battle tested.”

Them: “That sounds interesting.  But I spoke with Sam, who dates my daughter, and he says it’s better to maintain 43 image files every month because the extra care and feeding makes it an important job.  And he graduated from a 2 year tech school.  And he dates my daughter, so you know how that goes.  But really, Bobby, I appreciate your concern.”

You: “It’s Ben.  But thank you.”

And finally…

You: “Good morning Ma’am.  I heard about the big tax changes and how we’re going to save $20 million this year alone.  I was wondering if you had a few minutes to discuss some ideas I have about infrastructure improvements to help streamline our operations and save money?”

Them: “I’m glad you asked.  Yes, but it’s actually around $22 million.  And we already have plans to apply that towards automation, to reduce our dependency on human labor.  Oh, and what was your name again?”

Or, you could just consider a career in the legal or medical field.

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!

Discussion Points / FudgePop again

20160305_121835

So I had a nice discussion about this FudgePop thing, which is starting to sound like a marketing ploy.  But trust me, it’s only a project, nothing being marketed.  I’m not sure if I’ll add any more stuff to it unless I get really bored or some sort of revenue scheme hatches from it.  Again, that’s unlikely at this point.  As with CMWT, GPODoc, and CMBuild, these are just for fun and exercise.  I’m pretty sure some of you are tired of hearing about this thing with a childish name attached to it, and that’s fine. But keep in mind, the same could be said about the U.S. government, but I digress. 🙂

In case you can’t tell already, I’m slowly getting back to blogging after a brief hiatus.  I still don’t know where this is going to go, or for how long, etc.  One day at a time.

So, given that this is all open source and available on GitHub, here’s some thoughts for anyone feeling bored enough to fork or branch this for a future pull, or just to run off and get rich while I toil for table scraps, here’s some roadmap thoughts…

Mighta, Oughta, Woulda, Coulda, Shoulda…

Inventory

Inventory collection and reporting would be fairly simple to add.  I already built a proof-of-concept branch to collect data and upload it to a SQL database in Azure.  Anyone can do that.  What I would do differently is store a local copy of the payload with a checksum, maybe store the checksum and timestamp in the Registry, along with a timestamp of “LastInventoryUpload”.  Then subsequent inventory cycles would compare the new output checksum against that previous and only upload if the values are different.  Sound familiar?

Offline Mode

Rather than reading the control XML in real-time on each execution cycle, it could download the latest version to a local cache.  Then continue to enforce that on subsequent execution cycles if there are no available Internet connections.

Smaller Stuff

Other suggestions for possible consideration:

  • Download caching for either (or both) the Files and Win32 Apps control groups (fairly simple)
  • Manage local Group Policy for workgroup computers (ideas) (somewhat complex and limited, but promising)
  • Add, modify local user accounts (easy)

What it can do now

As of build 1.0.16, FudgePop can do the following on remote computers which are configured with the agent service:

  • Chocolatey Packages
    • Install, Update, Remove
  • Win32 Application Packages
    • Install, Uninstall
  •  Files
    • Copy, Move, Rename, Delete, Download
  • Folders
    • Create, Delete, Empty
  • Windows Services
    • Modify/Configure, Start, Stop, Restart
  • Registry
    • Create, Delete (keys, values)
  • Permissions (ACLs)
    • Files/Folders: Modify
    • Registry: Not implemented
  • PowerShell Modules
    • Install, Update
  • Shortcuts
    • Create, Delete
  • AppX Applications
    • Remove
  • Windows Update
    • Force Scan/Download/Installation
  • Inventory
    • Basic HTML reporting
  • Targeting
    • Device = comma-delimited list of device names (NetBIOS names)
    • Collection = arbitrary name which is then assigned a comma-delimited list of device names.
    • Enable = true/false (per setting or group, or per control file)
    • Central authority = deploy changes from central XML file, even redirect to new XML files without touching remote device by hand.
  • Ingredients
    • PowerShell and XML, and a sprinkle of cloud storage (to host control files)
  • Tools
    • Visual Studio Code, Notepad++, Paint.Net (for the spiffy icon)

The Future

Who knows.  I don’t even know what my 401-k is doing tomorrow.

Quick Rundown on FudgePop and why the Silly Name

The name comes from a wine-infused discussion around Chocolatey, which was around Nuget, which was around Brooklyn Brewery’s Black Chocolatey Stout, which was bout $9 per bottle.  This post however, was sponsored by half a bottle of Pinot Noir, by an unnamed winery somewhere in Wineville.  FudgePop itself was contrived from a casual “bet” over a bottle of Dogfish Head 120 IPA that it’s possible to use nothing but free tools and features included with Windows 10 to manage a “group” of such devices from a central location, regardless of where those other devices are located.

Btw, I just uploaded 1.0.16 to the PowerShell gallery

Installation

Install-Module FudgePop
Import-Module FudgePop

Note: .NET framework 3.5 is recommended for some Chocolatey packages.  FudgePop does not install .NET 3.5 by default.

Use the following to confirm/verify the latest version…

Get-Module

Once the module has been installed on each subsequent victim, er, I mean “device”, scaling out is just a matter of replicating the same steps as the previous device.  On domain-joined devices, you can use Group Policy to deploy it as well as via PowerShell deployment from Intune for devices joined to Azure AD Premium.  Workgroup computers require manual intervention (hands-on, remote connection, etc.)

Functions

New-FudgePopTemplate

Creates a new XML control file using the default (sample) provided with the module.  Other samples are posted on the project GitHub site.  Note that all settings are disabled by default, and filled in with sample/example information only.

New-FudgePopTemplate -OutputFile "c:\devtest\control.xml"

Install-FudgePop

Configures default options such as control file location, enable/disable recurring scheduled execution, and hourly interval between scheduled executions.

Install-FudgePop

Invoke-FudgePop

Executes the FudgePop agent.  If you configured it correctly, magical things happen before your drunken eyes.  If you goofed up the configuration, it forces you to watch The View until your eyeballs bleed.  That last feature is not yet enabled.  Note that this function is what is called by the RunFudgePop.bat script during each scheduled execution (if scheduled execution is enabled).

Invoke-FudgePop -TestMode -Verbose
Invoke-FudgePop -Verbose

Remove-FudgePop

Disables and uninstalls FudgePop from a client device.  It then applies 440 volts of taser current to your genitals until you reinstall it.  jk

Remove-FudgePop -Complete

Show-FudgePop

Displays information about current configuration, last runtime status and rectal thermometer temperature of your cat or dog.  That last feature is not yet enabled.

Show-FudgePop

Get-FudgePopInventory

Bonus, low-calorie, gluten-free, and totally vegan function to export basic inventory data from your meth-addicted Windows device.  It was a proof-of-concept to export a basic set of juicy and utterly useless data into an Azure SQL database so I could win a bet and enjoy a free sushi lunch.  The Azure SQL interface is planned for a future version, but will ultimately depend on user feedback (i.e. does anyone really want that capability?) and how badly I want more sushi.

Get-FudgePopInventory
Get-FudgePopInventory -Computer d001,d002,d003
Get-FudgePopInventory -FilePath "c:\reports\"
Get-FudgePopInventory -StyleSheet "c:\reports\custom.css"

Help

The markdown files were cranked out by a team of recovering caffeine addicts fresh from the Port Authority bus terminal.  Actually, they were cranked out with PlatyPs, which is pretty cool, and doesn’t come from the bus terminal.  You can find them in the “docs” folder beneath the module path (e.g. “c:\program files\WindowsPowerShell\Modules\fudgepop\1.0.16\docs”).

Use FudgePop in a Sentence

Hey man.  I just took a FudgePop on your mattress.”

Sample Scenario

You’re drunk.  But that’s not unusual with your day job as an airline pilot.  You staggered out of an airport terminal, and fell face-first into a random Uber vehicle with the doors open.  You wake up the next morning at your apartment, in a bathtub filled with ice, and a clear plastic aquarium tube attached to where your left kidney used to be.  You get up carefully, and drag the tube with you to the kitchen and make some fresh ramen with Srirachi sauce and a cup of coffee.  The entire time you keep thinking that of all his pranks, your roommate did a fantastic job of making these sutures look and feel authentic.

You grab your roommate’s laptop which has Windows 10 1709 installed, and you logon as a local administrator account and open a PowerShell console using “Run as Administrator”

You set the execution policy to Unrestricted, while staring at the PowerShell book with Don Jones’ picture on it, and say to yourself, “I know, this is very very bad, but I live on the edge baby.”

Set-ExecutionPolicy Unrestricted

You then use one finger on each hand to type:

Install-Module FudgePop

…and press Enter.

(example only. actual results may vary, depending upon your alcohol intake and criminal record)

Then, you can’t help it, but you hurl directly onto your cat, who returns the favor by urinating in your snow boots.  You use the cat to wipe your face off, and return back to the keyboard and type:

Import-Module FudgePop

…and press Enter.

After an IV drip of Death From Above coffee, and a Cat Shampoo enema, you type:

New-FudgePopTemplate -OutputFile wtfisthis.xml

…and make a new control XML file.  You edit it to suit your test environment (computer names, collection names, apps, etc.) and copy the XML file to your GitHub Gist.  You get the “raw” Gist URL and copy the address to your clipboard.

You make some breakfast from whatever isn’t fuzzy in the fridge and then go back to the keyboard, where you cat fell asleep, causing the letter “zzzzzz” to overflow the buffer and make a machine gun beep sound.  You realize that wasn’t Cat Shampoo, but Drano that your poured into the Cat Shampoo bottle because the Drano bottle leaked after you dropped while trying to light your vaporizer with a match.  You scoot the kitty off the keyboard, brush off the hair balls and type…

Install-FudgePop

You answer the prompts with one hand, choosing to enable the scheduled run option for 3 hour intervals, while the other hand is manipulating a pair of greasy chopsticks you found in the trashcan because you couldn’t find a fork, spoon, or plastic spork anywhere.

You look around for the mouse, but it’s gone.  After scouring the entire house/apartment, you find it buried in the kitty litter box.  You recover it, wipe it off on your pants and set it back on the desk and use it to poke around to see what all this FudgePop mess did to your roommate’s computer…

  • It created a registry hive under HKLM:Software\FudgePop
  • It created a PowerShell module folder under $env:PSModulePath
  • It created a Scheduled Task named “FudgePop Agent” under the root folder
  • It added $100 to your bank account (not really)

You go back to the PowerShell console, pause, look around for the cat, and think “what in the **** am I doing anyway?” and after 30 seconds of staring into space you remember that you were using your roommate’s laptop for an important experiment, and you continue on.

You type in…

Invoke-FudgePop -TestMode -Verbose

…so you can see everything it would have done if it weren’t using that stupid -TestMode switch.  It prompts you to trust some mysterious thing called an “untrusted repository”, but you’ve got 55 gallons of testosterone coursing through your veins, and no stupid sissy warnings are going to scare you off.  And besides, you can’t spell “untrusted” without the word “trust” so how could it be bad?  Just like your cousin who kept whining about putting that safety “on” when you were shooting at tin cans and you ignored him and shoot him in the foot.  Like that’s any excuse to use safety stuff.  Yeah.  But it’s okay, because FudgePop is only asking you to trust the PowerShell Gallery, so it can install some needed tools.

You toss back another glass of liquor, notice the cat staring at you, making you wonder if she spiked your glass with something special.  You ignore that feeling and type…

Invoke-FudgePop -Verbose

…just to see what it’s doing to diabolically reconfigure your roommate’s laptop into a tactical nuclear toilet flushing device.  Not really, but it’s likely that it’s creating a desktop shortcut for Internet Explorer, installed a bunch of Chocolatey packages like 7-Zip, Visual Studio Code, Office 365 ProPlus, and Putty, added some folders, files and registry keys, reconfigured some services, and installed a custom .MSI or .EXE from an on-premises server share (you know, the “Chris Hansen Kiddy Porn Undercover Arrest Me Kit 2015 Premium Edition.exe” with the important /S switch).

Everything looks great.

But, being that you don’t trust anyone who’s birth certificate says their name is really ‘skatterbrainz’ you decide to look under C:\Windows\Temp and find a “fudgepop.log” file and open it up.  Your skull falls in pieces on the floor due to the overload of retinal bombardment of verbosity and quantum-level granularity, and because you’re still hung over AF.  But that’s beside the point.  You make some tweaks to the control XML file, rub your hands together while nodding and grinning, laughing like a German lab scientist in a WWII movie, not realizing your cat is going to the bathroom on something else you value on the other side of the room.  You install FudgePop on another device and repeat the process.

You carefully tie that plastic kidney tube closed using the twisty-tie from the plastic bag you use for the litter box.

Later, your room mate returns, sees what you’ve done and pounds your face into the sofa and leaves.

I hope to return in 2018.  Until then: Happy New Year!

Rants about Configuration Manager and PowerShell

Note: Although I’m still on hiatus, I was reminded about a few blog posts sitting in my drafts queue that need to get posted before they get stale like me.  There may be a few more.  Until then – cheers!

How many times have you seen PowerShell code that looks similar to the following?

param (
  [parameter(Mandatory = $True, HelpMessage = "Site Server Name", ValueFromPipeline = $True)]
  [ValidateNotNullOrEmpty()]
  [string] $ServerName, 
  [parameter(Mandatory = $True, HelpMessage = "Site Code")]
  [ValidateNotNullOrEmpty()]
  [string] $SiteCode
)
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" -Verbose:$False

Notice how this is expecting the user to (manually) provide the name of the server, the site code, and so on?  What bothers me most about this is that these two pieces of information are easy to obtain directly from the local computer.  Even when running on a workstation or member server which is not a ConfigMgr site system, you can easily obtain the site server name and the site code.  So why ask a user to key this in manually?

I’ve blogged about this general topic a few times before, but I still see most snippets posted online today doing this exact same approach to setting up the most basic, albeit “core” aspects, on which the rest of the script depends.  Bad idea!  So 1990’s.

Think of this in alternate contextual forms:

  • We expect to drop AD computers and users into Organizational Units (OUs) to automate Group Policy management processes.
  • We expect to drop ConfigMgr resources into Collections to automate policy and content deployment processes.
  • We expect to place AD domain controllers into Sites to automate replication optimization processes.
  • We expect to place AD users into security groups to automate permissions inheritance processes.
  • So why don’t we expect our scripts to drop into execution environments and inherit and automate processes as well?

Reiterating one of the lectures from my CS days in college, “every program needs to start with stated assumptions“.  Other great bits of advice: “If it can be automated, then automate the shit out of it.”, and, “If you automate a broken process, you can only get an automated broken process.” (that was from a manager, not a professor, but still top of my list).  I could go on much longer, but maybe that would be best for an in-person discussion or speaking event.  God help you.

So, the questions should be:  what then are the expectations when executing a program (or script)?  I realize this is 100-level stuff right here, but so-often I see people dive into writing code before they pause to answer some basic questions about how it will be used.  The most basic questions should be…

Where will it be used?

When will it be used?

How will it be used?

and… Who, will use it?

Let’s define some base assumptions:

  • Where?  On the ConfigMgr site server (locally or via PSRemoting, WSMAN/Rexec/WinRS/PsExec, etc.)
  • When?  On demand, or via scheduled job
  • How?  PowerShell + ConfigMgr Admin Console framework
  • Who?  A user or process-owner account which has local Administrator rights

Assuming this is going to be invoked on a Central Administration Server (CAS) or Primary Site Server (PSS), we can also assume that the ConfigMgr admin console will be installed.  And along with that, it will have the PowerShell cmdlet library available as well.

In this scenario, we can easily obtain the name of the server, as well as the Configuration Manager site code.  There’s no need to ask a user to manually input this information, because, as we’ve seen many times, manual intervention causes cars to crash, trains to derail, and space shuttles to explode.  Humans are bad.

There are several ways to get the site server name (locally):

# environment
$ServerName = ($env:COMPUTERNAME+'.'+$env:USERDNSDOMAIN)

# WMI
$ServerName = Get-WmiObject -Class Win32_ComputerSystem | Foreach {$_.Name+'.'+$_.Domain}

# registry
$ServerName = (Get-Item -Path HKLM:SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName).GetValue('ComputerName')

You get the idea.  The easiest (and fastest) may be the environment variable option.  So, we can also use this to set a default value even when using input parameters…

param (
  [parameter(Mandatory = $False, HelpMessage = "Site Server Name", ValueFromPipeline = $True)]
  [ValidateNotNullOrEmpty()]
  [string] $ServerName = $($env:COMPUTERNAME+'.'+$env:USERDNSDOMAIN)
)
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" -Verbose:$False

We can also fetch the ConfigMgr Site Code using the Registry…

$SiteCode = (Get-Item -Path HKLM:\SOFTWARE\Microsoft\SMS\Identification).GetValue('Site Code')
$OldLoc = (Get-Location).Path
Set-Location "$($SiteCode):\" -Verbose:$False
...

So, that works fine when the assumption is that the script will be invoked directly on a ConfigMgr site server.

As a side note, there’s plenty of other useful information exposed in the Registry location HKLM:SOFTWARE\Microsoft\SMS

Going Remote

Now, let’s change the assumptions a bit.  Now the script will be invoked on a workstation, which is joined to the same AD domain as the ConfigMgr site.  Assuming the workstation is also a ConfigMgr client, and the desired Site Server is also the Management Point (MP) for this workstation, we can fetch the server name from the local machine as well, but it resides under the client Registry tree, rather than the site system Registry tree…

$mp = ((Get-Item -Path HKLM:SOFTWARE\Microsoft\CCMSetup).GetValue('LastValidMP') -split '//')[1]

Even if the MP is not the Primary we wish to connect to, we can use the MP information and perform additional queries against its Registry to “walk-up” the hierarchy to find the Primary we wish to connect with (if necessary).

Note: The actual value of “LastValidMP” is stored in URI format… example…

"http://cm01.contoso.com"

So if we split the string into a 2-element array on the instance of double slashes, we can then grab the index=1 value (2nd element), which is the FQDN of the MP.  You could also use .Substring() or .Replace() to manipulate the string in order to remove the http:// prefix.

$mp = (Get-Item -Path HKLM:SOFTWARE\Microsoft\CCMSetup).GetValue('LastValidMP')
$mp = $mp.Substring(7)
# or
$mp = $mp.Replace('http://', '') # or -replace 'http://', ''

So, now we have the ConfigMgr site server (again, assuming this is a small site and the MP is the primary), we can still fetch the site code either from the local client environment, or from the remote registry.  Either will work…

$SiteCode = (Get-Item -Path HKLM:SOFTWARE\Microsoft\CCM\CcmEval).GetValue('LastSiteCode')

You may be thinking (or saying aloud) right about now “so what? what can I do with this from a workstation?”  Well, if the ConfigMgr Admin console is installed, you have access to the same PowerShell module that is available on the site server.  So, if you intend to run your script locally on a workstation (or member server) which has the ConfigMgr Admin console installed, you can automate the site server name, and site code parts of your script very easily…

$mp = ((Get-Item -Path HKLM:SOFTWARE\Microsoft\CCMSetup).GetValue('LastValidMP') -split '//')[1]
$SiteCode = (Get-Item -Path HKLM:SOFTWARE\Microsoft\CCM\CcmEval).GetValue('LastSiteCode')
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" -Verbose:$False
$OldLoc = (Get-Location).Path
Set-Location "$($SiteCode):\" -Verbose:$False

Keep in mind that no matter where you execute your script code, it will only be able to access resources which are allowed for the user context under which it is running.  So, if you run the script under your own domain account, and that account has limited rights in ConfigMgr, it’s going to be limited in what it can do against the site system environment as well.  I know many of you will shake your heads when reading this, but it is very often overlooked.

Speaking of the ConfigMgr Registry (SMS) tree

Beneath the HKLM:SOFTWARE\Microsoft\SMS registry tree, there are plenty of other useful pieces of information.

  • Server
  • Full Version
  • Domain
  • Parent Site Code (useful for Secondary sites and CAS environments)
  • Parent Server (ditto)
  • Site Name
  • Installation Directory
  • DatabaseMachineName
  • DatabaseName

So, even if your script needs to make some database connections to SQL Server (ADO, etc.) you can fetch the site database server and site database name, to automate the connection setup and continue onward.

Okay, so now what?  Well, there’s more.  Another thing I see way too-often is reinventing the wheel.  And not just any wheel, but octagonal wheels.  Here’s a few examples, and corresponding suggestions to avoid unnecessary work:

  • Writing elaborate ACL manipulation code, or invoking a blob of .NET reflection mess.
  • Writing elaborate code to manipulate local user permisions, like “logon as a service”
    • Use the Carbon PowerShell module – done (thank you Rob!)
  • Writing elaborate code to query or manipulate SQL Server settings
    • Use dbatools or SQLServer PowerShell modules
    • You can configure server memory and recovery model settings this way also (example)
  • Writing elaborate code to check if script is being executed via “run as administrator”
  • Manually writing help documentation
    • Enforce consistent commenting
    • Use PlatyPs to generate markdown files automatically (thank you Kevin!)
  • And finally…

Some final bits of advice:  NEVER test your scripts on a live Configuration Manager environment.  If you don’t have a test environment, build one, and test everything there BEFORE introducing into the production environment.  Also, when you are testing scripts against Configuration Manager and/or SQL Server, always keep the Task Manager window open and watch the Performance tab closely.

Summary

Am I some sort of “expert” when it comes to PowerShell or Configuration Manager?  Only when I’m around people who can’t spell “computer” and they’re serving alcohol.   I’ve just spent too many years soaking up what others have shared.  You are free to disregard everything I’ve said.  In fact, in America, it’s expected. But that’s okay too.

Random Stuff, Part 42

Between work, studying, tinkering and trying to have something close to being considered “a life”, I haven’t been blogging much lately.  And every time I get close to having that magical, mythical thing called “a life”, I have to travel.  I can’t complain, since it gives me new perspectives on “life”, which help me to feel like I have “a life”.

And speaking of travel, here’s a cheap diagrammatic view of how I roll (literally, since my suitcase does in fact have wheels)…

packing.png

This is just the backpack.  I also didn’t include tampons, whips, chains, hand grenades, latex gloves, surgical masks, or bags of unmarked pills.  Those tend to slow me down with TSA, and I’d rather they spend most of their time with their hands around my privates.  If I touch myself in public it looks unsettling, but when they do it for me, it’s professionalism at its best, and they love it when I smile during the procedure.

Speaking of TSA, I’ve found that the passive aggressive score follows the scale of the airport, at least in the U.S.  Meaning, the bigger the airport, the less humor they tolerate.  The friendliest bunch I’ve encountered would be Medford, Oregon (MFR), and the other end of the scale would be Boston (BOS).  I love Boston.  The TSA have a consistent and warm way of welcoming travelers to bean town with that glaring “I’ll stomp your face in if you make eye contact for more than 5 seconds!”

I’ve also been updating some PowerShell-related projects.  I have always maintained personal project time to keep my sanity.  It also makes my dog want my attention more.  She leaves me little gifts to express how much she misses my attention.  And at 95 lbs, the size of those gifts can almost clog the toilet.

Here’s a few examples of what too much caffeine, too much vlog watching, and access to PowerPoint will do to someone like me, a latent marketing student.  I’m just kidding, I would’ve gone into statistics as a “statistician” but it’s too difficult to pronounce after 3 or 4 beers, and the pay doesn’t come close to most IT related jobs.

fudgepop.pngFudgePop

 

cmhealthcheck.pngCMHealthCheck

gpodoc.pngGPODoc

cmbuild.pngCMBuild

They almost look professional.  And almost as if I know what I’m doing.  Cooked up with only a frying pan, a little butter, some chunks of PowerPoint and sprinkled with Paint.Net.  All four took a whopping hour to create.  The pencil was the most fun.  I highly recommend the shape tools (Boolean stuff, like Union, Subtract, etc.), you can spend hours immersed in that strange world, forgetting to shave and bathe too.

You can find the rest of this exciting stuff at https://www.powershellgallery.com/profiles/skatterbrainz/ – where I publish things I almost know how to do.  CMBuild is still in beta, so if you get really, really, reeeeeeally bored, and you have a lab environment in which to try things like this – feel free to post angry, hurtful, mocking and demoralizing comments and bug reports.  The more condescending the better. My doctor enjoys this too.  The visits for medication help his kids through another semester at medical school, and I don’t want to let him down.

Travel

I forgot to mention that MFR, while being a very small airport, also has some really nice artwork on the walls around baggage claim…

20171105_213501.jpg

Approaching Norfolk (ORF), the most dynamic and interesting place for underpaid IT professionals…

20171111_102616.jpg

Leaving San Fran (SFO).  The most dynamic and interesting place for well-paid IT professionals who can’t afford to live there…

20171110_193714.jpg

Getting ready to board my next flight.  I have the window seat just behind the wing…

20171110_204509_Burst01.jpg

Back in my office…

20170902_231019.jpg

Technical Stuff

In the past month, I’ve been dunked into projects involving a variety of different beatings, I mean challenges.

  • 2 involving MDT+Windows 10 with distributed/replicated MDT deployment shares.  One using DFS and the other using Nasuni, for the replication service.  Both worked out very well.
  • 2 involving Office 365 ProPlus.  One mixing C2R Office with MSI Visio and Project.  The other mixing C2R Office using O365/AzureAD licensing, with C2R Visio/Project using KMS licensing.  Neither was that difficult, but I did come away with a continued wonder and amazement at how something so simple (C2R deployments) could be left half-baked by Microsoft and nobody seems to care.
  • 3 involving Configuration Manager.  1 focused on SUP strategies for servers.  1 focused on being a crying shoulder for an overloaded admin and under-give-a-shit managers.  1 focused on replacing some horrific mess some other (independent) consultant attempted while in between binges of drinking and glue sniffing.

The rest of the time has been Azure, Intune, O365, PowerShell, PowerShell with Azure AD, PowerShell with Intune, PowerShell with System Center, System Center with PowerShell, PowerShell with PowerShell, and a little bit of PowerShell. I’d think by now I’d know something about PowerShell, but I’m not going to pat myself on the back just yet.

User Groups

Our geographic region seems to have very few IT-related user groups with regards to the population of professionals.  We do have a few, such as groups for Docker, SQL Server, .NET, Machine Learning/AI, and a few others.  So, I’ve been trying once again (third time) to get a Microsoft-related group off the ground.  And I’m happy to say it’s actually starting to get off the ground!  It’s called Hampton Roads Cloud Users Group.  “HRCloudGroup” on Slack, and Facebook.

For those not familiar with this interesting little area, it’s officially comprised of 7 cities in the southeastern corner of Virginia, at the North Carolina border.  Mouth of the Chesapeake Bay.  But the actual list of surround municipalities include Norfolk, Virginia Beach, Portsmouth, Chesapeake, Hampton, Newport News, Williamsburg, Yorktown, Suffolk, Surry, and Smithfield.  There’s also a large number of people who commute from North Carolina to jobs in this area, so it extends beyond Virginia.

Some call it “Tidewater”, which is a stupid name.  Some call it “Hampton Roads”, which is a less stupid name.  Some call it “that shitty place I hated being stationed at while in the Navy/Marines/Air Force/Army/Coast Guard/CIA/FBI/NSA/DEA/NATO…” eh, you get the idea.  I would venture to say it is the most militarized area of land in the United States, maybe in the world.  Every branch of military, intelligence, logistics, special operations, tactical operations, is located within a small enough radius to be a ridiculously appealing target for Russian satellites.  My house, is under the flight path between Little Creek JEB (SEAL team 6 or DEVGRU), Fort Story and Oceana NAS.  I can name the fighter jet, cargo plane, or helicopter models by sound alone. I just haven’t found a way to earn a living doing that yet.

Enough Rambo talk. Our group is still very small, at about a dozen members, with about 4 or 5 people attending the monthly meet-ups so far, we’ve been fortunate to get some very skilled, very creative members, so I couldn’t be happier.  I feel like my role is more of a facilitator than a leader.  The others have way more experience than I at this point, so I’m happy to just connect the wires and keep the engine running, and learn what I can along the way.  We’ve only had 2 meet-ups so far, but I’m optimistic.  Our next one is December 14, 2017 at 6pm.  If you live in the area, hit us up.

Miscellaneous

As if the entire blog post isn’t already “miscellaneous”.  Shit, my whole life is “miscellaneous” when I get down to it.  But who’s complaining? Okay, I do from time to time.  Anyhow, shotgun blast…

  • PlatyPS is cool.  Once you remember to actually put comments in the right places and import the module before running New-MarkdownHelp for fifth time and cursing at the monitor for not reading my my mind.
  • Carbon is still cool.  Even cooler.
  • The Tesla semi is freaking awesome.  The Roadster is obviously cool as well.  I can afford neither.
  • I had my first MSATA failure today.  A Lite On 256 GB card in my HP Elitebook.  RIP.  It was nice having you while you lasted.
  • Shout out to Whitner’s BBQ in Virginia Beach.  Still the best I’ve had anywhere I’ve traveled, and it’s right in my backyard.
  • Shout out to the group of kids who yelled across the busy street “I like your chocolate dog!!”  She loved it too.
  • I need fish food for the aquarium.  Off to the stores on a Saturday.  Wish me luck.

Chocolate dog.  Aka “Dory”

20171117_131721.jpg