ICC Home  /  Members  /  Meetings  /  Peer Support  /  Documentation  /  Projects

Login Scripts  

Return to IT/SA Services Documentation: Active Directory

Updates to handle Vista and Windows 7 (December 2009)

In mid-December of 2009, Andrew Carey made some changes, mostly to how printers get
, but also in the basic means for kicking-off the login script so it runs differently on
Vista and Windows 7. Instead of pointing directly to the login script as was done in the
past, another script (CheckOS.vbs) was substituted and it is that script which is now called
directly by the IFAS-Co-managed user GPO. When CheckOS.vbs is launched, it checks the client
OS, and then either runs the login script as before (if the OS is XP or earlier) or runs
launchapp.wsf with the login script name as an argument, which sets up a scheduled task
to run the login script (if the OS is Vista or Windows 7.)

The only other login script change was the addition of a call to EnumMappings.vbs
which logs the network drives and printers that are being mapped at logon into a database.
This script was previously directly called from the logon scripts area of the IFAS-Co-Managed
User GPO (along with the actual IFAS login script) but had to be moved so that it would run on
Vista and Windows 7.

Further Updates to address issues with multi-user machines (February 25, 2010)

Previously, the IF-Co-Managed User GPO called CheckOS.vbs which determined the users
operating system and then either called Login script.vbs directly if the user was
running Windows XP or earlier or called launchapp.wsf which then scheduled the
running of login script.vbs as a scheduled task if the user was running Windows
Vista or later. The scheduled task was named "Launch App As Interactive User"
regardless of who logged in which caused a problem:

  1. The first user to log into a Windows Vista or Windows 7 computer creates a
    scheduled task (via the logon script) to map their drives, printers, etc. This
    user has full control over the scheduled task because it was created under their
    user context.
  2. The next user to log onto the computer without admin rights attempts to
    create / modify the same scheduled task (via the login script) but cannot because
    by default, users have rights to create new tasks and view existing tasks, but
    not modify existing tasks. The login script does not run for this user.

In this latest revision, Andrew modified the scheduled task name to "IFAS Login Script
for username” so that multiple users can run the script without conflicting and set the
task to delete itself three minutes after it is run so that communal computers don’t
become clogged with a scheduled task for each user that logs in.

Andrew also simplified the login script process by combining the CheckOS.vbs and
launchapp.wsf scripts into a single script (CheckOS.vbs.) Having a script calling a
script, calling another script made troubleshooting the location of a problem challenging.
The functionality of both scripts was preserved – the script still determines the user’s
operating system and either runs login script.vbs or schedules it as a task depending on
the OS version.


All IFAS users run a unified Login Script. The script is located on each domain controller
in \\ad.ufl.edu\netlogon\ifas. This universal login script has several functions:

  1. It runs a printer installation script (for non IF-ADMx accounts)
  2. . As mentioned above,
    this printer script was revamped considerably by Andrew Carey in December 2009.
  3. It determines group membership of the user who logged in and launches login scripts for
    each of these groups if they are present.
    This is implemented via placing properly named scripts in the correct location
    of the netlogon share ( \\ad.ufl.edu\netlogon\ifas). Group scripts must be named
    "groupname.vbs" where groupname is identical to the actual security group name
    minus the ". " prefix. Those scripts must be placed in the "OU" subfolder
    corresponding to the user's NMB setting.
  4. It launches a login script for the individual user.
    User specific scripts must be named "GLusername.vbs" where GLusername is
    identical to the user's gatorlink username. Those scripts must be placed in the
    "User" subfolder of the the "OU" subfolder corresponding to the user's NMB setting.
    There is no order precedence to competing scripts. To implement that, one could
    place a delay in a particular script (to make it run last) via adding in the
    wscript.sleep command.
  5. It removes the "Restore" button from the "Previous Versions" tab of the file/folder
    properties dialog. This is to make it more difficult for users to overwrite the contents
    of a share inadvertently.

Regarding the logon scripts, lets say we have a user named gogators who is in the CALS people OU.
By being in this OU they are automatically a member of the group:


In addition this user is a member of the following groups:


For this user four login scripts would execute:


As you can see the location of the login scripts is based on the location
of the user and the location of the group.

Detailed Run-through

The first few lines set up objects that are needed throughout the rest of the script

On Error Resume Next
Set objNetwork = CreateObject("Wscript.Network")
Set objShell = CreateObject("WScript.Shell")
Set objFileSystem = CreateObject("Scripting.FileSystemObject")

'*** Needed for InIFAS query

The next block of code is a pause that waits until the username variable is populated.
This section may be able to go away, as it is believed necessary only for Windows 98
computers. If testing verifies that, then this section will be removed.

UserName = ""
Do While UserName = ""
    UserName = objNetwork.UserName
    Wscript.Sleep 10
On Error Goto 0

The following section converts from the Gatorlink name to the distinquished name (DN)
and then binds to the object. There is another way to do that using the
IADsNameTranslate ADSI interface to which this script may be switched at some point.

DNQuery = "SELECT distinguishedName FROM 'LDAP://DC=ad, DC=ufl,DC=edu' where CN='" & UserName & "'"
Set Conn = CreateObject("ADODB.Connection")
Conn.Provider = "ADSDSOObject"
Conn.Open "ADs Provider"
Set rs = Conn.Execute(DNQuery)
Username = rs.Fields(0)
Set objUser = GetObject("LDAP://" & Username)

The next section checks whether a computer object is in the IFAS OU

InIFAS = 0
Set objCOmmand.ActiveConnection = Conn
objCommand.CommandText = _
    "Select ADsPATH from 'LDAP://ou=ifas,ou=departments,ou=uf,DC=ad,DC=ufl,DC=edu' " _
        & "where objectClass='computer' AND name='" & Computer & "'"
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Timeout") = 30 
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
objCommand.Properties("Cache Results") = False 
Set objRecordSet = objCommand.Execute
If NOT (objRecordset.BOF AND objRecordset.EOF) Then
    result = objRecordSet.Fields("ADsPATH").Value
    if UCase(Right(result,45)) = "IFAS,OU=DEPARTMENTS,OU=UF,DC=AD,DC=UFL,DC=EDU" then
        InIFAS = 1
    End If
End if

The following section disables user access to the VSS previous versions tab so multiple users
of a share can't so easily tromp on each other's files.

objShell.Run "REG ADD HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer /v NoPreviousVersionsRestore /t REG_DWORD /d 1 /f"

