Logon scripts

Some companies use simple bat files with a few "net use" commands, others use VBScript files mainly using MapNetworkDrive and other functions from the WScript.Network object. In this article, we will provide some much easier and much more scalable ways to create logon scripts.

Assuming you read the article in the "Setting it up" section, we will provide some template examples of login scripts.

The examples on this page assumes you put the content in the prelogon.fsh script that executes before the explorer starts. You can put all or some of the content in your PostLogon.fsh as well, but then it is execute after the users explorer starts.

Simple logon script

Let's take a look at an extremely simple logon script we put into prelogon.fsh just for the basic understanding:

''==== SHOW WELCOME SCREEN ====

Splash Welcome to ACME Corporation,[UserFullName]

 

''==== CONNECT SHARES ====

ConnectShare J:,\\AcmeServer\CommonShare

ConnectShare [UserHomeDrive],[UserHomeDir]

IF UserIsMemberOf SalesStaff Then ConnectShare J:,\\AcmeServer\SalesShare

 

''==== SET CLIENT TIME ====

SetTimeFromServer

With these 5 scriptlines we have accomplished:
- Shown a nice welcome screen, we could optionally have given a corporate logo as third parameter
- Connected a common share, users personal share and a common sales personnel share
- Synchronized the clients time

For most companies this is of course hardly enough functionality for a logon script. So in the next sections we will look into how we can easily create more complex things with very few script lines.

Group-share connection

You may use your Active Directory to connect certain shares for certain people based on their OU, but it is certainly not easy to get a clear picture of what is connected for who. The smarter thing to do is to use the Active Directory information to run scripts. This will also give you the ability to do more than just connecting shares. Active Directory groups are the same as the Domain Groups, so this will also work without an AD. Consider this example:

Loop Group,[UserGroups]

 IF FileExists GroupScripts\[Var Group].fsh Then Include GroupScripts\[Var Group].fsh

End Loop

With these three lines you have made things a lot easier for yourself. Create a directory called "GroupScripts". For each user that logs in, it will execute all the scripts that has the same name as one of their groups. So you can just put a single connect line in each script or you can do more like synchronizing document templates to the users documents template folder or whatever you want done just for users in the specific group.

Determining location

The first problem you run into is determining where people are. Although your Active Directory might tell you where a person is suppose to be, they roam between sites. So the only thing you can truely trust is the IP address. A common setup is to have the same share with the same common data and maybe some programs replicated to a server on each location. To find out which one is closest, you can of course write some if-statements, but if you have more than a couple of locations, this is not a smart solution. Instead, create an XML file and put it in your logonscript folder with the information you need, like this:
<?xml version="1.0"?>
<Acme>
  <Locations>
    <Scope_172.18 Name="Houston" Server="HoustonServer" />
    <Scope_172.19 Name="Dallas" Server="DallasServer" />
    <Scope_172.20 Name="Los Angeles" Server="LAServer" />
    <Scope_172.21 Name="San Fransisco" Server="SFServer" />
    <Scope_172.22 Name="Seattle" Server="SeattleServer" />
  </Locations>
</Acme>
In the logon script you can easily use this information to determine the location. So the first few lines of your logon script could look something like this:

''==== DETERMINE LOCATION ====

SetVar LocationName,[XMLAttribute Locations.xml,Acme/Locations/Scope_[IPAddressPart 2],Name]

SetVar ServerName,[XMLAttribute Locations.xml,Acme/Locations/Scope_[IPAddressPart 2],Server]

 

''==== SHOW WELCOME SCREEN ====

Splash Welcome to ACME [Var LocationName],[UserFullName]

 

''==== CONNECT THE LOCAL SHARE ====

ConnectShare O:,\\[var ServerName]\Data

 

''==== WRITE LOCATION BASED INFORMATION, SO OTHER APPLICATIONS CAN GET IT ====

WriteRegistry HKCU\Software\Acme\Location\Name,[Var LocationName]

WriteRegistry HKCU\Software\Acme\Location\Server,[Var ServerName]

This will display for instance "Welcome to ACME Los Angeles" like the one on the frontpage of this web and connect the Los Angeles server share if that is where you are. You could extend the attributes with more information about the location in the XML file as needed with just one extra line to get each. If you don't all entirely have class 2 addresses (2 digits subnet) you can make multiple sections in your XML file and write an extra lookup in your script if the first lookup returns blank. If you don't have a complete picture of your IP scopes, you could test for blank LocationName and then read default settings from one of the locations.

Location based printer connection

