SCCM crashes before task sequence on usb boot media

Ok, so just wanted to post this real quick post that might help someone since I had a lot of trouble finding the answer.  I couldn’t use pxe and needed to be able to boot at a location with usb bootable media.  So easy I’ll just create some.  Thing was I would have it reboot as soon as I would put in the password for the boot media.  No errors network showed connected which is a typical issue with drivers not being in your boot media.  So I continued to restart and study my smsts.log and came across the below.

Failed to run unattended because there is no mandatory deployment.

After thinking about it a while I remembered I had set it to allow unattended deployment.  Well it turns out if no deployments are deployed to the machine as required that option doesn’t let it choose a task sequence.  So just uncheck that box and you will be off to the races.


Getting email alert and smsts log when imaging fails via PowerShell

So in follow up to my last post I have been testing a script to look for the smsts log when the task sequence fails and send me an email with the smsts.log as attachment.

I set this up in my MDT task sequence under the gather logs and statestore on failure section so that way whenever the task sequence has an error I get the logs.

#Script to send email when imaging fails. Wrote by Logan Seals.

$serial = gwmi win32_bios | select-object SerialNumber | Format-Table -HideTableHeaders | Out-String
$serial = $serial.Trim()
$make = gwmi win32_bios | select-object Manufacturer | Format-Table -HideTableHeaders | Out-String
$make = $make.Trim()
$model = gwmi win32_computersystem | select-object model | Format-Table -HideTableHeaders | Out-String
$model = $model.Trim()
$hostname = hostname
$processor = gwmi win32_processor | select-object name | Format-Table -HideTableHeaders | Out-String
$processor = $processor.Trim()
$totalmemory = gwmi Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | Foreach {"{0:N2}" -f ([math]::round(($_.Sum / 1GB),2))}
$operatingsystem = gwmi Win32_OperatingSystem | Select-Object caption, version | Format-Table -HideTableHeaders | Out-String
$operatingsystem = $operatingsystem.Trim()
$msgSubject = “$hostname has failed imaging!”

