PowerShell CSS Tricks for Fun

This is really, really, really, really, really, simple CSS (Cascading Style Sheets) goofing around.  The point of this is to show what you can do with a few basic style properties and modifiers like :hover, and sneaking it in like a stealthy ninja.


$OutputFile = "$($env:USERPROFILE)\documents\sample.html"
it's okay to change the values in the following block
of code, but be careful not to mess with indenting it a lot.
$styles = "<style type=`"text/css`">
body {
table {
  width: 850px;
  display: table;
  border: 1px solid #c1c1c1;
  border-collapse: collapse;
  border-spacing: 2px;
th,td {
  border: 1px solid #c1c1c1;
th {
tr:hover {

pipe an example WMI class, filtered, into an array which
is then piped into HTML code, and then piped into a file

Get-WmiObject -Class Win32_LogicalDisk |
  Select 'Name','Size','FreeSpace','FileSystem','Description' |
    ConvertTo-Html -Body $_ -Head $Styles -Title "Logical Disks" |
      Out-File -FilePath $OutputFile

# open the HTML file using the default browser...

if (Test-Path $OutputFile) {
  Invoke-Item $OutputFile

Mess around with it yourself, but heed the usual boring legal disclaimer stuff:


Sending SCCM Logs in ZIP using GMail, with French Fries, Ketchup and a Soft Drink

I’m too tired to write anything stupid or funny.  Here you go.  Enjoy and I hope it helps you in some remote way…

 Send-CmSiteServerLogs.ps1 collects SCCM site server logs, compresses
 them into a tasty little chocolate-covered ZIP file, and sends it out
 through the vast and spacious Internet, using Gmail as the courier 

 The Synopsis should be enough. Or maybe I'm doing this wrong?

 [string] (required) sender's Gmail address

 [string] (required) recipient's email address

 [string] (optional) wildcard pattern for collecting only a subset
 of log files to send. Example "w*"

 Author..... skattebrainz.wordpress.com / GitHub / Twitter
 Created.... 10/27/2016
 Support.... 800.555.1212


param (
 [parameter(Mandatory=$True)] [string] $SendFrom,
 [parameter(Mandatory=$True)] [string] $SendTo,
 [parameter(Mandatory=$False)] [string] $LogFilter = ""

$smtp = "smtp.gmail.com"
$port = 587
$Subject = "SCCM Log Sender`: $($env:COMPUTERNAME)"

$temp = $env:TEMP

