Quick PowerShell Script to list all Primary and Secondary sites with Site Version

Just a quick example for listing all your sites – run this against your central site.

#replace MySiteServer with central site server name, 
#and LAB with site code
$sites = Get-Wmiobject SMS_Site -computer MySiteServer -namespace root\sms\site_LAB
#display information to the screen
$sites | select-object ServerName, SiteCode, Status, Type, Version, BuildNumber, ReportingSiteCode | sort-object ReportingSitecode
#or if you'd like, export to a .csv
$sites | select ServerName, SiteCode, Status, Type, Version, BuildNumber, ReportingSiteCode | sort ReportingSitecode | export-csv c:\temp\ConfigMgrSites.csv -notypeinformation

Greg

How To: List all servers used by your ConfigMgr Infrastructure

Here’s a quick PowerShell script to show all servers used in your ConfigMgr Hierarchy:

$myServers  = get-wmiobject  SMS_SystemResourceList `
   -namespace root\sms\site_LAB –computer LABServer
$myServers | select-object servername -unique `
   | sort Servername | out-gridview

You can alter that script a little to show all Roles for each server:

$myServers  = get-wmiobject  SMS_SystemResourceList `
    -namespace root\sms\site_LAB –computer LABServer
$myServers | select-object servername, RoleName  `
    | sort Servername | out-gridview

To run these in your environment, launch in PowerShell with proper rights to query your hierarchy, and replace “LAB” with your Central site ConfigMgr Site Code, and replace LABServer with your Central site server name.

Happy Scripting,

Greg

ramseyg@hotmail.com

Fun with WMIC

(When preparing to write this brief post, I see that my MVP colleague Sherry Kissinger also has a post on WMIC and Windows Installer. Check it out – it’s a good read too.) 

Here are a couple more examples to add to your tool belt, especially when working with teammates in remote offices, and you need information from WinPE. My perfect example is that a tech reports in that OSD isn’t working, the symptom is that no fixed disks appear to be present on the system. This error usually means that you don’t have a mass storage driver in WinPE for the hardware. Of course, this error can also mean that you have a hard disk error, or that it’s not connected to your system.

Back to task, here are two example command lines for querying win32_pnpentity to display all Plug-and-Play information for a system.

Wmic /namespace:\\ROOT\cimv2 path win32_pnpentity get /format:hform >”c:\temp\data.htm”

Wmic /namespace:\\ROOT\cimv2 path win32_pnpentity get /format:csv >”c:\temp\test.csv”

The first example writes the information to a .htm file, and the second writes the information to a .csv file.

Once you have the PNP IDs, you can begin your journey to find the appropriate mass storage drivers.

More info: Creating and editing formats in WMIC.

Greg

How to: Enable Incremental Collection Updates With PowerShell

ConfigMgr 2007 R3 shipped with a feature called Incremental Updates for collections, and ConfigMgr 2012 also supports this feature. From the official docs, here’s what incremental updates do for you:

Select this option to periodically scan for only new or changed resources from the previous collection evaluation and update the collection membership with only these resources, independently of a full collection evaluation. By default, incremental updates occur at 10 minute intervals.

This post will demonstrate how to identify collections with incremental updates enabled, as well as how to enable incremental updates for a collection.

Here’s an example to list all collections that have incremental updates enabled:

#display collections with incremental updates enabled
#replace mycfgmgrlab with site server name, LAB with Site code
gwmi sms_collection -computer mycfgmgrlab `
  -namespace root\sms\site_LAB | foreach {
  $Coll = [wmi] $_.__Path
  if ($Coll.RefreshType -eq 6) {
        write-host $Coll.CollectionID "`t" $Coll.Name
    }
}

Since RefreshType is a lazy property, you must take some extra steps. use get-wmiobject (alias is gwmi) to get all collections, then perform a for-each loop to use query the instance directly using the [wmi] accelerator for PowerShell. Finally, check to see if RefreshType = 6.

Here’s an example to enable incremental updates on a collection:


#enable incremental updates on a collection
#replace mycfgmgrlab with site server name, LAB with Site code,
#and LAB007DE with desired collecitonid
$a = [wmi] "\\mycfgmgrlab\root\sms\site_LAB:SMS_Collection.CollectionID='LAB007DE'"
$a.RefreshType = 6
$a.put()

Use the [WMI] accelerator to grab the specific instance with lazy properties, and set RefreshType = 6

Valid values for RefreshType:

  • 6 = Incremental and Periodic Updates
  • 4 = Incremental Updates Only
  • 2 = Periodic Updates only
  • 1 = Manual Update only

For more information about Incremental Updates, review’ the Microsoft page for Creating Collections in ConfigMgr 2012 (expand the node “To Create a Device Collection” to see the details.) Also note that the following classes do not support incremental updates:

  • SMS_G_System_CollectedFile
  • SMS_G_System_LastSoftwareScan
  • SMS_G_System_AppClientState
  • SMS_G_System_DCMDeploymentState
  • SMS_G_System_DCMDeploymentErrorAssetDetails
  • SMS_G_System_DCMDeploymentCompliantAssetDetails
  • SMS_G_System_DCMDeploymentNonCompliantAssetDetails
  • SMS_G_User_DCMDeploymentCompliantAssetDetails (for collections of users only)
  • SMS_G_User_DCMDeploymentNonCompliantAssetDetails (for collections of users only)
  • SMS_G_System_SoftwareUsageData
  • SMS_G_System_CI_ComplianceState
  • SMS_G_System_EndpointProtectionStatus
  • SMS_GH_System_*
  • SMS_GEH_System_*

More information about Lazy Properties:

Greg

 

[edit 6/18/2012 to add 4=Incremental Updates Only - Thanks Josef!]

How To: Inject Drivers from USB During a ConfigMgr Operating System Task Sequence

ConfigMgr OSD does a great job of injecting drivers ‘on the fly’ into your OS Deployment process. For example, you can create task sequence steps with conditional statements to apply drivers for a specific model. That’s great for your standard build, but how do you handle those one-offs, those non-standard builds? Here’s a process that you can you for those non-standard builds, or for that hardware that you’re testing, but haven’t quite committed to being a standard yet.  All we need is a vbScript, raw drivers, and an additional step in your task sequence (haven’t tested with MDT, but should work there as well). The following process ONLY works on Windows 7 and Windows Server 2008 R2. If there is enough demand, I’ll create a similar script for previous Operating System versions.

Step 1 – Create a USB folder with raw drivers for the desired hardware.

  • Create a folder in the root of a USB drive named “ExportedDrivers”
  • Copy desired drivers to this folder. You can create subfolders to help with organization if you’d like. Please note that *everything* in the ExportedDrivers AND ALL SUBFOLDERS will be processed, so try to keep the folder structure organized, and to ONLY include the desired raw drivers.
  • Your folder should look similar to this:
  • We have a few extra folders here to keep things organized, but you can just put them in the root of “ExportedDrivers” if desired.

Step 2 – Create a package with ImportCustomDrivers.vbs

  • Create a new Package (or just add this file to an existing package)
  • Download ImportCustomDrivers.txt, and rename to ImportCustomDrivers.vbs.
  • Send to DPs.

Step 3 – Add new step to OSD Task Sequence

  • This step should run in WinPE, just before all other “Apply Driver Package”or “Auto Apply Drivers” step.
  • Your Task Sequence step would look similar to this:
  • Depending on your environment, you may want to enable the ‘continue on error’ checkbox on the Options tab. If the script attempts to import a driver that does not apply to the current operating system, it will return a failure exit code.
  • If you have ADDITIONAL “Apply Driver Package”, or “Auto Apply Drivers”steps, and you want to skip these steps if we import drivers from the USB, enter a conditional where Task sequence variable “OSDCustomDriversApplied” not equals “True” (this variable is set in the .vbs when it runs).

Now that you have your task sequence configured, insert the USB drive into the test system and launch a test build. At the “Add Custom Drivers…” step. you will see a command prompt that shows the status of the drivers that are being injected.

  • In WinPE, two log files will be created in X:\Windows\Temp\SMSTSLog:
    • OSD_CustomDrivers.log – this is the log for the vbscript
    • DISMCustomImport.log – this is the out file from the DISM command to import everything under USBDRIVE:\ExportedDrivers\
  • The log files will also be copied to the ConfigMgr log file directory to allow for post-image troubleshooting.

Again, this process is meant for those one-off scenarios. If you plan to fully support a platform, be sure to handle driver installation using ConfigMgr driver management.

Greg

ramseyg@hotmail.com

Source Code:


'Use this script to import custom drivers for Server 2008 R2, Win7, and newer - full blog post on http://gregramsey.wordpress.com/
'Created by: Greg Ramsey

Log "ImportCustomDrivers - Start"
strComputer = "."
strDriverFolder = "ExportedDrivers"
intReturnCode = 0
intFinalReturnCode = 0
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = WScript.CreateObject("WScript.Shell")
Set colDisks = objWMIService.ExecQuery("Select * from Win32_LogicalDisk")

'enum each drive letter, and see if strDriverFolder exists in the root.
For Each objDisk In colDisks
'Check each drive letter to see if there is a
If objFSO.FolderExists(objDisk.DeviceID & "\" & strDriverFolder) Then
'this will only run in a TS environment, so fail if we can't connect to sms.tsenvironment
Log vbTab & "Connecting to SMS.TSEnvironment"
Set oTSEnv = CreateObject("Microsoft.SMS.TSEnvironment")
If err.number <> 0 Then
Log vbTAB & "Unable to connect to Microsoft.SMS.TSEnvironment"
Log "ImportCustomDrivers - End"
WScript.quit(err.number)
Else
'prepare the command line, and launch the DISM command
Log vbTAB & objDisk.DeviceID & "\" & strDriverFolder & " Exists, Importing drivers.."
strCommand = CStr("Dism /image:" & oTSEnv("OSDTARGETSYSTEMDRIVE") & "\ /logpath:%windir%\temp\smstslog\DismCustomImport.log /Add-Driver /driver:" & objDisk.DeviceID & "\" & strDriverFolder & " /recurse")
Log vbTAB & "Preparing to run the following command: " & strCommand
intReturnCode = oShell.Run(strCommand, 1, True)
Log vbTAB & "Return Code = " & intReturnCode
Log vbTAB & "Setting TS Variable OSDCustomDriversApplied = True"
oTSEnv("OSDCustomDriversApplied") = "True"
End If
Else
'no custom drivers exist
End If
'slightly cheesy - if more than one drive have the special folder, the DISM command will run more than once
' so we're using this to capture if ANY of the exit code are <> 0, so we can capture that if there are any failures
' you'll have to review the %windir%\temp\smstslog\DISMCustomImport.log for details
If intReturnCode <> 0 Then intFinalReturnCode = intReturnCode
Next
Log "Final Return code = " & intFinalReturnCode
Log "ImportCustomDrivers - End"
WScript.Quit(intFinalReturnCode)

'a simple logging subroutine
Sub Log(message)
WScript.Echo message
Const ForAppending = 8
Set WshShell = CreateObject("WScript.Shell")
strSystemRoot = WshShell.ExpandEnvironmentStrings("%SystemRoot%")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(strSystemRoot & "\Temp\SMSTSLog\") Then
objFSO.CreateFolder(strSystemRoot & "\Temp\SMSTSLog\")
End If
'Create Output Log
stroutputlog = strSystemRoot & "\temp\SMSTSLog\OSD_CustomDrivers.log"
Set objTextFile = objFSO.OpenTextFile(strOutputLog, ForAppending, True)
On Error Resume Next
txtstatus.value = Trim(Replace((message & " " & Now()), vbTab, ""))
On Error Goto 0
message = Now() & " " & message
'
' Log the given message
'
objTextFile.writeline(message)
objTextFile.Close

End Sub

Dell Systems and Advanced Format Hard Drives

If you’re new to OSD, make sure you understand Advance Format Drives. Chances are, you already have them in your environment. If you have new systems (or old systems with new hard disks) where users are reporting degradation of performance, or issues with Windows Update in the event log, you could be a victim. If you are responsible for Operating System Deployment, I highly recommend the following resources:

Deploying Dell Systems with Advanced Format Hard Drives from DellTechCenter

If there’s one thing I suggest you do, it’s this: Start your change control process to perform the following tasks asap:

  1. Update the WAIK to 3.1 and then update your OSD boot disk, or  apply KB 982018 to your WinPE boot disk.
  2. Deploy KB 982018 to all Win7, Server 2008 R2 systems (or upgrade them to Sp1)
  3. Update Intel Mass Storage Drivers in your OSD Process, if necessary

The easiest way to avoid any advanced format drive headaches is to get your build process updated asap.  

Greg

Interesting issue with thumbs.db

I’m surprised I just ran into this today – seems easy enough to run into a long time ago.  I was working in ConfigMgr 2012 Beta 2, and was receiving failures when sending content to a distribution point. Looking at distmgr.log, I saw the following errors:

CreateFileW failed for \\servername\sharename\thumbs.db

Failed to add the file. Please check if this file exists. Error 0×80070020

 

Thumbs.db is a hidden file that contains a thumbnail cache for the current directory. I tried to delete the file, and received an error that the file was in use by Windows Explorer. I decided to test this same process in ConfigMgr 2007, and encountered the same issue (which is why I’m surprised I haven’t experienced this issue before). Finally, I terminated and restarted my Windows Explorer process (explorer.exe), and then could successfully delete the evil thumbs.db, and could then update my distribution points successfully.

To prevent this in the future, you need to disable the creation of the thumbnail cache. You can read more for how to disable this using either folder options or group policy. Both links refer to Windows 7, but the same applies to Server 2008R2. You would need to disable this feature on any system you use to browse to the package source. This issue obviously doesn’t occur all the time, but is something to be aware of moving forward.

*Note: this can also affect you if a user who has admin rights browses to a ConfigMgr DP share and thumbs.db is created. Now the hash of this folder if different than ConfigMgr expects, causing a hash mismatch error when running the program.

 

Greg

How To: Enable the “Suppress Program Notifications” Checkbox for all Programs in a Package

In a previous post, I wrote how to enable the “Suppress Program Notifications” Checkbox for Program Properties for all programs in your environment. By request, in this post we’re going to modify the script slightly to modify all programs for one package, given the PackageID.

#Select all programs for one package
#(Update MySiteServer and LAB with your ConfigMgr Server name and Site code, and PackageID with a valid packageID)
$prgs = get-wmiobject sms_program -computername MySiteServer -namespace root\sms\site_LAB -filter "PackageID='LAB0023C'"
$prgs | foreach {
#ProgramFlags are a lazy property, so make explicit call.
$prg = [wmi] $_.__Path
if ($prg.ProgramFlags -band ([math]::pow(2,10)))
{
# Suppress already enabled
}
else
{
# Not suppressed - display programname and packageID
$prg.Programname + "`t" + $prg.PackageiD
# flip the programflags bit to enable suppression
$prg.ProgramFlags = $prg.ProgramFlags -bor ([math]::pow(2,10))
# use Put to save changes
$prg.put()
}
#rinse and repeat
}

The only change we had to make was to add the filter command to the get-wmiobject cmdlet. -filter “PackageID=’LAB0023C’”

 Read more about SMS_Program and ProgramFlags.

Greg

How To: Enable the “Suppress Program Notifications” Checkbox for Program Properties

After rebuilding our ConfigMgr 2012 site to RC2, we had to run the Migration Tool to migrate Packages from ConfigMgr 2007. One of the site-wide settings that we took advantage of in ConfigMgr 2007 was to hide the “New Program is Available” systray notification. This works slightly different in ConfigMgr 2012, so we had to enable this checkbox for all programs. We’ll save the details on ConfigMgr systray notifications for a separate post, but for now, here’s a quick PowerShell script to enable the “Suppress program notifications” checkbox for every program in  your ConfigMgr 2012 (or ConfigMgr 2007) environment.

(mouse over code and click the “view source” icon to copy the code)

#Select all programs (Update MySiteServer and LAB with your ConfigMgr Server name and Site code)
$prgs = get-wmiobject sms_program -computername MySiteServer -namespace root\sms\site_LAB
$prgs | foreach {
#ProgramFlags are a lazy property, so make explicit call.
$prg = [wmi] $_.__Path
if ($prg.ProgramFlags -band ([math]::pow(2,10)))
{
# Suppress already enabled
}
else
{
# Not suppressed - display programname and packageID
$prg.Programname + "`t" + $prg.PackageiD
# flip the programflags bit to enable suppression
$prg.ProgramFlags = $prg.ProgramFlags -bor ([math]::pow(2,10))
# use Put to save changes
$prg.put()
}
#rinse and repeat
}

Read more about SMS_Program and ProgramFlags.

Greg

TechNet Wiki Page – List of Public KB Articles and Hotfixes for Configuration Manager 2007 SP2

This TechNet Wiki page appears to be kept up to date pretty well – nice list of KBs there for ConfigMgr.

List of Public KB Articles and Hotfixes for Configuration Manager 2007 Sp2

Follow

Get every new post delivered to your Inbox.

Join 1,045 other followers