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.

Advertisements

cm_siteconfig 1.2

I’ve been busy this Labor Day weekend. Besides vacuuming up water from a broken water heater at 4am, mowing a ridiculously big lawn with a ridiculously small lawnmower, and avoiding the oceanfront tourist freakshow (or almost), I spent a fair amount of time on cm_build and cm_siteconfig.  Needless to say, I’m not feeling very funny right now, but I assure you that I will return to my usual tasteless, dry, ill-timed humor after a word from these sponsors.  Even though I don’t have any yet.  Actually, if you blink, you might miss some hidden jestering below.

I’ve already discussed these two PowerShell scripts in a previous blog post, but to update things: cm_build is still at 1.2.02 from 9/2/2017, and cm_siteconfig is now at 1.2.22 from 9/2/2017.  That’s a lot of 2’s.  Anyhow, here’s what each does as of the latest versions:

Note: The version numbers are in parenthesis to indicate lab configuration.  The XML allows *YOU* to configure the installation ANY WAY YOU DESIRE, and to reference ANY VERSION you desire.  The versions below are just what I used to test this thing (so far) about 84 times.

LAB TEST NOTE: Prior to running this script, build the server, assign a name, static IP address, and join to an Active Directory domain.  Then take a snapshot (VMware) or checkpoint (Hyper-V) to roll back if anything spews chunks along the way.

Prep Work

cm_build.ps1 / cm_build.xml

  • Install Windows Server roles and features (except for WSUS)
  • Install Windows 10 ADK (1703)
  • Install Microsoft Deployment Toolkit (MDT) (8443)
  • Install SQL Server (2016)
  • Install SQL Server Management Studio (2017)
  • Configure SQL Server maximum memory allocation
  • Configure SQL Server ReportServer DB recovery model
  • Install WSUS server role
  • Run the WSUS post-install configuration
  • Install System Center Configuration Manager 1702
  • Install ConfigMgr Toolkit 2012 R2
  • Install Recast Right-Click Tools

GENERAL NOTES:  The cm_build.xml structure starts with the “packages” section, which dictates what gets executed and in what order.  The “name” element establishes the package code link used by all of the other sections, such as payloads, detections, files, and features. Note that the files section only requires the pkg key value for SQLSERVER and CONFIGMGR.  Other files can be created without using a matching pkg key if desired.

LAB TEST NOTE: I strongly recommend taking another snapshot (VMware) or checkpoint (Hyper-V) at this point, prior to running cm_siteconfig.ps1.  This will help avoid angst and loss of temper while making iterative changes to cm_siteconfig.xml and retesting.

cm_siteconfig.ps1 / cm_siteconfig.xml

  • Create SCCM accounts
  • Configure the AD Forest connection
  • Configure Server Settings
    • Software Deployment Network Access Account
  • Configure Discovery Methods
    • The template AD User Discovery Method adds AD attributes: department, division, title.
    • The template AD User and System Discovery Methods add filtering for password set and login periods of 90 days each
  • Configure Boundary Groups
    • The template creates 4 sample boundary groups
    • You can enable creating Site Boundaries as well, but the default is to allow the AD Discovery to create subnet/IP range boundaries
  • Configure Site Roles
    • Management Point
    • Service Connection Point
    • Distribution Point (with PXE)
    • Cloud Management Gateway (still in development)
    • Software Update Point
    • Reporting Services Point
    • Application Catalog Web Service Point
    • Application Catalog Website Point
    • Asset Intelligence Synchronization Point
    • (more to come)
  • Client Settings
    • Still in development, but…
    • The template creates two (2) sample device policies: Servers and Workstations
  • Client Push Installation Settings
    • Still in development
  • Create DP groups
    • The template creates 4 sample DP groups
  • Create console Folders
    • The template creates sample folders beneath: Applications, Device Collections, User Collections, Boot Images, Task Sequences, and Driver Packages
  • Create Custom Queries
    • The template creates two (2) sample device queries
  • Create Custom Device Collections
    • The template creates three (3) sample user query-rule collections, and 15 sample device query-rule collections
  • Create Custom User Collections
  • Import OS Images
    • The template imports two (2) OS images: Windows 10 1703 and Windows Server 2016
    • Source media is not included.  Batteries not included.  Just add hot water and stir.
  • Import OS Upgrade Installers
    • The template imports two (2) OS upgrade packages
  • Configure Site Maintenance Tasks
    • Excludes Site Backup, and Database Reindex tasks for now.  I plan to have these enabled soon.
  • Create Application Categories
    • The template includes (5) sample categories: IT, Developer, Engineering, Finance, General and Sales
    • For now, the detection rules are implemented using a chunk of freshly-cut, carefully seasoned, and slow-roasted PowerShell code, because it’s easier to shoe-horn into this process and provide flexibility and adaptability.  And besides, all those syllables sound kind of impressive after a few mixed drinks.
  • Create Applications
    • The template includes examples for 7-Zip, Notepad++, VLC Player, and Microsoft RDC Manager

