Set your Powershell scripts to always use the closest Domain Controller

When writing a new script, I like to make sure I know which DC my AD cmdlets are talking to. I do this by using the -Server flag, but rather than hard-coding a specific DC into my scripts, I always use the closest writable DC by starting all my scripts with this line:

$domainController  = (Get-ADDomainController -Writable -Discover -NextClosestSite).name

You’ll then specify this DC when you’re making your AD calls:

Get-ADUser -identity 'Benjamin Atman' -server $domainController

Starting your scripts this way will ensure you’re always talking to the closest DC, and that you always know which one you’re talking to.

Forcing Weekly Reboots via SCCM

In my environment, it was decided that we would reboot all PCs once a week. The merits of this are intensely debated on the internet, so this may not be the right route for your organization to take, but it definitely does serve some valid purposes in our opinion.

  • Ensures that all PCs are regularly rebooted
  • Ensures that all PCs are in a state that will allow upgrades of third-party software (Java, for example) that will fail if the software or other certain applications are running
  • Eliminates the user-side guesswork of whether this is the week their computer will reboot for patching; through a series of Powershell scripts, we send an email to each of our offices at 1:15pm local time every Tuesday (right around when most people are getting back from lunch) to remind them that their computer will reboot overnight

Like I said, there are many people who see this as unnecessary or detrimental, but others who think it’s a great idea. For the most part, we’re in the latter camp. In order to set this up, I first created a collection with a Maintenance Window from 10pm Tuesday night until 3am Wednesday morning. It is very important that you have a Maintenance Window configured before you set up these forced reboots, otherwise machines that are already powered off before the users left for the night will reboot themselves when powered back on the next day.

To set up the forced reboot advertisement:

  1. Create a new package called “ForcedReboot”
  2. Right-click Programs and select New Program.
  3. I named mine simply “ForcedReboot”. Set Start In to c:\windows\system32, and set After Running to Program restarts computer.
  4. My command line is shutdown.exe -r -t 300 -c “Initiating scheduled reboot for system maintenance. You have 5 minutes to save your work before mandatory forced reboot.” This gives a reboot with 5 minutes of lead-time, and displays the message in quotes to any users who may still be logged in.
  5. Create an advertisement with a mandatory advertisement a little bit into your Maintenance Window (you want to give yourself some time to run things before the reboots if necessary). I advertise this to the same collection I use for Microsoft Updates. Set it to recur every 1 week the night of your Maintenance Window. You’ll also need to change the Program Run Behavior of the advertisement to Always Rerun Program.

It’s important to note that your clients will not reboot at exactly the time you set the advertisement for. For example, if you have it set to run at 10:30pm, but have a Countdown Notification Length of 5 minutes, your machines won’t reboot until 10:40pm (advertisement time + Countdown Notification Length + lead time built into the command line). Also important to note: users with administrative privileges can execute a shutdown /a to abort the shutdown, but only after the Countdown Notification has ended.

Resolving RegUtils error per-machine when deploying Java via SCCM

I’ve previously discussed how to deploy Java via SCCM 2007. The most common reason for this deployment to fail in our environment is “Internal Error 2753. regutils.dll”. It looks like this error is typically caused by having a browser or Java itself running when you try to update it. Here’s what we do to resolve it (with JavaRa and JavaMSIFix on network shares, this whole process takes less than a minute per client):

1. Open SCCM Client Center and connect to the PC in question
2. In the Inventory Actions section, select the AddRemove Programs tab and click Get Installed Software.
3. If Java is listed, remote onto their machine and go to in IE. Click Do I have Java?. You should get a message that Java is installed, or maybe one saying your version of Java is out of date. This is good (unless your environment should have the latest version of Java). You’re done!
4. If Java is not listed, remote into their machine and close out of all web browsers. Run JavaRA as Admin. Select Remove Older Versions. Once that’s complete, you should get a text file logging the progress. Close out of that.
5. Run JavaMSIFix.exe (also as Admin). It’s pretty self-explanatory.
6. Go back to the SCCM Client Center, and rerun the appropriate Java advertisement.
7. Check to make sure Java is now correctly installed by pulling up Add/Remove Programs. If it’s listed there, you’re all set!

