Novell Home

Automated ZEN Imaging: The Next Step

Novell Cool Solutions: Trench
By Jim Shank

Digg This - Slashdot This

Posted: 3 Apr 2003
 

Here's an exceptionally detailed explanation of how to deploy Windows 2000 to workstations and get them up and running on the desktops of the employees in a hurry. Jim Shank takes you through the entire process he developed at his company, and along the way offers excellent insight into how to use many different tools and bits of information to create a unique solution. (Which is, after all, our our whole raison d'etre here at Cool Solutions.) Thanks, Jim!

Update: We've added all the files Jim shared in this solution to a zip file for your convenience, so the line breaks on this page don't drive you mad. See the Files section.

Introduction

Like many of you, I work for a medium-size organization using ZENworks imaging in order to deploy stock workstations to our employees. I wanted to be able to deploy a Windows 2000 PC with Novell Client to the desktop without needing to revisit it for any additional configuration. In fact, if it weren't for the need to set the PC to boot from the NIC and put the asset tag in BIOS, I could have the systems shipped directly to the location. The goal was to create an image that when deployed would have the following abilities:

  • Automatically join the local domain
  • Automatically name itself (something identifiable)
  • Support changes within the post image scripting without requiring a re-image
  • Update ZIS and create a workstation object

I started this process reviewing the excellent article Getting ZEN Imaging to work with SYSPREP by Michael J. Prentice. I used his steps to begin the process but along the way, realized that batch scripting, without enhancements, was not going to get me far enough. I needed a scripting platform with maximum flexibility with minimum additional software installation. After reviewing KiXtart, Perl for Windows and VBScript, I settled on VBScript as my automation language of choice. The main benefit being that it runs natively without any additional software installs and gives quick and dirty access to the file system and registry. Without further introduction, let's look at the imaging process outline (that's your cue to print this out, get a drink and come back. Then use the printout of the files to compare to the process outlined next):