$msgBody = “PC has failed imaging is host $hostname with Serial $serial and Make and Model $make $model. Processor is $processor. Ram is $totalmemory GB. Operating System is $operatingsystem”
$files = @('x:\windows\temp\smstslog\smsts.log','x:\smstslog\smsts.log','c:\_SMSTaskSequence\Logs\Smstslog\smsts.log',`

foreach ($file in $files) {
if (Test-Path $file) {
if (Test-Path C:\SMSTSLog) {
mkdir C:\emaillogs
$date = (Get-Date -Format yyyyMMddTHHmmssffff).ToString()
$newfilename = "smstslog$date.log"
Copy-Item $file -Destination "C:\emaillogs\$newfilename"
if (Test-Path X:\sources) {
mkdir X:\emaillogs
$date = (Get-Date -Format yyyyMMddTHHmmssffff).ToString()
$newfilename = "smstslog$date.log"
Copy-Item $file -Destination "X:\emaillogs\$newfilename"
if (Test-Path C:\emaillogs) {
Get-ChildItem "C:\emaillogs" | Where {-NOT $_.PSIsContainer} | foreach `
{$_.fullname} | `
send-mailmessage -from "" -to "" -subject $msgSubject -Body $msgBody -Priority High -dno OnSuccess, onFailure `
-smtpServer x.x.x.x

if (Test-Path X:\emaillogs) {
Get-ChildItem "X:\emaillogs" | Where {-NOT $_.PSIsContainer} | foreach `
{$_.fullname} | `
send-mailmessage -from "" -to "" -subject $msgSubject -Body $msgBody -Priority High -dno OnSuccess, onFailure `
-smtpServer x.x.x.x

I have a nice array of locations of the smsts log and a foreach loop to look through them test if they exist using Test-Path cmdlet and attach them to my email.

Seems to work well from what I have seen so far.  Below is what you get in an email.

Update – I have revised the script as I have had files be locked and I realized that by only attaching the first file it finds I can miss attaching a later smsts.log.  I think this will be more robust and work better.  I am still debating if there is a better way than to sending two different emails depending if C:\smstslog is available.  The goal was to still allow it to send logs even after it is out of the pxe boot image phase of imaging.  Not sure if that  piece works yet.


Getting email alert when imaging is finished

I wanted to get some details every time a machine was imaged for my own details.  Mostly for asset tracking purposes I set up the below script to run at the end of my task sequence.

$serial = gwmi win32_bios | select-object SerialNumber | Format-Table -HideTableHeaders | Out-String
$serial = $serial.Trim()
$make = gwmi win32_bios | select-object Manufacturer | Format-Table -HideTableHeaders | Out-String
$make = $make.Trim()
$model = gwmi win32_computersystem | select-object model | Format-Table -HideTableHeaders | Out-String
$model = $model.Trim()
$hostname = hostname
$processor = gwmi win32_processor | select-object name | Format-Table -HideTableHeaders | Out-String
$processor = $processor.Trim()
$totalmemory = gwmi Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | Foreach {"{0:N2}" -f ([math]::round(($_.Sum / 1GB),2))}
$operatingsystem = gwmi Win32_OperatingSystem | Select-Object caption, version | Format-Table -HideTableHeaders | Out-String
$operatingsystem = $operatingsystem.Trim()

$EmailFrom = “”

$EmailTo = “”

$Subject = “$hostname has been imaged”

$Body = “PC imaged is $hostname with Serial $serial and Make and Model $make $model. Processor is $processor. Ram is $totalmemory GB. Operating System is $operatingsystem”

$SMTPServer = “ipaddress”

$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)

$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

It is really nice to get all this info.

PC imaged is PCname with Serial R9ZRLB8 and Make and Model LENOVO 23594LU.  Processor is Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz.  Ram is 8.00 GB.  Operating System is Microsoft Windows 10 Pro 10.0.15063

I suppose this could also be modified so that the tech imaging the machine could also get the email.  Maybe basing it off of the machine’s OU.  Hopefully someone finds this useful but I have found it quite handy.  I have also finished a script to gather logs when the task sequence fails and send them to me but I am still testing that out and will save that for my next post.

Update – So just wanted to update that if you wanted to make this easier there is actually a send-mailmessage powershell cmdlet that does the same thing for the send email portion.  Mine still work just fine though 🙂

More info on send-mailmessage below.




SCCM Package not distributing

So I had to delete a package off a distribution point and redistribute yesterday and ran into an issue where it would not distribute.  I continued to read my logs and noticed that the distmgr.log continually retried the package but never actually distributed it.  It just kept saying no action specified for package.  Well after a ton of research I came across a blog post detailing how resolve that.

First check your action and updatemask

SELECT * FROM PkgServers where NALPath = '["Display=\\\"]MSWNET:["SMS_SITE="]\\\' and PkgID = ''

This particular distribution point had an update mask and action totally different than any of the other servers.


I then deleted that record.

DELETE FROM PkgServers where NALPath = '["Display=\\SEA-DP-SERVER\"]MSWNET:["SMS_SITE=SEA"]\\SEA-DP-SERVER\' and PkgID = SEA0008D'

Once I did that I was able to finally redistribute the content.

Thanks a bunch to Daniel Eyer’s blog.

SCCM WSUS Sync errors/WSUS cleanup

As an SCCM administrator it is easy to install SCCM and simply forget about WSUS being an integral part of SCCM and forgetting its even there.   That is until you start getting synchronization errors or other WSUS errors.  So to fix or prevent that from happening you should really go to the wsus server cleanup wizard which can be found in the wsus console under options.  What do you do though if you haven’t been running it and the wsus server cleanup wizard fails.
wsus error

Well to start you can rerun the wsus server cleanup wizard with all but the first option and then rerun with only the first option but that won’t always work especially if you are really behind on wsus cleanup.  So your options are to reinstall the wsus database or do a manual cleanup.  In the past when I had seen issues with this occur I had reinstalled the wsus database but that isn’t really the right solution so instead you can run the below on the wsus db.


DECLARE @msg nvarchar(100)

CREATE TABLE #results (Col1 INT)

INSERT INTO #results(Col1) EXEC spGetObsoleteUpdatesToCleanup



SELECT Col1 FROM #results



INTO @var1


BEGIN SET @msg = ‘Deleting’ + CONVERT(varchar(10), @var1)

RAISERROR(@msg,0,1) WITH NOWAIT EXEC spDeleteUpdate @localUpdateID=@var1




DROP TABLE #results

This will find and delete all the obsolete updates for you and then you can rerun server cleanup and it should finish successfully.  Once that is done you should probably either run or schedule wsus cleanup on a regular basis.

I can’t take credit for that sql query though and you can find more info at the below post which I found after I had figured this all out myself.  I was doing the same thing to cleanup but his script is a little better/easier to use than mine.  Take a look at the below post as it goes through setting wsus cleanup and reindexing on a schedule in very great detail.

Alternate Names for File Servers

I had a server I had to quickly give a alternate name to so that the existing users could point to the new server but I didn’t want to rename it the same as the old one.  Traditionally you would simply add the following registry entry.

Registry location:

DWORD name: DisableStrictNameChecking
DWORD value: 1

Problem is this only works if you have SMB1.0 enabled on both the server and client and you know how unsecure that is (think EternalBlue exploited by Wanna cry).

The proper way is to use netdom to add an alternative name by doing the below.

netdom computername "currentname" /add "myothername.mydomain.local"

This will add a new SPN in active directory for the current machine name.

Special thanks to Dimitri’s Wanderings which is in the first link below as that saved me a lot of time.


Removing unneeded software updates from SCCM

Happy Friday everyone,  I can’t take any credit at all for this one but someone (much better at Powershell than me) has wrote this amazing script on removing updates that are not deployed or not required on any machines but are still in a deployment package. This is been something I’ve needed for a long time to save disk space on DP’s.

See link below.

Critical Update Confusion

Happy Wednesday, (Well as happy as an Wednesday can be I guess…) I was prompted by a user that their machine was behind on updates as were many others as they tried updating from the web and got lots of updates.  I did some checking and all the updates looked to be fairly recent within the last month but were listed as Critical level updates.  This confused me as I have critical level updates deploying more often than once a month to not get behind on security vulnerabilities as Microsoft patches them.  After some research I realized there is a difference between Critical level severity and Critical level update classifications.  Microsoft defines Critical Updates as “A widely released fix for a specific problem that addresses a critical, non-security-related bug.”  So just because it’s in the critical update classification it may not have an severity level of critical.  In fact critical level updates have a severity of none as they are not related to security.  So critical severity updates are security only.  Critical update classification is non security updates.  The critical severity level updates fall into the security update classification.  So if your like me and push out critical severity security updates more often than your other updates don’t start thinking SCCM isn’t working since you got confused between Update classifications and Severity levels.  Found my answer on the technet forums as someone else was confused like I was.  Happy Updating.

Technet Forum post referenced

Number of active active sync devices connected to Exchange

Happy Monday everyone,  I haven’t posted anything in a while so I thought I would do a quick post of a short script I wrote the other day.  I was curious how many ActiveSync devices connected that were actively being used in our Exchange.  So after scouring around and discovering the get-mobiledevicestatistics cmdlet for Exchange I came up with the below.

get-mailbox -resultsize unlimited | foreach {Get-MobileDeviceStatistics -mailbox $_.Identity  | Where-Object {$_.LastSuccessSync -gt "06/01/2017"} | select-object identity, LastSuccessSync }

This will give you the identity of the device and the last successful sync time.  You could then pipe this into a export-csv to get a copy of the report or measure-object  to get a count of the objects.   Make sure to change the LastSuccessSync date.

Have a great week everyone.