MDT

Back to Basic – CustomSettings.ini – Explained

One of the most important files in MDT (and in SCCM with MDT) is customsettings.ini, it is the rule file to rule your deployment. Yesterday Johan and I did a session at MMS and besides getting great scores and that is always fun. During that session I did a couple of demos around customsettings.ini and I would like to explain this a bit more. Because if you do understand the rules you can become much more dynamic and that will hopefully lead to less hassle and more work done in less time.

So, let’s start from the beginning:

When you use the MDT Toolkit (standalone, with WDS, with SCCM, it does not matter) the toolkit will as a part of the process run a script called ZTIGather.wsf, this script will do an asset inventory and also read the customsettings.ini file. This will result in a massive amount of information stored in memory (and in a file) during deployment that we then can use to dynamically update the unattend.xml file on the fly and also control conditions and that way also settings and steps in the TaskSequence

The best thing is that you can run this script without deploying any OS, so this way you can test the rules before you even begin deploying, and you can also test thousands of deployments in a couple of hours. (Here is a blog post on that https://deploymentbunny.com/2011/04/27/quick-and-dirty-testing-customsettings-ini-variables-in-mdt)

CustomSettings.ini – Act I

The basic Customsettings.ini looks like this

In the first row we see the section called [Settings] and this is what the script are looking for and on the next row you can see Priority=Default. That means that it will now consume everything in that section and convert all those lines in to varables in MDT. All the Properties you see under the Section [Default] is built into MDT, there are +100 properties that can be used and most of them are documented in the help file, just search for Properties and you will find a huge list. If we run ZTIGather.wsf against this file we will get the following output

And as you can see, it is using my customsettings.ini file that I pointed out by running cscript.exe ZTIgather.wsf /Inifile:”..\Control\customsttings.ini”, we can also see that the script is reading settings and finding the priority and then process the [Default Section]

CustomSettings.ini – Act II

Now let us assume that you would like to automatically set some settings based on location, things like computer name, language, time zone, something like that In that case, we would use the default gateway as an identifier for the location and would use part of the serial number to calculate a unique name for the computer that is based on the location and the serial number, but hey, let us do something crazy here, let us also add laptop or desktop into the name, so if the laptop is located in Stockholm the name should be STH-LT-0123456 and if a desktop is located in Redmond it would be called RDM-DT-0123456. So, that would look like this

Now, this is slightly “bigger”, but let me guide you through this one, it is not that hard.

The Settings Section

In the [Settings] section we added Init, ByLaptop, ByDesktop and DefaultGateway. The [Init] Section is things that I would like to be set in any situation, like default, but BEFORE default is running. The ByLapTop and ByDesktop contain something called SubSection and we will get back to that. DefaultGateway is a property in MDT so the script will take my current default gateway and match that to what I really have, more on that later.

Next line is the CustomProperties= and here we added a couple of properties that we will fill with data so that we later can use them to populate many variables into one, that’s how we can “build” the computer name, since that will be a combination of computer location + computer type + the first 7 characters in the serial number. So the complete Settings section look like this:

[Settings]
Priority=Init, ByLaptop, ByDesktop, DefaultGateway, Default
Properties=ComputerLocationName, ComputerTypeName, ComputerSerialNumber

The Init Section

The Init section will use the serial number (that has been inventoried by the script already), pick the 7 characters to the left and put that into my custom property ComputerSerialNumber, so that section would look like this: (You can to basically any kind of calculations like this, just go ahead and play with it)

[Init]
ComputerSerialNumber=#Left(“%SerialNumber%”,7)#

The ByLapTop Section and the ByDeskTop Section

These two sections are a bit fun, what we do here is that we tell the script to jump to a subsection called LapTop-%IsLapTop% and %IsLapTop% will either be true or false and we will tell it to do the same for Desktop, and will also return the value of True or False, and since it cannot be a Laptop and an desktop at the same time, either will LapTop-True be true or DeskTop-True be true, so it will pick up regarding case type and then set the name to match that, like this:

[ByLaptop]
SubSection=Laptop-%IsLapTop%
ComputerTypeName=LT

[ByDesktop]
SubSection=Desktop-%IsDesktop%
ComputerTypeName=DT

In my case I have a laptop, so it will set the value of %IsLapTop% to True and the value of %IsDeskTop% to false, resulting in that the ComputerTypeName will be set to LT

The Default Gateway Section

This section will use the value from the gather script regarding the Default Gateway and based on the set jump to the name I have set for that Gateway, so in this case it will go to the section Stockholm if my Default gateway happens to be 10.2.0.4 and in that case it will set the Swedish keyboard and compterlocationname to STH and that part looks like this:

[Stockholm]
ComputerLocationName=STH
UserLocale=sv-SE
UILanguage=sv-SE
KeyboardLocale=041d:0000041d

The Default Section

This section will run last, not because it is last, it will be the last section since it is last on the priority line. That also means that if I have any property value here that has already been set the rule of thumb is that “First Writer Wins”, so they will not be over written (there are exceptions). Here you can see that I have property values for ComputerLocationName and ComputerTypeName, so why do I have that? Well I will set the name to UNK (Short for Unknown) if the computer is not a Laptop and neither a Desktop (Could be a Server? And yes, we could create rules for that to), also if the default gateway is something that I did not add in the customsettings.ini file, and then it will get the location name set to UNK to. So here is how it looks:

[Default]
OSInstall=Y
ComputerLocationName=UNK
ComputerTypeName=UNK
OSDComputername=%ComputerLocationName%-%ComputerTypeName%-%ComputerSerialNumber%
SkipCapture=NO
SkipAdminPassword=YES
SkipProductKey=YES
SkipComputerBackup=NO
SkipBitLocker=NO

The fun part is that OSDcomputername is built by parts of location, type and serial number.

Running the Script will result in this:

 

So, here is how you could create dynamic deployment rules using notepad and a textile, I think that is really cool, but hey, I’m just a Bunny anyway J

(if you would like more samples, let me know…)

/mike

Categories: MDT, SCCM

66 replies »

  1. Mikael
    thank you for sharing and giving us your wisdom. I read your blog every time you post an article.
    (if you would like more samples, let me know…) <—- Write a book I'll buy it. Some of us are not fortunate to have SCCM. We can only use MDT. I have the book that you wrote with Johan Deployment Fundamentals V1. It has helped me a lot, but how about you write the sequel of the first book "Extended Deployment Fundamentals V 1.1" in which you share tip and tricks, troubleshooting, deployment to sites without a server, etc. I know if I search online (which i did) I can find all the answer to my question, but it is nicer to have a book to have as a reference any time.

    Oh well! One can dream of such a book.

    Keep posting … we will be reading.
    thanks again.

    Saludos
    Jorge

    • Thank you so much, I can tell you this, we have started to work on Volume number 4, That os going to be MDT 2012, Windows 7 and Windows 8 and we are going to pack it more then ever with “stuff”, we are going add “notes from the filed” and “Behind The Scenes” information, tell me waht you need more specific and we will try to get that in to Volume IV.
      /mike

  2. Excellent article! Anyone who is using MDT should read and understand this.
    Went through this last year and took me quite a while to ‘figure it out’ by piecing the documentation together and much trial and error.
    Nice to have this concept well documented in one post.

  3. Excellent write up. Right now I am using task sequence variable to prompt a technician for computer name. Is there a way that I could still propmpt the tech for a name but if the name was blank then it would just use the serial number from the machine as a name?
    Sam

    • As long as the calculation happens before the Wizard runs, you should have no problem, if for example I use the serial number as base for the computer name and you run the LTI wizard, it will show the caluculated name in the dialig box. If you do the name calculation in the tasksequence, well then its harder, the you need to have the wizard do the calculation, it is a bit more tricky, but possible. (And thanks, :-))

      • Thanks for the fast response Mikael, you must have recovered from MMS faster than I did ;-)
        I rechecked and I am actually setting OSDComputerName as a collection variable for all unknown computers. So what you are saying is it should get set at the CS.ini level and then I could choose to change it when prompted during the start of the deployment or is it the other way around?
        Sam

  4. Great article.
    Does this work in MDT 2010?
    ComputerSerialNumber=#right(“%SerialNumber%”,7)#

    Kind regards
    BRB

  5. This is a great example/tutorial. I have tried following you steps, but I still can not get the computer name to generate properly. Is my TS do I need to tell all of the Gather steps to process rules or just the first gather

      • Do you know where I can disable this MDT Configure Computer name wizzard, because I believe it causing my CS.ini not to set the computers
        based on OSDComputername=%ComputerLocationName%-%ComputerTypeName%-%ComputerSerialNumber%

      • Yes, you can skip the Wizardpage by settings SkipComputerName=YES in customsettings.ini but I’m not sure that will help you. I see that you are trying to set the name using OSDComputername=%ComputerLocationName%-%ComputerTypeName%-%ComputerSerialNumber%, so in that case all properties like %ComputerLocationName%, %ComputerTypeName%, %ComputerSerialNumber% must first be set before you can use this combo of name. You should be able to run the ZTIgather script to verify that all is set correctly, no need to deploy a machine to verify this.

  6. Thanks, I finally got the CS to generate the computer name for me. How can I get the dash removed out of the computer name.
    Example I have computer name MMPOM-V-5494-704. I would like to only have a dash between MMPOMV and the Serial Number So that it would look like this: MMPOMV-5495

  7. Hi Mikael,

    Thanks for those Back to Basic articles. I’m trying to find a way to customize my CS.ini but I’m not sure if it is possible.
    I have modified the Wizard and created a variable called %COMPANY% because I need to customize my deployment depending on the company (JoinDomain, GPOPack….). I added COMPANY in my CS.ini properties but I don’t know how to modify the deployment behavior.
    Is there a way to do this in cs.ini?

  8. Excellent Write up Mikael. I have worked with you on EBS 2008 Beta (MS – Support for EBS Beta) before and met you in Redmond.

    Just to add, I would add the following in your thread.

    The thumb rule about “First-writer-wins” works for all except for the following properties:
    DeployRoot, ResourceRoot, DeployDrive, ResourceDrive, DeploymentMethod, DeploymentType, Phase, DestinationDisk, DestinationPartition

  9. What happens if you set set same property in cs.ini and in mdt database? For example if you set joindomain property in both..which one takes presedence? Actually what i was thinking is situation where you set joinworkgroup=workgroup in Default setting in cs.ini first…this setting would be for workstations that are not added to database. Most of the workstations would be then added to database using their MAC´s. Domain join information would be set in details of workstations in database or in details of Roles.

    In other words if i set Default section first in Settings – Priority in CS.ini would it be so that those settings are set first (for all wks´s) and if there is same setting specified in database (the wks´s set with their mac´s), that setting overwrites the one set in CS.ini default section?

    • Basically all properties has “first” writer wins, so it follows the settings you have in priority in the first section in customsettings.ini. However, if you set the value direct in the tasksequence it will override.

      • No, customsettings.ini is the file hat is used first, but it does not mean that the values in customsetting.ini is used, it depends on the first line in customsettings.ini, the Priority=

        In this case, cs.ini defines that it should try to find the the mac, assettag, serialnumber or guid in the database first and if it finds a name in the db, that will be used.

        [Settings]
        Priority=CSettings, Default

        [Default]
        OSDComputrname=BOB

        [CSettings]
        SQLServer=SCVMM01
        Database=MDTPRD01
        Netlib=DBNMPNTW
        SQLShare=MDTPrd$
        Table=ComputerSettings
        Parameters=UUID, AssetTag, SerialNumber, MacAddress
        ParameterCondition=OR

        However, if you switch CSettings and default, the OSDComputername will always be BOB

        [Settings]
        Priority=Default, CSettings

        [Default]
        OSDComputrname=BOB

        [CSettings]
        SQLServer=SCVMM01
        Database=MDTPRD01
        Netlib=DBNMPNTW
        SQLShare=MDTPrd$
        Table=ComputerSettings
        Parameters=UUID, AssetTag, SerialNumber, MacAddress
        ParameterCondition=OR

  10. I really had no idea you could do this much with the customsettings.ini file this post is amazing and so clear my boss is really impressed with me (you :P) I got some really great ideas from this thread thank you very much.

  11. is there a way to do further text parsing? In your example you show: LEFT(“%SerialNumber%”,7)#
    Could I collect the 5th,6th and 8th character? If so, where can I find the syntax required to do such manipulation?
    Thanks!

  12. I figured it out, thank you!
    #mid(“%Serialnumber%”,5,1)&mid(“%Serialnumber%”,6,1)&mid(“%Serialnumber%”,8,1)#
    cool stuff, I was creating scripts to do this

  13. Ok, I have a question, how can I feed a Power Shell script (computername.ps1) so that output of the script will be computer name? I created a script that will query AD for next available computer so I want to feed that into computer name, is there a way to do this? Also I compile that script in .exe file (coputername.exe) if needed I can feed that as well, but just don’t know how. Thank you.

    • Darko, if you have the ADSI plugin in your Windows PE image you can query AD (will take some tweaking in your syntax likely) however once you have your “computername” value you can simply set the TS variable OSDComputerName to equal it.
      The powershell code to init the TS environment: $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
      Followed by: $tsenv.Value(“OSDComputerName”) = “YOURVALUEHERE”

      Just ensure you don’t overwrite this value in a later step.

      • Or, you can add PowerShell script that does this: query AD for next available computer name and change the name of current PC with result that came back from query and reboot. (PS script for this is easy to find on net. I wrote one myself since every new PC has number higher then last one joined on domain so it was peace of cake). Add this in TS at the end and should be good.

  14. I can’t get this to name a desktop properly. It starts every name with an “L”. Has something changed with MDT 2012 update 1?

  15. Mikael,
    It prefills great, but the workstation never is named correctly…always goes to auto generated one…WIN-XXXX. You have any ideas? Been working on this issue for a while!…any help would be great.

  16. Mykael, your blog is phenomenal. Thanks so much for the contributions! Is there a way to expand on the example above and place computers from a particular location into separate OU’s based on that location? For example, if a system built in and determined to be in New York and is also a laptop could you place that in a particular OU? if it was a system determined to be a desktop from New York and is also a desktop could that be placed in another OU?

    Thanks!

  17. Mykael, your blog is phenomenal. Thanks so much for the contributions! Is there a way to expand on the example above and place computers from a particular location into separate OU’s based on that location? For example, if a system built in and determined to be in New York and is also a laptop could you place that in a particular OU? if it was a system determined to be a desktop from New York could that be placed in another OU?

    Thanks!

  18. Hello! Thanks in advance. I have one question. It is possible to create custom sections and force CUSTOMSETTINGS that works with it? For example i want to create a section called COUNTRY, and i’m passing parameter like 001=COLOMBIA. If parameter match, i need that the COLOMBIA sub section execute.

    Thnks in advance for your help!

  19. Please help.
    I need to rename a Hyper-V VM. I’m getting Task Sequence has failed with the error code 0x80220005. It works with Laptops and Desktops but not with VM

    This is my customsettings
    [Settings]
    Priority=ByLaptop, ByDesktop, ByVM, Default
    Properties=MyCustomProperty

    [ByLaptop]
    subsection=Laptop-%IsLaptop%

    [Laptop-True]
    OSDComputerName=LT-%SerialNumber%
    MachineObjectOU=OU=Laptops,OU=USA,OU=Sites,DC=rayados,DC=com

    [ByDesktop]
    subsection=Desktop-%IsDesktop%

    [Desktop-True]
    OSDComputerName=DT-%SerialNumber%
    MachineObjectOU=OU=Desktops,OU=USA,OU=Sites,DC=rayados,DC=com

    [ByVM]
    subsection=VM-%IsVM%

    [VM-True]
    OSDComputerName=VM-#Right(“%SerialNumber%”,8)#
    MachineObjectOU=OU=Virtual_Machines,OU=USA,OU=Sites,DC=rayados,DC=com

    [Default]
    OSInstall=Y
    SkipCapture=YES
    SkipAdminPassword=NO
    SkipProductKey=YES
    Reply
    Alejandro said
    Your comment is awaiting moderation.
    March 20, 2018 at 21:58

    i have also tried this: OSDComputerName=VM-#Right(Replace(Replace(oEnvironment.Item(“SerialNumber”),” “,””),”-“,””),8)#
    MachineObjectOU=OU=Virtual Machines,OU=USA,OU=Sites,DC=rayados,DC=com
    this is for my lab at home. i need to deploy VM to test an i need to rename them. I don’t want to get the name MININT-EVRCP6A

    • That’s easy to fix, the issue is the Priority, you need to change the order to ByVM, ByLaptop, ByDesktop and reason is that all VM’s are desktop and therefore it never gets to the ByVM section.

      • It did not work. vm name was created with MININT-D5VA499. Wrong OU also.
        Reply
        Alejandro said
        March 21, 2018 at 19:27

        this is my new settings
        [Settings]
        Priority=ByVM, ByLaptop, ByDesktop, Default
        Properties=MyCustomProperty

        [ByVM]
        subsection=VM-%IsVM%

        [VM-True]
        OSDComputerName=VM-#Right(Replace(Replace(oEnvironment.Item(“SerialNumber”),” “,””),”-“,””),8)#
        MachineObjectOU=OU=Virtual_Machines,OU=USA,OU=Sites,DC=rayados,DC=com

        [ByLaptop]
        subsection=Laptop-%IsLaptop%

        [Laptop-True]
        OSDComputerName=LT-%SerialNumber%
        MachineObjectOU=OU=Laptops,OU=USA,OU=Sites,DC=rayados,DC=com

        [ByDesktop]
        subsection=Desktop-%IsDesktop%

        [Desktop-True]
        OSDComputerName=DT-%SerialNumber%
        MachineObjectOU=OU=Desktops,OU=USA,OU=Sites,DC=rayados,DC=com

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

  20. this is my new settings
    [Settings]
    Priority=ByVM, ByLaptop, ByDesktop, Default
    Properties=MyCustomProperty

    [ByVM]
    subsection=VM-%IsVM%

    [VM-True]
    OSDComputerName=VM-#Right(Replace(Replace(oEnvironment.Item(“SerialNumber”),” “,””),”-“,””),8)#
    MachineObjectOU=OU=Virtual_Machines,OU=USA,OU=Sites,DC=rayados,DC=com

    [ByLaptop]
    subsection=Laptop-%IsLaptop%

    [Laptop-True]
    OSDComputerName=LT-%SerialNumber%
    MachineObjectOU=OU=Laptops,OU=USA,OU=Sites,DC=rayados,DC=com

    [ByDesktop]
    subsection=Desktop-%IsDesktop%

    [Desktop-True]
    OSDComputerName=DT-%SerialNumber%
    MachineObjectOU=OU=Desktops,OU=USA,OU=Sites,DC=rayados,DC=com

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

  21. i fixed it, i just modified [Desktop-True]
    OSDComputerName=DT-#Left(“%SerialNumber%”,12)#

    • This blog is amazing, i have a question tho about serialnumber that is used here, at the moment I work with Lenovo, is the serialnumber always unique among different lenovo model/machines?

      In another project we named the computers after MAC adress but they dont want to use that in this case

      • Yes, serial numbers are always unique according to the vendor, You can use the MDT database, add the serial number for each computer and then assign it a name.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.