CustomSettings.ini

Deployment Error Invalid DeploymentType value "" specified.  The deployment will not proceed.

MDT Tutorial Part 11: Troubleshooting Part 5: Invalid DeploymentType value “” specified. The deployment will not proceed.

Living Table of Contents

 

What These Guides Are:
A guide to help give you some insight into the troubleshooting process in general.

What These Guides Are Not:
A guide to fix all issues you’re going to encounter.

We’re going to role-play a bunch of scenarios and try to work through them.  Remember in math where you had to show your work?  Well, what follows is like that which is why this post is [more than] a [little] lengthy.

Invalid DeploymentType value “” specified. The deployment will not proceed.

You enabled the Windows Updates steps in the Build & Capture Task Sequence so you can have a fully patched Windows 10 v1511 WIM.

Troubleshoot-014.PNG

And you also updated your CustomSettings.ini so that your Build & Capture VM would set all the properties/variables but not start immediately.


[Settings]
Priority=MACAddress,GetAbbrModel,Build,Default
Properties=OfficeCode,AbbrModel

;vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
; BEGIN MACADDRESS SECTION
; This is my Windows 10 v1511 build & capture VM
[00:15:5D:13:79:01]
SkipTaskSequence=NO
TaskSequenceID=BC151164ENT
SkipComputerName=NO
OSDComputerName=BnC-#UCase(Right(Replace(Replace("0000000%SERIALNUMBER%"," ","",1,-1,1),"-","",1,-1,1),8))#
SkipDomainMembership=NO
JoinWorkgroup=BnC-WrkGrp
SkipUserData=NO
SkipComputerBackup=NO
ComputerBackupLocation=NETWORK
BackupDir=Captures\%OSDComputerName%
BackupFile=%OSDComputerName%_%TaskSequenceID%_#year(date) & "-" & month(date) & "-" & day(date) & "_" & Hour(Now()) & Minute(Now())#.wim
SkipProductKey=NO
SkipLocaleSelection=NO
SkipTimeZone=NO
SkipAdminPassword=NO
SkipCapture=NO
DoCapture=YES
SkipBitLocker=NO
SkipSummary=NO

; END MACADDRESS SECTION
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
; BEGIN GETABBRMODEL SECTION
; Lets get the abbreviated model
[GetAbbrModel]
UserExit=jgp_GetAbbrModel.vbs
AbbrModel=#GetAbbrModel#
; END GETABBRMODEL SECTION
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
; BEGIN BUILD SECTION
; Set things here for use below
[Build]
OSDComputerName=%OfficeCode%-%AbbrModel%-#UCase(Right(Replace(Replace("0000000%SERIALNUMBER%"," ","",1,-1,1),"-","",1,-1,1),8))#
; END GETABBRMODEL SECTION
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
; BEGIN DEFAULT SECTION
[Default]
OSInstall=Y
; Skip Screen: Task Sequence
SkipTaskSequence=NO
; Skip Screen: Computer Details
SkipComputerName=NO
; Skip Screen: Computer Details
SkipDomainMembership=NO
; Skip Screen: Move Data and Settings & User Data (Restore)
SkipUserData=NO
; Skip Screen: Computer Backup
SkipComputerBackup=NO
; Skip Screen: Product Key
SkipProductKey=NO
; Skip Screen: Locale & Time
SkipLocaleSelection=NO
KeyboardLocale=en-US
UserLocale=en-US
UILanguage=en-US
; Skip Screen: Locale & Time
SkipTimeZone=NO
; https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx
TimeZoneName=Eastern Standard Time
; Skip Screen: Administrator Password
SkipAdminPassword=NO
; Skip Screen: Capture Image
SkipCapture=NO
; Skip Screen: BitLocker
SkipBitLocker=NO
; Skip Screen: Ready to begin
SkipSummary=NO
; Skip Screen: R
SkipFinalSummary=NO
SLShare=%DeployRoot%\TSLogs
SLShareDynamicLogging=%DeployRoot%\TSLogs\%OSDComputerName%
EventService=http://ITF1MDT01:9800
; END DEFAULTSECTION
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Having learned your lesson from last time, you test the updated CustomSettings.ini & spent a few minutes verifying the output in the console.  Feeling confident, you boot into WinPE and when the Wizard I displays, verify all the defaults are set correctly.

This slideshow requires JavaScript.

You click begin and almost immediately the process halts with an obscure error:

Deployment Error Invalid DeploymentType value

Deployment Error Invalid DeploymentType value “” specified.  The deployment will not proceed.

You’d be forgiven for thinking you’ve made a mistake and I’d be willing to bet you’d figure this out but that road wouldn’t be fun.

Fortunately Michael Niehaus himself confirmed this is a bug (SRC1, SRC2) and there are two options to fixing/working around the bug:

  1. Easiest: Update your CS.INI with SkipProductKey=YES.
  2. Hardest (and arguably unsupported?):
    1. Open DeployWiz_ProductKeyVista.vbs in the Scripts directory
    2. Find: ​if oProperties("DeploymentType") = "UPGRADE" then
    3. Replace: If Property("DeploymentType") = "UPGRADE" then
    4. Save the file and try again
Note: There appears to be a plausible explanation of what’s happening here if you’re interested.

Since you rarely need to prompt for a Product Key – especially considering you can stick it in the unattend.xml or you go down the easy path and now the image kicks off.

Troubleshoot-028.PNG

