Group Membership Based Windows Logon Scripts

This was done and written a while back – late February. Since then, all it’s needed is some cleansing of company specific names and wiki markup. Even though it was low-hanging fruit, I’ve only gotten around to it now.

Windows has the ability to run batch files (yes, dos-era batch files, with several years of extensions) at certain times based on definitions in active directory. Principally, these times are logon, and log off. Among the many things one might do with this, we are using it to map network drives with updated definitions, in case things change or new drives need to be added. Unfortunately, the drives which are mapped are not the same for all users.

Ways to assign a script: Per User

A logon script can be defined for a particular domain user, in that users properties – Active Directory Users and Computers/Users/(the user)/properties/profile/Logon script. This is marginally manageable for small domains, but still annoying if there are any major changes.

Logon scripts are located in a domain controller’s %SYSDIR%/SYSVOL/sysvol/(domain.name)/scripts

Finding all users with a certain script:

http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/Server/Q_23069895.html

Load AD users and computer and right click Saved Queries
Select New, Query
Give it an appropriate name and description
Leave the qeury root at the root of your domain (i.e. ..\domainname)
Click Define Query In the Find dropdown box, select Custom Search
Click the Advanced TAB
Paste this in there:
(&(objectCategory=user)(objectClass=user)(scriptPath=yoursoldlogonscriptname.bat))

Use !scriptPath... for inversion.

Group Polciy

Logon scripts can be set in group policy, (GPMC/Default Domain Policy/User Configuration/Windows Settings/Scripts (Logon/Logoff)) but then it must be assigned to an organizational unit, and users can only belong to one OU, possibly nested in strict hierarchy.

Scripts assigned by group policy must be stored in the group policy object itself. They can however, use absolute paths to reference the same netlogon share used by per-user scripts. \\domain-controller\netlogon\

Basic drive mapping

REM delete a drive, to make sure we can insert the new definition
net use x: /d

REM map the new address
net use x: \\server\share

We have several instances of these. At one point, there were about four different logon scripts, assigned to individual users, with such creative names as logon.bat, logon1.bat, and logon2.bat. With such meaningful identifiers, I had track down an active directory search trick to figure out what the heck was going on.

I refactored the scripts so that common drives were mapped in one batch file, called by master batch files for each type of user. It’s already more maintainable, I just have to go through and re-assign the logon script to every user in the company. As above, possible, but no fun. There is no obvious way to do this en masse.

Conditional Logic

In the course of looking for a batch-reassign, I ran across a useful program; ifmember.exe checks to see if the current user is a member of named groups, and returns the result in ERRORLEVEL, so you can branch on it in batch scripts. Despite being a simple little program, you have to promise your first-born to WGA to download it.

So now, you can do something like this:

ifmember "DOMAIN\ERP User"
IF NOT ERRORLEVEL 1 goto not_erp
net use m: /d
net use m: \\erp-server\erp
:not_erp

Actually, I already had factored batch files, so it looked something more like this:

ifmember "DOMAIN\ERP User"
IF NOT ERRORLEVEL 1 goto not_erp
call erp.bat
:not_erp

But you still have to repeat the whole ugly block five times, with minor variations. Can’t batch files take parameters?

ifmember "DOMAIN\%~1"
IF NOT ERRORLEVEL 1 goto nop
call %2.bat
:nop

That tilde is a clever hack of batch syntax to remove quotes for groups like “ERP User”

So our call looks like this:

call check.bat "ERP User" erp

A little too clever?

Huh, what if we called our batch file “ERP User.bat”? Now we only have to pass one parameter.

Wouldn’t it be nice if we could just iterate over the file names? Try for /? at a command prompt some time; you never really realize what crazy stuff windows has these days.

FOR %%F IN (\\domain-server\netlogon\groups\*.bat) DO call
\\domain-server\netlogon\check.bat "%%~nF"

%% is a necessary escape to get %F. ~n gives us just the base file name. All the other hardcoded regular expressions are listed in for /?

There are a few other absolute paths in check.bat to get around the uncertain current directory when the script runs.

\\domain-server\netlogon\ifmember "DOMAIN\%~1"
IF NOT ERRORLEVEL 1 goto nop
call \\domain-server\netlogon\groups\%1.bat
:nop

At this point, I copied the main script to group policy, set it for all users, and removed the individual logon scripts from their profiles.

Posted Sunday, June 29th, 2008 under Essay.

Tags:

4 comments