Network Deployment and Pre-Configuration

This topic covers various ways that customers can deploy Virtual Modem to workstations over a network.

Administrative rights are required to install the program!

Administrative Installation

An administrative installation is the first step in preparing an MSI installer for deployment over a network.

To invoke an administrative installation, you use the /a command line switch. For example:

msiexec /a "virtual-modem.msi" TARGETDIR="C:\SharedFolder"

Once the admin install is deployed to the shared folder, there are a number of ways that it can be used to install the product onto a workstation: pulled interactive installs from the workstation, non-interactive (aka "quiet") installs from the workstation, or pushed installations using tools such as Active Directory and PSEXEC.

Manually launch the installer on the client

One easy way to pull the installation from an administrative image is to run it manually. This involves sitting at the client machine and launching the installation interactively from the site on which it is being shared.

The main advantage of the manual install method is that you can choose the options desired during the installation, such as the path to which you want the program installed and desired shortcuts.

Launch the installer on the client using "quiet" mode

If you don't need to customize the installation options (e.g. the install path), then you can run the install non-interactively with the quiet switch. This method requires invocation with a command line switch, as illustrated here:

msiexec /i "\\network path\virtual-modem.msi" /qb

The /q part of the switch signifies the quiet mode, and the "b" indicates to use the basic UI level, which in this case would include a progress bar while the installer runs. When run in this mode, the default options will be used for all items that would be presented as choices in the interactive install.

A more comprehensive way to install from the command line

The simple command line syntax shown above will work in most cases, but the following section illustrates a more industrial-strength method of installing quietly.

The more expansive version of the syntax looks like this:

%Comspec% /c msiexec /i "\\network path\virtual-modem.msi" /qn

Here's an explanation of the arguments used the command-line example above:

For further details about command line options available for msiexec, please refer to Command-Line Options in the MSDN Library.

Public properties configurable in MSI

There are several public MSI properties with which you can configure Virtual Modem.

Property name Description
LICENSE_KEY String that contains license key. If this property is not present, the program will be installed in TRIAL mode.
SHOW_SPLASH Show splash window on startup. If this property is present and contains 0, splash window will not be shown.
CHECK_FOR_NEW_VERSION Check for new version periodically. If this property is present and contains 0, the program will not check for new version.
INSTALLMENUSHORTCUTS Install shortcuts in Start menu. Remove this property to prevent installing shortcuts.
INSTALLDESKTOPSHORTCUTS Install shortcuts on Desktop. Remove this property to prevent installing shortcuts.
OPEN_URL Open quick start and uinstall URLs at the end of install and uninstall. If this property is present and contains 0, URLs will not be open.
LOG If this property is present and contains 1, extended installation log file will be generated. This log file will be generated in the same folder from where MSI file is launched.

Configuring properties via command line

Here's an example of the command line syntax you can use to override the default values of these public properties:

%Comspec% /c msiexec /i "\\network path\virtual-modem.msi" SHOW_SPLASH=0 CHECK_FOR_NEW_VERSION=0 OPEN_URL=0 INSTALLDESKTOPSHORTCUTS=""

Configuring license key via VBS script

Here is a sample Visual Basic Script that reads text license key from file and injects it into MSI file.

Being changed, MSI file becomes unsigned!

'InjectKey.vbs

Const MSIDBOPEN_DIRECT = 2
Const ForReading = 1

Dim argNum, argCount

argCount = Wscript.Arguments.Count

If (argCount < 2) Then
	Wscript.Echo "USAGE: InjectKey.vbs <file.msi> <license_key_file>"
	Wscript.Quit 1
End If

Dim FILE, FSO, WI, DB, View, KEY

'Open KEY file
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FILE = FSO.GetFile(WScript.Arguments(1))
If FILE.Size > 0 Then
    Set objReadFile = FSO.OpenTextFile(WScript.Arguments(1), ForReading)
    KEY = objReadFile.ReadAll
    objReadFile.Close
Else
    Wscript.Echo "The key file is empty."
    Wscript.Quit 1
End If

KEY = Replace(KEY, Chr(10), "")
KEY = Replace(KEY, Chr(13), "")

'Update PROPERTY table
Set WI = CreateObject("WindowsInstaller.Installer")
Set DB = WI.OpenDatabase(WScript.Arguments(0), MSIDBOPEN_DIRECT)
Set View = DB.OpenView("DELETE FROM Property WHERE Property.Property='LICENSE_KEY'")
View.Execute
Set View = DB.OpenView("INSERT INTO Property(Property,Value) VALUES ('LICENSE_KEY','"+KEY+"')")
View.Execute
DB.Commit
View.Close

Configuring properties via VBS script

Here is a sample Visual Basic Script that sets SHOW_SPLASH, CHECK_FOR_NEW_VERSION and OPEN_URL to 0.

Being changed, MSI file becomes unsigned!

'InjectProperties.vbs

Const MSIDBOPEN_DIRECT = 2
Const ForReading = 1

Dim WI, DB, View

argCount = Wscript.Arguments.Count

If (argCount < 1) Then
   Wscript.Echo "USAGE: InjectParameters.vbs <file.msi>"
   Wscript.Quit 1
End If

'Update PROPERTY table
Set WI = CreateObject("WindowsInstaller.Installer")
Set DB = WI.OpenDatabase(WScript.Arguments(0), MSIDBOPEN_DIRECT)

'Do not show splash
Set View = DB.OpenView("DELETE FROM Property WHERE Property.Property='SHOW_SPLASH'")
View.Execute
Set View = DB.OpenView("INSERT INTO Property(Property,Value) VALUES ('SHOW_SPLASH','0')")
View.Execute

