This is a script we use to customize systems - both servers and workstations. It is part of our #INSTALL process described elsewhere on this board.

It performs the following:
  • Creates \temp, \usr\lib, & \usr\local\bin
  • Copies UDFs from .\lib to \usr\lib
  • Copies admin tools from .\tools to \usr\local\bin
  • Copies .\System32\Kixforms.dll to %SystemRoot%\system32 & registers the dll
  • Installs a customized command prompt
  • Adds identification to the system in My Computer and %PROMPT%
  • Defines Open and Edit associations for .KIX, .KXW, .KXF, & .UDF
The #INSTALL.BAT code that calles this script is shown below. The reference to \bin insures that the latest Kix version is called from the software install folder.
code:
 
@\bin\kix32.exe customize.kix $ARGS="%*"

This can be called with -r:rmt_server to "push" the configuration to a remote system. This requires that the PSEXEC.EXE tool from the SysInternals freeware collection to perform the register on the remote system.
To Test:
  • Create a folder to hold this script and subfolders.
  • Create the install.bat with the above line in your base folder. Edit the batch file to reflect the location of your kix32 executable.
  • Create a Tools subfolder and place Kix32.exe in it. You could also place any other useful tool here. These will be copied to \usr\local\bin.
  • Create a System32 subfolder to hold a copy of KixForms.dll - this will be copied to %SystemRoot%\System32 and registered.
  • Create a LIB subfolder to hold a few UDFs - these will be copied to \usr\lib.
  • Create a shortcut to your Command Prompt and place it in your base folder. Open the command prompt and make some obvious color chanes. Name it "OS_Command Prompt.lnk", where OS is NT, 2K, or XP - as required by your test system.
  • To test PUSH installation, obtain a copy of PSEXEC.EXE and put it in your base folder with this script.
Run "install" to install on the local system, or "isntall -r:testpc" to install on "testpc"
While this is pretty simple and non-invasive, YOU SHOULD TEST THIS ON A TEST BOX!!! [Big Grin]
This script works if you have the proper directory structure to deploy the files.. While you may find it useful, I present it here to demonstrate some of the UDFs I've posted tonight, and to illustrate how an application can target either a local or remote system.
Enjoy!

Glenn



; CUSTOMIZE.KIX - KixTart script to customize the system
; 2001,2003 - Glenn Barnas / FRIT-EROC
;
; VERSION 4.0  - 3/2003
;
; Adds C:\temp & c:\usr\local\bin directories
; Adds common Command-Line Tools
; Updates PATH
; Customizes Command-Line Prompt
; Defines customized command-prompt shortcut at top of Start Menu
; Sets "My Computer" to display "UserID on SystemName"
; Associates .KIX with Kixtart and adds secondary EDIT association,  defines ICON for .KIX files
; Supports "push" optoin to deploy to remote server
; Supports -q, which logs output to %TEMP%\customize.log (prints DONE! to console)
;
; Changes in new release:
; - Requires Kix version 4.x, relies on UDFs
; - Uses Kix functions to unset R/O attribute, delete, then copy new tools
; - Uses PSExec.exe from www.SysInternals.com to register the KixForms dll on remote sys tems

Break ON                ; allow script to be interrupted



;===============================================================================
; Confirm proper version is installed - don't support pre-v4 or BETA releases
; App will die if we aren't running at least version 4.0
;
$RC = KixVer(4.2)



;===============================================================================
; Define some constants...

; how to invoke your favorite kixtart script editing tool
$KIXEDITOR  = "%%SystemRoot%%\System32\Notepad.exe"

