h1

VBScript: Run Optional SCCM Advertisements

October 13, 2009

Here’s a fairly simple script that will check for and execute all optional advertisments on a client machine. This could be modified to include checks for adverts that have already ran and not rerun or put a GUI around it to choose which adverts to run selectively.
If the code has not been downloaded to the client yet a content retrieval will be made automatically prior to running.

CAREFUL OF WORD WRAPPING

'==========================================================================
'
' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 2009
'
' NAME: RunOptionalAdvertisements.vbs
'
' AUTHOR: William Bracken
' DATE : 10/12/2009
'
' COMMENT: Run optional advertisments
'
'==========================================================================
Dim oUIResource, programArray(), fs, f
Dim oPrograms, x, i, strLogFile, strFileName, UserTempPath, WindowsTempPath
Dim oProgram, programId, packageId, myProgram, WinTempLog, UsrTempLog
Const ForReading = 1, TemporaryFolder = 2, ForAppending = 8
Set fs = CreateObject("Scripting.FileSystemObject")
Set WSHShell = CreateObject("WScript.Shell")
windir = WSHShell.ExpandEnvironmentStrings("%WINDIR%")
UserTempPath = WSHShell.ExpandEnvironmentStrings("%TEMP%")
WindowsTempPath = windir & "\temp"
strFileName = "RunOptionalAdverts.log"
WinTempLog = WindowsTempPath & "\" & strFileName
UsrTempLog = UserTempPath & "\"& strFileName
strLogFile = UsrTempLog

CLEANLOG strLogFile
COLLECTMSG "Begin Logging", ""

' Validate connection to SCCM Client
Set oUIResource = CreateObject ("UIResource.UIResourceMgr")
If oUIResource Is Nothing Then
COLLECTMSG "CONNECT TO SCCM CLIENT", "Could not create Resource Object - quitting"
wscript.echo "Could not create Resource Object - quitting"
WScript.Quit
End If

'==========================================================================
' Begin Process
'==========================================================================
' Call ShowPrograms routine to get array of programs available
ShowPrograms

' Split Array And Call Sub to install
For Each program In programArray
strStrings = Split (program,";")
programId = strStrings(0)
packageId = strStrings(1)
' Call RunProgam routine to invoke installation
'RunProgram programId,packageId
Next

' Cleanup
Set oProgram=Nothing
Set oUIResource=Nothing

'==========================================================================
' Routines
'==========================================================================
Sub ShowPrograms
On Error Resume Next

Set oPrograms = oUIResource.GetAvailableApplications

If oPrograms Is Nothing Then
COLLECTMSG "SHOWPROGRAMS", "Failed to get programs object - quitting"
wscript.echo "Failed to get programs object - quitting"
Set oUIResource=Nothing
Exit Sub
End If
strCount = oPrograms.Count
COLLECTMSG "SHOWPROGRAMS", "There are " & strCount & " programs"
wscript.echo "There are " & strCount & " programs"
wscript.echo
strCount = strCount - 1

ReDim programArray(strCount)
x = 0
For Each oProgram In oPrograms
COLLECTMSG "SHOWPROGRAMS", "ProgramName:" & oProgram.Name & ";" & "PackageID:" & oProgram.PackageId
WScript.Echo "Program Name: " & oProgram.Name
WScript.Echo " Package ID: " & oProgram.PackageId
' build array
programArray(x) = oProgram.Name & ";" & oProgram.packageId
x = x + 1
Next
End Sub

Sub RunProgram(programId,packageId)
On Error Resume Next
' #region Disabled code
' if oUIResourceMgr.IsMandatoryProgramPending = 1 Then
' Wscript.Echo "Mandatory program pending. Try again later."
' Set oUIResource=Nothing
' Exit Sub
' End If
' #endregion

' Get Program object
Set oProgram = oUIResource.GetProgram(programId,packageId)
'WScript.Echo "oProgram: " & oProgram.Name
if oProgram is Nothing Then
COLLECTMSG "RUNPROGRAMS", "Couldn't get the program"
WScript.Echo "Couldn't get the program"
Set oUIResource=Nothing
Exit Sub
End If

