Tuesday, July 19, 2016

ConfigMgr 2012 Name Computer During OSD Task Sequence

ConfigMgr 2012 Name Computer During OSD Task Sequence

Problem

I needed a way to prompt for computer name during the OSD sequence.  I found an old post by texasmcse found here that got me started.  The second part that was needed was to get some validation around the name that is input so it would follow our naming standards.

Resolution

 

I created a new script with parts of code from the post above to prompt for a site code, then prompt for computer role, and finally it takes the last 7 characters of the serial to form the computer name.  It uses a csv file to validate the site code and role are correct before moving on.  If there is an incorrect configuration it will respond and start over.  It will check the computer name that is stored in the task sequence variable _SMSTSMachineName.  If the variable is set to MININT it will prompt for computer naming.  If it is set to something else, it will utilize what ConfigMgr is passing it.  I hope this is useful to others.  I am sure the code could be cleaner but it works well. In the code the CSV file is named Win10OUMap.csv.  The Win10OUMap.csv file has 5 columns in the following order; Name,OU,BusinessUnit,SiteCode,Role.  This is a ; delimited file.  The Name column is what is used to validate the name of the computer as it will contain the site and role format to ensure it is valid.  When you modify the script file remember that when you import a CSV file in VB the first column is 0 not 1.  Again hope this helps.

Code:

'On Error Resume Next

Set WshShell = WScript.CreateObject("WScript.Shell")

Set NetworkObject = CreateObject("WScript.Network")

Set objFSO = CreateObject("Scripting.FileSystemObject")

set SCCMenv = CreateObject("Microsoft.SMS.TSEnvironment")

 

'Find if known in SCCM

NameLookup = SCCMenv("_SMSTSMachineName")

'NameLookup = "MININT-234343"

SearchChar = "MININT"

'msgbox NameLookup

StrComputer = "."

