March 6 2012

Capture and deploy Windows 8 with SCCM 2007 R3



----------------------------------------------------------------------------
I use a maximum of one Google Ad per post to help offset some of my blog hosting costs.

----------------------------------------------------------------------------

I had a bit of time this weekend to play around with the latest Windows 8 Consumer Preview release. One of the first things I wanted to try and do was capture a reference image and redeploy it with SCCM 2007 R3. Firstly I tried to do this using the Capture task sequence media (Capture Image Wizard) however this was continuously failing at one of the first step – ‘Running sysprep command’. Looking in the smsts.log, I could see it was failing with error – ‘Failed to prepare the system partition for staging.
Wait Callback (Error: D0000004; Source: WinHTTP)’. See image below:

So I went back to the way I used to do OSD in SMS 2003. I manually ran c:windowssystem32sysprepsysprep.exe and selected the options below:

Once the machine was shutdown, I restarted it and booted into WinPE from my WDS server (you could use a CD/DVD/USB instead) and opened a command prompt (F8). I mapped a drive to the location of my WAIK files (Win7 WAIK v6.1.7600.16385) so I could have access to imagex.exe and ran imagex.exe /capture c: z:win8.wim “Windows 8” as you can see below:

There were a few error messages about extended attributes, however I could see the image was still being captured:

Once the capture process was complete, I simply added this into SCCM 2007 R3 as an OS image just like you would for Windows XP / 2008 / 7 and created a simple task sequence. Windows 8 was then successfully deployed!

Of course, none of this is supported by Microsoft and since we are only playing with a Consumer Preview version, nobody is going to be running this in a production environment. As far as I’m aware, even SCCM 2012 does not yet support deployment of Windows 8, so hopefully that is updated before RTM. Hopefully there is also an update for SCCM 2007!


 
 
 
 



----------------------------------------------------------------------------
I use a maximum of one Google Ad per post to help offset some of my blog hosting costs.

----------------------------------------------------------------------------

May 4 2011

Schedule SCCM reports to be emailed without SQL reporting services

I recently had a requirement to be able to email SCCM reports on a schedule in an environment without SQL reporting services. I achieved this by creating a VB script to create an email that has the report ASP page as the body of the email. The script I used and scheduled as a Windows scheduled task was:


Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = "Computers that do NOT have ......"
objMessage.From = "from@email.address"
objMessage.To = "to@email.address"
'==This section provides the configuration information for the remote SMTP server.
'==Normally you will only change the server name or IP.
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
'Name or IP of Remote SMTP Server
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.server.address.here"
'Server port (typically 25)
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objMessage.Configuration.Fields.Update
'==End remote SMTP server configuration section==
'The line below shows how to send a webpage from a remote site
objMessage.CreateMHTMLBody "http://serverURL/SMSReporting_P00/Report.asp?ReportID=422"
objMessage.Send

Just change the variables for your environment.
 
 

March 12 2009

Balance mailboxes across databases – Exchange 2007