'When was the program last ran?
Set myProgram = oUIResource.GetProgram(programId, packageId)
oldTime = myProgram.LastRunTime
COLLECTMSG "RUNPROGRAMS", "Last Run Time: " & oldTime
WScript.Echo oldTime

' Execute program
COLLECTMSG "RUNPROGRAMS", "Running program: " & programId & " " & packageId
Wscript.Echo "Running program: " & programId & " " & packageId
oUIResource.ExecuteProgram programId, packageId, True

' Wait for last ran to change...
Set myProgram = oUIResource.GetProgram(programId, packageId)
Do While myProgram.LastRunTime = oldTime
Wscript.Sleep(2500)
Set myProgram = oUIResource.GetProgram(programId, packageId)
Loop
COLLECTMSG "RUNPROGRAMS", "Return Code: " & Err
WScript.Echo "Return Code: " & Err
End Sub

'*************************************************************
'*** Method: COLLECTMSG
'*** Description: Collections Errors for logging to log file
'*************************************************************
Sub COLLECTMSG(szLocation, errmsg)
'on error resume next
'Dim f
strmsg=errmsg
Set f = fs.OpenTextFile(strLogFile, ForAppending, True)
strmsg = Now & " | " & szLocation & " | "& errmsg
if err0 then
strmsg=strmsg & vbCrLf _
& "Error | " & Hex(Err.Number) & " h (" & CStr(Err.Number) & ") | Description |" & Err.Description
end if
f.Writeline strmsg
f.Close
strmsg=""
Err.Clear
End Sub

Sub CLEANLOG(strLogFile)
If fs.FileExists(strLogFile) Then
fs.DeleteFile strLogFile
End If
End Sub

h1

Adding Duplicate Drivers to SCCM SP1

September 26, 2009

Another one of the most glaring deficiencies in my opinion with OS deployment using SCCM is the inability to import the same drivers for different models.  I personally prefer to import ALL drivers for every model of machine I have versus trying to dig through other imported drivers and piece together what each model actually needs.  It can be quite frustrating to say the least.  I break up my drivers by model and would love to out of the box (I believe this may addresses in SP2) simply import the entire driver set in each subfolder, then create a package per model and assign the drivers from the subfolders to their respective package.  Well the good news is you CAN!  You simply have to trick SCCM into allowing you to do this.  Its quite simple actually. SCCM bases whether drivers are the “same” based on the calculated hash value of the driver files.  By simply adding a unique text file to the driver folder it creates a different hash value and allows you to import them even if the actual drivers have already been imported.  How I do it:

Break your drivers down by model in their own subfolders:
Example:
\\Server\share$\Drivers\Latitude E6500\Audio
\\Server\share$\Drivers\Latitude E6500\Video
Etc..

\\Server\share$\Drivers\Latitude E4300\Audio
\\Server\share$\Drivers\Latitude E4300\Chipset
etc..

Now open the root folder and create a new txt file based on the model.
Example:
\\Server\share$\Drivers\Latitude E4300\Latitude E4300.txt

Now copy this file to your clipboard, then do a windows search within the root directory for “*”.  Sort by type to gather all the folders at the top of the search.  Right click on EACH folder within the search and past the model specific txt file.

Do this for each of your driver sets and when you import them into their own sub-folder under the drivers node they will import even if the actual driver has already been imported.  :-)   you can now make corresponding packages for each model all with their OWN version of their drivers.

I know this has made my life SO much better with managing drivers in SCCM.  I hope it helps someone else.

h1

How to prevent optional PXE Adv from popping on clients

January 27, 2009

