Wednesday, June 14, 2017

ConfigMgr Current Branch Custom Task Sequence Variable for Computer Role

Reactions: 

ConfigMgr Current Branch Custom Task Sequence Variable for Computer Role

Problem

I needed a way to identify the type or role a machine was going to be within the PE portion of an OSD sequence.  The initial thought was to read the computer name with wmi and use the like variable to control different actions within the task sequence.  This would have worked but I needed to get this information within Windows PE and the computer name would typically be MININT-xxxxxx.  You could call the task sequence variable _SMSTSMachineName or OSDComputerName but a task sequence variable can only be equal or not equal.  The like variable is not allowed on any task sequence variable.

Resolution

I created a PowerShell script that will create a custom OSD Task Sequence Variable called OSDComputerRole.  This script is set to run after the computer naming script that I created in a previous post found here.  You can download the previous posts scripts and files from here.  This new script is set to run after the OSDComputerName variable is set.  The new script also uses the same csv file that the naming script utilized which is explained in the previous post.  The OSDComputerRole allows for the computer role to be read from the csv file and then you can call the task sequence variable as a condition to the task sequence step.  I hope this helps someone else in their search to do something similar.  The code to the PowerShell script is below and can be downloaded from here.

$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment

 

$ComputerName = $tsenv.Value('OSDComputerName')

$csv = Import-Csv .\Win10OUMap.csv -delimiter ';'

    foreach ($line in $csv) { 

        IF ($computername -Match $line.NAME){

            $tsenv.Value('OSDComputerRole') = $line.Role

                                           Exit

            }

        Else {

            $tsenv.Value('OSDComputerRole') = 'Unknown'

            }

    }

 

 

Tuesday, July 19, 2016

ConfigMgr 2012 Name Computer During OSD Task Sequence

Reactions: 

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

Reactions: 

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

Reactions: 

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) }

 

Friday, September 18, 2015

Windows 10: Fully Remove Universal Apps for All Users

Reactions: 

Windows 10: Fully Remove Default Universal Apps

Purpose

To help others in fully removing the default universal apps for use of deployment in a corporate image.

Table of Contents

Purpose. 1

Scope. 1

Procedure. 1

Remove Universal Apps. 1

Deployment 1

 

Scope

Fully remove Universal Apps from system in order to have a clean image for deployment

Procedure

Remove Universal Apps

1.       Copy the following script and save it as a .ps1 file (This script leaves the store intact for NEW user profiles.)

 

 

 