So we have established where the user is. The same location problem exists for automatically connecting printers, but in fact this is bigger problem than share connection. People in two ends of a fairly large building is not going to want to use the same printers. So we need a little help from the user, but we will only trouble them once per location or if they want to change printers within the location.

To do this the best way requires a bit complex scripts, in fact this is probably the most complex scripts you will ever need. The first thing we need is to create a repository with printerinformation and for this we will simply expand the XML file like this (the last 3 locations would of course also have printers):
<?xml version="1.0"?>
<Acme>
  <Locations>
    <Scope_172.18 Name="Houston" Server="HoustonServer" />
    <Scope_172.19 Name="Dallas" Server="DallasServer" />
    <Scope_172.20 Name="Los Angeles" Server="LAServer" />
    <Scope_172.21 Name="San Fransisco" Server="SFServer" />
    <Scope_172.22 Name="Seattle" Server="SeattleServer" />
  </Locations>
  <Printers>
    <Houston>
      <PrinterSite Name="Houston Building 1. Floor" Printers="\\HoustonServer\Printer01,\\HoustonServer\Printer02"/>
      <PrinterSite Name="Houston Building 2. Floor" Printers="\\HoustonServer\Printer03,\\HoustonServer\Printer04"/>
    </Houston>
    <Dallas>
      <PrinterSite Name="Dallas Building Reception" Printers="\\DallasServer\Printer01,\\DallasServer\Printer02"/>
      <PrinterSite Name="Dallas Building 1. Floor" Printers="\\DallasServer\Printer03,\\DallasServer\Printer04"/>
    </Dallas>
  </Printers>
</Acme>
But be careful! A malformed XML file will cause runtime errors, so be careful when modifying the file. This simplest way to test if it is malformed or not is simply to logout and logon again on a workstation and check that is still shows the location in the splash.

Now we have defined sub locations for each site. We now want to accomplish this:
- The first time users logs on on every location, they should be asked which printers they want
- The user must have a shortcut to get the menu again and re-select printers
- If we change the printers in the list, we want it automatically to be enforced on all clients

We need three parts to accomplish this, one for each of the above. The first part is to detect when a user enters a location for the first time and if they have logged in on the location before, we need to enforce changes. So in the logonscript we do this:

If [RegistryValue HKCU\Software\Acme\Sites\[Var LocationName]\PrinterSite]=[Blank] Then

  RemoveSplash

  Include PrinterConnect.fsh

Else

  Include PrinterReconnect.fsh

End If

If UserOnce PrinterShortcut Then

  CreateShortcut "[UserStartMenuDir]","Select Printers",[UserAppDataDir]\FastTrack\PrinterConnect.fsh

End If

The first time the user logs on to the site, PrinterConnect.fsh is executed because the registry key is unique for each location, which will show a nice menu of choices. Once for every user on the network we create a shortcut to reconnect the printers that points to PrinterConnect.fsh. The PrinterConnect.fsh script would have these four script lines:

SetVar LocationName,[XMLAttribute Locations.xml,Acme/Locations/Scope_[IPAddressPart 2],Name]

SetVar XmlLocations,[XMLMultiAttributes Locations.xml,Acme/Printers/[var LocationName]/PrinterSite,Name]

SetVar SelectedPrinters,[ListMenuWithoutCancel Select location,[Var XmlLocations]]

WriteRegistry HKCU\Software\Acme\Sites\[Var LocationName]\PrinterSite,[Var SelectedPrinters]

Include Reconnect.fsh

Observe that we read the locations off the registry. This is because you don't have the variable if you start this script from a shortcut. The last part is the actual connection of printers. It is the same scripts that reconnects and connects. It is a bit tricky to get the actual information we need partly from the registry and partly from our xml file, so the script is a bit complex. It looks like this:

SetVar LocationName,[XMLAttribute Locations.xml,Acme/Locations/Scope_[IPAddressPart 2],Name]

SetVar PrinterSet,"[RegistryValue HKCU\Software\Acme\Sites\[Var LocationName]\PrinterSite]"

SetVar XmlPath,Acme/Printers/[Var LocationName]/PrinterSite

SetVar PrinterList,"[XMLPairAttribute Locations.xml,[Var XmlPath],Name,[Var PrinterSet],Printers]"

SetVar DefaultPrinter,Yes

Loop Printer,[Var PrinterList]

  ConnectPrinter [Var Printer]

  IF [Var DefaultPrinter]=Yes Then SetPrinterDefault [Var Printer]

  SetVar DefaultPrinter,No

End Loop

DisconnectNonConnectedPrinters

The first printer in the list will be connected as the default printer. Running ConnectPrinter does nothing if the printer is already connected so we don't need to test if it is already connected. The last line will delete all network printers that has not been through the ConnectPrinter command in this script context, removing all printers from other sites or previous XML settings.