Automatically Apply Regional Settings by IP

Here at the company I work for, we have a number of offices scattered around the world. Computers imaged at each office have to be placed in an OU specific to each office, have an office-specific Local Admin password set, and have the timezone set. Originally, we had a separate Task Sequence for each office, and we’d have to pick the right one. Unfortunately, this also meant that we had at least 5 of each Task Sequence, which made updating software packages pretty tedious, as we’d then have to update them in each TS.

I didn’t want to create an HTA to have the local IT guy manually select an office, and I was also averse to having the local IT guy enter specific values in the form of a Task Sequence Variable. Our offices each have well-defined subnets, so I knew there’d have to be a way to have the task sequence automatically apply these regional settings based on the IP address. Here’s how to do it (note: these instructions are for SCCM 2007; I’m not sure how they’d need to be modified for SCCM 2012 at this time):

  1. Start by closing out of the Configuration Manager Console on the Site Server
  2. Download Microsoft Deployment Tools (MDT) 2012 and install on the Site Server.
  3. After installing, go to Start > All Programs > Microsoft Deployment Toolkit > Configure ConfigMgr Integration.
  4. You’ll want to select the radio button for Install the MDT extensions for Configuration Manager, and check the boxes for Install the MDT console extensions for ConfigMgr 2007 and Add the MDT task sequence actions to a ConfigMgr server:
  5. Next, re-launch the Configuration Manager Console and create a new package (I just called mine “MDT”). You’ll want to set the source to the location of the “Templates\Distribution” folder within your MDT installation (using the UNC path). For me, that was “\\[SiteServer]\c$\Program Files\Microsoft Deployment Toolkit\Templates\Distribution”.
  6. Distribute this package (no need to create any programs here) to your Distribution Points as normal.
  7. Open up the Task Sequence you want to modify. I created a new group within this TS and called it “Regional Settings,” and put all the following steps within that group just for organization.
  8. In the Task Sequence Editor, select AddMDTUse Toolkit Package. Click on this step and add your Toolkit Package by clicking the Browse button and locating your MDT package.
  9. Add another step: AddMDTGather, and specify for that step to Gather only local data (do not process rules).
  10. Now, let’s create a group for each region/office. Each group should contain the Apply Windows Settings and Apply Network Settings steps, with Local Admin password, Time Zone, and OU set accordingly (and any other region-specific settings; I’m working on having the task sequence install a Language Pack for our German office as well, but haven’t gotten that far yet). I also included a Set Task Sequence Variable step called “Set Location Variable” in which I create a TS Variable called “OSDLocation” and assign a specific two-letter code, because I’ll probably eventually start assigning specific software titles to specific offices as well.
  11. For each group, click the Options tab and click Add Condition. First, we’ll add an If Statement, to run if Any conditions are true.
  12. Under that If Any statement, click Add Task Sequence Variable. The Variable we’re going to be looking at is called DefaultGateway001, and we’ll want to set it to equal whatever this office’s Default Gateway is. Some of our offices have multiple possible Default Gateways, so you’ll just want to set this for any possible Default Gateway in each office.
  13. Test your Task Sequence! It should image successfully, and show up in the correct OU, with the right Time Zone and Local Admin password.

You’re all set! If you have any trouble with any part of this, please leave a comment below!

OSD Hangs on “Installing Updates” Step

We were experiencing an issue at one of our remote offices where our OSD task sequence would get stuck right before it began installing updates (Windows and Office Updates). This issue seemed to only affect machines that were already in SCCM’s database; unknown machines were unaffected. The issue was most prevalent in one specific remote office (affected approximately 60-70% of machines being reimaged), but was documented only sporadically at other offices. For what it’s worth, our environment is SCCM 2007 R2 running on Windows Server 2008 Enterprise.

My first inclination was that there were just too many updates involved. I built a new Windows image that already included all of the Windows 7 updates that we’ve deployed to-date (a good practice we’ve decided we should do every few months anyway, just to cut down on OSD time). Unfortunately, this still did not work.

A bit of Googling yielded promising results: a hotfix available from Microsoft- “Task sequence that installs many updates stops responding on a System Center Configuration Manager 2007 SP2 client.” Perfect! I downloaded the hotfix, and proceeded to install it on the Site Server. Once that’s done, it also creates a new package called “KB2509007 – Advanced Client Hotfix – [Site Code]”. I had our remote techs try kicking off some OSD at this point, but apparently, I’d jumped the gun.

At this point, what needs to be done is to update your “Microsoft Configuration Manager Client Upgrade 4.0 ALL” package on all your Distribution Points. Also take note of this package’s Package ID, as you’ll need to add the following to the Installation Properties of your “Setup Windows and Configuration Manager” step in each of your Task Sequences:

PATCH=”C:\_SMSTaskSequence\OSD\[Package ID for Client Upgrade 4.0] \i386\hotfix\KB2509007\sccm2007ac-sp2-kb2509007-x86-enu.msp”

Once this is added to your OSD TSs, and the package is updated on your DPs, your Task Sequences should stop hanging during the Installing Updates step!

Packaging MS AdCenter for SCCM Deployment

One would think that since Microsoft created SCCM, it would be really easy to distribute their software using it.

One would be wrong to think that.

Recent updates to Microsoft AdCenter are forcing users to update to the newest version, which is not possible for users in our environment who are not Admins due to the way our GP is configured. I spoke with a number of people at Microsoft, finally getting in touch with a Senior Development Lead for AdCenter who was actually super-helpful. Apparently, the installer used to be available as an MSI, but was changed to only allow per-user installs (so that non-admin users could update the software themselves) after requests from companies that apparently have very different setups than mine. Until the installers can be changed to allow the inclusion of an OPTION of a per-system install, here is my solution:

  1. Download the from as well as the AdCenter Installer executable.
  2. Run the command line wix36-binaries\dark.exe adcenterdesktopinstaller.exe -x <output directory> (this will put the MSI for AdCenter and the EXE for the AdCenter Prereqs in “<output directory>\AttachedContainer\”)
  3. Use a program like Advanced Repackager (free to try for 30 days) to capture the installation of the MSI, and then use Advanced Installer to modify the installation directory to put the files in “Program Files (x86)” instead.
  4. Create a package in SCCM for the Prerequisites using the EXE from step 2 with the command line “adCenterDesktopPrerequisites.exe /q” to run it silently.
  5. Create another package (via definition) for the AdCenter install itself using the rebuilt MSI you created in Step 3.
  6. Set it so that the AdCenter Prerequisites installation runs before the AdCenter installation in SCCM.
  7. Deploy!

Let me know if you have any questions!!

Deploy Latest Silverlight via SCCM using MSI

When creating packages in SCCM, I strongly prefer to use MSIs over EXEs. They’re just way simpler. A few clicks and you’ve got all the command lines there for you automatically, instead of having to test and re-test or guess at the command line switches for an EXE. One thing that boggles my mind is Microsoft’s inability to release MSIs for their own products. Silverlight and AdCenter both saw updates recently, and both were released as EXEs.

Here are some quick steps to take the Silverlight EXE and get a usable MSI from it:

  1. Download the EXE from Microsoft’s site here.
  2. Open the EXE using 7-Zip and extract the contents to a folder. You should have an MSI and an MSP as well as some other files.
  3. Open a command prompt in the folder you extracted the Silverlight files to.
  4. Use this command line to apply the patch to the installer: msiexec /a silverlight.msi /p silverlight.msp
  5. You’ll notice a new folder appears in the folder you extracted the files to called “PFiles.” Make sure you include this in your SCCM Source Files folder for the Silverlight installer, or the install will fail.

Once installed, future patches can be managed via Software Updates in SCCM.

Capture Task Sequence Logs during OSD

SCCM has this really annoying habit of not keeping TS logs accessible after completing an OSD task sequence. Unfortunately, this also applies when the TS fails. To combat this problem, I implemented the following solution from Steve Rachui, which moves the TS logs to a network share for proper archiving and ease of access.

To do this, I added a new group to my main task sequence called Log Upload. I selected the “Log Upload” group and went to the Options tab, and added a Task Sequence Variable condition wherein we check whether _SMSTSLastActionSucceeded equals false. If so, it executes the group. I added four steps to this group:

  1. Connect to SMSTSLogUploads – This is a Connect to Network Folder step, which connects to a folder on our SAN using our SCCM service account, mapping it to Z:\.
  2. Erase pre-existing folder for machine – This is a Run Command Line step, which executes the following command line step to delete any folder that had already been created for the machine being imaged: cmd.exe /c rd /s /q z:\%_smstsmachinename%%
  3. Create log folder for current machine – This is another Run Command Line step, which creates a folder on the share for the computer currently running the TS: cmd.exe /c md z:\%_smstsmachinename%%
  4. Copy logs to folder – Our last step, also a Run Command Line step, this actually handles the copying of the log files to the newly-created folder: cmd.exe /c copy %_smstslogpath%\*.* z:\%_smstsmachinename%

It’s important to set this whole group to “Continue on Error,” otherwise it will fail if any of the individual steps fail, and report your entire TS execution as a failure. In my first test run, I hadn’t set this option, and the TS failed when it wasn’t able to delete the not-yet-existing folder on the share in step 2. Note that you’ll also want the preceding steps to continue on error as well, otherwise the TS won’t even get to this part on failure.

Next time, I’ll talk about using a script to send an alert email when a task sequence fails!

Test Your Command-Line Before Pushing a Package!

SCCM installs software using the local system account. This sometimes presents issues when testing before packaging in SCCM, as there is no straight-forward way to run things as this account. Packaging the software, testing by deploying to a test machine, and waiting for the results can be time-consuming, so here’s an alternative method for testing your command-line as the local system account:

1. You should have PsExec on the test machine (for example, my test machine has it located in C:\Program Files (x86)\PsExec.exe). Open an admin command prompt and navigate to the location of your PsExec.

2. Enter psexec -si cmd.exe to open a command prompt as the local system account. To confirm that you’re running this command prompt as the system, you can use the command whoami. It should return nt authority\system.

3. You can now use your command line installation to run under the same conditions as SCCM!

For even more betterness, you can create a desktop shortcut with the following target (be sure to sub in a valid admin username):

C:\Windows\System32\runas.exe /user:[domain]\[admin account] “c:\program files (x86)\psexec -si cmd.exe”

This will prompt for the admin account’s password, and then launch the system command prompt.

-Derived from Richard Balsley’s post, found here

Deploying Java with SCCM

Here’s how I’ve been able to deploy Java via SCCM 2007 (this method works for both Java 6 and Java 7):

1. Download the version of Java JRE you want to deploy HERE (specifically, the Offline installer; we use x86 even though we have x64 machines).

2. Run the Java EXE.

3. Find the temp folder it unpacked to (probably C:\Users\%USERNAME%\AppData\LocalLow\Sun\Java for whatever user context you ran it under).

4. Take the MSI in that folder, along with Put BOTH those in your source folder (it will fail if you don’t copy as well).

5. Create Package from Definition using that MSI.

6. Deploy! It is very important that when you deploy this to your clients, all browsers are closed and Java is not running, otherwise your deployment may fail. My environment forces all client machines to reboot half an hour into our weekly Maintenance Window, so we always push these updates after that reboot to ensure Java and browsers are not running.

If you have a more efficient method, or any questions, leave a comment!