Copypasta Closing

Hopefully these examples will help give you an idea of the overall troubleshooting process.  Most of the time the problems you’ll encounter will be caused by a typso, order of operations or a ‘known issue’ that requires a specific process to be followed.

As you make changes to your environment, here’s what I recommend:

  • Be diligent about keeping a change log so you can easily backtrack
  • Backup your CS.INI or Bootstrap.ini before you make any changes
  • Backup your ts.xml or unattend.xml (in DeploymentShare\Control\TaskSequenceID) before you make any changes
  • Introduce small changes at time with set checkpoints in between and set milestones markers where you backup core files (e.g cs.ini bootstrap.ini ts.xml unattend.xml etc) to help minimize frustration troubleshooting.

And if when you do run into some turbulence, upload relevant logs (at least smsts.log but be prepared to submit others depending on the issue) to a file sharing service like OneDrive, post on TechNet then give a shout to your resources on Twitter.

Good Providence to you!

MDT Tutorial Part 11: Troubleshooting Part 4: Task Sequence Variable is Being Overwritten

Living Table of Contents

 

What These Guides Are:
A guide to help give you some insight into the troubleshooting process in general.

What These Guides Are Not:
A guide to fix all issues you’re going to encounter.

We’re going to role-play a bunch of scenarios and try to work through them.  Remember in math where you had to show your work?  Well, what follows is like that which is why this post is [more than] a [little] lengthy.

Task Sequence Variable is Being Overwritten – The Case of the Incorrectly Named Log Folder

After [finally] fixing your computer naming issue, you decide to take a look at the live BDD.log just to keep an eye on things.  You hop into the TSLogs directory & find 2 directories that have the same time stamp:

Troubleshoot-008

According to your CS.INI the “real” log directory should be named after the machine so how did that other one get created?  You open the BDD.log in BLD-HPV-22404895 and it’s practically empty, but you do see that the property is being set to the other directory.

Troubleshoot-009.PNG

There are some clues in the BDD that lead you to above that point to a smoking gun.

You open the BDD.log in the other directory & scroll to the top & see a familiar set of lines: The same ones you see when testing the CustomSettings.ini manually:

Troubleshoot-011

While the machine is imaging you press F8 to launch a console, fire up CMTrace, open the smsts.log (in %temp%\smstslog), scroll to the top & search downwards for ‘dyn’:

Troubleshoot-012.PNG

Ok, you’re piecing it together:

  1. Initially it’s good, points to the proper location
  2. Then at some point it changes
  3. In the first, short, BDD.log you see ‘Task Sequence’ mentioned
  4. In the second, long, BDD.log you see lines that look like it’s processing the CustomSettings.ini, something that also happens during the Task Sequence,
  5. The smsts.log shows a step that sets a variable
  6. SLShareDynamicLogging isn’t a property (or variable) that is ‘last write wins’, so it can’t be a case of a rogue CustomSettings.ini

So maybe it’s the Task Sequence?

Troubleshoot-013

Bingo was his name.

 

Copypasta Closing

Hopefully these examples will help give you an idea of the overall troubleshooting process.  Most of the time the problems you’ll encounter will be caused by a typso, order of operations or a ‘known issue’ that requires a specific process to be followed.

As you make changes to your environment, here’s what I recommend:

  • Be diligent about keeping a change log so you can easily backtrack
  • Backup your CS.INI or Bootstrap.ini before you make any changes
  • Backup your ts.xml or unattend.xml (in DeploymentShare\Control\TaskSequenceID) before you make any changes
  • Introduce small changes at time with set checkpoints in between and set milestones markers where you backup core files (e.g cs.ini bootstrap.ini ts.xml unattend.xml etc) to help minimize frustration troubleshooting.

And if when you do run into some turbulence, upload relevant logs (at least smsts.log but be prepared to submit others depending on the issue) to a file sharing service like OneDrive, post on TechNet then give a shout to your resources on Twitter.

Good Providence to you!

MDT Tutorial Part 9: Logging

Living Table of Contents

 

Today’s Agenda:

  • Centralized Logging
  • Enable Logging
  • Log Locations

At some point you’re going to run into a problem with your imaging process and knowing where to look to get some answers is going to be paramount.

Recommended Reading:

Centralized Logging

I prefer to keep logs in a central location so they’re easy to find when needed, and for that, we’ll create a new share on our MDT server.  Run the below from the MDT server.


New-Item -Path "C:\DeploymentShare\TSLogs" -ItemType directory

New-SmbShare -Name "TSLogs$" -Path "C:\DeploymentShare\TSLogs" -FullAccess Administrators

Enable Logging

Open your CustomSettings.ini and find a suitable place to add the entries for SLShare and SLShareDynamicLogging depending on your preferred scenario.  Either is fine, just depends on your preference and environment.

Hard Coded Path


SLShare=\\MDTServer\TSLogs$

SLShareDynamicLogging=\\MDTServer\TSLogs$

Relative Path


SLShare=%DeployRoot%\TSLogs

SLShareDynamicLogging=%DeployRoot%\TSLogs

Set Logging via Task Sequence

Alternatively you could add steps to the Task Sequence itself to set those variables to their appropriate values, be it hard coded or relative.

Logging-001

Get Creative!

You can get pretty creative, and for automated deployments, I usually default to something like this:


SLShare=%DeployRoot%\TSLogs\%TaskSequenceID%

SLShareDynamicLogging=%DeployRoot%\TSLogs\%TaskSequenceID%\%OSDComputerName%

This way I can see what Task Sequence a particular machine ran.
But, to each their own.

SLShare vs SLShareDynamicLogging

Both values do different things:

  • When the SLShare property is set, MDT will copy the deployment logs to that location in a directory named after the computer, pulled from the %OSDComputerName% Task Sequence property (aka variable).  So if you named your machine PC-1511amd64 the full path to find the logs will be \\MDTServer\TSLogs$\PC-1511amd64.
    .
  • The SLShareDynamicLogging property is used for real-time debugging as ALL MDT logs will be written to that file during the Task Sequence.  It will create a file named BDD.log in the specified directory which means if you set SLShareDynamicLogging it to \\MDTServer\Logs you’ll find a file named BDD.log in that directory.  This obviously presents a problem if multiple machines are being imaged at the same time: they’d all be logged in the same file which might make it challenging to follow along.  This is why I recommend appending \%OSDComputerName% to the path so that the BDD.log is in the ‘correct’ directory.
    For our purposes, you can leave this property enabled, but please note this enabling SLShareDynamicLogging does add a bit of overhead, so in a production environment:

    • Only enable it when actually actively troubleshooting an issue and
    • Ideally have it log to a location close to the machine being imaged versus a remote server to avoid traversing the WAN

Putting It All Together

With the CustomSettings.ini updated, image a machine and check your log directory for a folder structure:

Logging002

  • The %OSDComputerName% directory is an artifact caused by the fact that the property (or variable) OSDComputerName wasn’t set at the time the SLShareDynamicLogging property was processed in the CustomSettings.ini.  In my production environment, I have logic in the CustomSettings.ini to properly name the machine based on specific criteria so that by the time we get to the area where SLShareDynamicLogging is assigned, the OSDComputerName property (aka variable) is set resulting in properly named directories.  However in our lab, this logic doesn’t exist (yet), hence why that directory exists.  To fix this, just add something like OSDComputerName=LAB-%SerialNumber% to your CustomSettings.ini and please note that the OSDComputerName property (variable) does not need to be declared.
    .
  • The other directory is the correct directory and it contains the BDD.log that’s actively being updated.

While a machine is imaging, open the BDD.log (in the latter directory mentioned above) with CMTrace from your MDTServer (or whatever machine you’re working on) and you will see live updates:

Logging-003

When the Task Sequence is finished go back into the log directory for that machine and you will to find the logs that were copied up by MDT:

Logging-004

Log Locations

MDT Logs can be a little challenging to locate initially so I recommend you study up those links mentioned in the recommended reading section above.

  • In WinPE & the disk is NOT partitioned:
    • X:\MININT\SMSOSD\OSDLOGS
      .
  • In WinPE & the disk IS partitioned:
    • C:\MININT\SMSOSD\OSDLOGS
    • X:\MININT\SMSOSD\OSDLOGS (very small amount)
      .
  • In WinPE & Task Sequence is running
    • smsts.log will be in X:\Windows\Temp\SMSTSLog
    • All other logs will be in their respective directories mentioned above
      .
  • In Windows & Task Sequence is running
    • smsts.log will be in C:\Users\Administrator\AppData\Local\Temp\SMSTSLog
    • C:\MININT\SMSOSD\OSDLOGS

Keep in mind there are other non-MDT logs you’ll probably need to review that are not listed here.

In Closing

You now have some historical data to dig into if something goes wrong, which will hopefully be few & far in between!

Good Providence to you!

MDT Tutorial Part 5: Bootstrap.ini

Living Table of Contents

 

Today’s Agenda:

  • Bootstrap.ini Overview
  • Facilitating Authentication
  • Skipping the Welcome Screen
  • Putting it All Together

Recommended Reading

Bootstrap.ini Overview

The BootStrap.ini is similar to the CustomSettings.ini in that the format, structure and processing logic is the same.  The major difference is mainly that the Bootstrap.ini is processed first and once when you boot into WinPE.  The CustomSettings.ini on the other hand is processed after the Welcome screen and at various points during the Task Sequence.

Just like the CustomSettings.ini, the Bootstrap.ini is accessible two ways:

  1. Via the ‘Edit Bootstrap.ini’ button on the ‘Rules’ tab of the Deployment Share properties.
  2. Via the Bootstrap.ini in the Control subdirectory of your Deployment Share, for example:
    1. C:\DeploymentShare\Control
    2. \\MDTServer\DeploymentShare$\Control

Currently your Bootstrap.ini is more bare bones than your CustomSettings.ini:


[Settings]
Priority=Default

[Default]
DeployRoot=\\ITF1MDT01\DeploymentShare$

Unlike the CustomSettings.ini however, when you make changes to your Bootstrap.ini, the changes are not ‘live’ immediately:  Because the Bootstrap.ini is baked into your boot media – hence its ability to be processed when WinPE loads – anytime you update your Bootstrap.ini you must update your Deployment Share to generate new media that contains your updated Bootstrap.ini.  Because of this, you probably want to keep edits to this file to a minimum, adding just the essentials to get you connected to the Deployment Share.

According to the documentation, there are only a handful of properties configured by Bootstrap.ini; so few I’ll include them here for reference:

_SMSTSOrgName Database DBID
DBPwd DeployRoot DestinationDisk
DestinationLogicalDrive DestinationPartition Instance
KeyboardLocale KeyboardLocalePE Location
NetLib Order Parameters
ParameterCondition Port Priority
Properties ResourceRoot Role
SkipBDDWelcome SQLServer SQLShare
StoredProcedure Table UserDomain
UserID UserPassword

However that same document doesn’t state you can use the ‘DefaultGateway’ in the Bootstrap.ini which is a completely valid configuration, so I’ll assume the documentation is dated or it was an oversight.

It’s also been said that you can customize the Bootstrap.ini to nearly the same degree as the CustomSettings.ini.  I personally have not done this so I can’t validate that (e.g.: will User Exit scripts work etc.) but since the documentation is clearly not complete, I also refute it either.  So yes, you can create new sections and custom properties but I will say this: Because edits to the Bootstrap.ini require rebuilding the media each time a change is made, I personally prefer to to keep it simple with the most static information possible.

Facilitating Authentication

The first thing I typically do is rid myself of that dreadful authentication prompt that appears after clicking the ‘Run the Deployment Wizard…’ button:

SBTS-002

And I accomplish that by adding the UserID, UserPassword and UserDomain properties to the Bootstrap.ini:


[Settings]
Priority=Default

[Default]
DeployRoot=\\ITF1MDT01\DeploymentShare$
UserID=Administrator
UserPassword=my sekret 1337 Cyph3r!
UserDomain=ITF1MDT01

The documentation states:

For a completely automated LTI deployment, provide this property in both CustomSettings.ini and BootStrap.ini.  However, note that storing the user credentials in these files stores the credentials in clear text and therefore is not secure.

This is an important thing to remember when setting this up and a documented risk for the security team.  Leading practice would be to use a dedicated MDT account with limited rights (like execute) to the Deployment Share and write access to the ‘Captures’ directory.  I would advise against using a privileged account, be it local to the ‘MDT Server’ or the a domain account.

Skipping the Welcome Screen

If you’re not a big fan of this screen:

SBTS-001

You can suppress it by adding the SkipBDDWelcome property and setting it to YES to the Bootstrap.ini.


[Settings]
Priority=Default

[Default]
DeployRoot=\\ITF1MDT01\DeploymentShare$
UserID=Administrator
UserPassword=my sekret 1337 Cyph3r!
UserDomain=ITF1MDT01
SkipBDDWelcome=YES

To undo, set it to NO or comment the code by placing a semicolon in front of it like ;SkipBDDWelcome=YES.

The documentation states:

For this property to function properly, it must be configured in both CustomSettings.ini and BootStrap.ini. BootStrap.ini is processed before a deployment share (which contains CustomSettings.ini) has been selected.

I’ll tell you that I don’t always add it to my CustomSetting.ini and yet the Welcome screen is been suppressed for every build and build & capture with that configuration.  Again, this could be a change in MDT behavior that wasn’t reflected in the documentation but I always recommend following the documentation.

Putting It All Together

Ok so now you’ve got the hang of it, let’s make some changes common to many environments.  Comments added to emphasize certain elements.


[Settings]
Priority=Init,DefaultGateway,BootStrapSection,Default
Properties=Office,MyBootStrapProperty

[Init]
DeployRoot=\\DFS\Namespace\DeploymentShare$
;SkipBDDWelcome=YES

[DefaultGateway]
; Put your real gateway for HQ
10.0.1.1=HQ
10.10.1.1=DC

[HQ]
; HQ is your current environment so put real information here
Office=HQ
; Point this to the real Deployment Share you setup
DeployRoot=\\ITF1MDT01\DeploymentShare$
; Use real credentials to connect to the above share
UserID=svc_ImagingAccount
UserPassword=Tr0ub4dor&3
UserDomain=ITF1MDT01

[DC]
; This is a fake location for illustration purposes
; But you could be in an environment with multiple Deployment Shares
Office=DC
DeployRoot=\\DCServer\DeploymentShare$
UserID=lclMDTUser
UserPassword=Correct Horse Battery St4pl3!
UserDomain=DCServer
SkipBDDWelcome=NO

[BootStrapSection]
MyBootStrapProperty=THIS IS MY BOOTSTRAP PROPERTY
_SMSTSOrgName=MDT Lab@%Office%

[Default]
SkipBDDWelcome=YES
; This is fake information because I set the real information above
; Again purely for illustration purposes
UserID=MDTAccount
UserPassword=my sekret 1337 Cyph3r!
UserDomain=DOMAIN.FQDN