if ($SendMail) {
 $cred = Get-Credential -Message "Provide credentials to use SMTP service" -UserName $SendFrom

 Get-CmSiteInstallPath returns [string] path to the base installation
 of System Center Configuration Manager on the site server.
 Returns the full SCCM installation path using a registry query.

function Get-CmSiteInstallPath {
 $x = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\SMS\setup"
 $x.'Installation Directory'

# begin the assault!

$cminst = Get-CmSiteInstallPath

if ($cminst -ne $null) {
 $cmlogpath = "$cminst\logs"
 if (Test-Path $cmlogpath) {
 Write-Output "Backing up site server log files..."
 $src = "$temp\logtemp"
 if (Test-Path $src) {
 Write-Output "Removing previous temp folder..."
 rd $src -Recurse -Force
 md $src
 if ($LogFilter -ne "") {
 Write-Output "Filtering logs: $LogFilter.log"
 copy "$cmlogpath\$LogFilter.log" "$src"
 $cmlogs = Get-ChildItem -Path $src -Filter "$LogFilter.log"
 else {
 copy "$cmlogpath\*.log" "$src"
 $cmlogs = Get-ChildItem -Path $src -Filter "*.log"
 $lc = $cmlogs.Length
 $dest = "$temp\sccmlogs.zip"
 if (Test-Path $dest) {
 Write-Output "Removing previous archive file..."
 del $dest -Force
 Write-Output "Compressing backup log files..."
 Add-Type -AssemblyName "system.io.compression.filesystem"
 if (Test-Path "$dest") {
 $size = $(Get-Item -Path "$dest").Length
 $size = [math]::Round($size / 1MB,2)
 Write-Output "Archive created: $dest ($size MB)"
 if ($SendMail) {
 $Message = "Sending $lc SCCM Log files"
 Write-Output "Sending email with zip attachment..."
 Send-MailMessage -Subject "$Subject" -Body "$Message" -From $SendFrom -To $SendTo -SmtpServer $smtp -Attachments "$dest" -Port $Port -UseSsl -Credential $cred
 Write-Output "finished!"
 else {
 Write-Output "error: unable to create archive"
 else {
 Write-Output "error: unable to locate logs folder"
else {
 Write-Output "error: SCCM installation path not found."

My IT Ammo Box

Current list of the tools and services I use for business and personal projects.  Updated from my previous post.


Windows Desktop Apps / Web Resources

Microsoft Remote Desktop Manager

Free: I use this to provide an aggregate RDP console to all of the machines in my lab environment, as well as remote servers at customer sites.  It’s still free.  It’s still a Windows Installer package, so it’s easy to deploy using a variety of tools, scripts, or good old fashioned elbow grease.

Chocolatey:  Yes

Microsoft RSAT for Windows 10

Free: A standard utility knife for most Windows administrators and engineers.  Provided as a Windows Update package (.msu), it’s easy to deploy through a variety of means (SCCM, AD-GPO, scripts, carrier pidgeon, pack mules, etc.)

Chocolatey: Sort of (outdated package)


Freemium: I use this to map out various types of projects, from software development to infrastructure implementations (SCCM, AD, 3rd Party apps, etc.), and home projects as well.  It’s free to start and offers premium features for “business” and “enterprise” needs at reasonable prices.

Chocolatey: N/A


Freemium: I have my own repository for storing scripts and code chunks, as well as working with other teams in a contributor role.  If you even dabble with scripts, you should consider making GitHub your foundation, since it helps with things like commenting, bug tracking, feature requests, team assignments (if you want or need to), and version control.

Chocolatey: Yes


Freemium: Slack is interesting, but I’m starting to think it’s days are numbered, as other players are quickly moving into the ball pit and looking to push them to the side.  It still has a nice feel and simple interface (almost too simple, some are confused at the lack of verbose options).  The only complaint I have is with the user side, as many Slack channels start out focused, but tend to drift into side-chatter, unrelated to the group or channel.  But still, if you maintain control it can be incredibly useful.  The free level of service is enough for most users, but they offer more advanced features for an additional cost.

Chocolatey: Yes

WMI Code Creator

Free:  The old-as-dirt version is still alive and well, and still works fine on Windows 10 and Windows Server 2016.  It still runs within certain constraints, as it always has (WMI permissions, array results, etc.) but it has been my go-to analysis and testing tool for years.  I love it.  I will ask that it is buried with me when I drop dead, hope that’s not anytime soon.

Chocolatey: N/A (portable app)


Free: The venerable, the honorable, the time-tested, customizable, extensible, unflappable text and code editor.  Still free

Chocolatey: Yes

Visual Studio Code

Free: A newer, slim-lined, Spartan-ized, Bauhaus-ish, cross-platform code editor from Microsoft.  It provides some extensible features (plug-ins, editable param files, themes, etc.), and is pretty easy to deploy into large/dispersed environments (if needed).  I like the IDE behavioral features (auto-completion, indents, tips, etc.) but it still feels rough in places (to me).  I use it often, but I also bounce between other editors, depending upon the language, the project structure (local/remote/cloud/team/etc) and so forth.  Still, it’s worth trying out.  Many of my colleagues have standardized their daily work on it, so it can’t be too bad.

Office 2016 Pro Plus / Project 2016 / Skype for Business / OneNote

Subscription: I don’t need to explain these.

Chocolatey: N/A

Google Drive / Docs / Sheets / Keep

Freemium:  Drive is fairly the same as other cloud storage services like DropBox, Box, OneDrive, and so on. Each of them offer something a little better or worse than the others, and each offers additional (paid) storage capacity and/or premium features.

Docs and Sheets has evolved to become a very capable alternative to Microsoft Office for SOME purposes.  Sheets in particular, has grown into a surprisingly capable tool actually.  Google’s other alternatives like Forms and Slides are so-so (imho) but probably sufficient for student needs.  They also provide a fairly comprehensive script API to build automation solutions.  The Google apps do not use a desktop client component like Office 365 uses for full editing capabilities.

Keep is sort of a duct-taped version of OneNote, and is also cloud based (no desktop client), but also offers a mobile app.  These are all part of the “G-Suite” of Google apps and services.

Chocolatey: Yes (some apps)

Windows PowerShell ISE

Built-in: The de facto editing and debugging tool for PowerShell scripting.  There are other products available, for free and for cost, but PowerShell ISE is built into Windows.



Built-in: Admittedly different than VMware Workstation, but it comes with Windows 10 and there’s no additional licensing cost.  You might still need to consider hardware as a potential cost (memory, storage, etc.), but it’s still very very useful for building virtual labs.


Windows Snipping Tool

Built-in: Easy and fast way to capture apps, screens, or rectangle windows.  Doesn’t do mouse cursor captures, but it’s free and included with Windows 10, so I can’t complain.

Chocolatey: N/A


Free: Even though Windows 10 includes Explorer shell integrated features for creating and managing archive files (.ZIP, etc.) it has some limitations.  There are other free and paid products available for this same purpose, but 7-Zip has been around long enough to prove itself and it remains free.  I wish it was better equipped to handle some niche formats, but it’s pretty good for general needs.

Chocolatey: Yes

Phone Apps

  • Office for Android (Word, Excel)
  • Skype for Business
  • Airline apps (Delta, United, etc.)
  • Travel booking apps (Orbitz, Expedia, etc.)
  • Facebook / Facebook Messenger
  • Slack
  • TeamViewer
  • AirDroid
  • Uber
  • Google Maps
  • Google Apps (all of them)
  • Outlook for Android
  • Reddit
  • Games and more games
  • Netflix
  • Podcast Addict (with following podcast channels)
    • NPR Fresh Air
    • 60 Minutes
    • Freakonomics
    • Bill Burr’s Monday Morning Podcast
    • WTF with Mark Maron
    • Gilbert Gottfried’s Amazing Colossal Podcast
    • The Tim Ferris Show
    • The Adam Carolla Show
    • The Adam and Drew Show

And More



SCCM PowerShell without SCCM PowerShell or SCCM PowerShell

Errrr, what?


  Export all Task Sequences for a given SCCM site

  [string] path location for exporting the task sequence .ZIP files
  (default = user profile "Documents" folder)

.PARAMETER Dependencies
  [switch] Indicates to export dependencies as well (not required)

  [switch] Indicates to export content as well (not required)

  Export-CmTaskSequences.ps1 -TargetPath "C:\CMTaskSequences"

  Author..... skatterbrainz.wordpress.com / GitHub / Twitter
  Created.... 10/26/2016
  Modified... TBD

param (
  [parameter(Mandatory=$False)] [string] $TargetPath = "$($env:USERPROFILE)\Documents",
  [parameter(Mandatory=$False)] [switch] $Dependencies, 
  [parameter(Mandatory=$False)] [switch] $Content,
  [parameter(Mandatory=$False)] [switch] $ListOnly

if (!($Dependencies)) { $Deps = $False } else { $Deps = $True }
if (!($Content)) { $Cont = $False } else { $Cont = $True }
$old = $pwd

  Get-CmSiteCode was created to persevere to endeavor
  on the path of journey to finding that elusive beast:
  the site code, for this mysterious thing called a SCCM site

  $sitecode = Get-CmSiteCode

function Get-CmSiteCode {
  $x = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\SMS"
  $smsp = $x.ServerAccountProvider

  Get-CmCmdletModule returns the [string] path location
  to the .PSD1 powershell module installed with SCCM

  $mpath = Get-CmCmdletModule

function Get-CmCmdletModule {
  $result = Get-ItemProperty "HKLM:SOFTWARE\Microsoft\SMS\Setup" | 
  Select-Object -ExpandProperty "UI Installation Directory"
  $cpath = "$result\bin\ConfigurationManager.psd1"
  if (Test-Path $cpath) { $cpath }

$cmsc = Get-CmSiteCode

if (!(Get-Module "ConfigurationManager")) {
  $cmm = Get-CmCmdletModule
  if ($cmm -ne $null) {
    Import-Module $cmm
    Set-Location "$cmsc`:"
  else {
    Write-Host "uh oh! Yo shit imploded, G." -ForegroundColor Yellow
else {
  Set-Location "$cmsc`:"

Write-Output "requesting task sequences from site: $cmsc..."

$tslist = Get-CMTaskSequence
if ($tslist -ne $null) {
  $tscount = $tslist.Length
  foreach ($ts in $tslist) {
    $TsName = $ts.Name
    $TsPath = "$TargetPath\$TsName.zip"
    if (!($ListOnly)) {
      Write-Output "Exporting: $TsName..."
      Export-CMTaskSequence -Name "$TsName" -ExportFilePath "$TsPath" -WithDependence $Deps -WithContent $Cont -ErrorAction Continue
    else {
      Write-Output "name: $TsName`n`texport: $TsPath"
  Write-Output "$tscount items were exported."
else {
  Write-Output "No task sequences were found"
cd $old

while (!($dead)) { no-sleep }

SCCM PowerShell without SCCM PowerShell

For those rare cases when I needed it…

# to allow for setting the current 'drive'...
function Get-CmSiteCode {
    $x = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\SMS"
    $smsp = $x.ServerAccountProvider
    $result = $smsp.Substring($smsp.Length-3,3)
# because I HATE hard-coded path references...
function Get-CmCmdletModule {
	$result = Get-ItemProperty "HKLM:SOFTWARE\Microsoft\SMS\Setup" | 
		Select-Object -ExpandProperty "UI Installation Directory"
	$cpath = "$result\bin\ConfigurationManager.psd1"
	if (Test-Path $cpath) { $cpath }

$cmsc = Get-CmSiteCode
$cmm  = Get-CmCmdletModule

if ($cmm -ne $null) {
	Import-Module $cmm
	Set-Location "$cmsc`:"

Dear IT Recruiters…


Like most IT folks, I get a fair amount of contact from IT business recruiters.  On average, about 10% speak legible English (American-style, bastardized, beaten and bruised English), while the remainder speak various dialects of Indian, Pakistani, and various places across the Middle East, Central and Southeast Asia.  Most are very polite.  Some are in a hurry and don’t have time to be overly courteous, no worries.  But I have a few tips to share with you, if I may…

5 Rambunctious Recruiter Recommendations

  1. Read the resume first

    When you say “I read your resume and you seem to be a good fit…” for a position that has absolutely nothing to do with anything even remotely mentioned on the resume, the first reaction is to delete your email without reading further.

    For example, you happily fire off that email “Dear Anita Drinkrightnow!  Good news!  After reading your resume, I have a position where you would be a great fit!  The job is Junior Java Developer in Bowlscrubber, TX.”  Anita’s resume clearly shows she is a “Senior DBA”, and at no point in her resume is the word “Java” or “JRE” ever mentioned.  Guess who’s email just got deleted.

    You have time to talk on a phone, you have time to skim the experience section for just the position titles and locations.  And let me tell you, the really good recruiters know how to weave that into the first minute of a discussion.  “Hey Dave.  I see you’re working Fudgepackers LLC in Nowhereville, MT.  I have a fantastic opportunity at Unpackers Inc. in Nobodycaresville, MT, which is only 20 miles away from you!

  2. Check the locations.

    When you ask someone to consider a job that requires being “on site” and it’s thousands of miles away, you’d better be prepared to discuss relocation costs.  If not, then your message is deleted.

    If you’re going to lie about claiming to have read our resume, at least try to fake that you read the location of the most recent position.  Then use Google Maps (or whatever you prefer) to pinpoint that place in contrast to wherever the advertised position is located.  If it’s a few hundred miles away, you should hear a “ding! ding!” sound in your head.  That’s the “Tell them about the exciting relocation package, Jim!” alert.  If there isn’t such a package, at least play up the pay rate.

  3. Check the position level.

    If the resume shows “Senior” or “Sr.” in the most-recent position title, be cautious about shoving a “Hey! Check this out!” email in front of me with a “Junior” or “Jr.” in the title.  And if you do this and ignore the two previous suggestions, I delete your email and block you as spam forever.

  4. Rates are Important

    Do not bother to ask someone to contact you if you can’t discuss the pay rate.  Period.  And if you’re not up-front with regards to who has to pay for benefits (employer or employee) you add 50 GTFO points to the score card and a deleted email.

    If you’re a “serious” recruiter, you should take an hour to search Google for regional pay rates and costs of living.  For example, you call John Phistedtodeath about a job at Hydraulic Tampon and Incendiaries Research.  John lives in Oppressedville, VA where labor rates are lower than US average.  The position is in New York City.  You enthusiastically tell John that the pay rate is $55 per hour, without benefits and no relocation costs.  John is making $75 per hour in Oppressedville, as an FTE, with benefits and a lease.  I’ll leave the rest to your imagination.

  5. Do Not Dragnet

    If you send out job offers with key words “Systems Administrator” when the position is “Insurance agent” you not only suck, but you should be beaten with a pepper spray can, and whipped with a chain made of razor wire.  You are what make spam filters necessary.

I realize that much of this disconnect comes from the constraints of whatever shitty software application is used to track position openings and potential candidates.  But still.

Preposterous Profile Propagation Perils


Question:  “Is it advisable to migrate Windows user data when refreshing or replacing their computer?”  This was asked in the context of two scenarios:

  1. Migrating an existing Windows 7 machine to Windows 10
  2. Refreshing a hosed-up Windows 10 machine to a known state

For scenario 2, I recommend the “Reset this PC” feature in Windows 10 1607.

For scenario 1, here’s my long-winded response:  Avoid allowing your environment to get into this scenario in the first place.

I compare this with how I treat my phone.  My photos, contacts, emails, bookmarks, apps list and settings are all stored in the cloud. The only items I’d lose if my phone were lost or stolen would be SMS threads.  Not a concern.  My phone, to me, is 100% disposable.  I don’t sweat losing anything valuable if my phone were crushed under a truck wheel, dropped in a bathtub, or doused in gasoline and ignited with a blow torch (although, that would be kind of cool, hmmm).

Desktops and laptops should be no different.  Now, I’m not saying “the cloud” is the primary solution here.  ANY centralized repository will suffice as an “off-device” storage point.


Because of the following potential faults:

  • Migrating data and settings is costly.  It takes time to design, build, test and maintain for an organization.  The more variations in the environment, the more work is often required on the back end.  Even when a process/system has been in place for a long time, that doesn’t justify it’s existence (i.e. “because that’s the way we’ve always done it” = space shuttle O-ring maintenance processes too)
  • Having data stored locally is a liability.  Period.  Ask any attorney.
  • Having data stored locally is a security risk. Ask your InfoSec person (drink additional coffee first)
  • Having data stored locally adds need for disk encryption, RMS and DLP controls (more time and cost).
  • Having data stored locally incurs additional storage capacity and performance requirements on each device (depending upon the nature of data formats)

If a device is lost, destroyed, or stolen, you will need to address…

  • the potential lost of a vital copy/version of each document on the device.
  • the potential leak of private/sensitive information on the device.
  • the additional downtime incurred from replacing the user’s device as compared with providing them a “vanilla” device which immediately restores their access to all documents they need to do their job.

Is it always possible to implement this client-centric data model?  No.  There are a variety of reasons, one classic example is local processing requirements, such as CAD, media authoring, music production, etc. (high-bandwidth or high CPU demand, particularly when extensive graphic performance are a concern).

However, over the last ten (10) years of consulting and FTE work where I’ve been involved with deployment processes, I’ve only seen a few that really needed it (mentioned above).  The majority don’t really need to support local storage of business data.

The reason I bring this up is that I often see a lot of hand-wringing, project investment, and focused effort on applying a “solution” to the wrong problem.  This is just one example.  I have plenty of others to share if you’d like me to.