$TARGET     = ""                         ; local system name (for registry)
$DEST       = "%SystemDrive%"            ; local system path (for files)
$HOST       = "@WKSTA"                   ; local system name (no "\"s)
$SOURCE     = "."                        ; Path to files - normally the current directory
$InstallLog = ""                         ; display messages on console or write to log if defined

;===============================================================================
; Args will be defined to perform an install to a remote system
; Evaluate the arguments and assign them to appropriate variables
; Only -r:target and -q are allowed
; -r:target - customizes the named target system
; -q        - for unattended installs, writes to log instead of console
;
If $ARGS <""

  $aryARGS = Split($ARGS," ", -1)

  For Each $ARG in $aryARGS
    Select
    Case Left($ARG,3) = "-r:"           ; target remote computer
      $HOST = SubStr($ARG499)       ; simple name
      $TARGET = "\\" + $HOST + "\"      ; server name format
      $DEST = $TARGET + "C$"            ; destination is remote C: drive

      ; check to insure that remote share is accessible
      If Exist($DEST + "\boot.ini") = 0
        ? "Invalid target!  - Cannot continue!" ?
        Beep
        Exit 1
      EndIf

    Case $ARG = "-q"
      Del "%TEMP%\customize.log"
      $InstallLog = "%TEMP%\customize.log"

    Case 1
      "Unknown Argument: $ARG" ?
      Exit 1

    EndSelect

  Next  ; for each $ARG

EndIf    ; $ARGS <> ""



;===============================================================================
; Determine the "all users" Start Menu path - this can vary depending on whether
; a system was installed fresh or upgraded from an earlier version
$SMPATH = ReadValue($TARGET + "HKEY_Local_Machine\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders""Common Start Menu")
$SMPATH = $DEST + SubStr($SMPATH3250)

; Obtain the SystemRoot location from local or remote system
$WSPATHR = ReadValue($TARGET + "HKEY_Local_Machine\SOFTWARE\Microsoft\Windows NT\CurrentVersion""SystemRoot")
$WSPATH = $DEST + SubStr($WSPATHR3250)



;===============================================================================
; determine the O/S installed & announce the findings..
;
$OSV = OSVer($TARGET

Msg("Customizing system: " + $HOST$InstallLog)

Select
Case $OSV = "4.0"
  Msg("  Windows NT Detected"$InstallLog)
  $OST = "NT"

Case $OSV = "5.0"
  Msg("  Windows 2000 Detected"$InstallLog)
  $OST = "2K"

Case $OSV = "5.1"
  Msg("  Windows XP Detected"$InstallLog)
  $OST = "XP"

EndSelect



;===============================================================================
; Insure that the \TEMP, \usr\local\bin, and \usr\lib directories exists
Msg("  Updating Directories \temp, \usr\local\bin, & \usr\lib..."$InstallLog)
MDPath($DEST + "\Temp")
MDPath($DEST + "\usr\local\bin")
MDPath($DEST + "\usr\lib")


; Install sets of files in the source directory to a target directory
Msg("  Updating Admin command-line tools and script libraries..."$InstallLog)
Install($SOURCE + "\tools"$DEST + "\usr\local\bin")
Install($SOURCE + "\lib"$DEST + "\usr\lib")
Install($SOURCE + "\local"$WSPATH + "\usr\local")
Install($SOURCE + "\system32"$WSPATH + "\system32")



;===============================================================================
; UnRegister / Register the KixForms.dll 
;
If $TARGET = ""                    ; local system
  Msg("  Registering local DLL"$InstallLog)
  $CMD = "regsvr32 /s /u " + $wSPATHR + "\system32\kixforms.dll"
  Shell $CMD
  $CMD = "regsvr32 /s    " + $wSPATHR + "\system32\kixforms.dll"
  Shell $CMD
Else                        ; remote system
  ; Note that in PSEXEC, the path reference is relative to the remote system!
  Msg("  Registering remote DLL"$InstallLog)
  $CMD = "%ComSpec% /c psexec " + $TARGET + " " + $wSPATHR + "\system32\regsvr32 /s /u "  + $wSPATHR + "\system32\kixforms.dll 2>&1>NUL:"
  Shell $CMD
  Msg("    Remote Unregister: @SERROR"$InstallLog)
  $CMD = "%ComSpec% /c psexec " + $TARGET + " " + $wSPATHR + "\system32\regsvr32 /s    "  + $wSPATHR + "\system32\kixforms.dll 2>&1>NUL:"
  Shell $CMD
  Msg("    Remote Register: @SERROR"$InstallLog)
EndIf



;===============================================================================
; Change the startup delay to 5 seconds by editing the BOOT.INI file
;
$FileAttr = getfileattr($DEST + "\boot.ini")            ; get existing file attributes
$RTN = setfileattr($DEST + "\boot.ini"0)              ; clear attributes
copy $DEST + "\boot.ini" $DEST + "\boot.BAK.ini"        ; backup the original file
$RTN = WRITEPROFILESTRING($DEST + "\boot.ini""boot loader""timeout""5")
$RTN = setfileattr($DEST + "\boot.ini"$X)             ; restore the original attributes
Msg("  Set boot-delay to 5 seconds"$InstallLog)



;===============================================================================
; define the system command prompt to include the server name 
fSetM("PROMPT=" + $HOST + " - $$P$$G"$Target)
Msg("  Set Command-line Prompt to: " + $HOST + " - $$P$$G"$InstallLog)



;===============================================================================
; add the tools dir to the path if it isn't there already
$PATH = fGetM("PATH"$Target)
If instr($PATH"\usr\local\bin") = 0
  fSetM("PATH=%%SYSTEMDRIVE%%\usr\local\bin;" + $PATH$Target)
  Msg("  Updated PATH with \usr\local\bin"$InstallLog)
Else
  Msg("  PATH was OK!"$InstallLog)
EndIf



;===============================================================================
; add .KIX & .KXW to the PATHEXT if it isn't there already - this permits
; KixScripts to be run directly from a command-line
;

; default to no PathExt modifications
$PathMod = 0

; Get the current PATHEXT value
$PathExt = fGetM("PATHEXT"$Target)

; trim any trailing ";" character
If Right($PathExt,1) = ";"
  $PathExt = Left($PathExt,Len($PathExt)-1)
EndIf

; Add the .KIX extension if needed
If InStr($PathExt".KIX") = 0
  $PathExt = $PathExt + ";.KIX"
  $PathMod = 1
  Msg("  Added .KIX to PATHEXT"$InstallLog)
Else
  Msg("  .KIX already defined in PATHEXT"$InstallLog)
EndIf

; Add the .KXW extension if needed
If InStr($PathExt".KXW") = 0
  $PathExt = $PathExt + ";.KXW"
  $PathMod = 1
  Msg("  Added .KXW to PATHEXT"$InstallLog)
Else
  Msg("  .KXW already defined in PATHEXT"$InstallLog)
EndIf

; Write the modified value back to the server
If $PathMod = 1
  fSETM("PATHEXT=" + $PathExt$Target)
EndIf



;===============================================================================
; delete the command prompt icon if it exists & replace it with a custom version
; A command prompt shortcut is hand-defined on each OS version, then that shortcut
; is copied to the distribution folder and given a name like "NT_Command Prompt.lnk". 
; OS-specific shortcuts should be created for each O/S. Deploying a 2K link on NT
; has exhibited problems such as taking 20-30 seconds to open the window!

Msg("  Updating Command Prompt on Start Menu"$InstallLog)

; Destination for the shortcut - top of the main (all users) Start Menu
$DFILE = $SMPATH + "\command prompt.lnk"

; O/S Version-specific shortcut
$SFILE = $SOURCE + "\" + $OST + "_command prompt.lnk"

; Delete the shortcut if it exists
$RTN = setfileattr($DFILE0)        ; clear attributes
del $DFILE

; copy the current settings file to the start menu
copy "$SFILE" "$DFILE"



;===============================================================================
; Define the registry key to set the "My Computer" icon name to "Username on Servername"
; Value is "Default" on NT and "Default" & "LocalizedString" on 2K/XP
; IMPORTANT! Delete the original STRING value & Replace it with a STRING_EXPAND value

Msg("  Changing 'My Computer' icon to identify Server and User"$InstallLog)

; DEFAULT for all platforms
$RTN = DelValue($TARGET + "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}""")
$RTN = WriteValue($TARGET + "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}""""%%USERNAME%% on %%COMPUTERNAME%%""REG_EXPAND_SZ")
$RTN = DelValue($TARGET + "HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}""LocalizedString")



;===============================================================================
; Associate Kix32 to .KIX files - allows scripts to be run without
; manually calling KIX32.EXE
;

;Define the executables to associate with OPEN and EDIT functions
; Kixtart Command Line Scripts
$KXOPEN = "%SYSTEMDRIVE%\usr\local\bin\kix32.exe " + CHR(34) + "%%1" + CHR(34)
; KixForms GUI Scripts
$KWOPEN = "%SYSTEMDRIVE%\usr\local\bin\Wkix32.exe /I " + CHR(34) + "%%1" + CHR(34)
; Editor for all types of Kixtart scripts
$KXEDIT = $KIXEDITOR + " " + CHR(34) + "%%1" + CHR(34)


Associate(".KIX""KixScript""Kixtart Script"$KXOPEN$KXEDIT0$TARGET)
Associate(".KXW""KixWScript""Kixtart GUI Script"$KWOPEN$KXEDIT0$TARGET)

; OPEN action uses the editor, no EDIT action
Associate(".KXF""KixLib""Kixtart Function Library"$KXEDIT0$TARGET)
; As above, but adds .UDF to the existing association
Associate(".UDF""KixLib""Kixtart Function Library"$KXEDIT""1$TARGET)

MSG("  Added Open and Edit associations for KiXtart"$InstallLog)


?



;===============================================================================
; Supporting functions follow
;===============================================================================
;;
;;======================================================================
;;
;;FUNCTION       Associate()
;;
;;ACTION         Associates a file extension with a particular action
;;
;;AUTHOR         Glenn Barnas / FRIT-EROC
;;
;;SYNTAX         Associate(Server, Extension, Type, Description, OPEN command, EDIT command, Add)
;;
;;PARAMETERS     Extension    - File extension to associate
;;               Type         - Short FileType description
;;               Description  - Description of File Type
;;               OPEN Command - Command to OPEN (execute) the associated file
;;               EDIT Command - Command to EDIT the associated file [optional]
;;               ADD          - Flag - if set, adds a new Extension to an existing
;;                              association definition.
;;               System       - System where association is to be made - null for local system
;;
;;
;;REMARKS       
;;
;;RETURNS        nothing
;;
;;DEPENDENCIES   None
;;
;;EXAMPLES       ; Define a new assocaiation for .KIX
;;               Associate(".KIX", "KixScript", "Kixtart Script", "Kix32.exe", "notepad.exe", "", "")
;;               ; Add .SCR extension to the KixScript association
;;               Associate(".SCR", "KixScript", "", "", "", 1, "")
;
Function Associate($Extension$Type$Description$OCmdOPTIONAL $ECmdOPTIONAL $AddFlagOPTIONAL $System)

  ; make sure the "dot" is specified
  If Left($Extension1) <"."
    $Extension = "." + $Extension
  EndIf

  ; insure that "$Server" has the right format if it's specified
  If $Server <""
    If Left($Server,2) <"\\" $Server = "\\" + $Server EndIf
    If Right($Server,1) <"\" $Server = $Server + "\" EndIf
  EndIf

  ; Define the Extension
  $RTN = DelTree($System + "HKEY_CLASSES_ROOT\" + $Extension)
  $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Extension)
  $RTN = WriteValue($System + "HKEY_CLASSES_ROOT\" + $Extension""$Type"REG_SZ")

  ; just return if we're adding a new Extension to an existing association
  If $AddFlag = 0
    Exit 0
  EndIf

  ; Create the definitions for the OPEN command
  $RTN = DelTree($System + "HKEY_CLASSES_ROOT\" + $Type)
  $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type)
  $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type + "\DefaultIcon")
  $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell")
  $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell\Open")
  $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell\Open\Command")

  $RTN = WriteValue($System + "HKEY_CLASSES_ROOT\" + $Type""$Description"REG_SZ")
  $RTN = WriteValue($System + "HKEY_CLASSES_ROOT\" + $Type + "\DefaultIcon""""C:\Windows\system32\SHELL32.dll,21""REG_SZ")
  $RTN = WriteValue($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell\Open\Command"""$OCmd"REG_EXPAND_SZ")

  ; Create the association for the EDIT command, if specified
  If $ECmd <""
    $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell\Edit")
    $RTN = AddKey($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell\Edit\Command")
    $RTN = WriteValue($System + "HKEY_CLASSES_ROOT\" + $Type + "\Shell\Edit\Command"""$ECmd"REG_EXPAND_SZ")
  EndIf

EndFunction


;;
;;======================================================================
;;
;;FUNCTION       fSetM()
;;
;;ACTION         fSetM: Sets an environment var on the local or target server
;;               fGetM: Gets an environment var from a local or target server
;;
;;AUTHOR         Glenn Barnas / FRIT-EROC
;;
;;SYNTAX         fSetM: fSetM(Value [, server])
;;               fGetM: $VAR = fGetM(Value [, server])
;;
;;PARAMETERS     fSetM: Value - Value to define, in the format "VARNAME=value"
;;               fGetM: Value - name of environment var to retrieve
;;
;;REMARKS       
;;
;;RETURNS        fSetM: Value of @ERROR
;;               fGetM: Value of environment variable
;;
;;DEPENDENCIES   SNVerify - included function to verify server name format
;;
;;EXAMPLES       $Path = fGetM("PATH")
;;               fSetM("PATH=c:\temp;" + $Path, "system2")
;
Function fSetM($EDEFOPTIONAL $Server)
  If $Server = ""
    SetM($EDEF)          ; use local SETM command
    Exit @ERROR
  Else
    $Server = SNVerify($Server)
    $fENVKEY = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
    $aryENVARGS = Split($EDEF"="2)
    $fnSetM = WriteValue($Server + $fENVKEY$aryENVARGS[0], $aryENVARGS[1], "REG_EXPAND_SZ")
    Exit @ERROR
  EndIF
EndFunction

Function fGetM($EDEFOPTIONAL $Server)
  If $Server = ""
    $RC = Execute("$$fVar = %" + $EDEF + "%")
    $fGetM = $fVar
  Else
    $Server = SNVerify($Server)
    $fENVKEY = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
    $fGetM = ReadValue($Server + $fENVKEY$EDEF)
  EndIF
EndFunction

; Insure server name has the format "\\server\" 
Function SNVerify($ServerName)
  If Left($ServerName,2) <"\\"
    $ServerName = "\\" + $ServerName
  EndIf
  If Right($ServerName,1) <"\"
    $ServerName = $ServerName + "\"
  EndIf
  $fSNVerify = $ServerName
EndFunction


;;
;;======================================================================
;;
;;FUNCTION       Install()
;;
;;ACTION         Installs all files from SourcePath to DestinationPath
;;
;;AUTHOR         Glenn Barnas / FRIT-EROC
;;
;;SYNTAX         Install("Sourcepath", "DestinationPath")
;;
;;PARAMETERS     SourcePath      - Directory containing files to copy
;;               DestinationPath - Directory where files will be installed
;;
;;REMARKS        Install locates the files in the SourcePath. For each file
;;               found it first removes any read-only attribute and deletes 
;;               any file with the same name found in the destination directory.
;;               It then copies the file to the destination folder. This insures
;;               that the latest version of a file is installed.
;;
;;RETURNS        nothing - creates directory path
;;
;;DEPENDENCIES   PathSplit()
;;
;;EXAMPLES       Instal(".\system32", "\\server\c$\winnt\system32")
;
Function Install($SrcDir$DstDir)

  Dim $FileName

  ; Add trailing slashes if not provided
  If Right($SrcDir,1) <"\"
    $SrcDir = $SrcDir + "\"
  EndIf
  If Right($DstDir,1) <"\"
    $DstDir = $DstDir + "\"
  EndIf

  $FileName = Dir($SrcDir + "*.*")
  While $FileName <"" And @ERROR = 0

  If Left($FileName,1) <"."  ; skip "." and ".."

      ; If the target file exists, remove all attributes and delete it
      If Exist($DstDir + $FileName)
        $RC = SetFileAttr($DstDir + $FileName0)
        Del $DstDir + $FileName
      EndIf

      ; Copy the new file to the destination
      Copy $SrcDir + $FileName $DstDir 

    EndIf

    $FileName = Dir()
  Loop

EndFunction


;;
;;======================================================================
;;
;;FUNCTION       KixVer(Minimum [, RETURN, BRC])
;;
;;ACTION         Exits if not running minimum Kix or Beta version 
;;
;;AUTHOR         Glenn Barnas /
_________________________
Actually I am a Rocket Scientist! \:D