There is a fantastic script on Kurtdepauw’s blog (http://kurtdepauw.wordpress.com/2007/11/10/dbbalancer-load-balance-your-exchange-mailbox-databases/) to assist in evenly balancing your Exchange 2007 databases so they are of similar size.

I have customized it slightly and highlight the 2 lines below as useful modifications:

Line 78 – added ‘| Where-Object {$_.Name -notlike “Archive Storage Group”}’ – this is very useful if you want to exclude certain databases from being touched by the balancing script

$DBs = Get-MailboxDatabase -Server $Global:hshParameters.MailboxServer | Where-Object {$_.Name -notlike "Archive Storage Group"}

Line 130 – added -PreserveMailboxSizeLimit switch – you will need to add this so that you can move mailboxes that exceed the database default limits

Move-Mailbox -Identity $Mailboxes[$intRandomMailbox] -TargetDatabase $Global:strSmallestDB.Split(";")[0] -PreserveMailboxSizeLimit -Confirm:$false

———-

Update 04/11/2009

I’ve been alerted that the link to Kurtdepauw’s blogis broken. I’ve posted the entire code below:

# DBBalancer Version 1.1
# Written by BoerLowie (sammybog@gmail.com)
# Modified by www.danovich.com.au - 12/03/2009 - www.danovich.com.au
#
# This script is used to maintain a balance between your different Exchange 2007 Mailbox Databases
#
# Configuration/Installation
# --------------------------
#
# To install the application, just place the script and the config file in C:Program FilesDBBalancer
#
# The configuration is stored in DBBalancer.xml  Use the line below as a reference XML Config file (just paste it in notepad and save it as DBBalancer.xml
#
# <Objs Version="1.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj RefId="RefId-0"><TN RefId="RefId-0"><T>Deserialized.System.Collections.Hashtable</T><T>Deserialized.System.Object</T></TN><DCT><En><S N="Key">ThresholdInGB</S><I32 N="Value">5</I32></En><En><S N="Key">MailboxServer</S><S N="Value">S-BE-KI-EX</S></En></DCT></Obj></Objs>
#
# You can run the script in foreground or schedule it.  To schedule it, create a task using the following command line:
#
# PowerShell.exe -PSConsoleFile "C:Program FilesMicrosoftExchange ServerBinexshell.psc1" -Command "C:DBBalancerDBBalancer.ps1"
#
# Make sure your account is at least an Exchange Server Administrator on the Mailbox Server.
#
# The following values are used in the xml file:
#  - ThresholdInGB:  The script will start to balance you databases if the difference between the biggest
#                    DB and the smallest DB exceeds this value.  This should be set to something like 5 GB.
#  - MailboxServer:  The MailboxServer to balance.  The script can be run from every machine with Exchange 2007 Management Tools
#                    installed on, so it needs to know which Mailbox Server it needs to connect to.  The script will balance all DB's on this
#                    mailbox server.
#
# Processing
# ----------
#
# The script will move a RANDOM mailbox from the Biggest DB to the Smallest DB until all DB are within the Threshold limit.  So if you
# set the Threshold to 5 GB, all DB's will be equally loaded with a maximum difference of 5 GB.
# Only one mailbox at a time will be moved to minimize user downtime.
#
# Logging
# -------
#
# You can follow the progress of the script in the Application Log.  Look for events of Source DBBalancer.
# Every mailbox move will be listed in the eventviewer.
#
# When all Mailbox Databases are balanced, the following will be displayed in the Event Viewer:
#  All Mailbox databases are balanced within the Threshold limit.

$ErrorActionPreference = "SilentlyContinue"

$Global:hshParameters = @{}
$Global:strBiggestDB = ""
$Global:strSmallestDB = ""
$Global:blnExecute = $True

Function Start-Init
{
$Global:hshParameters = Import-Clixml "C:Exchange_Maintenance_ScriptsDBBalancerDBBalancer.xml"
$Global:objEventLog = New-Object System.Diagnostics.EventLog("Application")
$Global:objEventLog.MachineName = "."
$Global:objEventLog.Source = "DBBalancer"
$Global:objEventLog.WriteEntry("Application Started." + [System.Environment]::NewLine + [System.Environment]::NewLine + `
"Target Mailbox Server :" + $Global:hshParameters.MailboxServer + [System.Environment]::NewLine + `
"Threshold in GB :" + $Global:hshParameters.ThresholdInGB)
}

Function Check-Prerequisites
{
If ((Get-MailboxDatabase -Server $Global:hshParameters.MailboxServer | Measure-Object).Count -gt 1)
{
Return $true
}
Else
{
Return $false
}
}

Function Get-BiggestandSmallestDB
{
Process
{
$DBs = Get-MailboxDatabase -Server $Global:hshParameters.MailboxServer | Where-Object {$_.Name -notlike "Archive Storage Group"}
$blnFirstRun = $true
foreach ($DB in $DBs)
{
$lonDBSize = (Get-MailboxStatistics -Database $DB.Identity | Measure-Object -Property TotalItemSize -Sum).Sum
If ($blnFirstRun -eq $true)
{
$Global:strBiggestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
$Global:strSmallestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
$blnFirstRun = $false
}
Else
{
If ($lonDBSize -lt $strSmallestDB.Split(";")[1])
{
$Global:strSmallestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
}
If ($lonDBSize -gt $strBiggestDB.Split(";")[1])
{
$Global:strBiggestDB = $DB.ServerName + "" + $DB.Name + ";" + $lonDBSize
}
}
}
}
}

Function Check-Threshold
{
If (([Long]$Global:strBiggestDB.Split(";")[1] - [Long]$Global:strSmallestDB.Split(";")[1]) -gt ($Global:hshParameters.ThresholdInGB * 1000000000))
{
Return $True
}
Else
{
Return $False
}
}

Function Do-MainLoop
{
While ($Global:blnExecute -eq $True)
{
Get-BiggestandSmallestDB
If (Check-Threshold -eq $True)
{
[Long]$lonDataToMove = ([Long]$Global:strBiggestDB.Split(";")[1] - [Long]$Global:strSmallestDB.Split(";")[1]) / 2
$Mailboxes = Get-Mailbox -Database $Global:strBiggestDB.Split(";")[0] -ResultSize "Unlimited"
$intRandomMailbox = New-Object System.Random
$intRandomMailbox = $intRandomMailbox.Next(0, ($Mailboxes.Count - 1))
$Global:objEventLog.WriteEntry("Moving " + $Mailboxes[$intRandomMailbox] + " from database " + $Global:strBiggestDB.Split(";")[0] + `
" to database " + $Global:strSmallestDB.Split(";")[0] + "." + [System.Environment]::NewLine + [System.Environment]::NewLine + `
"The mailbox has a size of " + ((Get-MailboxStatistics -Identity $Mailboxes[$intRandomMailbox]).TotalItemSize) + "ytes.")
Move-Mailbox -Identity $Mailboxes[$intRandomMailbox] -TargetDatabase $Global:strSmallestDB.Split(";")[0] -PreserveMailboxSizeLimit -Confirm:$false
}
Else
{
$Global:blnExecute = $False
}
}
Return $True
}

Start-Init
If (Check-Prerequisites -eq $true)
{
If (Do-MainLoop -eq $True)
{
$Global:objEventLog.WriteEntry("All Mailbox databases are balanced within the Threshold limit.")
}
}
Else
{
$Global:objEventLog.WriteEntry("Prerequisites check failed.  You probably have only 1 Mailbox Database and therefor we can't move mailboxes around.")
}