-->

mandag 31. mars 2014

Customizing Offline Servicing of Operating System Images

This blog describes how to change the drive used for Offline Servicing of operating system images in System Center 2012 Configuration Manager. Very useful if your C drive is a bit to small...

http://blogs.technet.com/b/configmgrteam/archive/2013/07/15/customizing-offline-servicing-of-operating-system-images.aspx

onsdag 19. mars 2014

Run ConfigMgr cmdlets from Orchestrator

This week I was asked to create an Orchestrator runbook that would add a new computer object to ConfigMgr. At first glance I thought this would be straight forward task, since there is an Integration Pack (IP) for System Center 2012 R2 Configuration Manager.

But this IP does only contain a subset of the tasks you could wish for.

As you can see there are no activity "Import Computer Information" available in the IP from Microsoft.

Well. I'll just use the ConfigMgr cmdlet in a Run .Net Script activity. It supports powershell as a script language. So this should be managable.

The cmdlet is called Import-CMComputerInformation and is documentet on technet: http://technet.microsoft.com/en-us/library/jj821991(v=sc.20).aspx

Basically you can run
Import-CMComputerInformation -ComputerName "NewComputerName" -MacAddress "00:11:22:33:44:55"

But first you need to import the ConfigMgr module in powershell:
1:  Import-Module -Name "$(split-path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1"  

Cool. So you can think if we just have the ConfigMgr cmdlets available on the runbook server we should be ok. Not so fast. In Orchestrator powershell commands are run in a Run .Net Script activity. Unfortunately the Run .Net Activity only supports version 2 of Powershell. So this won't work on the Orchestrator Runbook Servers, at least not directly. You could of course invoke a script that start itself in Powershell version 3. But my solution is to create a PSSession against the ConfigMgr server and run the commands directly.

I have created a few global variables in the Orchestrator environment:
- {CM_ADMIN_USER} - a user with privileges in ConfigMgr.
- {CM_ADMIN_PW}     - the users password.
- {CM_SITE_SERVER}  - the site server we connect to.

These are the Powershell commands I execute in the Run .Net Script activity:
$username = "{CM_ADMIN_USER}"
$password = "{CM_ADMIN_PASSWORD}"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))

$session = New-PSSession -ComputerName "{CM_SITE_SERVER}" -Credential $cred
$result = Invoke-Command -session $session -ScriptBlock {
    Import-Module -Name "$(split-path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1"
    $PSD = Get-PSDrive -PSProvider CMSite
    CD "$($PSD):"
    Import-CMComputerInformation -CollectionName "All Systems" -ComputerName "{New_Name}" -MacAddress "{MacAddress_from_Input}"

}
Remove-PSSession -Session $Session

Curly brackets is a placeholder for information in Orchestrator. It can be global variables or published data from previous actions. My runbook takes the Location the machine is placed, if it is a desktop or a laptop, and the MacAddress of the computer, queries the database for the last name with the given prefix based on this information, creates a NewName and imports the computer with the NewName and MacAddress.


EDIT:
Dexter Dhami gave me a tip about import-module pointed out by MVP David O Brien.
So I have replaced
Import-Module ($Env:SMS_ADMIN_UI_PATH.Substring(0,$Env:SMS_ADMIN_UI_PATH.Length-5) + "\ConfigurationManager.psd1")
with
Import-Module -Name "$(split-path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1"

fredag 14. mars 2014

Finding ConfigMgr SQL Server with Powershell

$sccmsrv=  "CM01" 

$site = (gwmi -ComputerName $sccmsrv -Namespace root\sms `
   -Class SMS_ProviderLocation).sitecode  
    
# enumerating SQL server name for the given SCCM site server  
$sccmCompquery = gwmi -q "Select distinct SiteSystem, Role, `
   SiteCode FROM SMS_SiteSystemSummarizer where role = `
  'SMS SQL Server' and siteCode = '$site' ORDER BY SiteCode" `
  -namespace "root\sms\site_$site" -ComputerName $sccmsrv  

[string]$tmpstr = `
   [regex]::Match($sccmCompquery.sitesystem, "\\\\w+\\$") 

$tmpstr = ($sccmCompquery.SiteSystem).SubString([regex]::Match( `
   $sccmCompquery.SiteSystem, "]\\").Index + 3)

$sccmSQLServer = $tmpstr.replace("\", "")

$sccmDB = "CM_$site"

torsdag 6. mars 2014

Searching for smsts.log... again

When I troubleshoot operating system deployments that are failing I usually start looking in the smsts.log for obvious errors or clues for what might have gone wrong. But ever so often I keep looking for the correct path to the log file...

smsts.log moves around during the different phases of the task sequence as described in the table below

Task Sequence Phase
Location of smsts.log
WinPE before disk is formatted
X:\Windows\temp\SMSTSLog\
WinPE after disk is formatted
C:\_SMSTaskSequence\Logs\SMSTSLog\
Windows OS prior to installation of SCCM agent
C:\_SMSTaskSequence\Logs\SMSTSLog\
Windows OS after installation of SCCM agent
C:\Windows\System32\CCM\Logs\SMSTSLog\
Windows OS x64 after installation of SCCM agent
C:\Windows\SysWOW64\CCM\Logs\SMSTSLog\
Windows OS after task sequence has completed
C:\Windows\System32\CCM\Logs\
Windows OS x64 after Task Sequence has completed
C:\Windows\SysWOW64\CCM\Logs\

You can also create a step in you task sequence that will copy the logs to a network share if the deployment fails. More about that in a later post.