|
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.