Windows Packager
Simple package distribution utility for Windows

This program is used to push/pull software packages, such as Service Packs, hotfixes, or program installations from a central server to a number of workstations.

Package definations are stored in packages.xml, profile definations in profiles.xml.

A package is a software entity that can be installed and removed by running a series of command lines. All of those commands must be successful, either by returning a zero exit code, or by returning an exit code listed for the command.

The system keeps track of what versions of what packages are currently installed and what version are available in order to decide weither to install, remove, or upgrade a package.

Profiles denote a certain "class" of workstations, such as departments. Profiles can depend on other profiles, the end result being they inherit all the dependent packages.

Installation consists of copying the wpkg.js, packages.xml, profiles.xml and hosts.xml files to a centralized folder on a file server. The administrator would then define his packages in packages.xml, and then define his profile structure in profiles.xml. Each workstation would need to be configured to run the wpkg command in order to install/update/remove packages from itself.

Logs are reported to the Windows Event Log. These can be retrieved in anyway appropiate for the network.


System Startup:

Our production environment is accomplishing this very easily. We are using the srvany.exe and instsrv.exe programs included with the Windows 2000 Resource Kit to install the wpkg.js script with the /synchronize /quiet options as a system service. This is working flawlessly. I cannot distribute the srvany.exe and instsrv.exe programs along with this software however. Licensing and all.

It is however, extremely trivial to implement this yourself:


  1. Pick a network drive. This drive must be accessable by the user wpkg is going to be configured to run as. We are using LocalSystem on Windows 2000. Windows XP has a new NetworkService account which begs examination. When LocalSystem attempts to access a file share, it does so under the identity of guest. Thus, guest must have read only access to your entire software share.
  
  
  2. Write an installation .bat file. Our's first copies srvany.exe and instsrv.exe to %SystemRoot%\System32. It then runs
  
  instsrv "Windows Packager" "%SystemRoot%\System32\srvany.exe"
  
  This creates the Windows service. It is however not yet started. Next, we install the latest version of Windows Script Host on the system. Windows 2000 out of the box does not have a good enough version. Check Microsoft's web site for the Windows script software. The executable is named scripten.exe. We launch it from the .bat file as follows:
  
  \\path\to\share\scripten.exe /Q /R:N
  
  This makes it install quietly and not reboot. Next in our bat file, setup the registry entries neccassary for srvany.exe to properly start Windows Packager. I do this by calling out to a JScript file: install-registry.js. I did this because the registry keys needed had the potential to be different for each system. Creating keys using code was ideal. The install-registry file sets the following keys:
  
  HKLM\System\CurrentControlSet\Services\Windows Packager\Parameters\Application
  HKLM\System\CurrentControlSet\Services\Windows Packager\Parameters\AppParameters
  
  The Application key specifies the full path to the executable that the service will run at boot. I give it %SystemRoot%\System32\cscript.exe. This is because we do not launch the wpkg.js file, we launch the Windows Scripting Host and instruct it to launch the wpkg.js file. Set the Parameters key to:
  
  \\path\to\share\wpkg.js /synchronize /quiet
  
  This instructs cscript.exe to run the wpkg script on the network share, with the two options shown. It will synchronize the system on boot, logging errors quietly.
  
  This is an example install-service.js file.
  
  var WshShell = WScript.CreateObject("WScript.Shell");
  var srvKey = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Windows Packager\\Parameters\\";
  var appKey = srvKey + "Application";
  var parKey = srvKey + "AppParameters";
  var srvPath = WshShell.ExpandEnvironmentStrings("%SystemRoot%") + "\\System32\\wscript.exe"
  var srvArgs = "\\\\path\\to\\share\\wpkg.js /synchronize /quiet";
  WshShell.RegWrite(appKey, srvPath, "REG_SZ");
  WshShell.RegWrite(parKey, srvArgs, "REG_SZ");
  
  The last entry in the .bat file should be net start "Windows Packager".
  
  Here is a sample .bat file:
  
  copy \\path\to\share\srvany.exe %SystemRoot%\System32
  copy \\path\to\share\instsrv.exe %SystemRoot%\System32
  instsrv "Windows Packager" "%SystemRoot%\System32\srvany.exe"
  \\path\to\share\scripten.exe /Q /R:N
  wscript.exe \\path\to\share\install-registry.js
  net start "Windows Packager"
  
  -- I am looking for improvements to the above code. Actually, I would like to exclusively use JScript for this. I just haven't yet had time to write it. Please donate code.
  
  3. Running the .bat file on a new system will now set up and run wpkg! Running this .bat file as part of your Windows install answer file is ideal.
  
  4. Watch Windows reboot. I have over 20 packages being installed, half of which require a reboot. It's amusing to see Windows reboot itself for 30 minutes installing stuff.
  
  
As you create package entries for common programs, please email them to me. I will be setting up a central location for them. To be accepted though they must work fully. That is they must install AND remove themselves correctly.