And here’s how it’s going to be processed:

  1. [Init] Section – This is the ‘Init’ section where I can set some default settings.  This isn’t required and you may or may not need something like this; just know that you can do something like this.
    1. DeployRoot is set to \\DFS\Namespace\DeploymentShare$
      This would be a catch-all default for offices that don’t have a separate Deployment Share.  In this scenario, if someone’s gateway was 10.20.20.1 they would default to this Deployment Share because there’s no rule below for that particular gateway.
      .
    2. SkipBDDWelcome was initially set to YES at some point but commented out because technicians in some offices wanted to use the other options on the Welcome screen.
      SkipBDDWelcome, like most MDT properties, is a write-once property so if we set it to ‘YES’ in [Init] we can’t alter it later.  Better to leave it alone to allow offices to customize it to their liking.
      .
  2. [DefaultGateway] Section
    1. 10.0.1.1 – If the default gateway matches this, it will go to the [HQ] section
      1. [HQ] Section
        1. We set a new property called Office to HQ.
          This could be useful for a variety of things like naming computers based on location
        2. The DeployRoot is set to \\ITF1MDT01\DeploymentShare$.
          DeployRoot is one of 9 properties that are re-writable out of the box so I can set this as many times as I need to.
        3. UserID is the username we’re going to use to connect to the above Deployment Share, in DeployRoot.  We have to do this because they’re smart and not using common username & password like other offices.
        4. UserPassword is the password for the above user
        5. UserDomain is the domain we’re authenticating against, in this case the DCServer.
        6. SkipBDDWelcome is set to NO because this office prefers to see the screen.
          .adsasdasd..
    2. 10.10.1.1 – If the default gateway matches this, it will go to the [DC] section.
      1. [DC] Section
        1. We set a new property called Office to DC.
        2. The DeployRoot is updated to point to a local Deployment Share in that office.
        3. UserID is the username we’re going to use to connect to the above Deployment Share, in DeployRoot.  We have to do this because they’re smart and not using common username & password like other offices.
        4. UserPassword is the password for the above user
        5. UserDomain is the domain we’re authenticating against, in this case the DCServer.
        6. SkipBDDWelcome is set to NO because this office prefers to see the screen.
          .
  3. [BootStrapSection] Section – An arbitrary section I created just because I can
    1. A new property called MyBootStrapProperty is set to ‘THIS IS MY BOOTSTRAP PROPERTY” – again purely to show that it can be done.
    2. The _SMSTSOrgName property is set and it references the Office code set further up.
      .
  4. ​​[Default] Section
    1. SkipBDDWelcome is set to YES because most offices don’t want to see it.
      If it’s not already set, it will get set to YES.
    2. UserID is the username we’re going to use to authenticate to the default Deployment Share, held in property DeployRoot, that we set in the [Init] section.
    3. UserPassword is the password for the above username
    4. UserDomain is the domain we’re authenticating against.

The proof is in the pudding:

  • After making the changes to the Bootstrap.ini, update your Deployment Share to create new media
  • Boot your new media
  • You will no longer see the Welcome screen
  • You will no longer receive an authentication prompt
  • You will be taken directly to the Task Sequence page
  • If you run a Task Sequence (build or build & capture) you’ll see the updated text in the progress bar area:
    • Bootstrap-002

I recommend opening the BDD.log file to review the processing, but this is something we haven’t touched on yet so brace yourself.

While in WinPE – say when you’re looking at the Task Sequence list – press F8 on your keyboard to open a command prompt which is unequivocally indispensable when it comes to troubleshooting!  Please note that on some laptops you may need to press the Function (Fn) key and F8 simultaneously to get this to work.  This isn’t an MDT problem but a hardware specific issue.

Bootstrap-003

In the command window just type notepad hit return and notepad will open.  From there you can go to File > Open & browse to find the BDD.log, which is in one of two locations depending on the state of the hard drive of the machine you’re testing:

  • Drive has NOT been partitioned:
    The BDD.log – and others – can be found in X:\MININT\SMSOSD\OSDLOGS
    .
  • Drive HAS been partitioned:
    The BDD.log – and others can be found in C:\MININT\SMSOSD\OSDLOGS

This slideshow requires JavaScript.

Once you navigate to that location, you won’t see anything because of the default ‘Files of type’ filter in notepad.  Change the drop down from ‘Text documents (*.txt)’ to ‘All Files’ and like magic a bunch of files will appear.  Now open the BDD.log

MDT generated logs are a little difficult to navigate in notepad but this is the kind of thing that really builds character.  In the log, search (CTRL+F) for one of the properties you set, like _SMSTSOrg or ‘MDT Lab@’ and you should find what you’re looking for it pretty quickly.

Below is my marked up version of the BDD.log highlighting the custom properties, the order of operations (Rule Priority) as well as the sections it processed; between each you’ll find log entries for the actions performed, like setting Properties (aka variables) like UserID, MyBootstrapProperty etc.

Bootstrap-001

As you can see, everything was processed accordingly and set correctly.

In Closing

This Bootstrap.ini example is a little complex only because it accounts for possible real world scenarios: Office specific configuration, Multiple Deployment Shares (aka DeployRoot), Different Credentials for each Deployment Share, customizing the progress bar with your branding/corporate information and so on.

For your lab environment, you really just need a bare bones config like this:


[Settings]
Priority=Default

[Default]
; Customize this to your liking
_SMSTSOrgName=My Custom MDT Lab
; Point this to the real Deployment Share you setup
DeployRoot=\\ITF1MDT01\DeploymentShare$
; Use real credentials to connect to the above share
UserID=svc_ImagingAccount
UserPassword=Tr0ub4dor&3
UserDomain=ITF1MDT01
; You might want to skip this but maybe not - your call
SkipBDDWelcome=YES

But at least you know how to handle those scenarios and scale up.

Good Providence to you!

MDT Tutorial Part 4: CustomSettings.ini

Living Table of Contents

 

Today’s Agenda:

  • CustomSettings.ini Overview

Recommended Reading

CustomSettings.ini

The CustomSettings.ini is a rules file processed by ZTIGather.wsf after the Bootstrap.ini is processed (more on that in my next post) as well as periodically during the Task Sequence.  The CustomSettings.ini contains instructions to perform specific actions and set various parameters in MDT.  You can great very creative when it comes to customizing the CustomSettings.ini, but that’s beyond the scope of this post.  Today I just want to focus on explaining what’s currently in your CustomSettings.ini to whet your appetite for getting this setup in your environment.