If we put a bit more data in the xml file, the user would see this when they are prompted for printer location:


Advanced logon script

So putting it all together our corporate ACME logonscript could look something like this:

''==== TERMINATE TERMINAL SERVER SESSIONS ====

IF TerminalServer Then

  ShowMessage "You are not allowed to logon through Terminal Services, please contact HelpDesk","Error"

  Logoff

End If

 

''==== DETERMINE LOCATION ====

SetVar LocationName,[XMLAttribute Locations.xml,Acme/Locations/Scope_[IPAddressPart 2],Name]

SetVar ServerName,[XMLAttribute Locations.xml,Acme/Locations/Scope_[IPAddressPart 2],Server]

 

''==== SHOW WELCOME SCREEN ====

Splash Welcome to ACME [Var LocationName],[UserFullName]

 

''==== CONNECT THE LOCAL SHARE ====

ConnectShare O:,\\[Var ServerName]\Data

 

''==== WRITE LOCATION BASED INFORMATION, SO OTHER APPLICATIONS CAN GET IT ====

WriteRegistry HKCU\Software\Acme\Location\Name,[var LocationName]

WriteRegistry HKCU\Software\Acme\Location\Server,[var ServerName]

 

''==== CONNECT SHARES ====

ConnectShare J:,\\AcmeServer\CommonShare

ConnectShare O:,\\[Var ServerName]\Data

ConnectShare [UserHomeDrive],[UserHomeDir]

 

''==== RUN GROUP SCRIPTS ====

Loop Group,[UserGroups]

 IF FileExists GroupScripts\[Var Group].fsh Then Include GroupScripts\[Var Group].fsh

End Loop

 

''==== SHOW LOW DISK ERROR ====

IF [FreeDiskSpace]<5 Then ShowMessage "Please contact HelpDesk, you are running out of disk space","Warning"

 

''==== ENSURE MINIMUM SCREEN RES ====

IF [ScreenWidth]<1024 Then SetScreenRes 1024,768

 

''==== BACKUP USERDATA ON PORTABLES ====

IF UserOnceAWeek Then

  IF Portable Then

    SmallSplash Running document backup, please wait...

    SyncDir [UserDocumentsDir],[UserHomeDir]\DocumentsBackup

  End If

End If

 

''==== CLEANUP ====

IF UserOnceAWeek Then DeleteDirPreserved [TempDir]

IF UserOnceAMonth Then DeleteDirPreserved [UserInternetCacheDir]

 

''==== SYNC COMMON ACME ICONS ====

SyncDir O:\CommonIcons,[UserStartMenuDir]\Acme

 

''==== SET CLIENT TIME ====

SetTimeFromServer

 

''==== RUN USER SETTINGS ONCE PER APPLICATION PER USER ====

Loop Application,[ApplicationsInstalled]

  IF FileExists UserDataScript\[Var Application].fsh Then

    IF UserSettingsOnce [Var Application] Then Include UserDataScript\[Var Application].fsh

  End If

End Loop

 

''==== CONNECT PRINTERS ====

If [RegistryValue HKCU\Software\Acme\Sites\[Var LocationName]\PrinterSite]=[Blank] Then

  RemoveSplash

  Include PrinterConnect.fsh

Else

  Include PrinterReconnect.fsh

End If

If UserOnce PrinterShortcut Then

  CreateShortcut [UserStartMenuDir],"Select Printers",[UserAppDataDir]\FastTrack\PrinterConnect.fsh

End If

If you disregard the blank lines and the comments, there are very very few actual script lines. And with these few sample script lines we have accomplished:
- Enforced that no one logs on through terminal services
- Determined where the user is
- Shown a nice welcome screen like the one on the frontpage
- Connected a common share, the user's home share and a location based share
- Written registry information for other applications about the current location
- For every group the user is a member of, we look for a script file and include it
- Asked the user to contact the HelpDesk if he is running out of disk space
- Ensured that no one runs a resolution below 1024x768
- Backed up the user's personal folder if it is a portable once a week
- Once a week we clean up temp
- Once a month we clean up temporary internet files folders
- Synchronized the company's common icons to the users profile
- Applied all needed user settings based on what the user has installed
- Synchronized the clients time
- Applied usersettings once per user for every scriptet application
- Automatically handled connecting the users printers

This article was ment as a template for getting started. You would probably do a whole lot more, like including some more advanced maintenance and cleanups scripts once a week or month or do a lot of registry modding and such. If you don't have a management system, you would probably also control installations with your logonscript, there is a specific article on this subject in the "Installations" menu.