Once of the glaring deficiencies of SCCM OSD deployment (in my opinion of course) is the default behavior of an optional PXE advertisement.  Effectively if you want to have more than one pxe advertised task sequence the one that you DIDN’T execute will eventually pop up on every machine that has not run it before as an optional advertisement.  If the user clicks it and tries to run it (assuming your task sequence is set to do so) it will fail as it should be designed to only run within Windows PE.  Not a concern from a user accidentally rebuilding their own pc however not a viable option to have this popup on everyone and thus freak out the organization.  Well fortunately I have discovered a workaround for this issue.  It’s quite simple actually.  ;)

This is assuming you have your “PXE” TS adverts and your “Push” TS Adverts separated.
*ALWAYS test any new changes in a lab environment prior to production implementation*
Right-Click your PXE advertisement and go to Properties.
Click the Advanced tab.
Select the radio button “This task sequence can only run on the specified client platforms”
Now find a platform that you will not have in your environment.  In my case I have selected “x64 Windows XP Professional SP1”.  I should not have this OS version on my network.  If I do it’s unsupported and the machine needs to be rebuilt as we currently do not support ANY x64 OS’s.  ;)
Give that several minutes to propagate the changes.
You can then turn off the mandatory advertisement.  Your client will receive the advertisement however they will reject it based on the platform restriction.  This has no effect on your PXE building since the platform is not evaluated as part of the PXE build process.

You can now have multiple PXE adverts.  This is invaluable for testing build updates, etc.

One thing to keep in mind is that when you make your adverts optional the auto PXE boot (after selecting the network card as your boot device) goes away and you must press F12 (again) to initiate the connection.

I have found a workaround for this in my environment however the big disclaimer here is that this is NOT a supported solution from Microsoft.

F12 workaround:
On your WDS server(s) navigate to
D:\RemoteInstall\SMSBoot\x86
Make a copy of your pxeboot.com (the version that prompts you to press F12)
Delete the original pxeboot.com
Make a copy of pxeboot.n12 (the version that bypasses the additional F12 prompt)
Rename this copy to pxeboot.com
Flag this file as READ-ONLY.  If you do not do this the next reboot of your server will revert this file back.
Restart your WDS service and away you go.

Hope this helps someone else out there!!

h1

Windows 7 Beta – Impressions

January 13, 2009

Hello, It has been quite some time since I have updated any entries on this blog.  Seems like everyday I get more and more to do so less time to post blogs! 

Anyway, I currently typing this post from a Windows 7 Beta machine (ie8).  I rolled my production Dell Latitude E6500 to Windows 7 the day the public Beta was released and so far (barring one Explorer.exe crash) I have to say I am fairly jazzed.  All the Vista drivers loaded no problem and pound for pound it is using less resources than Vista did.  The performance in general really just feels much more solid than Vista and this is still Beta!  Some of the new functionality that is built into W7’s Areo is actually quite functional.   The new “Show Desktop” is pretty freakin cool.  ;)

I am running this Beta in production right now joined to our domain so I will be putting it to the coals so to speak.  With this being Beta, barring any major screwups this could be the new generation OS I have been waiting for.  Its nice be excited again about a new desktop OS.  I was very disappointed with Vista sadly (as were many) so it appears that MS may be back on track.  Keeping my fingers crossed!

I’ll post back with more info after I give it a proper go.

h1

Export Computer list from AD

October 21, 2008

I find myself using this quite often so I figured I would post here for a nice copy and paste for future uses.  ;)
*Requires Windows 2003 Admin tools (adminpak.msi) to be installed

Export computer objects from a specified OU and all sub OU’s(careful of wordwrap):

dsquery computer “ou=laptops,ou=devices,ou=site,dc=subdomain,dc=domain,dc=com” -limit 0 -o samid >>Laptops.txt

-limit 0 tells the script to return ALL matching values (Default is 100)
-o samid tells the script to return the “friendly” name. (Default is the full DN)

Obviously replace the values with ones specific to your environment.  ;)

h1

Image Capture: VPC vs VMWare

October 20, 2008

Just thought I may be able to save someone else out there a headache..