The CustomSettings.ini can be accessed two ways:

  1. In the ‘Rules’ tab of the Deployment Share properties
  2. The CustomSettings.ini file in the Control subdirectory of your Deployment Share, for example:
    1. C:\DeploymentShare\Control
    2. \\MDTServer\DeploymentShare$\Control

At the moment your current CustomSettings.ini it pretty bare bones


[Settings]
Priority=Default
Properties=MyCustomProperty

[Default]
OSInstall=Y
SkipCapture=NO
SkipAdminPassword=YES
SkipProductKey=YES
SkipComputerBackup=NO
SkipBitLocker=NO

I want to start by pointing out that everything in the [Default] section is set to ‘NO’ except for ‘SkipAdminPassword’ and ‘SkipProductKey’.  If you recall when we created the first Deployment Share, we saw the screen below:

NDS-004

Everything was checked except for ‘Ask for a product key’ and ‘Ask to set the local Administrator password’ which if you can guess corresponds to what we’re seeing in the CustomSettings.ini.

The OSInstall property is provided out of the box and I suppose it’s meant to tip the MDT Admin that you can set it to N if need be.  It’s important to note that this property is not required, and if it’s missing an OS installation will proceed by default.  So don’t go thinking that by deleting that you’re going to prevent OS’ from installing.

Another baked in property is MyCustomProperty which has no references anywhere.  This is really just to let the MDT Admin know that this is where they can declare properties (like declaring variables) for use in the CustomSetitngs.ini and thus the MDT environment.  We’ll get into that more a little later but just know that you can delete ‘MyCustomProperty’ – and in fact that whole line – and things would work fine.

At the moment there are two Sections – the square bracket surrounded text – in your CustomSettings.ini:

  1. Settings
  2. Default

And the rest are properties, or variables, that we’ll explore further.

The [Settings] Section

The settings section holds just two properties

  • Prioroty
  • Properties

Priority

The Priority property is a reserved property used for determining the order in which sections within the CustomSettings.ini will process items.  I like to think of Priority as a listing of declared Functions I want to call in a specific order when the CustomSettings.ini is processed, and each of these functions do something.  Let’s go over some basic real-world examples to help explain.

Say your CustomSettings.ini looked like this:


[Settings]
Priority=MACAddress,Default

[00:11:22:33:44:55]
SkipAdminPassword=NO

[00:11:22:33:44:56]
OSInstall=Y

[TestGroup]
SkipCapture=YES

[Default]
OSInstall=Y
SkipCapture=NO
SkipAdminPassword=YES
SkipProductKey=YES
SkipComputerBackup=NO
SkipBitLocker=NO

When the CustomSettings.ini is processed it will read the Priority line to determine the order in which the sections need to be processed.

  1. MACAddress
  2. Default

The MACAddress directive is a special one that is built-into MDT that doesn’t look for a section called [MACAddress] but instead determines your machine’s MACAddress and looks for a section that matches your machine’s MAC Address, like [00:11:22:33:44:55].  If a matching section is found, it processes the properties in that section, which in this case is just SkipAdminPassword=NO.  When that’s done it’ll move into the [Default] section and process everything there and then it’s done.

But wait a minute, what about that third section called [TestGroup] with it’s own set of properties?  Well the [TestGroup] section would not be processed because it was not specified on the Priority line, so it’s ignored completely.

Let’s try another example: Suppose you wanted to add a section to do something special for machines using a particular default gateway IP address:


[Settings]
Priority=DefaultGateway,MACAddress,Default

[192.168.1.1]
SkipProductKey=NO
SkipAdminPassword=NO

[00:11:22:33:44:55]
OSInstall=N

[00:11:22:33:44:56]
OSInstall=Y

[TestGroup]
SkipCapture=YES

[Default]
OSInstall=Y
SkipCapture=NO
SkipAdminPassword=YES
SkipProductKey=YES
SkipComputerBackup=NO
SkipBitLocker=NO

From a processing perspective this is the order:

  1. DefaultGateway
  2. MACAddress
  3. Default

Like MACAddress, DefaultGateway is a special directive that looks up the default gateway IP address of the machine in question.  In this scenario, any machines with a Default Gateway of 192.168.1.1 will always display the MDT screens that prompt for the product key and administrator password, which may seem a little odd considering in the [Default] section we’re suppressing them, which brings me to my next important point.

For most MDT properties, once it has been set, it becomes ‘read-only’ and won’t be changed again via processing of the CustomSettings.ini.  The ‘documentation’ calls these variables ‘first value wins’ but I usually refer to them as ‘write-once’.  This is very important because once an internal MDT property is set, say in Section A, it will not be altered in Section C even if it’s present with a different value.

However, there are some variables that are ‘last value wins’, meaning they can be overwritten multiple times, and I’m only aware of 9 that fit into this category:

  1. DeployRoot
  2. ResourceRoot
  3. DeployDrive
  4. ResourceDrive
  5. DeploymentMethod
  6. DeploymentType
  7. Phase
  8. DestinationDisk
  9. DestinationPartition

Can you override this behavior?  Yes, by editing the ZTIGather.xml, but I’d advise against it unless you know what you’re doing.  Plus by doing so you may not be in a supported configuration and Microsoft Support would probably ask you to undo your changes.

Properties