What’s Next?

  • I’m still working on this, so more changes/improvements will be coming.

Q & A

  • Is it really “open source”?
    • Yes! Go ahead and pinch yourself.
  • Did you write all this code yourself?
    • Yes, sort of.  Some of the pieces were adapted from, or inspired by, the outstanding work done by other amazing people like Niall Brady, Nickolaj Andersen, Johan Arwidmark, Mikael Nystrom, Maurice Daly, Stephen Owen, Anders Rodland, Raphael Perez, Chrissie LeMaire, Jason Sandys, Sherry Kissinger, and many others I can’t think of right now.  Thanks to Kevin B. and Chris D. for helping me find better ways to solve key areas of the overall project.  The XML constructs and process model are my own hallucinatory work.
  • Can I Make Suggestions / Request Changes?
    • ABSOLUTELY!
    • Please use the “Issues” feature in Github to submit bugs, feature changes and enhancements, etc.  I will make every effort to review, assess, feebly attempt, fail to satisfy, cry over insecurities of self-doubt, angrily assign blame, throw objects across room while swearing like a drunk sailor, solemnly accept defeat, and ultimately: try to make it work as requested.
    • Note that creating a Github account is required for submitting Issues.  Github accounts are free and they make you feel warm and fuzzy inside.
  • Does cm_build also download required installation media?
    • No.  I’m too lazy.
    • 99.999999% of my customer engagements involve a ‘kick-off’ call in which we discuss prerequisite action-items prior to beginning work. This typically includes requesting the customer to have all installation media and licensing information ready to go.  Which they typically do, so I didn’t feel the need to bother with that aspect (not to mention, try to keep up with version changes and new URL’s over time)
  • Can cm_build be used to install a Central Administration Site?
    • Yes.
  • Can cm_build be used to install a Secondary Site?
    • Yes.
  • Can cm_build be used to destroy alien civilizations?
    • Probably not.
  • How was this thing Tested?
    • In a small dungeon beneath a floating castle in a lake atop a tall mountain.  Okay, in my home lab, next to the dog’s sofa.
    • It’s been tested about 84 times as of 9/4/2017.  That’s about 55 times for cm_build and 29 times for cm_siteconfig.  But by the time you’ve read this, it’ll have increased again.
  • What was/is your Test Environment like?
    • Windows Server 2016 (Dell R710) server with Hyper-V
    • 3 virtual machines: DC1 (domain controller), FS1 (file server) and CM01 (configuration manager server)
    • CM01:
      • 16 GB memory, 4 disks (C: for OS, E: for apps, F: for content, G: for logs, etc.), 2 vCPUs
      • Windows Server 2016 Standard
    • Me:
      • Coffee cups falling off the desk, on ever flat surface, in the trash can, on top of one of my dogs, and a few more in the kitchen sink
      • Empty snack bar wrappers strewn across the room
      • A tattered doggie toy-squirrel hanging on a door knob for some strange reason.
  • What’s the point?
    • It’s been challenging, and fun, to work on.  It saves me time and headache at work and in my home lab.
    • It opens up potential secondary capabilities, like automating installation documentation and building an extract/build process to close the circle of life, open a wormhole, fill it with black holes and jump in for a ride.  I really need to stop listening to so many podcasts.
  • Why should I care?
    • You shouldn’t.  You can go do something fun now instead.
  • Why XML?
    • Because I &^%$ing hate JSON, and INI is too limited.  I thought about YAML, which looks a little bit like JSON, but not like it was punched in the face with a meat tenderizer mallet, but then I had to mow the lawn, and completely forgot why.
  • What have been (or continued to be) the biggest Challenges?
    • Time
    • Sleep
    • Deciding where to draw logical boundaries between automating and leaving out for manual work later
    • Refactoring, refactoring, re-refactoring, and re-re-refactoring before refactoring some more
    • More refactoring
    • Incomplete Microsoft ConfigMgr PowerShell cmdlet reference documentation*
    • Incomplete/inconsistent Microsoft ConfigMgr PowerShell cmdlet features*
    • Incomplete/inconsistent mental capacity (mine)
    • Occasional power and Internet service outages and lack of a power backup system (budget, weather, drunk drivers)
  • Does humor belong in IT?
    • Yeah.  It has to. Over 35 years in this field of work, I’ve seen what happens to people who forget that. It doesn’t end well.

*  I’m not going to beat them up on this, since they are already making Herculean efforts towards modernizing and cleaning up ConfigMgr, so the gravy should have a few lumps.

GPODoc – PowerShell Module

I just posted my first PowerShell module to the PowerShell Gallery, even though it’s been available on my GitHub site for a little while longer.  It’s a small project, with only two (2) functions, so far.  Get-GPOComment and Export-GPOCommentReport.

Get-GPOComment is purely CLI and helps query GPO’s to return embedded descriptions, comments and so on.

Export-GPOCommentReport is a CLI function as well, but produces an HTML report, which is technically GUI output, of embedded GPO comments and descriptions.

The module is simple to load by way of the Install-Module and Import-Module cmdlets (see below).  The only requirement is to have the GroupPolicy PowerShell module installed first.  This is normally installed on all AD domain controllers, as well as other servers and workstations which have the Windows 10 RSAT package installed (tip: You can also use Chocolatey to install RSAT:  choco install rsat <or> cinst rsat)

Loading The PowerShell Module

Install-Module GPODoc

Trying it out: Get-GPOComment

Get-GPOComment -GPOName '*' -PolicyGroup Policy

get-gpocomment1

Get-GPOComment -GPOName '*' -PolicyGroup Preferences

get-gpocomment2You can easily modify the output layout since the output is in hash table format…

Get-GPOComment -GPOName '*' -PolicyGroup Preferences | Format-Table

If you want more flexibility in selecting the inputs, you can use the Get-GPO cmdlet and channel the output through a pipeline.  For example…

Get-GPO -All | Where-Object {$_.DisplayName -like "U *"} | 
  Select-Object -ExpandProperty DisplayName | 
    Foreach-Object {Get-GPOComment -GPOName $_ -PolicyGroup Policy}

get-gpocomment3

The parameters for this function are as follows:

  • GPOName
    • [string] single or array of GPO names
  • PolicyGroup
    • [string] (select list) = “Policy”, “Preferences” or “Settings”
    • Policy = query the GPO descriptions only
    • Settings = query the comments attached to GPO internal settings only
    • Preferences = query the comments attached to GPO Preferences internal settings only

This also respects -Verbose if you want to see more background details.

Export-GPOCommentReport

This function only takes two (2) inputs:

  • GPOName
    • [string] single or array of GPO names
  • ReportFile
    • [string] the path/filename for the HTML report file to create.

It invokes Get-GPOComment, combining “policy”,”preferences” and “settings” output, and writes it all to an HTML report file of your choosing.  The CSS formatting is hard-coded for now, but I’m open to feedback if you want more options. You can specify the GPO name(s) directly, or feed them via the pipeline.

export-gpocommentreport1

Example web report…