Imaging Process

  1. The workstation is received; first thing we do is place an asset tag on the system and boot to BIOS. Set the boot order to NIC 1st and then enter the asset tag in the BIOS in the System ID's section (we use Compaq Evo slim lines). The PC is then warehoused or immediately deployed to the employee's desktop.
  2. Once deployed, the PC is booted for the first time. ZENworks policies determine that the box doesn't have a workstation object and therefore, begins the imaging process.
  3. The image is received and the machine automatically reboots.
  4. Sysprep runs in fully automatic configuration mode.
    1. Sysprep checks for different hardware than the base image and locates the drivers in the OemPNPDriversPath and adds any new hardware to the system.
    2. Sysprep licenses the product.
    3. Sysprep does basic network configuration including activating DHCP and joining the Imaging Workgroup (we will join the domain later).
    4. Sysprep names the machine AURORA-xxxxxxx where xxxxxxx is a randomly generated string by Sysprep. The aurora comes from the first word in the OrgName title in sysprep.inf.
    5. Sysprep sets up Autologin so we can do fully automated post imaging scripting.
    6. Sysprep sets the runonce key to run 1strun.vbs on the first full boot (after Sysprep).
  5. The machine reboots and performs 1strun.vbs.
    1. 1strun.vbs logs to the event log that the post imaging scripting has started.
    2. 1strun.vbs logs to the event log that 1strun.vbs has started.
    3. 1strun.vbs puts ziswin.exe back into the registry so that it will run on the next boot, it is removed directly prior to imaging the system so that it doesn't interfere with Sysprep.
    4. 1strun.vbs removes the desktop update component so that we can update the desktop information stamp at will instead of on each run (this will be covered in a future article).
    5. 1strun.vbs sets the runonce key to run 2ndrun.vbs on the next boot.
    6. 1strun.vbs removes the desktop to show that we are in an automated imaging environment, this also acts as a failsafe should imaging fail, it would be extremely obvious when the desktop is missing.
    7. 1strun.vbs checks for the existence of c:\sysinfo\debug.txt, I can include this file in the image if I want to pause for debugging. Nice if you want to see what has happened and adjust the timing of events during testing.
    8. 1strun.vbs logs to the event log that 1strun.vbs has completed.
    9. 1strun.vbs uses ncshtdwn to reboot the system (more info on ncshtdwn later).
  6. The machine reboots and performs 2ndrun.vbs.
    1. 2ndrun.vbs logs to the event log that 2ndrun.vbs has started.
    2. 2ndrun.vbs clears out the current domain name so that there is no error on reboot (from Michael J. Prentice's article).
    3. 2ndrun.vbs determines the current name of the machine by reading from registry.
    4. 2ndrun.vbs uses some logic to determine if the machine has had its name corrected or not. In Sysprep, we use the auto naming system which allows Sysprep to generate a random name with a fixed prefix. By testing for this prefix, we are able to determine if the machine has been named or not. Most of this logic is designed so that this scripting can be run if a machine has recovered its information from ZIS. A feature that I haven't gotten working yet.
    5. 2ndrun.vbs reads in from WMI which is the interface for accessing BIOS information from the OS, this is some of the real magic.
    6. 2ndrun.vbs then checks the asset tag to verify it has been properly entered and formatted correctly. If not, we preset the (hopefully) desktop tech with the ability to manually correct the name and then fix it in BIOS and log the event to the event log. If it is named correctly we use ENGL Zcnc Lite to:
      1. Name the machine from the BIOS asset tag.
      2. Remove the ZENwsimport record from the hosts file (more on this later).
      3. Force the change and do it without prompting.
    7. 2ndrun.vbs sets the runonce key to run 3rdrun.vbs on the next boot.
    8. 2ndrun.vbs checks for the existence of c:\sysinfo\debug.txt, once again, for debugging purposes and pauses if found.
    9. 2ndrun.vbs logs to the event log that 2ndrun.vbs has completed.
    10. 2ndrun.vbs uses ncshtdwn to reboot the system.
  7. The machine reboots and performs 3rdrun.vbs. This is the meat of the post imaging process and as such, I decided to throw in a control that allows me to put up a progress bar and message. This utility is a hack for VBScript that allows you to show dialog boxes while your script runs, it's not necessary but provides that ?wow? factor many of us thrive on. As it is not necessary, I will not comment on it directly, you may use the in-line commenting included with the files and determine if you want it in your scripts.
  8. 3rdrun.vbs uses netdom to join the domain; this utility is included in the Windows 2000 support tools. Netdom was updated in SP3 and can be found here.
  9. 3rdrun.vbs uses the return code generated by netdom to determine if we were successful or not, if so, we log to the event log that we successfully joined the domain. As an added benefit, I have found that if you use netdom to rejoin a domain it will not create the dreaded trust relationship broken error that is often a result of joining a domain in which the workstation is already listed. If there was an error, 3rdrun.vbs will log the error code to the event log and then preset us with a dialog requesting that we join the domain manually and then click ok on our message box.
  10. 3rdrun.vbs will check once again to see if we are in debug mode and, if so, tell us what the result code was of running netdom.
  11. 3rdrun.vbs then implements a fix for the auto admin logon process (from Michael J. Prentice's article).
  12. 3rdrun.vbs locks down the c:\winnt\zmg directory so that only administrators can read it. Since we have stored the password in plain text to join the domain, we don't want users snooping around in this directory (from Michael J. Prentice's's article).
  13. 3rdrun.vbs updates the service pack source path in registry. Oddly enough, when Sysprep is run, the path to where the slipstreamed service pack files are stored is reset to the CDROM drive. This can be repaired by updating the registry value.
  14. 3rdrun.vbs runs another script, locationprofiletz.vbs. This script is responsible for managing location specific information on the system. It is based on determining the users IP address and then comparing it to an array to find out what location it is in. It then updates the time zone information and applies the correct wallpaper for the location. I have also incorporated some code to remove IPX in our pure IP offices. I will include the entire file later on.
  15. 3rdrun.vbs updates the profiles path in the registry. In a previous attempt to move the profiles directory to the users home drive, I found out that the mapping doesn't happen until after the OS needs access to create the profiles directory. I left this key in so that I could update it should a solution ever be found.
  16. 3rdrun.vbs uses vidchng.exe to set the desktop resolution and depth to our corporate standard. I found this jewel on appdeploy.com, written by Tony Pombo. It can be found here.
  17. 3rdrun.vbs updates the desktop information stamp (a future article).
  18. 3rdrun.vbs puts the desktop information stamp utility back in startup.
  19. 3rdrun.vbs re-enables the desktop so that we have a visual queue that the imaging process completed running all the login scripts.
  20. 3rdrun.vbs checks for the existence of c:\sysinfo\debug.txt, once again, for debugging purposes and pauses if found.
  21. 3rdrun.vbs logs to the event log that 3rdrun.vbs has completed.
  22. 3rdrun.vbs logs to the event log that the post imaging scripting has completed.
  23. 3rdrun.vbs uses ncshtdwn to reboot the system.

If you have made it this far, congratulations, that was the bulk of what happens. Next we will review the preparation work that goes into getting your image ready for this process. You might think it strange to put the prep work after the actual imaging but I thought it would make more sense to see why you need it. Here are the few changes that need to be made before imaging.

Preparation Work

  1. Remove HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\System\ziswin.exe from the registry. Use the ZISWIN switches and functionality article listed in the tools section.
  2. In the hosts file, add ZENwsimport to the line that resolves localhost. This will keep the workstation from creating a workstation object until we are done changing the name. This line is eventually removed by zcnc lite. (e.g. 127.0.0.1 localhost ZENwsimport)
  3. Run Sysprep with the Sysprep.inf options shown below.

Tools and Resources

There are quite a few tools and articles on how to use them that are included in this process. Here is a list of everything you need and where it is from. (Includes articles that I found useful in learning these tools.)

Personal disclaimer

I have tried to give credit to the sources of the code and utilities used within this program. If there is anyone I have missed, please contact me directly and I will gladly add credit or remove the reference to your utility/code upon request. All information contained in this document is expressed by Jim Shank and does not implicitly or explicitly represent official positions and policies of Aurora Loan Services.

This information is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.

Files

NEW: Here are all the files in one zip file, for your convenience.

sysprep.inf file

;SetupMgrTag
[Unattended]
    DriverSigningPolicy=Ignore
    OemSkipEula=Yes
    OemPNPDriversPath=\Compaq\NIC;\Compaq\video;\
	Compaq\WBEM;\Compaq\Audio;\Compaq\eak\drv2k;\
	Compaq\misc1;\Compaq\Misc4;\Compaq\Misc3;\
	Compaq\Misc5;\Compaq\SP21181\SMAXWDM\W2K_XP\;\
	Compaq\O2Micro\Win2K

[GuiUnattended]
    AdminPassword=verysecurepassword
    AutoLogon = Yes
    AutoLogonCount = 3
    OemSkipWelcome=1
    OEMSkipRegional=1
    OEMDuplicatorstring="My  Image 2.0 1/27/03"
    TimeZone=010

[UserData]
    FullName="Aurora User"
    ComputerName=*
    OrgName=Aurora Company
    productid=XXXXX-XXXXX-XXXXX-XXXXX-XXXXX

[TapiLocation]
    CountryCode=1

[RegionalSettings]
    LanguageGroup=1
    Language=00000409

[Identification]
    JoinWorkgroup=Imaging

[Networking]
    InstallDefaultComponents=Yes

[GUIRunOnce]
    Command0="c:\winnt\zmg\1strun.vbs"

[SysprepCleanup]

1strun.vbs

'1strun.vbs
'Written by Jim Shank 1/28/03
Option Explicit
Dim WshShell, oFso
Set WshShell=Wscript.CreateObject("Wscript.shell")
Set oFso = CreateObject("Scripting.FileSystemObject")
WshShell.LogEvent 0, "Post imaging scripting started"
WshShell.LogEvent 0, WScript.ScriptName & " started"
WshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows NT\
CurrentVersion\Winlogon\System","ziswin.exe"
WshShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\
Microsoft\Windows\CurrentVersion\Run\ALSUpdate"
WshShell.RegWrite "HKCU\Software\Microsoft\Windows\
CurrentVersion\Runonce\2run","c:\winnt\zmg\2ndrun.vbs"
WshShell.RegWrite "HKLM\Software\Microsoft\Windows\
CurrentVersion\Policies\Explorer\NoDesktop",1,"REG_DWORD"
if (oFso.FileExists("C:\sysinfo\debug.txt")) then
	WshShell.LogEvent 4, "Entering debug mode scripting"
	msgbox "Pausing for debug"
end if
WshShell.LogEvent 0, WScript.ScriptName & " completed successfully"
WshShell.Run "c:\winnt\zmg\ncshtdwn.exe /7"

2ndrun.vbs

'The purpose of this script is to 
determine if the machine has had ZIS recovered on it 
yet, and if not,
'run zcnc, recover the asset tag from BIOS 
and name the machine. 
Added the rest of 2ndrun.bat so we can 
'internally handle the timing. 
'Written by Jim Shank 1/28/03
Option Explicit
Dim WshShell, current_name, oFso, bios, 
SystemAT,oWMI 
Set WshShell=Wscript.CreateObject
("Wscript.shell")
Set oFso = CreateObject
("Scripting.FileSystemObject")
WshShell.LogEvent 0, 
WScript.ScriptName & " started"
'Clear out the current domain name 
so that there is no error on reboot
WshShell.RegWrite 
"HKLM\SOFTWARE\Microsoft\Windows NT\
CurrentVersion\Winlogon\DefaultDomainName",""
'Find out the current name of 
the machine on the next line
current_name = WshShell.RegRead
("HKLM\SYSTEM\CurrentControlSet\
Control\ComputerName\
ActiveComputerName\ComputerName")
'If the machine hasn't been ZISed, 
it will read Aurora-<random characters>, 
otherwise it will have ALS as the
'beginning of the asset tag.
if left(current_name,3) <> "ALS" then
	' This logic will check 
	before we set the machine name from 
	BIOS that the machine name 
	actually is in BIOS
	Set oWMI = GetObject("winmgmts:")
	For Each bios In oWMI.InstancesOf
	("Win32_SystemEnclosure")
		SystemAT = bios.SMBIOSAssetTag
	Next
	if left(SystemAT,3) <> "ALS" then
		WshShell.LogEvent 1,
		"Malformed BIOS asset tag: 
		" & SystemAT & ". 
		Enabling manual machine name 
		dialog."
		msgbox "This workstation does 
		not have the correctly formed 
		asset tag defined in BIOS, 
		you must manually name this PC. 
		Please call x2600 or 000-555-1212 
		for assistance. If you are with 
		PC Support click OK to continue 
		and rename the PC to the 
		asset tag.",vbOKOnly,"Critical 
		Imaging Error"
		WshShell.Run "c:\winnt\zmg\Zcnc.exe
		 /remZEN /m:cccnnnn",7
	else
		WshShell.Run chr(34) & 
		"c:\winnt\zmg\Zcnc.exe" 
		& chr(34) & " 
		/q /remZEN /forcerun 
		/wmi:" & chr(34) & 
		"Win32_SystemEnclosure,
		SMBIOSAssetTag" & chr(34) 
		& " /sn:" 
		& chr(34) & chr(34),7
		WshShell.LogEvent 0,
		"ZCNC Rename completed"
	end if
end if
WshShell.RegWrite 
"HKCU\Software\Microsoft\Windows\CurrentVersion\
Runonce\3run",
"c:\winnt\zmg\3rdrun.vbs"
if (oFso.FileExists("C:\sysinfo\debug.txt")) then
	msgbox "Pausing for debug"
end if
WshShell.LogEvent 0, 
WScript.ScriptName & " completed successfully"
WshShell.Run "c:\winnt\zmg\ncshtdwn.exe /7"

3rdrun.vbs

' ALS Imaging Script with progress
' Written by Jim Shank
' 1/29/03
Option Explicit
Dim WshShell, i, oFso, returncode
Set WshShell=Wscript.CreateObject("Wscript.shell")
Set oFso = CreateObject("Scripting.FileSystemObject")
Dim oNMD : Call Instantiate(oNMD, 
"wshLtWtNonModalDialog.ucNMD", "oNMD_")  ' as Object

' --- module level variables ---------------------
Dim m_btnStartID  ' as integer
Dim m_btnCancelID  ' as integer
'
Dim bCloseFlag  ' t/f if user closed the form...
Dim bStartClick, bCancelClick  ' as boolean
Dim iSetPoint, pctDone
Dim m_MSTitles(10), m_MSRemark(10)

'
' --- constant declarations ----------------------
Const sDlgCaption = "ALS Post-imaging Scripting"
' --- end of declarations and constants ----------

' ================================================
' === MAIN LINE SCRIPT LOGIC =====================
' ================================================
WshShell.LogEvent 0, WScript.ScriptName & " started"
  ' Create the Form, and add the controls...
  Call Create_Form(sDlgCaption)

  oNMD.AddLine "Beginning post imaging 
  configuration "  ' space
  oNMD.AddLine "Process Initiated"
  oNMD.PctComplete 5  ' advance progbar
  oNMD.AddLine "Joining the domain..."
  ' Joins the domain
  returncode = WshShell.Run 
  ("c:\winnt\zmg\netdom.exe join 
  %computername% /Domain:ALS-TREE /UserD:
  secureaccount 
  /PasswordD:securepassword",7,TRUE)
  if returncode = 0 then 
	WshShell.LogEvent 4, "Netdom successfully 
	joined the domain"
  end if
  if returncode <> 0 then
    WshShell.LogEvent 1, "Netdom was unable to 
	join the domain. 
	Error code was: " & returncode
	wshshell.popup "Unable to join the domain!!! 
	The netdom join command failed. You 
	will need to manually join the domain now. 
	When you are finished, click ok on this box. 
	If you have any 
	questions about this error, please contact 
	the help desk.",,"Critical 
	Imaging Error", 0 + 16
  end if
  if (oFso.FileExists("C:\sysinfo\debug.txt")) then
	msgbox "Netdom return code " & returncode
  end if
  oNMD.AddLine "Updating Auto-Admin Logon..."
  oNMD.PctComplete 40  ' advance progbar
  
  ' ###Implements a fix for the Auto Admin Login count 
  bug and stop the Auto Admin Login.###
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows NT\
  CurrentVersion\Winlogon\AutoAdminLogon","0"
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows NT\
  CurrentVersion\Winlogon\DefaultUserName",""
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows NT\
  CurrentVersion\Winlogon\DefaultPassword",""
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows NT\
  CurrentVersion\Winlogon\DefaultDomainName",""
  oNMD.PctComplete 55

  ' Lockdown the ZMG directory
  oNMD.AddLine "Updating security..."
  WshShell.Run 
  "cmd /c " & chr(34) & "echo y|cacls c:\winnt\
  zmg /t /g BUILTIN\Administrators:F" & chr(34),7
  WshShell.Run 
  "cmd /c " & chr(34) & "echo y|cacls c:\winnt\
  zmg /t /e /g " & chr(34) 
  & "NT Authority" & chr(34) & "\
  System:F" & chr(34) & "&&",7
  oNMD.PctComplete 60

  ' Fix Service Pack Source Path Key
  oNMD.AddLine "Fixing 
  Service Pack Source Path..."
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows\
  CurrentVersion\Setup\SourcePath","c:\"
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows\
  CurrentVersion\Setup\ServicePackSourcePath","c:\"
  oNMD.PctComplete 65

  ' Update Location Profile
  oNMD.AddLine "Updating 
  Location Profile..."
  WshShell.Run "c:\sysinfo\
  locationtzprofile.vbs",7
  oNMD.PctComplete 70

  ' Update Profile Path
  oNMD.AddLine "Updating profile path..."
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\
  Windows NT\CurrentVersion\
  ProfileList\ProfilesDirectory","
%systemdrive%\Documents and Settings",
"REG_EXPAND_SZ"
  oNMD.PctComplete 75

  'Apply Corporate display standards
  oNMD.AddLine "Applying Corporate 
  display standards..."
  WshShell.Run "c:\sysinfo\vidchng 
  -q 1024x768x32@75",7
  oNMD.PctComplete 80

  ' Apply Corporate desktop
  oNMD.AddLine "Applying Corporate 
  desktop..."
  WScript.Sleep 3000
  WshShell.Run "c:\sysinfo\
  CorpDT.vbs",7,TRUE
  oNMD.PctComplete 85
  
  oNMD.AddLine "Re-enabling 
  CorpDT Autorun..."
  WshShell.RegWrite 
  "HKLM\SOFTWARE\Microsoft\Windows\
  CurrentVersion\Run\ALSUpdate",
  "C:\sysinfo\CorpDT.vbs"
  oNMD.PctComplete 90  
  

  oNMD.AddLine 
  "Re-enabling Desktop..."
  WshShell.RegWrite 
  "HKLM\Software\Microsoft\Windows\
  CurrentVersion\Policies\
  Explorer\NoDesktop",0,"REG_DWORD"
  oNMD.PctComplete 95

  oNMD.AddLine "Completed 
  Successfully"
  oNMD.PctComplete 100
  if (oFso.FileExists
  ("C:\sysinfo\debug.txt")) then
	msgbox "Pausing for debug"
  end if
  oNMD.ShowDialog False  
  ' clean up oNMD...
  oNMD.UnloadDialog  
  set oNMD = Nothing
  WshShell.LogEvent 0, 
  WScript.ScriptName & " 
  completed successfully"
  WshShell.LogEvent 0, 
  "Post imaging scripting completed"
  WshShell.Run 
  "c:\winnt\zmg\ncshtdwn.exe /7"
  WScript.Quit  ' 
  end of script



' ================================================
' === SUBROUTINES FOLLOW =========================
' ================================================

' --- this code creates the form and adds the controls ---
Sub Create_Form(sCaption)
Dim wdForm, htForm, wdBtn, htBtn, wdBtnSp  ' as long
Const sLBLabel = "Configuring System"

  ' do some geometry calculations...
  wdForm = 460 : htForm = 320 : 
  wdBtn = 100 : htBtn = 25
  wdBtnSp = Int((wdForm - wdBtn) 
  / 2) - 3

  oNMD.CreateDialog sCaption, 
  80,100, wdForm,htForm
  oNMD.MinMaxBtns = False  ' 
  hide the min/max buttons
        
  oNMD.AddLabel sLBLabel, 
  20,10, 300,20
  oNMD.AddLstBox 20,30, 
  400,170
    
  oNMD.AddProgressBar 40,
  205, 360,20

  oNMD.ShowDialog True

End Sub 


' --- INSTANTIATE ACTX OBJECT (or class) AND CHECK ----
'   (using a sub to get this ugly instantiation code 
out of main line code)...

Sub Instantiate (oObject, sProgramID, 
sEventPrefix)
Const sME = "[sub Instantiate], "
  ' check variant sub-type 
  parameters...
  BugAssert (VarType(sProgramID) = 
  vbString), sME & 
  "sProgramID must be a STRING!"
  BugAssert (VarType(sEventPrefix) = 
  vbString), sME & 
  "sEventPrefix must be a STRING!"
  On Error Resume Next  ' turn on 
  error checking
  Set oObject = WScript.CreateObject
  (sProgramID, sEventPrefix)
    BugAssert (err.number = 0), sME 
	& "This script requires: " 
	& sProgramID & vbCrlf _
        & "     kindly INSTALL and 
		REGISTER this ActX component... "
    On Error goto 0  ' turn off 
	error checking...
End Sub


' --- BUGASSERT (yes, it's for debugging) --------

Sub BugAssert (bTest, sErrMsg)

  ' BugAssert is a Bruce McKinney 
  creation.
  '   It is used to test for 
  intermediate results...
  if  bTest  then  Exit Sub
  MsgBox "Error Detected by 
  BugAssert: " & vbCr & vbCr & sErrMsg, _
    vbCritical, " 
	<< BugAssert FAILED >> "
  WScript.Quit

End Sub

locationprofiletz.vbs

I have edited this file specifically for this document to remove specific information about my company's infrastructure. As such, you should debug this code since I have not tested it since editing it.

' LocationProfileTZ.vbs - Utility to determine the 
IP address and set timezone, desktop logo, removed IPX if in ROC,
' and set Import Server key for SBF.
' Last update 2/25/03 by JShank
Option Explicit
' On Error Resume Next
Dim IP_Address : IP_Address = GetIP() ' Let's get 
the first IP address on the system
Dim filesys,wshShell,bfsrange,alsrange,arr_midip,midip,
compip,desktop,parange,pacifictz,mountaintz,centraltz,
easterntz,pacificoffset,mountainoffset,centraloffset,
easternoffset,comprange,rocrange' Dim all of our variables
Set filesys = CreateObject("Scripting.FileSystemObject") 
Set wshShell = CreateObject("WScript.Shell") 
'We have to define our IP subnets for workstations 
in our locations. Since we only care about the 2nd and 3rd 
'octet, thats all we specify and compare. 
? I have removed the arrays that go here because they would 
represent a security risk to our company's 
network and replaced them with
? ficticious ranges.
parange = Array ("2.10","2.11","2.12")
pacifictz = Array ()
mountaintz = Array ()
centraltz = Array ()
easterntz = Array (parange)
rocrange = Array (parange)
pacificoffset = 480 ' -8 from GMT = 8 hours x 60 minutes = 480
mountainoffset = 420 ' -7 from GMT = 7 hours x 60 minutes = 420
centraloffset = 360 ' -6 from GMT = 6 hours x 60 minutes = 360
easternoffset = 300 ' -5 from GMT = 5 hours x 60 minutes = 300
 
arr_midip = Split(IP_Address, ".") ' Breaking up the IP 
address so we can look at the middle octets
midip = arr_midip(1) & "." & arr_midip(2) ' Recompose 
the 2nd & 3rd octets
'Here is the logic for changing the timezone
For Each comprange in pacifictz
	For Each compip in comprange
		if compip = midip then
			'If they are in the 
			Pacific timezone
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
ActiveTimeBias",pacificoffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\Bias",
			pacificoffset,"REG_DWORD"
			WshShell.RegWrite "HKLM\SYSTEM\
			CurrentControlSet\
			Control\TimeZoneInformation\
			StandardName","Pacific Standard Time"
			WshShell.RegWrite "HKLM\SYSTEM\
			CurrentControlSet\
			Control\TimeZoneInformation\
			DaylightName","
			Pacific Daylight Time"
			WshShell.LogEvent 4,"IP Detected: 
			" & IP_Address & ". 
			Set for Pacific TimeZone"
		end if
	Next
Next

For Each comprange in mountaintz
	For Each compip in comprange
		if compip = midip then
			'If they are in the 
			Mountain timezone
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
ActiveTimeBias",mountainoffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
Bias",mountainoffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
			StandardName",
			"Mountain Standard Time"
			WshShell.RegWrite "HKLM\SYSTEM\
			CurrentControlSet\
			Control\TimeZoneInformation\
			DaylightName",
			"Mountain Daylight Time"
			WshShell.LogEvent 4,"IP Detected:
			 " & IP_Address & ". 
			Set for Mountain TimeZone"
		end if
	Next
Next

For Each comprange in centraltz
	For Each compip in comprange
		if compip = midip then
			'If they are in the Central timezone
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
ActiveTimeBias",centraloffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
			Bias",centraloffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
			StandardName","Central Standard Time"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
			DaylightName","Central Daylight Time"
			WshShell.LogEvent 4,"IP Detected:
			 " & IP_Address & ". 
			Set for Central TimeZone"
		end if
	Next
Next

For Each comprange in easterntz
	For Each compip in comprange
		if compip = midip then
			'If they are in the 
			Eastern timezone
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\Control\
TimeZoneInformation\ActiveTimeBias",easternoffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\Bias",
			easternoffset,"REG_DWORD"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
			StandardName","Eastern Standard Time"
			WshShell.RegWrite 
			"HKLM\SYSTEM\CurrentControlSet\
			Control\TimeZoneInformation\
			DaylightName","Eastern Daylight Time"
			WshShell.LogEvent 4,"IP Detected:
			 " & IP_Address & ". 
			Set for Eastern TimeZone"
		end if
	Next
Next

For Each compip in bfsrange
	if compip = midip then
		'If they are in BFS
		set desktop = filesys.GetFile
		("c:\sysinfo\Desktop.bmp")
		desktop.attributes = 0 
		' Set this to read/write since 
		it can be set to read only on the image
		filesys.CopyFile 
		"C:\sysinfo\BFSDesktop.bmp",desktop,1 
		' Copy the BFS image to desktop.bmp
		wshShell.Run("c:\sysinfo\bginfo.exe 
		/ic:\sysinfo\alsdefault.bgi 
		/timer:0") ' Run BGInfo to stamp 
		the new desktop
		WshShell.LogEvent 4,"Set BFS Logo Desktop"
	end if
Next

For Each compip in alsrange
	if compip = midip then
		'If they are in ALS
		set desktop = filesys.GetFile
		("c:\sysinfo\Desktop.bmp")
		desktop.attributes = 0
		filesys.CopyFile 
		"C:\sysinfo\ALSDesktop.bmp",desktop,1 
		' See above example, 
		this sets it to ALS desktop.
		wshShell.Run("c:\sysinfo\bginfo.exe 
		/ic:\sysinfo\alsdefault.bgi /timer:0")
		WshShell.LogEvent 4,"Set ALS Logo Desktop"
	end if
Next

' I needed to add some logic to change the ZENwsimport 
server based on location. This section updates the 
' registry key for ZENwsimport so workstations would import 
into the proper container.
For Each compip in nerange
	if compip = midip then
		'If they are in NE
		WshShell.RegWrite 
		"HKEY_LOCAL_MACHINE\SOFTWARE\Novell\
		Workstation Manager\
		Import Server\","10.5.1.74"
	end if
Next

For Each comprange in rocrange
	For Each compip in comprange
		if compip = midip then
			'If they are in a ROC, 
			remove IPX
			wshshell.popup "Remote 
			IP detected, 
			removing IPX!",3,
			"ALS Scripting", 0 + 16
			WshShell.Run "c:\winnt\
			system32\NetWare\Nwmigw2k\
			setupw2k.exe /u ms_nwipx",
			7,TRUE
			WshShell.LogEvent 0,
			"ROC detected: Removed IPX"
		end if
	Next
Next

Function GetIP()
  Dim ws : Set ws = CreateObject("WScript.Shell")
  Dim fso : Set fso = CreateObject
  ("Scripting.FileSystemObject")
  Dim TmpFile : TmpFile = fso.GetSpecialFolder(2)
   & "/ip.txt"
  Dim ThisLine, IP
  IP = "0"
  If ws.Environment("SYSTEM")("OS") = "" Then
    ws.run "winipcfg /batch " & TmpFile, 0, True
  Else
    ws.run "%comspec% /c ipconfig > " & TmpFile, 
	0, True
  End If
  With fso.GetFile(TmpFile).OpenAsTextStream
    Do While NOT .AtEndOfStream
      ThisLine = .ReadLine
      if IP = "0" then ' A little logic to make 
	  it read the 	  1st IP address if the machine 
	  has multiple IP's
		If InStr(ThisLine, "Address") <> 0 Then IP = 
		Mid(ThisLine, InStr(ThisLine, ":") + 2)
	  end if
    Loop
    .Close
  End With
  'WinXP (NT? 2K?) leaves a carriage return at the end of line
  If IP <> "" Then
    If Asc(Right(IP, 1)) = 13 Then IP = Left(IP, Len(IP) - 1)
  End If
  GetIP = IP
  fso.GetFile(TmpFile).Delete  
  Set fso = Nothing
  Set ws = Nothing
End Function

If you have any questions you may contact Jim at zenhelp@theshanks.net


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell