Most Windows sysadmins use a Group Policy object to launch their login script. You may have noticed that Windows 7 and Vista fail to connect network drives defined in the login script if the user is a local admin and UAC is enabled. The script completes successfully and no error condition is encountered, but no drive mappings. Run it again manually and everything’s fine.
This is in fact by design, and it’s caused by the way UAC works. When you’re a member of the Administrators group and you log in, your account is busted down to a non-privileged user by UAC. This running context is completely separate from the context you get when you right-click Command Prompt and launch as an administrator. As you’ll probably have noticed, network drives connected in one context are not visible in the other. The problem is that GPO-based login scripts are being executed in the Administrator context – not the ordinary user context.
So, how do we get it working? Microsoft offer an unsupported kludge in KB937624 – getting around the issue by weakening Windows security and forcing network connections to be common to both user contexts. They carefully designed this not to be the case, so modifying the behaviour does seem like a bad idea.
However, Microsoft’s preferred solution (example launchapp.wsf script in the appendix of that page) is to use the GPO-triggered script to set a Scheduled Task to run immediately in the other (non-admin) context, and run your login script from there – much better.
The reasons I’m writing all this up are that:
- Microsoft’s example script has some illegal character/line-wrap in there – copying and pasting it won’t work!
- This method doesn’t work with XP so some forking logic is needed if you have mixed clients.
- They make no allowances for multiple admin/non-admin users sharing the same PC.
- This appears to be Microsoft’s sole example document of how to program using the Task Scheduler 2.0 API, and it neglects to define several absolutely essential object properties if you want to do something more useful than simply open Notepad.
My particular problem was that I needed to launch a script with a space character in the path, e.g.:
cscript.exe //nologo "\\domain.com\netlogon\departmentX users\logon.vbs"
For me changing this path name was not an option as there were many other dependencies. I spent a long time wondering why the API was eating my quotes as I fed it the above string and I tried various ways to escape them. Eventually I launched the Scheduled Tasks MMC tool (click on the root of Task Scheduler Library to see the job). Looking in the Action properties I realised that there are separate fields for the starting directory and for the arguments. Manually editing the job to use these got it working:
Frustratingly, there don’t seem to be any examples on the Web showing you how to populate these fields programmatically. Guessing the Arguments property was straighforward but StartIn is not a valid propery name. I read on Wikipedia that Task Scheduler 2.0 uses XML to store its jobs so I exported the job and viewed it. Luckily they used consistent property names in the XML (Arguments and WorkingDirectory) and I was able to set them in VBScript (see highlighted lines below).
There was an additional complication though. Once a user has run the Scheduled Task, it’s left behind on the system. In my initial testing this wasn’t a problem because I was testing admin users, but I soon discovered that a non-privileged user cannot delete and recreate the task if one created by another user already exists. So we need only schedule the task if the current user is running in an elevated security context. By far the simplest method is to parse the output of the whoami /groups command, as explained in this post:
http://blogs.technet.com/b/jhoward/archive/2008/11/19/how-to-detect-uac-elevation-from-vbscript.aspx
UPDATE – added some logic to prevent the login script from launching for RemoteApp sessions to Terminal Servers.
'launchapp.vbs, modified from Microsoft's launchapp.wsf 'launches a process as interactive user, NOT as the elevated privilege user context Option Explicit Const TriggerTypeRegistration = 7 Const ActionTypeExecutable = 0 Const FlagTaskCreate = 2 Const LogonTypeInteractive = 3 Dim strWorkingDirectory, strHostname, strOSVer, colProcessList, strUser, strDomain Dim objNetwork, objComputer, objShell, objExec, objWMI, objItem, strScriptName, strStdOut strWorkingDirectory = "\\domain.com\netlogon\DepartmentX Users" 'launch this login script strScriptName = "logon.vbs" Set objNetwork = CreateObject("WScript.Network") Set objShell = CreateObject("WScript.Shell") Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") strHostname = objNetwork.ComputerName Set objComputer = GetObject("WinNT://" & strHostname & ",computer") strOSVer = objComputer.OperatingSystemVersion If strOSVer >= "6.0" Then If IsElevated() Then 'Machine has UAC and user is elevated so use LAUNCHAPP.WSF Task Scheduler method based 'on appendix from http://technet.microsoft.com/en-us/library/cc766208(WS.10).aspx 'Are we launched in a RemoteApp session on a Terminal Server? If so, quit. Set colProcessList = objWMI.ExecQuery("Select * from Win32_Process Where Name = 'rdpshell.exe'") For Each objItem In colProcessList objItem.GetOwner strUser, strDomain 'If we're an admin we can see all users' processes so we need to check only our own If strUser = objNetwork.UserName Then WScript.Quit End If Next LaunchApp Else 'User is not elevated, so launch the script normally objShell.Run "cscript.exe //nologo " & Chr(34) & strWorkingDirectory & "\" & strScriptName & Chr(34), 1 End If Else 'This is a Windows XP/2003 machine, so launch the script normally objShell.Run "cscript.exe //nologo " & Chr(34) & strWorkingDirectory & "\" & strScriptName & Chr(34), 1 End If Set objNetwork = nothing Set objComputer = nothing Set objShell = nothing Function IsElevated() IsElevated = False strStdOut = "" Set objExec = objShell.Exec ("whoami /groups") Do While (objExec.Status = 0) WScript.Sleep 100 If Not objExec.StdOut.AtEndOfStream Then strStdOut = strStdOut & objExec.StdOut.ReadAll End If Loop If InStr(strStdOut,"S-1-16-12288") Then IsElevated = True End If Set objExec = nothing End Function Sub LaunchApp Dim objTaskService Dim strTaskName, rootFolder, taskDefinition, triggers, trigger, Action 'Create the TaskService object Set objTaskService = CreateObject("Schedule.Service") Call objTaskService.Connect() strTaskName = "Launch App As Interactive User" 'Get a folder to create a task definition in Set rootFolder = objTaskService.GetFolder("\") 'Delete the task if already present On Error Resume Next Call rootFolder.DeleteTask(strTaskName, 0) Err.Clear 'Create the new task Set taskDefinition = objTaskService.NewTask(0) 'Create a registration trigger Set triggers = taskDefinition.Triggers Set trigger = triggers.Create(TriggerTypeRegistration) 'Create the action for the task to execute Set Action = taskDefinition.Actions.Create(ActionTypeExecutable) Action.Path = "cscript.exe" Action.Arguments = "//nologo " & strScriptName Action.WorkingDirectory = strWorkingDirectory 'Register (create) the task call rootFolder.RegisterTaskDefinition(strTaskName, taskDefinition, FlagTaskCreate,,, LogonTypeInteractive) Set objTaskService = nothing End Sub
There’s a bug in your logic above. Line 41 should be a ELSE instead of END IF.
Thanks Eric. I edited it a couple of times and hadn’t spotted that. Note the extra End If on line 44. I had tried to roll all of it into one single condition but the whoami.exe command is missing on XP machines so you can’t run the IsElevated function.
We are facing the similar issue in one of our client place recently, and their environment is
1. The file server is not part of the AD Domain
2. Windows 7 users can manually execute the login script and mapped to the file server
3. Users are NOT part of the local administrator group
The login script defined in GPO completed successfully, but users will only see a RED Cross on the mapped network drive.
After several days of finding, the root cause of this issues due to the “Act as part of the operating system” configure for only domain users and administrator. Once we disable this in the GPO, this issue had been resolved.
Hope the information helps.
Can this script be made to act like the standard launchapp.wsf script so that you do not have to hard-code the path and script variables?
You are free to modify it however you want. I’m not going to customize it for you though. :)
When the the file is run as .vbs with a windows 7 client I get:
Script: launchapp.vbs
Line: 31
Char: 5
Error: Object required: ”
Code: 800A01A8
Source: Microsoft VBScript runtime error
Still works fine with XP clients.
Definitely works on XP/Win7x86/Win7x64 for me. Are you sure you’re copying the text properly (use the icons at the top of the script pane which appear when you mouse over)? If not then perhaps you have some group policy set that stops users querying WMI, since line 31 checks the running process list through WMI.
There is no line to create the objWMI object. The script needs to include something like:
Set objWMI = GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2”)
That should clear up the “Object Required” issue.
And the reason it works fine on XP is because that code isn’t run on XP, only on strOSVer >= 6.0″, i.e. Vista or greater.
Well spotted William – thanks. I only added the RemoteApp session detection bit later in my production environment, and edited the script posted here, but forgetting that line. Oops!
I determined the error is from users that login with an administrative context. That is their domain login is a member of the local administrators group so they have elevated privileges. The users that do not work fine. Any tips on remedying this?
Thanks
This definitely works for me, and I’m a local admin. As I mentioned, it looks to me like you have something stopping you connecting to WMI (which is what happens on line 31) – perhaps an ACL in Group Policy is stopping this. Run the Group Policy Modelling tool from the GPMC and check.
How about you download the scriptomatic tool here:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=09dfc342-648b-4119-b7eb-783b0f7d1178
and query some WMI objects, specifically say the running processes. If that doesn’t work then you have a generic problem with your workstation security settings.
If all else fails Stephen, you can delete lines 29-39 if you don’t use RemoteApp on terminal servers in your environment.
Thanks Patters, removing the RemoteApp portion did the trick!
Having this same problem in a major way at my company. Trying to move all workstations and render nodes to win7x64 before upgrading domain controllers from win2k3 SP2. Bletch. such a pain.
In response to Stephen: If you care about getting the terminal services bit of the code working, I got this script running by setting the objWMI above where all the other objects are declared:
Set objShell = CreateObject(“WScript.Shell”)
Set objWMI = GetObject(“winmgmts:”)
strHostname = objNetwork.ComputerName
Seems to work,
HOWEVER, here’s my question. When I set it as a domain group policy login script, it still fails to mount any drives. If I navigate all the way to the folder where the scripts are located, and run the vbs file manually, it works fine. I even see the various taskeng.exe shells running when a user logs in. But the drives won’t actually mount until the computer is more… awake? happy? I’m honestly not sure. Is win7 trying to execute this script before it is fully established on the network, and if so, is there any way to build a 5 second timer or something slick in here to fix it?
Any help appreciated! Hope this thread isn’t dead.
Something must be going wrong, because this script is designed to prevent the very thing you’re talking about. Are you sure that your workstations are not invoking several different scripts? You mention multiple taskeng windows appearing. When the drives fail to mount, can you see the drive letters when you launch a command prompt as Administrator?
Hey Patters, thanks for your reply.
It’s at the point where, if I’m really lucky, the AD pushing the script through Default Domain Policy will work 1 in maybe 10 times. The script works 100% if I navigate to it and double click it.
I found and added a 5 second timer in case it was so problem with getting the network online, which was dumb… given that it doesn’t have a problem finding the vbs script… on the network.
UAC is turned off completely on the machines I’ve been testing on. The accounts I log into to test are added from our domain and then set as local admins.
Can’t CD to the drives in CMD as Admin. Please let me know if I can provide any helpful details.
Thanks again!
Try it again with UAC enabled. The script was intended for it being enabled…
No love with UAC back at original level.
I might also mention that I’m running these under the user logon default policy, not the machine startup default policy, if it matters, if it’s not obvious.
Is there any way I can modify the script to just leave itself up on screen, like a echo on type thing. Then I could actually see if it’s posting an error.
Best,
Well you could launch it from policy with something like:
cscript “\\domain\netlogon\scripts\launchapp.vbs” > c:\temp\error.log 2>&1
The 2>&1 redirects standard error to the file, together with standard output.
Patters, thanks again for all your help.
Unfortunately we stumbled upon a solution that just works, no vBS, every time.
Win2k8 R2. Well, we didn’t discover it. I just finally convinced them upgrading was a must.
Shouldn’t disabling the UAC all together make this a far simpler affair? do i really need to enable it to get this to run properly? I would really rather not…
I am in the same boat as Hot. If i log in as a standard user, member of only the domain users group, with no admin rights what so ever the script runs, but still fails to mount the drives. Once the machine is logged in, if i drill down to the domain\sysvol\policies\{sid}\scripts…. etc i can double click and run the .vbs just fine.
I also have noticed a bit of latency with the drives mapping but I also assume that is part in the complexity of my actual login script. I have left UAC enabled on all of my hosts and User and Administrators map fine on WinXP and Win7 hosts.
Have anyone noticed that if Task Scheduler launch the logon.vbs script that has a objShell.Run syntax to run another script, you will basically be prompted with the “Unknown Publisher” security warning when the new script is run. This doesn’t happen if the logon.vbs script is ran via the actual logon script GPO, only in Task Scheduler. This is giving me headaches as I have the logon.vbs calling some other scripts for users with administrative rights.
Hi Eric,
I have exactly the same problem as you, Did you find a solution ?
Thank you
Rather late reply but hopefully it helps
http://support.microsoft.com/kb/889815
http://www.ithastobecool.com/2009/12/23/how-to-suppress-the-open-file-dialog-zone-checking/
Hi,
I don’t know if this post is still being checked, but I recently implemented this script into our environment, and it worked almost very well. We have a mixture of laptops and desktops. The crazy thing seems to be that in XP, on laptops it worked just fine, but on desktops, it almost completely failed to map anyone’s drives (300+ users). Any idea why this would be? I can’t imagine this script is hardware-dependant.
Thanks!
Sounds like it could be down to some kind of Group Policy difference between the two types of machine in your environment perhaps?
No. And it’s funny that no one seems to have this issue except for us. I haven’t really tried it but I did play around with the idea of creating multiple tasks in the Task Scheduler for each objShell.Run command.. What do you think?
Forget the launchapp. Add the registry key:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
Create “EnableLinkedConnections” REG_DWORD, set value to 1
This allows “muliple level” accounts to see the mappings made during logon by a script.
The ultimate catch here is that this does not only affect Administrators but the “dummy” group Power Users as well.
Have fun.
Peter
Doing that is a really bad idea. You’re merging two different security contexts, and disabling a security feature that Microsoft went out of their way to design. It’s not solving a problem, it’s setting up a huge one for later. It also clearly states in Microsoft’s KB article for this workaround (referenced in the 3rd paragraph of my post) that it’s unsupported – not a great situation for a production infrastructure.
That’s all well and good patters, but what are we supposed to do?!
Setting up mapped drives for multiple user types in a W2K3 domain is about as common a task as there is, & yet there is a Documented Problem stretching back to Vista on this!
The registry hack isn’t ideal, but the workaround referenced in the technet article doesn’t work!!!!
Typically poor form from Microsoft…
Miscrosoft example script doesn’t work as is, & the echo lines are unnecessary & annoying.
I’ve spent over an hour looking at various forums & the only reliable solution seems to be the registry hack.
Options seem to be:
i. the launchapp.wsf which doesn’t work for many users ( http://technet.microsoft.com/en-us/library/cc766208%28WS.10%29.aspx )
ii. install additional power tools to elevate the script: ( http://social.technet.microsoft.com/Forums/en-IE/winserverGP/thread/ca9681db-8483-49c6-bb67-de52068fd494 )
iii. install RSAT to Windows 7 to manage the domain ( http://www.sevenforums.com/network-sharing/21644-login-script-problems-2.html )
iv. use the registry hack – referenced by MS themselves – http://support.microsoft.com/default.aspx?scid=kb;EN-US;937624
A Frustrated Support Engineer
Pingback: Problème de script de lecteurs réseaux par GPO sous Windows 7 : La Solution « Kevin PECQUET
It doesn’t work if a user is a member of “Power User” Group. How is it possible?
Pingback: What does registry setting EnableLinkedConnections do on a technical level? - Admins Goodies
Pingback: Working in the new year
Wow, great script and many thanks for the time and effort you put into this. I had been wrestling with this for a few days now as we try to roll out Windows 7. I had read all the stuff saying that Admin users wouldn’t see their mapped drives because of the UAC problem. In our environment though, it was standard users who could not get mapped drives, but Admin users worked fine. But implementing your script in a Group Policy User Login script seems to have resolved it for us.
Tim
I did not want to use the MS reg hack, but also I did not want to use Task Scheduler as I want to make sure the logon sciprt runs before the user gets the desktop. I found a simply modification to my existing logon scirpt solved the problem.
In the existing logon script where you have code such as:
objNetwork.MapNetworkDrive strDriveLetter, strUNC
objNetwork.RemoveNetworkDrive strDriveLetter
Replace with:
objShell.Run “net use ” & strDriveLetter & ” ” & chr(34) & strUNC & Chr(34),0,True
objShell.Run “net use ” & strDriveLetter & ” /d”,0,True
This code maps drives for admins & non-admins alike and should be ok on any OS although I only tested on Win7 myself.
I believe this works as the command line items called by the objShell.Run command are excecuted with the user token rather than the admin token (whereas the VBS is runnign in admin token), eitherway it works for me and seemed the simplest solution to the problem.
Russ
Russ, this doesn’t work. I get an error saying Object required: “.
Code 800A01A8. I used your exact net use line to connect the drive and even changed my variables to match yours. Any ideas?
Worked great, thanks. I’ve been putting off fixing this problem for months… Thanks again for posting the solution.
Its great that others are willing to share their efforts, I am using this to add an extra ‘home drive’ for a migration of staff (teachers) to a new environment. We use group policy preferences usually and this works a treat for me.
Wow, leave it to the brilliant folks at Microsoft to mess up something as simple as logon scripts! Thanks for the write up, this was driving me nuts but I never did get around to diving in to the “why” behind the problem.
As another solution, you can still use the old-style logon scripts by setting in User Profile…especially for things that don’t need to operate on users within a specific OU.
please try and clear dfs cache from the windows 7 pc if you are having dfs deployed in your infrastructure
Is there something that can be added to make the scheduled task Hidden? I’d prefer the users didn’t see the taskeng.exe window popup when they log in to their computer.
Thanks for the script! In my case, the scheduled task took care of the elevated Win7 users, but did not work for non-elevated ones, or on WinXP. The script appeared to run, but drives were not getting mapped. Turns out that the fix was to disable the “run logon scripts syncronously” property in the GPO, as mentioned here: http://joshuamorgan.wordpress.com/2012/01/30/windows-7-wscript-shell-run-method-from-logon-script/ .
Hope this helps somebody out there.
chris
Pingback: Answer: Why won't my logon scripts map drives under Windows 7? #fix #answer #programming | Good Answer
Pingback: How to: Why won't my logon scripts map drives under Windows 7? #answer #it #dev | IT Info
Pingback: Answer: Why won't my logon scripts map drives under Windows 7? #solution #answer #it | SevenNet
Pingback: Answer: What does registry setting EnableLinkedConnections do on a technical level? #solution #computers #answer | IT Info
Pingback: ITEA » Windows 10 – Why is my logon script not mapping any drives?