About Ben Peterson

This is my professional blog. My less professional content is hosted elsewhere.


Connecting in to SCCM via PowerShell

It’s easy to launch an interactive PowerShell window by launching the SCCM Console and clicking “Connect via Windows PowerShell”

But it’s kind of a pain in the butt when you want to use the PowerShell ISE or make an automated script that needs to connect in.

Here’s a quick function you can drop in to any script or the ISE script pane to get you up and running:
Function Connect-SCCM {
[string]$SCCMCmdlet = "${env:ProgramFiles(x86)}\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
if (!(Test-Path -Path $SCCMCmdlet -PathType Leaf)) { Write-Error "ConfigurationManager.psd1 not found. Make sure the Configuration Manager Console is installed" -ErrorAction Stop } #Make sure module exists
if (!(Get-Module -Name ConfigurationManager)) { Import-Module $SCCMCmdlet } #Import module if not already loaded
Set-Location ((Get-PSDrive -PSProvider CMSite | Select-Object -First 1).Name + ":") #Change directory to the first site detected



SCCM – App Requirement to detect laptops

I have an application I need to push out to only laptops that are used by a specific AD user group. I already have a collection set up to target my AD group, but I didn’t have a filter to target just the laptops.
To do this, I created a new global condition called Hardware Type. This houses a PowerShell script that checks the model against a known list of laptop model names and returns back either “Desktop” or “Laptop” as appropriate. From there, I can add the custom condition to my application and make sure that it only installs for users in my collection that have a laptop.

I named my Global Condition Hardware Type. It’s a Windows Setting and the setting type is Script and the data type is String.
Here’s my script (we’re mostly an HP shop and these are the models I use to identify laptops):

$Model = (Get-WMIObject win32_ComputerSystem).Model
$LaptopModels = @("Surface","EliteBook","Spectre","ZBook","Elite x2")
$LaptopModels | ForEach-Object { if ($Model.Contains($_)) { $LaptopDetected = $True } }
if ($LaptopDetected) { "Laptop" } else { "Desktop" }

From there, I just had to add a Requirement that Hardware Type = “Laptop”.



PXE Wizardry

Today was our (partial) production cutover from SCCM 2007 to SCCM 1511.
The main change is that new machines we set up starting today are using the new deployment process. It’s not so much of a technical thing as a “Use the new process instead of the old one” thing.

Well, there was one technical change… and it was complicated: PXE Booting. Up until yesterday, everyone’s been using USB or ISO files to boot to the new deployment environment. But with this cutover, we can repoint PXE booting from SCCM 2007 to the shiny new stuff.

Here’s some things to be aware of as part of the process:



PowerShell function Update-Registry

I’m retooling my process for building Windows reference images and tweaking existing OS deployments. I was annoyed at needing extra handling for New-ItemProperty since it won’t automatically create a New-Item if the path doesn’t exist.

In the spirit of making everything modular, I created a simple function that combines the two. And because it’s me, I added way too many notes and other things. But, it’s a copy/paste to add this to my other scripts, so I’d say it’s worth it. Function is below.



Building Windows 10 Boot media for SCCM 2012 R2

Once you have your SP1 and your CU1, and your ADK and maybe your MDT, you’re probably sick of acronyms and just want to get things done.

Here’s a script that preps your ADK boot media for importing into SCCM. It’s a bit prettier than what’s on the Technet blogs, although I wish I had time to just convert it into PowerShell.


REM This script prepares boot media to be imported into SCCM
REM Only the first three SET commands should need to be customized

REM The source used during the “Add Boot Image” wizard in the admin console
SET SCCMContent=E:\Software\Operating Systems\Boot Media
REM The install path for the Windows 10 ADK
SET ADKSource=C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment
REM The staging folder where the boot wim is built/mounted
SET StagingDir=E:\Boot Media

SET Arch=x86
CALL :Build

SET Arch=amd64
CALL :Build


ECHO Creating %Arch% package…

SET WorkingDir=E:\Boot Media\%Arch%
SET Source=%ADKSource%\%Arch%
SET Destination=E:\Software\Operating Systems\Boot Media\%Arch%

MKDIR “%WorkingDir%\Mount” 2>NUL
MKDIR “%Destination%” 2>NUL

COPY /Y “%Source%\en-us\winpe.wim” “%WorkingDir%\boot.wim”

dism.exe /mount-wim /wimfile:”%WorkingDir%\boot.wim” /index:1 /mountdir:”%WorkingDir%\mount”
dism.exe /image:”%WorkingDir%\mount” /add-package /packagepath:”%Source%\WinPE_OCs\winpe-wmi.cab”
dism.exe /image:”%WorkingDir%\mount” /add-package /packagepath:”%Source%\WinPE_OCs\winpe-scripting.cab”
dism.exe /image:”%WorkingDir%\mount” /add-package /packagepath:”%Source%\WinPE_OCs\winpe-wds-tools.cab”
dism.exe /unmount-wim /mountdir:”%WorkingDir%\mount” /commit
COPY /Y “%WorkingDir%\boot.wim” “%Destination%”




Progress Feels Good


It’s been a rough week or two at work. Security tightening is never a bad thing but it sure can slow things down. Despite that, today I hit a major milestone on a project I’ve been working on for almost a year. Here it is in all it’s glory – a production instance of SCCM 2012 R2. It was a cool 25 minute smooth install for the most part.

InstallThere were a few times I ended up referring to this blog article from System Center Dudes. It’s a bit outdated, but overall solid. Probably worth the $20 PDF which is supposedly being maintained with updates.

Quick note about something I haven’t seen documented elsewhere: Now that Windows 10 is out, I thought I’d be OK doing this new installing using the Windows 10 ADK. Nope – Start with the 8.1 ADK so that pre-reqs are met and the base install can be completed. Then do your SP1 update, and then your cumulative update, and then finally remove ADK 8.1 and install ADK 10.




Microsoft Deployment Toolkit 2013 Update 1 – Good News!

Super excited that the update with Windows 10 support finally came out!

My first panic attack over the Dev upgrade I just completed has come and gone.

Good news! The custom code out there to have each Task Sequence call and read a separate CustomSettings.ini file still works. So does the hack to show a list of human-friendly OU paths for domain joins. Just don’t do what I did and completely forget about those customizations – after you update your deployment share, all those tweaks you’ve done to the Scripts folder will have to be redone.

I had great success using NotePad++ and the Compare plugin to copy over the needed differences.



PowerShell + SSH

I dunno how this one slipped by me, but back in June Microsoft officially announced that running an SSH connection inside PowerShell will be an officially supported, real thing. How cool is that!? I mean, PuTTY and friends isn’t terrible, but I sure am looking forward to having a native, pre-installed alternative. Especially if it can run in WinPE.




Happy Sysadmin Day!

Hug your backup guy! Buy a beer for the network dude! Go easy on the helpdesk! Change your password and wink at the security team!



Continuous Integration

I’m a little late to the game, but this Google talk called Move Fast & Don’t Break Things is particularly apt for the challenges I’m faced with at work lately. Focusing on unit testing and downplaying the end-to-end testing has always been a preference for me, but when working with folk who much prefer the slow waterfall approach to all projects, I have a tough time finding the right words to use to defend this more streamlined release cycle. This slide deck, even if you don’t watch the youtube video presentation for it, is really helpful. I suppose maybe I should seek out some formalized Continuous Integration training…