[Note: the script used to install a spyware blocklist at this point but that was commented out
in April 2009. That solution has a number of drawbacks, including that it wrote to the HKLM branch
of the registry (and therefore only worked for those with local admin rights, that the list was not
maintained, and that it caused slowness problems for IE8 among other things.]

'***Spyware Blocklist
'***Create as GPO
If InIFAS then
	'objShell.Run "regedit.exe /S \\ad.ufl.edu\NETLOGON\IFAS\ie-ads.reg"
	objShell.Run "\\ad.ufl.edu\NETLOGON\IFAS\Lsclient.exe lansweeper.ifas.ufl.edu",0
End If

This action line of this script has been commented out and ePO is no longer pushed, but it begins
by testing if the user is an admin and skips this and the following section if that is the case. This
was done because the WSUS server cannot have ePO installed; also there was a request to not have ePO
automatically installed on servers and printers as well. For others an ePO install is performed,
provided a test of the registry shows that the current version is not installed. This portion of the
script would have to be updated each time a new ePO package is created to reflect the new version

If Left(Username,9) <> "CN=IF-ADM" then
	'***Install EPO Agent
	on error resume next
	If InIFAS then
          Version = objShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Network Associates\ePolicy Orchestrator\Application Plugins\EPOAGENT3000\Version")
	  If Version <> "" then
	    If Version <> "" then
	      Set FileSystem = WScript.CreateObject("Scripting.FileSystemObject")
	      If FileSystem.FileExists("\\IF-SRV-EPO.ad.ufl.edu\EPO-Installs$\" & objNetwork.ComputerName & ".txt") Then
		Set objFile = FileSystem.OpenTextFile("\\IF-SRV-EPO.ad.ufl.edu\EPO-Installs$\" & objNetwork.ComputerName & ".txt", 8)
		Set objFile = FileSystem.CreateTextFile("\\IF-SRV-EPO.ad.ufl.edu\EPO-Installs$\" & objNetwork.ComputerName & ".txt", True)
	      End If
	      objFile.WriteLine Now & "," & Version & "," & objNetwork.Username 
'*	      objShell.Run "\\ad.ufl.edu\NETLOGON\IFAS\UFAD_ePOAgent-36HF10.exe /INSTALL=AGENT /FORCEINSTALL /SILENT"
	    End If
	  End If
	End If
	on error goto 0

Then the printer installation script is run--except for IF-ADMx logons.

	'***Runs Printer Installation Script
	objShell.Run Chr(34) & "\\ad.ufl.edu\netlogon\IFAS\printers.vbs" & Chr(34),0,FALSE
End If

The following section was temporarily placed to assist with the transition to using
"GatorLinkUsername@ufl.edu" addresses. Listserv owners and editors may have had an incorrect
cookie stored for their old listserv logons, and this will help remove those. The intention is to
leave this in until February 2006. The called-out script is detailed here.

'Deletes Old Listserv Cookie
objShell.Run Chr(34) & "\\ad.ufl.edu\netlogon\IFAS\DeleteCookie.vbs" & Chr(34),0,FALSE

This next major section is the portion of the script that determines the user's group memberships
based on the "member of" tab of the user account. It only checks for group that a user is directly a member
of and will not include nested relationships. The code begins by using the "split" function to dice the DN
of each group into an array containing its hierarchical parts. Those parts are then tested through a number
of checks to determine which OU a particular group is located in, so the script can look in the proper folder
when it executes the various logon scripts. The checks include looking for groups within the "IFAS" OU,
bypassing any within "-Central-IT". Groups within "CEODIST" have to be handled specially because of their
deeper nesting level. The line beginning with "Set objOUCheck" checks to see if the user is in a sub-OU of one
of the root OUs; users in the districts and AEC/PDEC would be examples of that. Presence or absence of an error
upon that check is used to separate the two processes that build the array of paths to the various scripts that
should then run for a user based on their direct group memberships. The last "elseif" portion of this big complex
section handles memberships in the various IFAS autogroups--those being outside the IFAS OU structure.

'***Determines group membership and builds path
Dim arrGroup()
Dim arrOU()
arrMemberOf = objUser.GetEx("memberOf")
For each Group in arrMemberOf
	CN = Split (Group, ",OU=")
	If ubound(CN) <> 0 then
		If CN(ubound(CN)-2) = "IFAS" Then
			If CN(ubound(CN)-3) <>"-Central-IT" Then
				If Left(CN(ubound(CN)-3),7) = "CEODIST" then
					redim Preserve arrGroup(Counter)
					arrGroup(Counter) = CN(ubound(CN)-3) & "\" & CN(ubound(CN)-4) & "\" & Right(CN(0),(Len(CN(0))-3))
					On Error Resume Next
					Set objOUCheck = GetObject("LDAP://OU=" & CN(ubound(CN)-4) & ", OU=" & CN(ubound(CN)-3) & ", OU=IFAS, OU=People, OU=UF, DC=ad, DC=ufl, DC=edu")
					If err.number <> "0" then
						redim Preserve arrGroup(Counter)
						arrGroup(Counter)= CN(ubound(CN)-3) & "\" & Right(CN(0),(Len(CN(0))-3))
						redim Preserve arrGroup(Counter)
						arrGroup(Counter) = CN(ubound(CN)-3) & "\" & CN(ubound(CN)-4) & "\" & Right(CN(0),(Len(CN(0))-3))
					End If
					On Error goto 0
				End If
			End If
		ElseIf CN(UBound(CN)-1) = "Groups" and Left(CN(0),9) = "CN=_IFAS-" then
			AutoGroup = split (CN(0), "-USERS_autoGS")
			If Len(AutoGroup(0)) <> "8" Then
				redim Preserve arrGroup(Counter)
				arrGroup(Counter) = Replace(Right(autogroup(0), (Len(AutoGroup(0))-9)), "-", "\") & "\" & Right(CN(0),(Len(CN(0))-3))
			End If
		End If
	End If

Once the arrays of groups and corresponding script paths have been created, the various group logon scripts
associated with that user are run. Since the IFAS groups are all prefaced by ". " by convention, and you cannot
have a file name that begins with that, the script removes it. The tests are done to separately handle users
within either the IFAS root OU or a sub-OU within IFAS.

'	***Executes group logon scripts
For each group in ArrGroup
	Group = Replace(Group, ". ","")
	GroupScript = "\\ad.ufl.edu\NETLOGON\IFAS\" & group  & ".VBS"
	If objFileSystem.FileExists(GroupScript) Then
		objShell.Run Chr(34) & GroupScript & Chr(34)
	End If

Then the any specific script for that user is also run.

'	***Executes user logon scripts
OU = Split (UserName, ",OU=")
If OU(ubound(OU)-2) = "IFAS" Then
	If Left(OU(ubound(OU)-4), 3) <> "CN=" then
		UserScript = "\\ad.ufl.edu\NETLOGON\IFAS\" & OU(ubound(OU)-3) & "\" & OU(ubound(OU)-4) & "\User\" & objNetwork.Username & ".VBS"
		UserScript = "\\ad.ufl.edu\NETLOGON\IFAS\" & OU(ubound(OU)-3) & "\User\" & objNetwork.Username & ".VBS"
	End If
	If objFileSystem.FileExists(UserScript) Then
		objShell.Run Chr(34) & UserScript & Chr(34)
	End If
End If

The next line is a change which Andrew Carey inserted during the December 2009 script update
As mentioned at top, this logs the network drives and printers that are being mapped at logon
into a database. This script was previously directly called from the logon scripts area of the
IFAS-Co-Managed User GPO (along with the actual IFAS login script) but had to be moved so that it
would run on Vista and Windows 7.

objShell.Run Chr(34) & "\\ad.ufl.edu\netlogon\IFAS\EnumMappings.vbs" & Chr(34),0,FALSE

This last large section is excluded for service accounts. This part of the code checks for a
password expiration and was written by Joe Gasper and Mike Kanofsky.

If Left(Username,6) <> "CN=IF-" then
	On Error Resume Next
	err.number = ""
	intNoticeDays = 14
	dtmADPwdSet = objUser.PasswordLastChanged
	dtmPwdSetDate = PwdSetDate(dtmADPwdSet)
	dtmPwdSetTime = PwdSetTime(dtmADPwdSet)
	dtmGLPwdExpired = objUser.Get("GLPwdExpired")
	dtmGLPwdExpiredDate = datevalue(left(dtmGLPwdExpired,10))

	If isdate(dtmGLPwdExpiredDate) Then
		strGLPwdExpiredValid = "true"
		strGLPwdExpiredValid = "false"
	End If

	If dtmGLPwdExpired = "" then
		wscript.echo "Password expiration not synced. Expiration time will be synced the next time password is changed."
	End if

	If strGLPwdExpiredValid = "true" then
		dtmGLPwdExpDate = left(objUser.GLPwdExpired,10)
		dtmGLPwdExpTime = right(objUser.GLPwdExpired,8)
		dtmToday =  FormatDateTime(Now(),2)
		dtmExpires = DateValue(FormatDateTime(Now(),2))-DateValue(Left(dtmGLPwdExpired,10))
		dtmExpiredays = datediff("d",now,dtmGLPwdExpDate)
		If Err.Number <> 0 Then
			If Err.Number = "-2147463155" Then
				dtmGLPwdExpired = "Not Set"
				dtmGLPwdExpired = "Unknown Error: " & Err.Number
			End If
		End If
	End If

	intIcon = VBInformation
	If (dtmExpiredays = 0)  and (strGLPwdExpiredValid = "true") then
		PwdChangeNow ()
		intIcon = vbCritical
		If (dtmExpiredays <= intNoticeDays) and (strGLPwdExpiredValid = "true")  then
			PwdChangeSoon ()
		End If
	End If
	Function PwdSetDate (varADPwdSet)
		dtmPwdSetYear  = datepart("yyyy",varADPwdSet)
		dtmPwdSetMonth = datepart("m",varADPwdSet)
		dtmPwdSetDay   = datepart("d",varADPwdSet)
		PwdSetDate =  dtmPwdSetMonth & "/" & dtmPwdSetDay &"/" & dtmPwdSetYear
	End Function

	Function PwdSetTime (dtmADPwdSet)
		dtmPwdSetHour  = datepart("h",objUser.PasswordLastChanged)
		dtmPwdSetMin   = datepart("n",objUser.PasswordLastChanged)
		dtmPwdSetSec   = datepart("s",objUser.PasswordLastChanged)
		PwdSetTime =  dtmPwdSetHour & ":" & dtmPwdSetMin &":" & dtmPwdSetSec
	End Function

	Function PwdChangeSoon ()
		strMsg = "Your GatorLink password will expire in " &  dtmExpiredays & " days on: " & dtmGLPwdExpDate & " at " & dtmGLPwdExpTime
		strMsgPwdSetTime= "You last set your GatorLink password on " & dtmPwdSetDate & " at " & dtmPwdSetTime
		strResetPass="Would you like to reset your password now at my.ufl.edu?"
		strMsgfull = strMsg & vbCrLf & strMsgPwdSetTime & vbCrLf &vbCrLf &  strResetPass
		intBoxType=vbYesNo + intIcon + vbDefaultButton2
		varMsgBox  = objShell.Popup(strMsgfull,10,"Password Expiration",intBoxType)
		Select Case varMsgBox
			Case vbYes
				objShell.Run "http://my.ufl.edu/psp/ps/EMPLOYEE/UF_PA_SSL/c/MAINTAIN_SECURITY.CHANGE_PASSWORD.GBL"
			Case vbNo
				strMsgRemind = "Remember that you will need to reset your password at http://my.ufl.edu before it expires"
				varMsgBox  = objShell.Popup(strMsgRemind,10,"Reminder",vbInformation)
	    End Select
	End Function

	Function PwdChangeNow ()
		strMsg = "Your GatorLink password has expired! You will be redirected to my.ufl.edu to reset it."
		varPopupBox = objShell.Popup(strMsg,3,"redirecting to my.ufl.edu...", vbExclamation)
		objShell.Run "http://my.ufl.edu/psp/ps/EMPLOYEE/UF_PA_SSL/c/MAINTAIN_SECURITY.CHANGE_PASSWORD.GBL"
	End Function
End If

last edited 8 March 2009 by Steve Lasley