export-gpocommentreport2

If you used 1.0.1 (posted a few days earlier) scrap that and get 1.0.2.  The older version had some major bugs in the Get-GPOComment function, and the Export-GPOCommentReport function wasn’t available until 1.0.2.

Feedback and suggestions are welcome.  Even if it’s “hey man, your shit sucks. Consider a dishwashing job, or something else.”  Any feedback is better than no feedback.

Thank you!

 

Documenting Your IT Environment (The Easy Way)

One of the most common, and tragically problematic, aspects of today’s IT world is the lack of sufficient documentation. In fact, ANY documentation. It’s not associated with any one area either. It crosses everything from help desk tickets, to change requests, to Active Directory objects, to Group Policy, to SQL Server, to System Center to Azure.

UPDATED 8/8/17 – added SQL and SCCM examples at very bottom.

When and Why Does It Matter?

It matters when things go wrong (or “sideways” as many of my colleagues would say).  There’s the “oh shit!” moments where you or your staff find the problem first.  Then there’s the “oh holy shit!!” moments when your boss, his/her boss, and their bosses find the problem first and come down hard on you and your team.  When shit goes wrong/sideways, the less time you waste on finding out the what/where/why/who/when questions for the pieces involved with the problem, the better.  To that end, you can document things in other places, like Word documents, spreadsheets, help desk and ITIL systems, post-it notes, whiteboards, etc.  Or you can attach comments DIRECTLY to the things which are changed.  This isn’t possible in all situations, but it is most definitely possibly for many of the things that will straight-up shove your day into shit storm, and I have no idea what that really means, but it just sounds cool.  Anyhow…

The best part of this approach is that you can leverage PowerShell and other (free and retail) utilities to access and search comments you nest throughout the environment.  For example, you can collect and query Group Policy Object comments…

Need to Get the Comment buried in a particular GPO or GPPref setting?  Here’s one example for querying a GPO under User Configuration / Preferences / Control Panel Settings / Folder Options…

#requires -modules GroupPolicy
<#
.SYNOPSIS
  Get-GPPrefFolderOptionsComments.ps1
#>
param (
  [parameter(Mandatory=$True)]
  [ValidateNotNullOrEmpty()]
  [string] $GPOName
)
try {
  $policy = Get-GPO -Name $GPOName -ErrorAction Stop
}
catch {
  Write-Error "Group Policy $GPOName not found"
  break
}
$policyID = $policy.ID
$policyDomain = $policy.DomainName
$policyName  = $policy.DisplayName
$policyVpath = "\\$($policyDomain)\SYSVOL\$($policyDomain)\Policies\{$($policyID)}\User\Preferences\FolderOptions\FolderOptions.xml"
Write-Verbose "loading: $policyVpath"

if (Test-Path $policyVpath) {
  [xml]$SettingXML = Get-Content $policyVpath
  $result = $SettingXML.FolderOptions.GlobalFolderOptionsVista.desc
}
else {
  Write-Error "unable to load xml data"
}
Write-Output $result

Example…

So, What Now?

So, in the interest of avoiding more bad Mondays, start documenting your environment now.  Need some examples of where to start?  Here you go…

 

Thank you for your support.

Poor Man’s IT Chain Reactions

wpid-chinese-take-out.jpg

Challenge:

Make sure every machine in the enterprise (connected to LAN or always-on VPN) has the latest version of psexec.exe on the local C: drive.

Why?

Why not?  That’s why.

Option 1:

AKA – the semi-automated, safety switch turned off, fully-loaded, drunk guy holding the trigger option.

  1. Download psexec.exe from live.sysinternals.com (or direct: https://live.sysinternals.com/psexec.exe) and place into AD domain SYSVOL scripts folder (e.g. \\contoso.com\netlogon)
    Example…

    $WebClient = New-Object System.Net.WebClient
    $WebClient.DownloadFile("https://live.sysinternals.com/psexec.exe","\\contoso.com\netlogon\psexec.exe"
  2. Create Group Policy Object (GPO) with Computer Preferences setting to copy psexec.exe from the SYSVOL share to a location on the local C: drive. Configure to “update” so that future version updates will be passed down to the clients.
  3. Create a Scheduled Task to keep the SYSVOL copy up to date with the latest version.

Pros

  • Cheap (free)
  • Fairly automated (just add water, makes it’s own sauce / set it and forget it)

Cons

  • Smells like duct tape and coat hanger wire

Option 2:

AKA – The “I have a budget, so kiss my butt” option.

  1. SCCM package or application deployment

Pros

  • You look cool pulling it off, but not as geeky as option 1.

Cons

  • More moving parts under the hood.
  • May require additional steps to maintain a consistent current version across all devices.

Option 3:

AKA – The “I don’t have a budget, so kiss my butt” option.

  1. Include within image configuration (MDT, SCCM, Ghost, Acronis, etc.)

Pros

  • Easy

Cons

  • Difficult to maintain a consistent and current version across the enterprise

Option 4:

AKA – the “most fun to laugh about during the next beer-meeting” option

  1. Send the new guy around with a USB thumb drive

Pros

  • Great fun in the office

Cons

  • Do I really need to spell this out?

 

The 5 Immutable Laws of IT Life

1 – The person you need most will be unavailable when you need them.
2 – The problem will stop as soon as you try to show it to someone else.
3 – The simplest task will end up taking the most time.
4 – The feature you need most will be the least documented.
5 – That which saves you time, will cost more money (and vice versa).

Setting up a Real World IT Lab

1wearandtear

Updated: v1.1 – Fixed bug in step 8.2 added final step for consultants

Whether it’s for your full-time job, a customer reflection platform as a consultant, or a certification study environment, if you work in IT today, you have to make or buy a lab in order to keep up.  It’s no longer a luxury, it’s a must-have.  But, while many resources exist for making a lab at home, or in the cloud, most are fairly clean and “textbook” configurations.  The real world is nasty, ugly and smells pretty bad.  If off-the-shelf lab tools and hydration kits were a dog, they’d be neatly-trimmed and bathed poodles, while the real world lab would be a dumpster filled with dead fish, baking in the Texas sun for weeks on end.  This is one of the trade secrets seasoned IT professionals keep close to their chest.

Well, fear not.  I have compiled and prepared a simple how-to outline for building your own lab, to reflect that beast we call the ‘real world’.  Let’s get started.

  1. First off, start with 5-8 year old hardware.  Make sure it doesn’t support anything really new, like TPM.  If it still has DB25 and PS/2 ports, that’s a winner.
  2. Beef it up to no more than 8 GB of DDR2 memory
  3. Stuff a hefty 250 GB 7200 RPM Hard Disk in it, and add a few others at either 5400 or 7200 RPM rates.  Find the nearest vacuum cleaner, and empty the dust bag into the vents on the server case.  The more dust, the better. Kind of like a seasoned cast-iron skillet.
  4. Load it up with Windows 2000 Server
  5. Install VMware Workstation 9
  6. DO NOT, and I repeat DO NOT, install ANY hotfixes or updates on it.
  7. Power it on and wait for it to get to the login prompt.  It should take around 15 to 20 minutes or so.  If it gets there sooner, remove some memory and reboot again.
  8. Configure an Active Directory forest and domain.
    1. Create 100 random OU’s
    2. Create 400 random GPO’s and link them to as many OU’s as possible.
    3. For added realism, randomly select a dozen GPO’s and apply inheritance blocking.
    4. Modify the Default Domain Policy to contain at least 75 settings.  It doesn’t matter what they are, random selections work best.
    5. Do not document any GPO settings whatsoever.
    6. Create 500 computer accounts with random names. Create 500 user accounts with random names. These will reflect a typical company environment which has 25 real computers and 35 real users.
  9. Turn off all firewalls, and install any antivirus that comes up in the sidebar ads while searching Bing for “ultimate antivirus”, but avoid any products with recognizable names.
  10. Add “Domain Users” and “Users” to the local “Administrators” group on every machine in your lab.
  11. Copy random files to every machine until the C: drive is around 96% full.

Now, you are ready to play the game of “ask management for an upgrade budget”

  1. If you’re married, put some clothes on and carefully knock on the bedroom door.  It works best if your wife/husband is watching his/her favorite show on his/her tablet or phone, that way your intrusion puts him/her in an authentic mood, to match that of a real MBA type, who’s busy updating Facebook and LinkedIn when you knock on their office door.
  2. If you’re not married, substitute your most-recent girlfriend/boyfriend.  Otherwise, use a random neighbor, stranger or off-duty bus driver.  Do not use anyone under 21 years of age who didn’t drop out of school, because they’ll be too smart for this.  Remember, the key here is to be authentic.
  3. Make your best pitch for a budget to replace all of that hardware and software with modern stuff.  If you want really real realism, ask for a budget to migrate everything to AWS or Azure.  Always double your asking price, so they’ll cut that in half, and approve 40% of the remainder.
  4. Ask for additional IT staff, but be sure to double that number as well, so when they reject the entire request, it will at least look like you tried.

Now comes the real work.

  1. Turn off the server and go mow the lawn, wash the car, do some dishes, walk your dog or cat around the block a few times.  This will simulate dealing with support request tickets and attending useless status meetings.
  2. If you get back to the server in less than 5 hours, you rushed it.  Go back and do it again until you use at least 5 or 6 hours.
  3. When you get back to the server, turn it on and then go take a shower.  This will simulate you trying to get caught up on email, Slack, Teams, SharePoint, Hangouts, and writing all the reports you were asked to do during all those daily meetings.
  4. When you get back to the server, it should be around 8 PM (assuming you started around 7:30 AM), so this is about perfect for a typical time to get started on actual technical work.
  5. After one hour, stop and ask your wife/girlfriend/boyfriend/neighbor/bus driver if they need anything from the nearby fast food place.  When you get back it should be around 11 PM or midnight, so it’s time to make coffee and get that last OU populated.
  6. If you’re doing this right, you should fall asleep at your desk around 1:30 AM at the earliest.
  7. Don’t forget tomorrow is that 6:30 AM all-hands meeting, that the CIO requested.
  8. And don’t forget that at 8:00 AM you’re supposed to demo how you’re planning to migrate all of your infrastructure to Azure using Hyper-V, PowerShell and Office 365, in front of all the executives who need to approve your request.  If you don’t have it ready yet, forget the sleep stuff tonight.

That should just about do it.  But there’s more.  For added realism, you can include the following:

  • Cut your sleep down to 2:30 AM to 6:00 AM, or 3:00 AM to 5:00 AM for optimal effect.
  • Start massive consumption of coffee, Red Bull or Monster.  In fact, never leave your desk without one of these in one of your hands
  • Always carry a mess of papers in one hand and coffee cup in the other, and your smartphone in the other.  Yes, that’s three hands, figure it out.  Always look stressed and anxious, and out of breathe.  This is commonly referred to as “office camouflage”
  • Stop eating healthy. It’s bad for you.  Doughnuts are the most efficient food source.  Pure calories for pure energy.
  • Time yourself in the desk chair.  If you’re getting out of your chair more than every 3 or 4 hours, that’s too much.
  • Wherever you sleep, if you do, make sure to keep your cell phone next to you, with the ringer volume at the max.  You’ll need this for on-call rotation practice.  Set the alarm to go off every 55 minutes for randomized effect.  If you have a friend that barely speaks your native language, ask them to have a friend of theirs call you at random times between midnight and 5 AM and scream about something crashing or being on fire.
  • Ask for a raise.  This is best practiced on someone who doesn’t understand your native language at all.  Not even one word.  Go ahead, make your best case.
  • Take up smoking. Not for your health, but as a proven excuse to out outside to call recruiters, searching for another job.  If smoking isn’t feasible, walking is an okay substitute, just not as good for your health.
  • Hire consultants

Within a few weeks, you’ll be out of the hospital and back to work, just a real IT professional.