Copy Reg Keys from HKCU to HKLM

email me

I wrote this script to copy registry keys from a current user registry hive to the local machine registry hive. I was using this with desktop management software.

ON ERROR RESUME NEXT

CONST HKEY_CURRENT_USER   = &H80000001  
CONST HKEY_LOCAL_MACHINE  = &H80000002
CONST REG_SZ = 1
CONST REG_DWORD = 4
  
'USE LOCAL COMPUTER NAME
strComputer = "."
SET StdOut = WScript.StdOut  
  
'CONNECT TO REGISTRY
SET objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")  
  
'REG KEY IMPORT FROM HKCU TO HKLM
strKeySource = "SOFTWARE\MYINFO"''''FROM THE CURRENT USER HIVE
strKeyDestination = "SOFTWARE\MYINFO"''''TO THE LOCAL MACHINE HIVE
  
'CREATE THE DESTINATION KEY  
objRegistry.CreateKey HKEY_LOCAL_MACHINE,strKeyDestination
  
'ENUMERATE KEYS FROM CURRENT USER AND THEN APPLY VALUES TO HKLM
objRegistry.EnumValues HKEY_CURRENT_USER, strKeySource, arrValueNames, arrValueTypes
FOR i = LBound(arrValueNames) To UBound(arrValueNames)  
         objRegistry.GetStringValue HKEY_CURRENT_USER,strKeyDestination,arrValueNames(i),value
	 objRegistry.SetStringValue HKEY_LOCAL_MACHINE,strKeyDestination,arrValueNames(i),value
NEXT

WScript.Quit(0)

Write AD FIM Properties to Reg Keys; IP Range File.

email me

I created this to write Active Directory user properties to the registry, which would then been queried by desktop management software for reporting purposes.

This does have built-in site detection, so you may or may not need that. For me, I needed to determine a user’s site using a range of IP’s from a text file, as well as query FIM data from AD.

ON ERROR RESUME NEXT

CONST ForReading = 1

DIM Line_Input, StartIP_Input, EndIP_in, StartIP, PerfServIP, PrefServName, IPRange, OctetIncrement 
DIM  OctetCompare, IP_Address, objFSO, objFile, objOutput, workingData, IsMatchFound, ws, SiteName
DIM RegCommand1, RegCommand2, RegCommand3, RegCommand4, RegCommand5, RegCommand6
DIM RegCommand7, RegCommand8, RegCommand9

SET objShell = CreateObject("Wscript.Shell")

'SETS CURRENT DIRECTORY TO VARIABLE
strCurrentDirectory = objShell.CurrentDirectory

IsMatchFound = 0'set to False by default

SET objFSO = createobject("Scripting.FileSystemObject") 
'List containing IP ranges and site names
'example from text file: 11.80.00.1,11.80.40.254,11.80.40.60,MyFileServerName,Florida.
SET objFile = objFSO.openTextFile(strCurrentDirectory & "\AllSiteList.txt", ForReading) 
'used for testing
'example of output: Texas
SET objOutput = objFSO.CreateTextFile(strCurrentDirectory & "\site.txt")
workingData = ""

'RETURN IP ADDRESS USING A FUNCTION
IP_Address = ReturnIPAddress()

'RETURN SITE LOCATION
DO UNTIL objFile.atEndOfStream 
'READ LINE FROM FILE
workingData = objFile.readLine & vbCrLf

'SPLIT THE LINE INTO AN ARRAY
Line_Input = Split(workingData, ",")

'SPLIT THE STARTING IP INTO IT'S BASE OCTETS
StartIP_Input = Split(Line_Input(0), ".")

'SPLIT THE ENDING IP RANGE INTO IT'S BASE OCTETS
EndIP_in = Split(Line_Input(1), ".")

'USES THE STARTIP STRING AS THE FIRST OF TWO COMPARISONS TO FIND A MATCHING IP WITHIN THE RANGE
StartIP = StartIP_Input(0) & "." & StartIP_Input(1) & "." & StartIP_Input(2)