IF inStr(NameLookup , SearchChar) Then

              SiteCodeMatch = 10

              SiteRoleMatch = 10

              PCNameMatch = 10

              Validated = False

                             'Get Computer Serial Number

              Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

              Set colSMBIOS = objWMIService.ExecQuery ("Select * from Win32_SystemEnclosure")

              For Each objSMBIOS in colSMBIOS

              SNStr = objSMBIOS.SerialNumber

              SNShort = RIGHT(SNStr,7)

                             'msgbox snshort

 

              Do While answer <> vbYes

                             Do While Validated = False

                                           Do while SiteCodeMatch < 20

                                                          set SiteCodeFile = objFSO.OpenTextFile("Win10OUMap.csv")

 

                                                          SiteCode = InputBox ("Enter the 4 Character Site Code" & vbCrLf & "I.e. CORP=Corporate, OLME=Mesa, INDY=Indianapolis etc..", "Prompt for Site Code:",,0,0)

                                                          SiteCode = UCase(SiteCode)

                                                          'msgbox SiteCode

                                                                        Do while NOT SiteCodeFile.AtEndOfStream

                                                                                      arrStrSiteCode = split(sitecodefile.ReadLine,";")

                                                                                       strSiteCode = arrStrSiteCode(3)

                                                                                      IF SiteCode = strSiteCode Then

                                                                                      'msgbox "EQUALS " & strSiteCode & " " & SiteCode

                                                                                      'msgbox "I Match"

                                                                                      SiteCodeMatch = 20

                                                                                      Exit Do

                                                                                      Else

                                                                                      'msgbox "Not Equal " & strSiteCode & " " & SiteCode

                                                                                      'msgbox "I dont match"

                                                                                      End IF

                                                                        loop

                                                                        SiteCodeFile.Close

                                                                        IF SiteCodeMatch < 20 Then

                                                                        MsgBox  "Invalid Site Code!  Site Codes are defined as a 4 Character Location, I.e. CORP=Corporate, OLME=Mesa OpenLane, INDY=Indianapolis, BOST=Boston, OLTO=Toronto Openlane etc.. If you do not know your site code please contact the ServiceDesk.", 69680

                                                                        Else

                                                                        End IF

                                           Loop

 

                                           'wscript.echo SiteCode

                                           'wscript.echo SiteCodeMatch

 

                                           Do while RoleCodeMatch < 20

                                                          set RoleCodeFile = objFSO.OpenTextFile("Win10OUMap.csv")

 

                                                          RoleCode = InputBox ("Enter the Single Character function role of the Computer," & vbCrLf & "i.e. W=Workstation L=Laptop K=Kiosk, B=Block, D=Digital Arb etc...", "Enter the Computer Role for " & sitecode & ":",,0,0)

                                                          RoleCode = UCase(RoleCode)

                                                          'msgbox RoleCode

                                                                        Do while NOT RoleCodeFile.AtEndOfStream

                                                                                      arrStrRoleCode = split(RoleCodefile.ReadLine,";")

                                                                                      strRoleCode = arrStrRoleCode(4)

                                                                                      IF RoleCode = strRoleCode Then

                                                                                      'msgbox "EQUALS " & strRoleCode & " " & RoleCode

                                                                                      'msgbox "I Match"

                                                                                      RoleCodeMatch = 20

                                                                                      Exit Do

                                                                                      Else

                                                                                      'msgbox "Not Equal " & strRoleCode & " " & RoleCode

                                                                                      'msgbox "I dont match"

                                                                                      End IF

                                                                        loop

                                                                        RoleCodeFile.Close

                                                                        IF RoleCodeMatch < 20 Then

                                                                        MsgBox  "Invalid Role Code!  Roles are Defined as a single character for the function of the Computer i.e. W=Workstation L=Laptop, K=Kiosk, B=Block, D=Digital Arb etc.. If you do not know the Function codes for site " & SiteCode & " please contact the ServiceDesk.", 69680

                                                                        Else

                                                                        End IF

                                           Loop

 

                                           'wscript.echo RoleCode

                                           'wscript.echo RoleCodeMatch

                                           PCName = SiteCode & "-" & RoleCode & "-" & SNShort

                                           set PCNameFile = objFSO.OpenTextFile("Win10OUMap.csv")

                                           Do while NOT PCNameFile.AtEndOfStream

                                                          arrStrPCName = split(PCNamefile.ReadLine,";")

                                                          strPCName = arrStrPCName(0)

                                                          IF inStr(PCName , strPCName) Then

                                                          'msgbox "EQUALS " & strPCName & " " & PCName

                                                          'msgbox "I Match"

                                                          PCNameMatch = 20

                             '                            Exit Do

                                                          Else

                                                          'msgbox "Not Equal " & strPCName & " " & PCName

                                                          'msgbox "I dont match"

                                                          End IF

                                           loop

                                           PCNameFile.Close

                                           IF PCNameMatch < 20 Then

                                           MsgBox  "PC Name is Invalid!  PC Name does not meet the standards in the PC Name to OU Map file.  If you do not know the naming standards for the site " & SiteCode & " please contact the ServiceDesk.", 69680

                                           Validated = False

                                           SiteCodeMatch = 10

                                           RoleCodeMatch = 10

                                           Else

                                           'MsgBox "PCNameValid"

                                           Validated = True

                                           End IF

                            

                             Loop

                                           If PCNameMatch = 20 Then

                                                          answer = MsgBox("Are you sure this correct?" & vbCrLf & PCName, 69668, "Verify Name")

                                                          IF answer = vbNo then

                                                                        SiteCodeMatch = 10

                                                                        RoleCodeMatch = 10

                                                                        Validated = False

                                                          Else

                                                         

                                                          PCNameFinal = PCName

                                                          'msgbox PCNameFinal

                                                          SCCMenv("OSDComputerName") = PCNameFinal

                                                          End If

                                           Else

                                           answer = vbNo

                                           End IF

              loop

              Next

Else

'msgbox "Did not match"

End IF

Friday, July 8, 2016