The Properties property is more like a variable declaration directive.  In the CustomSettings.ini you can’t just create lines for various properties all willy nilly:


[Settings]
Priority=DefaultGateway,MACAddress,Default
Properties=SkipWindowsUpdates

[192.168.1.1]
SkipProductKey=NO
SkipAdminPassword=NO

[00:11:22:33:44:55]
OSInstall=N

[00:11:22:33:44:56]
OSInstall=Y

[TestGroup]
SkipCapture=YES

[Default]
OSInstall=Y
SkipCapture=NO
SkipAdminPassword=YES
SkipProductKey=YES
SkipComputerBackup=NO
SkipBitLocker=NO
SkipWindowsUpdates=YES
InstallOffice2016=YES

In the above example, I declared a new property (or variable) called SkipWindowsUpdates via the ‘Properties’ line.

In the [Default] section I added the new declared property, SkipWindowsUpdates, and set it to YES.

In the [Default] section I also added a property called InstallOffice2016 and set that to YES.

Unfortunately only the SkipWindowsUpdates property (or variable) is going to get picked up by MDT.  The InstallOffice2016 property is ignored because it’s not ‘declared’ in the Properties line in the [Settings] section.

Please note that SkipWindowsUpdates is NOT a built-in MDT property; I just made it up and that is why I had to ‘declare’ it.  Any custom properties you create must be declared – added to the Properties line under Settings – before you can use them.

The [Default] Section

There’s no special meaning behind the name ‘Default’ – it’s just the name of a section.  It could be called Chazwazza and it would work just as well.  But generally speaking the ‘Default’ section is the last section to be processed and that’s where you set all of the ‘Default’ settings not set in the sections above.

  • OSInstall=Y – Indicates an OS will be installed.
  • SkipCapture=NO – Indicates the Capture screen will NOT be suppressed and thus visible.
  • SkipAdminPassword=YES – Indicates the Password screen WILL be suppressed and thus NOT visible.
  • SkipProductKey=YES – Indicates the Product Key screen WILL be suppressed and thus NOT visible.
  • SkipComputerBackup=NO – Indicates the Computer Backup screen will NOT be suppressed and thus visible.  Please note that this is not a screen we’ve seen yet.
  • SkipBitLocker=NO – Indicates the BitLocker screen NOT be suppressed and thus visible.

You can completely change the ordering of the Default section or even have other sections execute after the Default section, provided you added (aka declared) it in the Priority line in the Settings section after Default.

Putting It All Together

Going back to our current stock CustomSettings.ini we’re going to alter some defaults just to show how it works and how it can streamline imaging.


[Settings]
Priority=Default
Properties=MyCustomProperty

[Default]
OSInstall=Y
SkipCapture=NO
SkipAdminPassword=YES
SkipProductKey=YES
SkipComputerBackup=NO
SkipBitLocker=YES
SkipUserData=YES

Since we’re not looking to backup and/or restore anything, and we’re not enabling BitLocker, we can skip those screens altogether by setting SkipBitLocker to ‘YES’ and adding a new property called SkipUserData and setting that to ‘YES’.

When you make changes to the CustomSettings.ini, they’re live right then and there so just boot your media and go again.

  • If you’re already in WinPE at the Welcome screen, the one with the ‘Run the Deployment Wizard…‘ button, click it and it’ll process your updated CustomSettings.ini.
  • However if you’re already at the Task Sequence screen you’ll need to reboot since the CustomSettings.ini was processed before you made you changes.

Now when I boot into WinPE and image, I no longer see those respective screens.
Before, I had both ‘Move Data and Settings’ and ‘USer Data (Restore)’ steps:

SBTS-011

After making the change, those screens are gone altogether:

NoBLNoUD

If I wanted to bring back BitLocker screen, I could Set SkipBitLocker to ‘NO’ or commend the line by adding a semicolon in front like ;SkipBitLocker=YES

In case you’re wondering, I didn’t declare SkipUserData because it’s a built-in MDT property that I’m just toggling.  Please see the links under recommended reading above for more information on [many] built-in variables.

In Closing

We’re really only scratching the surface here at what we can do with the CustomSettings.ini.  You can do so much from here including calling a UserExit script which is a way for the CustomSettings.ini to call an external vbscript that will return a value which will get set as the property (or variable) value.

In the next post we’ll talk about the other .INI file, Bootstrap.ini and we’ll make some other adjustments to both files to make some things a little easier for us.

For now, I bid you Good Providence.

Getting Real Lenovo Model Details

Our computer naming convention includes a portion of the model number to make it easier to identify trends and those with old, or new, assets.  Coming from a Dell shop where we did something similar, I was disappointed to learn that Lenovo machines didn’t populate the Model details the same way.  So instead of seeing something like ThinkPad W541, we were seeing something very cryptic: 20EFCTO1WW

Get your Decoder Ring

Thinking something was up with the built-in scripts or logic I ran the below on a Lenovo machine which confirmed it was what it was:


wmic path win32_computersystem get model

Model
20EFCTO1WW

For a while we kept a matrix of sorts that we’d feed into our CustomSettings.ini to ensure machines were named correctly.  We expected this pain as models were phased out and new models came in, but it was also very frustrating as the details would change mid-stream for the same model.  This led us to studying the Lenovo Product Specifications Reference or PSREF.

Not being keen on this, I learned somewhere (unsure of the actual source) that Lenovo stashes the bits we were after in Win32_ComputerSystemProduct under Version