'Do not check for new version
Set View = DB.OpenView("DELETE FROM Property WHERE Property.Property='CHECK_FOR_NEW_VERSION'")
View.Execute
Set View = DB.OpenView("INSERT INTO Property(Property,Value) VALUES ('CHECK_FOR_NEW_VERSION','0')")
View.Execute

'Do not open URLs
Set View = DB.OpenView("DELETE FROM Property WHERE Property.Property='OPEN_URL'")
View.Execute
Set View = DB.OpenView("INSERT INTO Property(Property,Value) VALUES ('OPEN_URL','0')")
View.Execute

DB.Commit
View.Close

How to install on multiple systems using Push techniques

When dealing with just a few machines, you might prefer to sit at each one, log in using an account that has local administrator rights for that machine, and run a generic batch routine posted to the network share.

However, this becomes time consuming when you have more than just a few machines. All of the methods described so far fall into the category of "pull" type installs, for which you use the client machine to pull the installer down from the server. Next we'll switch to a discussion of "push" type installs, in which you push the installation to client machines, using either a server or another workstation used for this purpose.

There are many commercial tools on the market for facilitating enterprise level software installation. One of the most commonly used tools is Microsoft's Active Directory, included with Windows Server 2003. It is beyond the scope of this paper to cover installations with Active Directory, but Windows Server 2003 Active Directory at Microsoft.com contains details about it if that is one of the scenarios you will be using.

For this discussion, we're not going to assume that you have an enterprise server available, and will instead describe some freeware tools you can use to push installs over a network using either workstations or servers. Here are the two tools we'll be describing:

  1. AT or SOON commands to schedule processes.
  2. PSEXEC or similar tool to "push" batch routines.

Using AT or SOON to start a process at a workstation

AT is built into the command processor. The AT command schedules commands and programs to run on a local or remote computer at a specified time.

SOON is a version of AT with the advantage that instead of running processes at a specific time, it runs them 'soon,' given a delay (you don't need to know what time it is, useful when scripting). At the time of this writing, SOON.EXE is a free Microsoft download.

Here are examples of how you would run these commands:

AT <\\targetPC> 4:30 /INTERACTIVE<\\myPC\myShare\quietInstall.bat>

and

SOON <\\targetPC> 60 /INTERACTIVE<\\myPC\myShare\quietInstall.bat>

Executing processes on a remote system is an obvious security concern. There are two caveats with the above approach, both stemming from Windows security. First is establishing privileges at your desk system to start a batch routine on a remote system. Second is subsequently establishing privileges at the remote system to access network resources when running that batch routine. A quick way to test whether you have the first problem is to start a command prompt at your desk, assuming that you sit at myPC and the remote system is targetPC, and enter: AT<\\targetPC> or DIR<\\targetPC\C$>

If you see an "Access denied" message, you have to work around the first security issue.

Because most workstations will allow a network administrator access to their remote scheduling services and root drives, the simplest workaround is to log on at your desk using a domain administrator account (log on to myPC asdomain\domainadmin). If this is not an option, use an account that has local administrative privileges at each workstation.

Available options are:

If this discussion seems too complex for your immediate needs, skip to the next section, which introduces a shareware push application called PSEXEC.EXE

The second issue with AT or SOON is that once you get the batch routine to execute at the remote workstation, the remote station might not have access to network resources. That means the shell running your batch at targetPC might not have access to the network resource <\\myPC\myShare> .

This is perplexing, since targetPC most likely is logged in to a user account on your domain. However, when the command processor runs your batch routine through the scheduler, it executes with Local System privileges. The workaround is to add NET commands to your batch routine. When the batch routine executes with localsystem access, the batch routine itself opens a privilege pipe to the network resource you're after. That looks something like this:

net use * <\\myPC\myShare> /user:domain\username password /persistent:no

Using PSEXEC to start a process at a workstation

Another alternative to using AT and SOON is PSEXEC. In many situations, PSEXEC is easier to work with, because it collapses the two Windows security issues into just one: "Can PSEXEC.EXE execute a command at the remote system or not?"

At the time of this writing, PSEXEC.EXE is a freeware download from Sysinternals.

To run the batch routine at a workstation using PSEXEC looks like this.

psexec \\targetPC -u domain\username -p password -i -c -f \\myPC\myShare\quietInstall.bat

In the example above, domain\username has local administrative privileges to that machine.

If it is simply not an option to create an account that has local admin privileges on the workstations, then your sysadmin will have to run AT, SOON or PSEXEC for you. You can set up this line to accept arguments, so that when you supply your domain admin with a batch routine, she can run it with her domain\username and password as arguments:

psexec \\targetPC -u %1 -p %2 -i -c -f \\myPC\myShare\quietInstall.bat

Using perl to run the batch routine on many systems

Here is a sample PERL routine that uses AT to schedule a batch routine. The machinelist.txt is a simple textfile in this format:

# begin contents of \\myPC\myShare\machinelist.txt
targetPC1
targetPC2
targetPC3
# end contents of \\myPC\myShare\machinelist.txt
Here is a sample Perl routine that parses the list of workstations above to install the program at each of them:
# begin contents of \\myPC\myShare\\machineLoop.pl
open (FILE, "< machineList.txt");

@lines = <FILE>;
@lines = reverse(@lines);
print "\n";
while ($line = pop @lines) {
    chomp($line);
    $cmdline = "AT \\\\$line 12:00 /INTERACTIVE '\\\\myPC\\myShare\\quietInstall.bat'" ;
    print "Running: $cmdline\n";
    system ("$cmdline");
}
close FILE;
# end contents of \\myPC\myShare\many.pl

Optional exercise: you could alter this sample script in Perl or Python to use SOON.EXE or PSEXEC instead of AT.