Although I am typically a much bigger proponent of VMWare products in terms of performance I found out the hard way that building and capturing an image from VMWare (Server 2.0) works great in most cases for newer hardware. I also discovered that the “IDE” mass storage driver in VMWare Server 2.0 would not allow the image to boot on older hardware (think Latitude D800, 600, etc). I spent a couple of days trying to find a set of driver that I could inject to get the machines working but to no avail. I had used Virtual PC 2007 in the past to build and capture but the performance is so lacking compared to VMWare I figured I would start there first. Well a long story short, after I went back to using Virtual PC 2007 (SP1) as my base machine for build and capture my “older” hardware is now back to booting properly and my newer hardware continues to function by injecting their mass storage drives as needed.

The moral of the story? Use Virtual PC 2007 to build and capture your image! Then you can turn it off and use VMWare for everything else. ;)

h1

PXEFilter.vbs update to auto clear last PXE Advert

September 27, 2008

** This script has been deprecated with the release of SCCM 2007 R2.  It supports “Unknown Machines” inherently

I have modified the PXEFilter.vbs that ships with MDT 2008 to automatically clear the last PXE advertisement of the machine that is PXE booting. This allows me to set a mandatory assignment for my OS Deployment and removes the requirement for field techs to have to open the admin console to re-image a machine via PXE.

The section I added was:

‘//————————————————————-
‘// Clear Last PXE Advertisement
‘//————————————————————-
On Error Resume Next
Dim resources
Dim InParams

‘ Set up the Resource array parameter.
resources = Array(1)
resources(0) = iResourceID

Set InParams = oSMS.Get(“SMS_Collection”).Methods_(“ClearLastNBSAdvForMachines”).InParameters.SpawnInstance_
InParams.ResourceIDs = resources

oSMS.ExecMethod “SMS_Collection”,”ClearLastNBSAdvForMachines”, InParams

if Err.number <> 0 Then
PXE.LogTrace “Failed to clear PXE advertisement for resource: ” & iResourceID
Else
PXE.LogTrace “Clear PXE Advertisement Completed successfully for resource: ” & iResourceID
End If

h1

Cleanup WSUS 3.0 Sync History

September 27, 2008

As any WSUS admin knows, the sync history for some unknown reason is not an option for cleanup using the built in cleanup wizard. This can result in excruciating load times when trying to view the sync history. Hopefully Microsoft will correct this in future releases however until then you can execute the following query against your WSUS DB to cleanup the Sync events.

DELETE FROM [SUSDB].[dbo].[tbEventInstance]
WHERE [EventID]=381 or [EventID]=382 or [EventID]=384 or [EventID]=386 or [EventID]=387

You may consider running this as a part of your monthly maintenance.

h1

SMS_SQL_MONITOR Service Fails after upgrade to SCCM

September 27, 2008

After upgrading my SMS 2003 SP2 site to SCCM 2007 SP1 the “SMS_SQL_MONITOR” service would fail to start stating Error 2: Cannot find the specified file.

I finally figured out (by stumbling across the website below) that this service is an SMS 2003 service only and is not required for SCCM. Apparently this is a bug in the Setup that doesn’t remove this service for you..

*I should also note that I verified that this service does not exists in my clean install of SCCM in my Lab.

Instructions on removing this service here:
http://blogs.technet.com/alipka/archive/2008/07/22/sccm-sp1-slipstream-setup-on-sms-2003-sp2-sp3-site-fails-to-remove-sms-sql-monitor-service.aspx

h1

Intel Graphics MiniSetup Hang issue

September 27, 2008

If anyone has used Sysprep with XP on a machine that uses an Intel Graphics chipset you have likely ran into the dreaded hang during mini-setup when plug and play installs the graphics driver. (Sits at the please wait screen and must be manually rebooted to continue)

Microsoft offers a hotfix for this (must be requested via the web form or through calling PSS)
http://support.microsoft.com/default.aspx/kb/883667

It is effectively a single dll file that needs to be replaced.

12-Aug-2004 17:50 5.1.2600.2505 247,808 Newdev.dll SP2QFE

I have tested and it definately seems to do the trick.