wmic path win32_computersystemproduct get version

Version
ThinkPad W541

Once confirmed across a few machines, I went right to work.

UserExit Script: GetAbbrModel.vbs

This is a modified version of the script we use in production but the result is the same: It gets the human-readable format of the model, trims the parts we don’t want and returns an abbreviated version of the model.  So a ThinkPad W541 ends up being returned to MDT/SCCM as W54.  You can modify to suit, like creating a new property/variable called RealModel and assigning the script output to that or overwrite the existing Model property via the script itself.

The script works on 99% of the machines in our environment but it does occasionally fail:

  • some unexpected data is in there: sometimes it’s really bizzare or mirrors Model in Win32_ComputerSystem or Name in Win32_ComputerSystemProduct.
  • most of the time it’s because the field is blank/null/empty and we typically see this on machines that were serviced, specifically a board replacement, and tech didn’t run the utility to set the bits in the BIOS.  Accidents happen.
  • it’s running on very hardware that should have been retired 🙂

Good Providence to you as you adjust it to suit your needs!


' //***************************************************************************
' //
' // Solution:Get Model Abbreviation for Microsoft Deployment
' // File: jgp_GetAbbrModel.vbs
' //
' // Purpose: Gets & sets the correct model abbreviation for use in computer name and other custom configurations
' //
' // ***** End Header *****
' //***************************************************************************

'//----------------------------------------------------------------------------
'//
'// Global constant and variable declarations
'//
'//----------------------------------------------------------------------------
Option Explicit

'//----------------------------------------------------------------------------
'// End declarations
'//----------------------------------------------------------------------------

'//----------------------------------------------------------------------------
'// Main routine
'//----------------------------------------------------------------------------
Function UserExit(sType, sWhen, sDetail, bSkip)
	UserExit = Success
End Function

Function GetAbbrModel()
	on error goto 0
	Dim sMake : sMake = oEnvironment.Item("Make")
	Dim sModel : sModel = oEnvironment.Item("Model")
	Dim sAbbrModel : sAbbrModel = "UNK"

	Select Case UCase(sMake)

		Case UCase("Dell")

			If InStr(1,sModel,"OptiPlex ",1) > 0 Then
				sAbbrModel = Left(Replace(sModel,"ptiPlex ","",1,-1,1),3)
			elseif InStr(1,sModel,"Latitude ",1) > 0 Then
				sAbbrModel = Left(Replace(sModel,"Latitude ","",1,-1,1),3)
			elseif InStr(1,sModel,"XPS",1) > 0 Then
				sAbbrModel = Left(Replace(sModel,"PS","",1,-1,1),3)
			end if

		Case UCase("Lenovo")
			Dim oCSP
			For Each oCSP in GetObject("winmgmts:").ExecQuery("SELECT Version,Name FROM Win32_ComputerSystemProduct")
				Dim sLenovoModel : sLenovoModel = oCSP.Version
				Dim sLenovoProductType : sLenovoProductType = oCSP.Name
				exit for
			Next

			If InStr(1,sLenovoModel,"ThinkCentre ",1) > 0 Then
				sAbbrModel = Left(Replace(sLenovoModel,"ThinkCentre ","",1,-1,1),3)
			elseif InStr(1,sLenovoModel,"ThinkStation ",1) > 0 Then
					sAbbrModel = Left(Replace(sLenovoModel,"ThinkStation ","",1,-1,1),3)
			elseif InStr(1,sLenovoModel,"ThinkPad ",1) > 0 Then
				if Instr(1,sLenovoModel,"Carbon",1) > 0 Then
					If InStr(1,sLenovoModel,"Carbon 4th",1) > 0 Then
						sAbbrModel = Left(Replace(Replace(Replace(sLenovoModel,"ThinkPad ","",1,-1,1),"arbon 4th","")," ",""),3)
					elseif InStr(1,sLenovoModel,"Carbon 3rd",1) > 0 Then
						sAbbrModel = Left(Replace(Replace(Replace(sLenovoModel,"ThinkPad ","",1,-1,1),"arbon 3rd","")," ",""),3)
					elseif InStr(1,sLenovoModel,"Carbon 2nd",1) > 0 Then
						sAbbrModel = Left(Replace(Replace(Replace(sLenovoModel,"ThinkPad ","",1,-1,1),"arbon 2nd","")," ",""),3)
					elseif InStr(1,sLenovoModel,"Carbon",1) > 0 Then
						sAbbrModel = Left(Replace(Replace(Replace(sLenovoModel,"ThinkPad ","",1,-1,1),"arbon","")," ",""),3)
					end if
				else
					sAbbrModel = Left(Replace(sLenovoModel,"ThinkPad ","",1,-1,1),3)
				end if
			else
				' Alternatively you could build & maintain (yuck) a table of product types
				Select Case UCase(Left(sLenovoProductType,4))
					Case UCase("5032")
						sAbbrModel = "M81"

					case UCase("20EF")
						sAbbrModel = "W54"
				End Select
			end if

		Case UCase("innotek GmbH")
			sAbbrModel = UCase(Left(sMake,1) & Mid(sMake,8,1) & Right(sMake,1))

		Case UCase("VMware, Inc.")
			sAbbrModel = UCase(Left(sMake,3))

		Case UCase("Microsoft Corporation")
			sAbbrModel = "HPV"

	End Select
	GetAbbrModel = sAbbrModel
End Function