'PLACES SITE INFORMATION INTO VARIABLE
SiteName = LINE_INPUT(4)''''add the site location name

'CALCULATE THE NUMBER OF IP SUBNETS WE NEED TO INCREMENT THROUGH TO CHECK THE RANGE
IPRange = CINT(EndIP_in(2)) - CINT(StartIP_Input(2))

'INITIALIZE THE INCREMENT
OctetIncrement = CINT(StartIP_Input(2))

'COMPARE IP OCTETS WITH IP RANGES (YOU COULD ADD GATEWAYS AS WELL)
FOR i = 0 TO IPRange
IF InStr(IP_Address, StartIP) > 0 THEN
OctetCompare = Split(IP_Address, ".")
IF CINT(OctetCompare(2)) = OctetIncrement THEN
IsMatchFound = 1'found match 
'objOutput.Write SiteName'writes to file
'msgbox SiteName'displays in message box
RegCommand1 = "reg add hkcu\MYINFO /v SiteLocation /t REG_SZ /d " & SiteName & " /f /reg:64"
objOutput.Close
OctetIncrement = IPRange
i = IPRange
EXIT DO
END IF
END IF
'if not found, increment until found
OctetIncrement = OctetIncrement + 1
StartIP = StartIP_Input(0) & "." & StartIP_Input(1) & "." & CSTR(OctetIncrement) 
NEXT


LOOP 
objFile.Close


DIM objSysInfo,objUser,objShell,strUser
SET objSysInfo = CreateObject("ADSystemInfo")

'RETURN CURRENT USER
strUser = objSysInfo.UserName

'CREATE AD USER OBJECT
SET objUser = GetObject("LDAP://" & strUser)

'IMPORT PROPERTIES INTO REG KEYS
'Location
objShell.Run RegCommand1,0,true'applies reg key

'Display Name
RegCommand2 = "reg add hkcu\MYINFO /v DisplayName /t REG_SZ /d " & chr(34) & objUser.displayName & chr(34) & " /f /reg:64"
objShell.Run RegCommand2,0,true'applies reg key

'SAM Account Name 
RegCommand3 = "reg add hkcu\MYINFO /v AccountName /t REG_SZ /d " & chr(34) & objUser.sAMAccountName & chr(34) & " /f /reg:64"
objShell.Run RegCommand3,0,true'applies reg key

'Business Unit
RegCommand4 = "reg add hkcu\MYINFO /v BusinessUnit /t REG_SZ /d " & objUser.fimwpoBusinessUnit & " /f /reg:64"
objShell.Run RegCommand4,0,true'applies reg key

'Business Unit Description
RegCommand5 = "reg add hkcu\MYINFO /v BusinessUnitDescription /t REG_SZ /d " & chr(34) & objUser.fimwpoBusinessUnitDescription & chr(34) & " /f /reg:64"
objShell.Run RegCommand5,0,true'applies reg key

'Business Title
RegCommand6 = "reg add hkcu\MYINFO /v BusinessTitle /t REG_SZ /d " & chr(34) & objUser.fimwpoBusinessTitle & chr(34) & " /f /reg:64"
objShell.Run RegCommand6,0,true'applies reg key

'User email address
RegCommand7 = "reg add hkcu\MYINFO /v EmailAddress /t REG_SZ /d " & chr(34) & objUser.mail & chr(34) & " /f /reg:64"
objShell.Run RegCommand7,0,true'applies reg key

'Employee ID
RegCommand8 = "reg add hkcu\MYINFO /v EmployeeID /t REG_SZ /d " & chr(34) & objUser.employeeID & chr(34) & " /f /reg:64"
objShell.Run RegCommand8,0,true'applies reg key

'Department
RegCommand9 = "reg add hkcu\MYINFO /v Department /t REG_SZ /d " & chr(34) & objUser.department & chr(34) & " /f /reg:64"
objShell.Run RegCommand9,0,true'applies reg key


'IP FUNCTION - WILL RETURN CURRENT IP ADDRESS
FUNCTION ReturnIPAddress()
DIM ws : SET ws = CreateObject("WScript.Shell")
DIM fso : SET fso = CreateObject("Scripting.FileSystemObject")
DIM tempFile : tempFile = fso.GetSpecialFolder(2) & "/ip.txt"
DIM LineFromOutput, IP
IF ws.Environment("SYSTEM")("OS") = "" Then
ws.run "winipcfg /batch " & tempFile, 0, True
ELSE
ws.run "%comspec% /c ipconfig > " & tempFile, 0, True
END IF
WITH fso.GetFile(tempFile).OpenAsTextStream
DO WHILE NOT .AtEndOfStream
LineFromOutput = .ReadLine
IF InStr(LineFromOutput, "Address") <> 0 Then IP = Mid(LineFromOutput, InStr(LineFromOutput, ":") + 2)
Loop
.Close
End WITH
IF IP <> "" Then
IF Asc(Right(IP, 1)) = 13 Then IP = Left(IP, Len(IP) - 1)
END IF
ReturnIPAddress = IP
fso.GetFile(tempFile).Delete 
SET fso = Nothing
SET ws = Nothing
End Function

Could be used for LANDesk, SCCM, or other desktop management software to read the stored values in the registry.

Elevated Custom MDT Task Sequence

email me

This is an interesting way to launch a MDT process in an elevated manner. First, I did try using the built-in credentials option in the task sequence; that did not work for the particular thing I was trying to achieve.

What I wanted to do is have a client machine write back to the Active Directory computer description field (just some dynamic text). Note, the script I created did work on the client when manually executed using a MDT service account….but would not work correctly through the task sequence itself. Thus, to get around this problem, I employed the use of cpau (an elevation program) in the task sequence itself. See screenshot. Once I did that, the task sequence launched my script correctly and wrote back to the computer object description field.

Notes

A custom coded elevation tool could also be used. CPAU.exe is slowly losing functionality.

Common Data Types

email me

This is a C# console app I created in Visual Studio to demonstrate some common data types.

using System;

namespace TypeConversionApplication

{
class StringConversion
{
static void Main(string[] args)
{
int i = 75;
float f = 53.005f;
double d = 2345.7652;
bool b = true;
Console.WriteLine("int: " + i.ToString());
Console.WriteLine("float: " + f.ToString());
Console.WriteLine("double: " + d.ToString());
Console.WriteLine("boolean: " + b.ToString());
Console.ReadKey();
}
}
}

 

Data Types

int : An integer(eg, 3).
Can be a whole number between -2147483648 and 2147483647

float : A fractional(floating point) number(eg, 3.25907).
Can be a number between roughly 1.5 x 10^45 to 3.4 10^38, in floating point format.

String : A sequence of characters(eg, “Hello User 6555”)
(no specified maximum length)

boolean : A true/false value.
Can only contain either the value true or false.

 

Others

Data Type Range
byte 0 .. 255
sbyte -128 .. 127
short -32,768 .. 32,767
ushort 0 .. 65,535
int -2,147,483,648 .. 2,147,483,647
uint 0 .. 4,294,967,295
long -9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807
ulong 0 .. 18,446,744,073,709,551,615
float -3.402823e38 .. 3.402823e38
double -1.79769313486232e308 .. 1.79769313486232e308
decimal -79228162514264337593543950335 .. 79228162514264337593543950335
char A Unicode character.
string A string of Unicode characters.
bool True or False.
object An object.

 

Reference

http://www.tutorialspoint.com/csharp/csharp_data_types.htm

VBScript – Return AD Properties

email me

This is a script I put together that returns some specific user account properties from Active Directory.

Option Explicit

DIM objSysInfo,objUser,objShell,strUser

SET objSysInfo = CreateObject("ADSystemInfo")
SET objShell = CreateObject( "WScript.Shell" )

'RETURN CURRENT USER
strUser = objSysInfo.UserName

'CREATE AD USER OBJECT
SET objUser = GetObject("LDAP://" & strUser)

'TEST OUTPUT
msgbox objUser.displayName
msgbox objUser.sAMAccountName
msgbox objUser.fimwpoBusinessUnit
msgbox objUser.fimwpoBusinessUnitDescription
msgbox objUser.fimwpoBusinessTitle
msgbox objUser.mail
msgbox objUser.employeeID

'COULD WRITE TO REGISTRY HERE
'TO BE ADDED

'COULD WRITE DIRECTLY TO LD DB HERE
'TO BE ADDED

WScript.Quit(0)

MDT – Windows 10 Enable BitLocker

email me

Configure the Windows 10 task sequence to enable BitLocker

When configuring a task sequence to run any BitLocker tool, either directly or using a custom script, it is helpful if you also add some logic to detect whether the BIOS is already configured on the machine. In this task sequence, we are using a sample script (ZTICheckforTPM.wsf). In the following task sequence, there are five actions (pay attention to step 2):

(1) Check TPM Status. Runs the ZTICheckforTPM.wsf script to determine if TPM is enabled. Depending on the status, the script will set the TPMEnabled and TPMActivated properties to either true or false.

(2) Configure BIOS for TPM. Runs the vendor tools (in this case, HP, Dell, and Lenovo). To ensure this action is run only when necessary, add a condition so the action is run only when the TPM chip is not already activated. Use the properties from the ZTICheckforTPM.wsf.

Note

  • It is common for organizations wrapping these tools in scripts to get additional logging and error handling.

(3) Restart computer. Reboots the computer.

(4) Check TPM Status. Runs the ZTICheckforTPM.wsf script again.

(5) Enable BitLocker. Activates BitLocker.

 

So, what happens if this fails to work?

First, verify all aspects of the server setup are correct: Bitlocker How to Deploy Bitlocker  2  3  MDT.

Test again. If that still fails, you can create your own scripts to do the Bitlocker setup and management.

In the task sequence,

Add your own TPM enabler script

(1) May contain vendor specific tools to set BIOS PW (“C:\SetPW.exe” /npwdfile:”C:\password.bin”)

(2) Contains the Microsoft script to enable the TPM (“C:\enablebitlocker.vbs” /on:tpm /l:c:\bitlocker.log). Add Microsoft script into script folder on your MDT server. Add into task sequence as a Run Command.


Add a restart
Select a Restart from the task sequence options


Add your own Bitlocker enabler script

(1) C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “Initialize-Tpm -AllowClear -AllowPhysicalPresence”

(2)  C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “Initialize-Tpm”

(3) C:\windows\system32\manage-bde -protectors -add C: -tpm

(4) C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “Enable-BitLocker -MountPoint “C:” -EncryptionMethod Aes256 -UsedSpaceOnly -RecoveryPasswordProtector”

If you want to import Bitlocker recovery info into AD,
(1) for /f “skip=4 tokens=2 delims=:” %%g in (‘”C:\Windows\System32\manage-bde.exe -protectors -get c:”‘) do set MyVar=%%g

(2) C:\Windows\System32\manage-bde.exe -protectors -adbackup c: -id%MyVar%

Windows 10 Computer Description

email me

A great field to store image version, release date, or other information is in the computer description.

To edit this field through the registry, or through scripting, use the following reg key.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\LanmanServer\Parameters]
“srvcomment”=”Image Version 4.2”

 

Screenshot

MDT Error Codes

email me

Here is a list of the ‘common’ MDT error codes.

Exit code Meaning Value in log file
0 Success 0x0
1 Bad command line 0xA001
2 User is not an administrator 0xA002
3 The OS is not supported for this product 0xA003
5 No devices were found that matched package INF files 0xA005
7 User refused a driver downgrade 0xA007
9 User canceled the installation 0xA009
10 Another install is already active 0xA00A
11 Error while extracting files 0xA00B
12 Nothing to do 0xA00C
13 A system restart is needed before setup can continue 0xA00D
14 Setup has completed successfully but a system restart is required 0xA00E
15 Setup has completed successfully and a system restart has been initiated 0xA00F
16 Bad installation path 0xA010
17 Error while installing driver 0xA011
255 General install failure Win32 error code

 

MDT Suppress Error Codes

email me

When installing an application using MDT, you have the ability to suppress specific error codes. For example, let’s say you don’t want to see the failed error code 3010, which is a forced reboot code, you can just add 3010 to the task sequence and it would be filtered. But, in some instances, the error may not be known, or is always changing. In this case, you want to suppress ‘all’ error codes for that specific application.

To do that, follow these steps

(1) Open your Task Sequence
(2) Click on Task Sequence Tab
(3) Locate the specific application task and select it.
(4) Add 1 to the Success codes (suppress errors). The value of 0 is usually there; 0 1 (or, -1).
(5) Run through the imaging process again, testing this mod.

Snapshot