$modernApps = @(@("Microsoft.3DBuilder","microsoft.windowscommunicationsapps","Microsoft.BingFinance","Microsoft.BingNews","Microsoft.BingSports","Microsoft.BingWeather","Microsoft.BingTravel","Microsoft.BingHealthAndFitness","Microsoft.BingFoodAndDrink","Microsoft.People","Microsoft.WindowsPhone","Microsoft.MicrosoftSolitaireCollection","Microsoft.WindowsSoundRecorder","Microsoft.XboxApp","Microsoft.WindowsCamera","Microsoft.ZuneMusic","Microsoft.ZuneVideo","Microsoft.Office.OneNote","Microsoft.SkypeApp","Microsoft.MicrosoftOfficeHub"

 

foreach ($modernApp in $modernApps) {

 

    Get-AppxProvisionedPackage -Online | Where-Object {$_.PackageName -match $modernApp} | Remove-AppxProvisionedPackage -Online

 

}

 

Get-AppxPackage -AllUsers | Remove-AppxPackage

 

a.       You can obviously remove some of the apps listed at the top of the script to leave them on the machine like Microsoft.BingWeather if you want to leave Weather intact

2.       Run the following command from Powershell as an Administrator

a.       powershell.exe -ExecutionPolicy Bypass -file ".\SomeFile.ps1"

                                                               i.      “.\SomeFile.ps1” is the name of the file you save the script above as

3.       If you need to get into the store after the script is run you may need to delete your profile and let it recreate.  All of the default apps will still be removed but Store will return.

Deployment

1.       You can deploy this by creating a script and run it during a task sequcne step within MDT or ConfigMgr or Caputre a new .WIM for deployment as part of your base image

Sources

http://pastebin.com/QuDajKAy

 

Windows 10: Customize and Deploy Start Menu

Reactions: 

Windows 10: Customize Default Start Menu

Purpose

To help others in creating a default start menu layout that can then be deployed via imaging solution.

Table of Contents

Purpose. 1

Scope. 1

Procedure. 1

Create Start Menu Modifications. 1

Export Start Menu Layout 1

Apply Start Menu Layout 1

There are two options to apply the change. 1

Option 1 (Microsoft Articles) 1

Option 2. 2

Deployment 2

 

Scope

Customize Start Menu for deployment

Procedure

Create Start Menu Modifications      

1.       Update Grouping Lables, Pinning or UnPinning applications, and reorder any Pinned applications to create your custom start menu.

Export Start Menu Layout

1.       Once your modifications are complete open powershell

2.       From Powershell run

a.       Export-StartLayout –path <path you have access to>\CustomLayout.xml

                                                               i.      ***Ensure the path exists before you start or the export will fail

Apply Start Menu Layout

There are two options to apply the change

Option 1 (Microsoft Articles)

1.       Launch Powershell as Administrator

a.       Run “Import-StartLayout –layoutpath <path you saved the xml>\CustomLayout.xml –MountPath C:\”

b.      All New Profiles created on the system will have the new Start Menu layout and users will still be able to customize it.

Option 2

1.       Rename CustomLayout.xml to LayoutModification.xml and copy to C:\Users\Default\AppData\Local\Microsoft\Windows\Shell

a.       All New Profiles created on the system will have the new Start Menu layout and users will still be able to customize it.

Deployment

1.       You can deploy this by creating a script to copy the xml file or run the import-startlayout command during a task sequcne step within MDT or ConfigMgr or Caputre a new .WIM for deployment as part of your base image.  You could probably also deploy the customization as a group policy preference. 

Tuesday, June 23, 2015

PeopleSoft Journal Import MSXML fix

Reactions: 

PeopleSoft Journal Import MSXML fix

Problem

The Macro distributed by PeopleSoft for Journal Import fails to work on Windows Vista, 7, and 8/8.1.  With Windows 7 and Vista the solution was simple.  Copy the MSXML.dll file from the C:\Windows\System32 folder from a Windows XP machine and place it in the C:\Windows\System32 and/or C:\Windows\SysWOW folder on the Vista/7 machine.  This may have also worked on Windows 8/8.1 x86 but it does not work on Windows 8/8.1 x64.  For 8/8.1 there are a few modifications to the JRNLMCRO.xla file that are needed. (this was done for Windows 8/8.1 running Excel 2013)

Solution

You have to modify the JRNLMCRO.xla file to include the Microsoft XML v6.0 dll and also modify two lines within the macro code.

Prerequisites

1.       Temporarily Trust Macros in Excel

2.       Ensure the Developer Tab is enabled in Excel

a.       File -> Options -> Customize Ribbon -> (Check) Developer Tab

Process

Open JRNLMCRO.xla

1.       Click Developer Tab

a.       Click Visual Basic

                                                               i.      Highlight Jrnlmcro from the Tree view

                                                             ii.      Click Tools Menu

1.       Click References

a.       Find and check Microsoft XML, v6.0 from the Available References list

b.      Click OK

                                                           iii.      Expand Modules from the Tree view

                                                           iv.      Double Click mImportControl

1.       Within the Code window for mImportControl search for MSXML2.DOMDocument

2.       Replace the two instances of MSXML2.DOMDocument with MSXML2.DOMDocument60

                                                             v.      Save the macro, exit Excel and try to run your Journal Import normally.