PowerShell failing in a ConfigMgr 2012 OSD Task Sequence

PowerShell failing in a ConfigMgr 2012 OSD Task Sequence

Problem

We had a PowerShell script trying to be executed from a Command Line task within our OSD Task Sequence.  This was failing with either running the command manually or calling it from within the package within the OSD Task Sequence.  What was odd and troublesome is if I ran the same commands within its own Custom Task Sequence outside of the OSD Task Sequence it would work.  The error that was seen in the smsts.log file was The term XXX is not recognized as the name of a cmdlets, function, script file, or operable program.  Check the spelling of the name, or if a path was included, verify the path is correct and try again.”  This error was found for almost every PowerShell action that the script was performing.

Resolution

I came across a post by Mike Griswold found here that explained part of the issue.  The issue is that when PowerShell is called within an OSD Task Sequence and within the OS (NOT PE) it does not have any modules loaded like default.  What I had to do was from the OS open PowerShell and run my script.  After the script completed I ran Get-Module from within the same PowerShell window.  This step was important as when running Get-Module by default from a fresh PowerShell window it will not give you all the modules the script referenced. After running Get-Module from within the same PowerShell window after the script ran it gave me the Modules that the script required.  I then modified my PowerShell script that I was using within my SCCM package to include the needed modules.  The specific lines I added to my .PS1 file are listed below.  I added the -verbose so I could see within the SMSTS.log file that the modules were in fact importing correctly.  After this modification everything started working as expected and my sanity returned.

import-module -Name C:\windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Management -verbose

import-module -Name C:\windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Security -verbose

import-module -Name C:\windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Utility -verbose

Tuesday, April 19, 2016

PowerShell: Disable, Move, Delete AD Computer Objects

PowerShell: Disable, Move, Delete AD Computer Objects

Problem

Stale computer objects being left behind in an Active Directory environment. 

Solution

This PowerShell script will resolve the problem.  It was written to search a specific OU and sub OU’s to find stale records.  Stale records are defined in the script as a computer that has not changed its password in greater than 4 months and has also not logged into the domain in greater than 4 months.  Both are configurable in the script.  It will then disable the computer, move it to a specified OU, and tag the description with the date that it was disabled for future reference.  I will go into detail on usage below.

Download Script

Download

CommandLine Options

This script must be called from the PowerShell shell.  It has 4 switches to enable different portions of the script.  By default, I have turned on –WhatIF on any actions that may cause issue in an environment.  –Force turns off –WhatIF on those commands as shown below   

-MoveAlreadyDisabled will MOVE already Disabled computers in a specified source OU ($DisableSourceOU) to a specified target OU ($DisableTargetOU).

-DisableAndMove will MOVE and DISABLE Enabled Computers in a specified source OU ($DisableSourceOU) to a specified target OU ($DisableTargetOU) based on criteria.  (Read Notes area)

-DeleteDisabled will DELETE already Disabled computers based on criteria and OU. ($DisableTargetOU) (Read Notes area)

-Force Will Turn Off -WhatIF where -WhatIF is defined (-WhatIF:$True is on by Default)

 

As each section is turned on they will create output files in C:\Scripts

 

Parts of the Script to Modify

$DisableSourceOU – This is the OU you want the script to Scan and look for stale records

$DisableTargetOU – This is the OU you want the script to place the stale OU

Change the (-x) after AddMonths to your desired time from current date (-4 goes in the past 4 months if you want to go in the future remove the - sign . 

1.       $DisableComputers = get-adcomputer -properties * -filter {enabled -eq "True"} -SearchBase $DisableSourceOU -SearchScope Subtree | where {($_.lastLogonDate -lt (get-date).AddMonths(-4)) -and ($_.passwordlastset -lt (get-date).AddMonths(-4)) }

2.       $DeleteComputers = get-adcomputer -properties * -filter {enabled -eq "False"} -searchbase $DisableTargetOU -SearchScope Subtree  | where { $_.Modified -lt (get-date).AddMonths(-1) }