mbt masai
 
Welcome !
         

                                
After experiencing a lot of down time, We decided to move this site to CrystalTech.com. CrystalTech.com is powered by only the finest Windows servers providing the best performance, reliability, and value anywhere.

 Logon Scripts under Vista

Author Message
turranx

  • Total Posts : 59
  • Scores: 0
  • Reward points : 0
  • Joined: 2/7/2006
  • Location: Cincinnati, OH
  • Status: offline
Logon Scripts under Vista Tuesday, November 25, 2008 11:22 AM (permalink)
0
Windows Vista includes a new feature called the User Account Control (UAC).  When this feature is enabled, it enforces a policy that makes a logged in user run with minimal rights.  This is called Least User Access or Least Privileged User Account (LUA).  If you perform a search on the Internet for "Vista Logon Script" you will find many unhappy SysAdmins grumbling on forums.  One of the more popular complaints is that drive mappings are no longer being made.  One of the more likely reasons why a logon script is not "executing correctly" is because of how your logon session is affected by the UAC.  Here is an excerpt from some Microsoft documentation that precisely describes the problem:


http://technet.microsoft.com/en-us/library/cc766208.aspx

By default, all users logging on to Windows Vista use their full token to process Group Policy and logon scripts. However, they use their limited user token to load the desktop and all subsequent processes. Nonadministrative limited and elevated tokens are mostly identical, with regard to privileges and groups. Therefore, a process started with a nonadministrative limited user token can view processes started with a nonadministrative elevated token. Windows allows this because the viewing application does not require any elevation to view the process started with the elevated token.

Windows processes a locally logging on administrator the same way. Group Policy and logon scripts process using the elevated user token, and the desktop and all subsequent processes use the limited token. However, there is a privilege difference between the limited and elevated user token. Therefore, Windows restricts processes started with a limited token from the ability to share information with processes started with the elevated token.

UAC may prevent Group Policy logon scripts from appearing to work properly. For example, a domain environment contains a GPO that includes a logon script to map network drives. A nonadministrative user logs on to the domain from a Windows Vista computer. After Windows Vista loads the desktop, the nonadministrative user starts Windows Explorer. The user sees their mapped drives. Under the same environment, an administrative user logs on to the domain from a Windows Vista computer. After Windows Vista loads the desktop, the administrative user starts Windows Explorer. The user does not see their mapped drives.


The solution to this problem is not to turn off UAC (as much as we would like to), but rather to run the logon scripts with limited credentials that match those used to load the Vista desktop.  This possible by getting Vista's Task Scheduler involved.  The quoted document goes on to describe how to edit your Group Policy Objects (Domain or Local) to use "launchapp.wsf".  Launchapp.wsf creates a new task.   The action of this task is to run your logon script.  The task is set to "Launch App As Interactive User"; translation: run with limited credentials.  Finally, the task is set to execute upon creation.  As soon as Launchapp.wsf finishes creating the task, it executes.  Your logon script has just executed with the same limited credentials as those used to load the Vista desktop while the desktop is being loaded; that is to say "at logon".

If you open the link to the quoted document  and search for the second instance of "launchapp.wsf", you will find instructions how to set up your Group Policy Object to use launchapp.wsf.  Within the same quoted document, search for "Appendix A:"; Microsoft was nice enough to write and post launchapp.wsf for us.

NOTE: UAC enabled is a requirement of the Federal Desktop Core Configuration (FDCC).  For more information on FDCC, please visit http://nvd.nist.gov/fdcc/index.cfm

Here is a picture of Vista's Task Scheduler after a logon script has run using launchapp.wsf.




The task that is highlighted in blue is the result of launchapp.wsf.  Launchapp.wsf is pretty good except for two flaws:
  1. The name is pretty generic. What if you had two scripts that needed to run at logon?
  2. launchapp.wsf fails with flying colors when you have more than one logon script that uses launchapp.wsf.
  3. launchapp.wsf is not mixed-environment friendly.


Why does launchapp.wsf fail when you have two or more logon scripts that depend upon it?  Because of these two lines of code:

 call rootFolder.DeleteTask(strTaskName, 0)
 
 ...
 
 call rootFolder.RegisterTaskDefinition( _
 strTaskName, taskDefinition, FlagTaskCreate, _
 ,, LogonTypeInteractive)
 


Each time launchapp.wsf runs, it first attempts to delete any existing tasks with the name "Launch App As Interactive User".  Then later on, it attempts to create a task called "Launch App As Interactive User".  So you tell me what will happen when two or more scripts try to simultaneously delete / create tasks with the name "Launch App As Interactive User"?!? 

Launchapp.wsf relies upon functionality that in Vista's Task Scheduler that doesn't exist within Windows 2000.  So if you were to deploy launchapp.wsf in its current form into a domain GPO that was enforced across Windows 2000, Windows XP, and Windows Vista machines, it would halt with an error on at least the Windows 2000 boxes (Professional & Server).

I have addressed all three issues with my own doctored-up version of launchapp.wsf.  I have posted my version below.  I also added a check to bypass Vista's Task Scheduler if UAC is disabled.

<job>
     <script language="VBScript">
 Option Explicit
 On Error Resume Next
 'More Details can be found here:
 'http://technet.microsoft.com/en-us/library/cc766208.aspx
 
 'Background Information: 
 'NOTE: This text (below) is taken directly from the link
 '      above and is quite possibly one of the most 
 '      important things you will ever read about scripting
 '      for Vista.
 ' Consumption of Windows Vista settings
 ' Group Policy Scripts can fail due to User Account Control
 ' 
 ' The main goal of User Account Control (UAC) is to lessen 
 ' the exposure and attack surface of the operating system. 
 ' UAC does this by requiring all users to run in standard 
 ' user mode. This limit minimizes the ability for users To 
 ' make changes that could destabilize their computers Or 
 ' unintentionally expose the network to viruses through 
 ' undetected malicious software (also called malware) that 
 ' has infected their computer.
 ' 
 ' With UAC, you can run most applications, components, And 
 ' processes with a limited privilege, but have "elevation 
 ' potential" for specific administrative tasks and 
 ' application functions. Windows accomplishes this by using 
 ' two access tokens for each user: limited and elevated 
 ' access tokens. Access tokens identify the user, the user's 
 ' groups, and the user's privileges. The system uses access 
 ' tokens to control access to securable objects and To 
 ' control the ability of the user to perform various 
 ' system-related operations on the local computer.
 ' 
 ' An elevated token, for a local administrator, includes And 
 ' enables all of the administrative privileges. UAC requires 
 ' local administrators to use their elevated token when 
 ' attempting to perform a system-only task or administrative 
 ' task. A limited token, for a local administrator, includes 
 ' all of the administrative privileges; however, these 
 ' privileges are disabled. This allows Windows to view the 
 ' administrative user and a normal user, with the option To 
 ' elevate their privileges.
 ' 
 ' By default, all users logging on to Windows Vista use 
 ' their full token to process Group Policy and logon scripts. 
 ' However, they use their limited user token to load the 
 ' desktop and all subsequent processes. Nonadministrative 
 ' limited and elevated tokens are mostly identical, With 
 ' regard to privileges and groups. Therefore, a process 
 ' started with a nonadministrative limited user token can 
 ' view processes started with a nonadministrative elevated 
 ' token. Windows allows this because the viewing application 
 ' does not require any elevation to view the process started 
 ' with the elevated token.
 ' 
 ' Windows processes a locally logging on administrator the 
 ' same way. Group Policy and logon scripts process using the 
 ' elevated user token, and the desktop and all subsequent 
 ' processes use the limited token. However, there is a 
 ' privilege difference between the limited and elevated user 
 ' token. Therefore, Windows restricts processes started With 
 ' a limited token from the ability to share information With 
 ' processes started with the elevated token.
 ' 
 ' UAC may prevent Group Policy logon scripts from appearing 
 ' to work properly. For example, a domain environment 
 ' contains a GPO that includes a logon script to map network 
 ' drives. A nonadministrative user logs on to the domain from 
 ' a Windows Vista computer. After Windows Vista loads the 
 ' desktop, the nonadministrative user starts Windows 
 ' Explorer. The user sees their mapped drives. Under the same 
 ' environment, an administrative user logs on to the domain 
 ' from a Windows Vista computer. After Windows Vista loads 
 ' the desktop, the administrative user starts Windows 
 ' Explorer. The user does not see their mapped drives.
 ' 
 ' When the administrative user logs on, Windows processes the 
 ' logon scripts using the elevated token. The script actually 
 ' works and maps the drive. However, Windows blocks the view 
 ' of the mapped network drives because the desktop uses the 
 ' limited token while the drives were mapped using the 
 ' elevated token.
 ' 
 ' To get around this issue, administrative users should map 
 ' network drives under the limited user token. This mapping 
 ' is accomplished by using the launchapp.wsf script shown In 
 ' Appendix A, which works by scheduling the commands using 
 ' the task scheduler. The task scheduler launches the script 
 ' under the administrative full token, thereby allowing 
 ' Windows Explorer, other limited token processes, and the 
 ' elevated token process to view the mapped network drives.
 
 
 '================================
 '       Define Constants
 '================================
 const TriggerTypeRegistration = 7
 const ActionTypeExecutable = 0 
 const FlagTaskCreate = 2 
 const LogonTypeInteractive = 3 
 
 
 '================================
 '        Define Variants
 '================================
 Dim strAppPath      'The full path and script name of what Is
                     ' to be executed.  Think "UNC Path".
 Dim boolDebug       'Enables / Disables comments to the screen
 Dim objService      'An object of something that interacts
                     ' With Vista's Task Scheduler Service
 Dim strTaskName     'The Task's Name
 Dim rootFolder      'The task definition will reside in this folder
 Dim taskDefinition  'The task that will be run with reduced credentials
 Dim triggers        'A reference to the triggers functionality
                     ' within the task object 'taskDefinition'
 Dim trigger         'The act of creating a trigger returns an object
                     ' The sole purpose of this Variant is to catch
                     ' the returning object. Nothing else is done with
                     ' it during the life of the script.
 Dim Action          'The action of the trigger.
 
 
 
 '================================
 '       Populate Variants
 '================================
 strAppPath = WScript.Arguments(0)
 boolDebug = False
 strTaskName = "Launch App As Interactive User - " & Split(strAppPath,"\")(Ubound(Split(strAppPath,"\")))
 
 
 
 '================================
 '      Check prerequisites 
 '       before continuing
 '================================
 If WScript.Arguments.Length <> 1 Then
     If boolDebug Then Wscript.Echo "Usage: cscript launchapp.wsf <AppPath>" 
     WScript.Quit
 End If
 
 If Is_UAC_Enabled(".") = False Then
     If boolDebug Then Wscript.Echo _
         "Vista's UAC (User Account Control) is not enabled. " & _
         VbCrLf & "Running code without Task Scheduler using Cscript."
     Run_Command Wscript.Arguments(0)
     WScript.Quit
 End If
 
 
 
 
 
 '================================
 '           Main Code
 '================================
 
 'This block of code connects to Vista's Task
 ' Scheduler service and removes the task that
 ' will be installed if it is already installed.
 ' An error might be generated.  Catch and 
 ' clear it.
 Set objService = CreateObject("Schedule.Service")
 call objService.Connect()
 Set rootFolder = objService.GetFolder("\")
 On Error Resume Next
 call rootFolder.DeleteTask(strTaskName, 0)
 If Err.Number <> 0 Then Err.Clear       
 'On Error Goto 0
 
 'Create a new Task.  Access its Trigger 
 ' properties.  Set the task to trigger
 ' (and therefore execute) upon registration.
 Set taskDefinition = objService.NewTask(0) 
 Set triggers = taskDefinition.triggers
 Set trigger = triggers.Create(TriggerTypeRegistration) 
 
 'Add an action to the task.
 'As best as I can figure it, 'Action' is not receiving a
 ' newly generated object from 'taskDefinition', but rather
 ' is being told to act as a "pointer" to an object within
 ' 'taskDefinition'.  This is why 'Action' does not appear
 ' in the command "call rootFolder.RegisterTaskDefinition()"
 ' that comes up in a few lines.  By editing 'Action.Path',
 ' you are really editing something within 'taskDefinition'.
 Set Action = taskDefinition.Actions.Create( ActionTypeExecutable )
 Action.Path = strAppPath
 If boolDebug Then Wscript.Echo "Task definition created. About to submit the task..." & _
                                vbcrlf & vbcrlf & "If the creation of the task fails then the" & _
                                vbcrlf & "user is probably not an Administrator." & _
                                vbcrlf & "The command will be run using objShell.Run."
 
 'Register (create) the task.
 ' Notice the inclusion of 'LogonTypeInteractive'.
 ' Now the script that was passed to this script as an
 ' argument will run with the reduced credentials.
 call rootFolder.RegisterTaskDefinition( _
 strTaskName, taskDefinition, FlagTaskCreate, _
 ,, LogonTypeInteractive)
 If Err.Number = 0 Then
     If boolDebug Then Wscript.Echo "Task submitted."
 Else
     Run_Command Wscript.Arguments(0)
     If boolDebug Then Wscript.Echo "Command Was Run without Task Scheduler"
 end If
 
 WScript.Quit
 
 
 
 '============================
 'Is_UAC_Enabled
 '============================
 Function Is_UAC_Enabled (strComputer)
     'Created: Nov 25th 2008
     '
     'Revisions:
     '(Nov 25th 2008) - Writing Function
     '
      'Description: Call to see if Vista's UAC Enabled?
      '
      'INPUT: strComputer -> A string
      '                       May contain a computer name or "." for local
      'Output: Return Value -> True, LUA is Enabled
      '                     -> False, LUA is NOT Enabled
      '
     Const HKLM = &H80000002
     
     Dim strKeyPath, strEntryName, strValue
     Dim objRegistry
     
     Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
     Is_UAC_Enabled = False
     strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
     strEntryName = "EnableLUA"
     strValue = ""
     
     objRegistry.GetDWORDValue HKLM,strKeyPath,strEntryName,strValue 
     Select Case strValue
         Case 1
             Is_UAC_Enabled = True
         Case 0
             Is_UAC_Enabled = False
         Case Else
             Is_UAC_Enabled = False
     End Select
 End Function
 
 
 
 '============================
 'Run_Command
 '============================
 Sub Run_Command(strCommand)
     'Created: Nov 25th 2008
     '
     'Revisions:
     '(Nov 25th 2008) - Writing Function
     '(Nov 26th 2008) - Call Cscript Interpreter if command is a script file
     '                - Make objShell.Run windows visible if boolDebug is True
     '
      'Description: Call to see if Vista's UAC Enabled?
      '
      'INPUT: strComputer -> A string
      '                       May contain a computer name or "." for local
      'Output: Return Value -> True, LUA is Enabled
      '                     -> False, LUA is NOT Enabled
      '
     Dim objShell
     
     Set objShell = WScript.CreateObject("WScript.Shell")   
     Select Case Lcase(Right(strCommand,4))
         Case ".vbs"
                 strCommand = "%systemroot%\system32\cscript.exe " & strCommand
         Case ".wsf"
                 strCommand = "%systemroot%\system32\cscript.exe " & strCommand
         Case ".ps1"
         Case Else
     End Select
     
     'Zero Hides the window and activates another window. 
     'False does not wait for the run window to finish executing
     If boolDebug Then WScript.Echo "About to start: " & vbcrlf & vbcrlf & _
                                    vbtab & strCommand & vbtab & _
                                    vbcrlf & vbcrlf & "without the task scheduler."
     If boolDebug Then
         'Run the command in a visible window
         objShell.Run strCommand, 1, True
     Else
         'Run the command in a hidden window
         objShell.Run strcommand, 0, True
     End If
     Set objShell = Nothing
 
 End Sub
     </script>
 </job>
 
 








Normally I stick to posting content that I have created; I don't like rehashing someone else's work.  I could probably find a two dozen scripters that almost verbatim copied (and reposted as their own) Microsoft's MSDN documentation on how to run a program with objShell.Run.  But after spending two days trying to track down why our Vista workstations were behaving like this, I found this article and had to share it.  I hope you benefit from it.

(Woohoo!  My 42nd post!  42: The Ultimate Answer to the Ultimate Question of Life, the Universe, and Everything.)
<message edited by turranx on Wednesday, November 26, 2008 11:38 AM>
Microsoft Windows 2000 Scripting Guide - The best book for newbie scripters
http://www.myspace.com/Evil__Overlord
#1
    turranx

    • Total Posts : 59
    • Scores: 0
    • Reward points : 0
    • Joined: 2/7/2006
    • Location: Cincinnati, OH
    • Status: offline
    Re:Logon Scripts under Vista Friday, September 25, 2009 4:02 AM (permalink)
    0
    I have an update...

    ~Multi-user Environment Warning~
    On 6/26/2009, the author discovered a problem with this process's behavior in a multi-user environment: ie. "Terminal Server" for Windows Server 2008 Release 1. When an Administrator runs the code, he is able to overwrite other Scheduled Tasks where as a general user cannot.  Therefore this will work: Admin1 logs in all of his logon scripts execute properly by creating or refreshing previous scheduled tasks.  Then Admin2 logs in.  His logon scripts also execute properly because he has full privileges over all scheduled tasks. Now along comes User1.  He logs in but none of his logon scripts execute because he cannot overwrite the scheduled tasks that were previously created by Admin1. The only way I've found to get around this hiccup is to append a unique ID to the end of each task name. Something like the user ID or full user name.

    ~Terminal Server Security Settings~
    7/1/2009.  I was still having massive issues with this code in a Terminal Server environment.  ~Sometimes~ users were not able to "recreate" jobs they created on their last login. For the life of me I couldn't figure out why.  Because documentation that could explain this behavior is a little thin, I had to grant Domain Users full access to the registry path "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache" and then use another script I wrote to purge old entries from the list.  I will post that to www.VisualBasicScript.com too (If I can find it).  The downside to this is that a healthy portion of the Task Scheduler has had its security settings opened up widely and all calls to "rootFolder.RegisterTaskDefinition()" work / behave like and administrator was calling it.


    <job args="\\oraucoc.org\sysvol\oraucoc.org\Policies\{6AACA3D9-F347-494D-AD78-9C5BA193641A}\User\Scripts\Logon\Drive_Mapping.vbs">  
         <script language="VBScript">  
     Option Explicit  
     On Error Resume Next  
     'More Details can be found here:  
     'http://technet.microsoft.com/en-us/library/cc766208.aspx  
     
     'Background Information:   
     'NOTE: This text (below) is taken directly from the link  
     '      above and is quite possibly one of the most   
     '      important things you will ever read about scripting  
     '      for Vista.  
     ' Consumption of Windows Vista settings  
     ' Group Policy Scripts can fail due to User Account Control  
     '   
     ' The main goal of User Account Control (UAC) is to lessen   
     ' the exposure and attack surface of the operating system.   
     ' UAC does this by requiring all users to run in standard   
     ' user mode. This limit minimizes the ability for users To   
     ' make changes that could destabilize their computers Or   
     ' unintentionally expose the network to viruses through   
     ' undetected malicious software (also called malware) that   
     ' has infected their computer.  
     '   
     ' With UAC, you can run most applications, components, And   
     ' processes with a limited privilege, but have "elevation   
     ' potential" for specific administrative tasks and   
     ' application functions. Windows accomplishes this by using   
     ' two access tokens for each user: limited and elevated   
     ' access tokens. Access tokens identify the user, the user's   
     ' groups, and the user's privileges. The system uses access   
     ' tokens to control access to securable objects and To   
     ' control the ability of the user to perform various   
     ' system-related operations on the local computer.  
     '   
     ' An elevated token, for a local administrator, includes And   
     ' enables all of the administrative privileges. UAC requires   
     ' local administrators to use their elevated token when   
     ' attempting to perform a system-only task or administrative   
     ' task. A limited token, for a local administrator, includes   
     ' all of the administrative privileges; however, these   
     ' privileges are disabled. This allows Windows to view the   
     ' administrative user and a normal user, with the option To   
     ' elevate their privileges.  
     '   
     ' By default, all users logging on to Windows Vista use   
     ' their full token to process Group Policy and logon scripts.   
     ' However, they use their limited user token to load the   
     ' desktop and all subsequent processes. Nonadministrative   
     ' limited and elevated tokens are mostly identical, With   
     ' regard to privileges and groups. Therefore, a process   
     ' started with a nonadministrative limited user token can   
     ' view processes started with a nonadministrative elevated   
     ' token. Windows allows this because the viewing application   
     ' does not require any elevation to view the process started   
     ' with the elevated token.  
     '   
     ' Windows processes a locally logging on administrator the   
     ' same way. Group Policy and logon scripts process using the   
     ' elevated user token, and the desktop and all subsequent   
     ' processes use the limited token. However, there is a   
     ' privilege difference between the limited and elevated user   
     ' token. Therefore, Windows restricts processes started With   
     ' a limited token from the ability to share information With   
     ' processes started with the elevated token.  
     '   
     ' UAC may prevent Group Policy logon scripts from appearing   
     ' to work properly. For example, a domain environment   
     ' contains a GPO that includes a logon script to map network   
     ' drives. A nonadministrative user logs on to the domain from   
     ' a Windows Vista computer. After Windows Vista loads the   
     ' desktop, the nonadministrative user starts Windows   
     ' Explorer. The user sees their mapped drives. Under the same   
     ' environment, an administrative user logs on to the domain   
     ' from a Windows Vista computer. After Windows Vista loads   
     ' the desktop, the administrative user starts Windows   
     ' Explorer. The user does not see their mapped drives.  
     '   
     ' When the administrative user logs on, Windows processes the   
     ' logon scripts using the elevated token. The script actually   
     ' works and maps the drive. However, Windows blocks the view   
     ' of the mapped network drives because the desktop uses the   
     ' limited token while the drives were mapped using the   
     ' elevated token.  
     '   
     ' To get around this issue, administrative users should map   
     ' network drives under the limited user token. This mapping   
     ' is accomplished by using the launchapp.wsf script shown In   
     ' Appendix A, which works by scheduling the commands using   
     ' the task scheduler. The task scheduler launches the script   
     ' under the administrative full token, thereby allowing   
     ' Windows Explorer, other limited token processes, and the   
     ' elevated token process to view the mapped network drives.  
     
     'NOTE: ~Multi-user Environment Warning~  
     ' On 6/26/2009, the author discovered a problem with this  
     ' process's behavior in a multi-user environment: ie.  
     ' "Terminal Server"for Windows Server 2008 Release 1.  
     ' When an Administrator runs the code,  
     ' he is able to overwrite other Scheduled Tasks where as  
     ' a general user cannot.  Therefore this will work: Admin1  
     ' logs in all of his logon scripts execute properly by   
     ' creating or refreshing previous scheduled tasks.  Then  
     ' Admin2 logs in.  His logon scripts also execute properly  
     ' because he has full privileges over all scheduled tasks.  
     ' Now along comes User1.  He logs in but none of his logon  
     ' scripts execute because he cannot overwrite the scheduled  
     ' tasks that were previously created by Admin1.  
     ' The only way I've found to get around this hiccup is to   
     ' append a unique ID to the end of each task name.    
     ' Something like the user ID or full user name.  
     
     'NOTE: ~Terminal Server Security Settings~  
     ' 7/1/2009.  I was still having massive issues with this code in a   
     ' Terminal Server environment.  ~Sometimes~ users were not  
     ' able to "recreate" jobs they created on their last login.  
     ' For the life of me I couldn't figure out why.  Because  
     ' documentation that could explain this behavior is a little  
     ' thin, I had to grant Domain Users full access to the  
     ' registry path   
     ' "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache"  
     ' and then use another script I wrote to purge old entries  
     ' from the list.  I will post that to   
     ' www.VisualBasicScript.com too.  The downside to this  
     ' is that a healthy portion of the Task Scheduler has had  
     ' its security settings opened up widely and all calls to  
     ' "rootFolder.RegisterTaskDefinition()" work / behave like  
     ' and administrator was calling it.  
     
     
     '================================  
     '       Define Constants  
     '================================  
     const TriggerTypeRegistration = 7  
     const ActionTypeExecutable = 0   
     const FlagTaskCreate = 2   
     const LogonTypeInteractive = 3   
     
     
     '================================  
     '        Define Variants  
     '================================  
     Dim strAppPath      'The full path and script name of what Is  
                         ' to be executed.  Think "UNC Path".  
     Dim boolDebug       'Enables / Disables comments to the screen  
     Dim objService      'An object of something that interacts  
                         ' With Vista's Task Scheduler Service  
     Dim strTaskName     'The Task's Name  
     Dim rootFolder      'The task definition will reside in this folder  
     Dim taskDefinition  'The task that will be run with reduced credentials  
     Dim triggers        'A reference to the triggers functionality  
                         ' within the task object 'taskDefinition'  
     Dim trigger         'The act of creating a trigger returns an object  
                         ' The sole purpose of this Variant is to catch  
                         ' the returning object. Nothing else is done with  
                         ' it during the life of the script.  
     Dim Action          'The action of the trigger.  
     Dim objLog_File     'Log File  
     Dim boolLog_Screen      'Send debug messages to the screen  
     Dim boolLog_File        'Send debug messages to a file located at %USERPROFILE%\Drive_Mapping_Log.txt  
     Dim objFSO  
     Dim objShell  
     Dim strUserName     'The Name of the user running this code  
     
     '================================  
     '       Populate Variants  
     '================================  
     boolLog_Screen = False  
     boolLog_File = True  
     strAppPath = WScript.Arguments(0)  
     boolDebug = False  
     strUserName = WScript.CreateObject("WScript.Network").UserName  
     strTaskName = "Launch App As Interactive User " & strUserName & " - " & Split(strAppPath,"\")(Ubound(Split(strAppPath,"\")))  
     strTaskName = Replace(strTaskName,".","_")  
     Set objShell = WScript.CreateObject("WScript.Shell")  
     Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")  
     Set objLog_File = objFSO.CreateTextFile(objShell.ExpandEnvironmentStrings(objShell.Environment("PROCESS")("USERPROFILE")) & _  
                       "\Vista_Launch_Script_Log_of_" & Split(strAppPath,"\")(Ubound(Split(strAppPath,"\"))) & ".txt",True)  
     If Err.Number <> 0 Then   
         Set objLog_File = Nothing  
         boolLog_File = False  
     End If  
     Log_Event "Vista Launch Script Started", boolLog_Screen, boolLog_File  
     
     
     '================================  
     '      Check prerequisites   
     '       before continuing  
     '================================  
     If WScript.Arguments.Length <> 1 Then  
         Log_Event "Usage: cscript launchapp.wsf <AppPath>" , boolLog_Screen, boolLog_File  
         Set objLog_File = Nothing  
         WScript.Quit  
     End If  
     
     If Is_UAC_Enabled(".") = False Then  
         Log_Event "Vista's UAC (User Account Control) is not enabled. ", boolLog_Screen, boolLog_File  
         Log_Event "Running code without Task Scheduler using Cscript.", boolLog_Screen, boolLog_File  
         Run_Command Wscript.Arguments(0)  
         Set objLogFile = Nothing  
         WScript.Quit  
     End If  
     
     
     
     
     
     '================================  
     '           Main Code  
     '================================  
     
     'This block of code connects to Vista's Task  
     ' Scheduler service and removes the task that  
     ' will be installed if it is already installed.  
     ' An error might be generated.  Catch and   
     ' clear it.  
     Log_Event "Creating Schedule.Service Object", boolLog_Screen, boolLog_File   
     Set objService = CreateObject("Schedule.Service")  
     Log_Event "Connecting to Scheduler Service", boolLog_Screen, boolLog_File  
     call objService.Connect()  
     Log_Event "Setting Root Folder and Deleting old Scheduled Event", boolLog_Screen, boolLog_File  
     Set rootFolder = objService.GetFolder("\")  
     On Error Resume Next  
     call rootFolder.DeleteTask(strTaskName, 0)  
     If Err.Number <> 0 Then Err.Clear         
     'On Error Goto 0  
     
     'Create a new Task.  Access its Trigger   
     ' properties.  Set the task to trigger  
     ' (and therefore execute) upon registration.  
     Log_Event "Creating New Task", boolLog_Screen, boolLog_File  
     Set taskDefinition = objService.NewTask(0)   
     Log_Event "Setting Task Trigger to Execute at end of Task Creation", boolLog_Screen, boolLog_File  
     Set triggers = taskDefinition.triggers  
     Set trigger = triggers.Create(TriggerTypeRegistration)   
     
     'Add an action to the task.  
     'As best as I can figure it, 'Action' is not receiving a  
     ' newly generated object from 'taskDefinition', but rather  
     ' is being told to act as a "pointer" to an object within  
     ' 'taskDefinition'.  This is why 'Action' does not appear  
     ' in the command "call rootFolder.RegisterTaskDefinition()"  
     ' that comes up in a few lines.  By editing 'Action.Path',  
     ' you are really editing something within 'taskDefinition'.  
     Set Action = taskDefinition.Actions.Create( ActionTypeExecutable )  
     Action.Path = strAppPath  
     Log_Event "Task definition created. About to submit the task..." & VbCrLf & VbCrLf, boolLog_Screen, boolLog_File  
     Log_Event "If the creation of the task fails then the user is probably ", boolLog_Screen, boolLog_File  
     Log_Event "not an Administrator.", boolLog_Screen, boolLog_File  
     
     'Register (create) the task.  
     ' Notice the inclusion of 'LogonTypeInteractive'.  
     ' Now the script that was passed to this script as an  
     ' argument will run with the reduced credentials.  
     Log_Event "Registering Task...", boolLog_Screen, boolLog_File  
     call rootFolder.RegisterTaskDefinition( _  
     strTaskName, taskDefinition, FlagTaskCreate,,, LogonTypeInteractive)  
     If Err.Number = 0 Then  
         Log_Event "Task submitted without Error", boolLog_Screen, boolLog_File  
         Log_Event "This script is now exiting.", boolLog_Screen, boolLog_File  
         'Remove_Task_CLI strTaskName, Wscript.Arguments(0)  
     Else  
         Log_Event "Programatic Task submission Errored. Trying CLI Task Scheduler.", boolLog_Screen, boolLog_File  
         'If WScript.CreateObject("WScript.Network").UserName = "gbread" then  
             Schedule_Task_CLI strTaskName, Wscript.Arguments(0)  
             'Remove_Task_CLI strTaskName, Wscript.Arguments(0)  
             Log_Event "...Script Ended...", boolLog_Screen, boolLog_File  
         'Else  
         '    Run_Command Wscript.Arguments(0)  
         '    Log_Event "Command Was Run without Task Scheduler.", boolLog_Screen, boolLog_File  
         'End IF  
     end If  
     Set objLog_File = Nothing  
     WScript.Quit  
     
     
     '============================  
     'Schedule_Task_CLI  
     '============================  
     Sub Schedule_Task_CLI(TaskName, strCommand)  
         'Created: Feb 9th 2009  
         '  
         'Revisions:  
         '(Feb 9th 2009) - Writing Function  
         'Description: Create a task using Vista's CLI Task Scheduler  
          '  
          'INPUT: strCommand -> A string  
          '  
         Dim objShell  
         'Dim TaskName  
           
         'TaskName = Split(strCommand,"\")(UBound(Split(strCommand,"\")))  
         'TaskName = Replace(TaskName,".","_")  
         Set objShell = WScript.CreateObject("WScript.Shell")     
         Select Case Lcase(Right(strCommand,4))  
             Case ".vbs"  
                     strCommand = "%systemroot%\system32\cscript.exe " & strCommand  
             Case ".wsf"  
                     strCommand = "%systemroot%\system32\cscript.exe " & strCommand  
             Case ".ps1"  
             Case Else  
         End Select  
           
         '/F -> Forcefully creates the task and suppresses warnings if the task already exists  
         '/RL LIMITED -> Run level for the job  
         '/SC ONCE -> The scheduled frequency  
         '/TN <blah> -> The task name  
         '/ST -> The start time  
         '/TR -> The path and file name of the program to be run at the scheduled time  
         strCommand = objShell.ExpandEnvironmentStrings("%systemroot%") & _  
                          "\system32\schtasks.exe /create /F /RL LIMITED /SC ONCE /TN " & _  
                          TaskName & " /ST " & chr(34) & split(formatdatetime(Now,4)," ")(0) & chr(34) & _  
                          " /TR " & chr(34) & strCommand & chr(34)  
           
         'Zero Hides the window and activates another window.   
         'False does not wait for the run window to finish executing  
         Log_Event "About to Register: " & vbcrlf & vbcrlf & _  
                                vbtab & strCommand & vbtab & _  
                                vbcrlf & vbcrlf & "with the CLI Task Scheduler.", _  
                                boolLog_Screen, boolLog_File  
         If boolLog_Screen Then  
             'Run the command in a visible window  
             Log_Event "Running visible", boolLog_Screen, boolLog_File  
             objShell.Run strCommand, 1, True  
         Else  
             'Run the command in a hidden window  
             Log_Event "Running minimized", boolLog_Screen, boolLog_File  
             objShell.Run strcommand, 0, True  
         End If  
           
         strCommand = objShell.ExpandEnvironmentStrings("%systemroot%") & _  
                          "\system32\schtasks.exe /Run /TN " & TaskName  
           
         Log_Event "About to Start: " & vbcrlf & vbcrlf & _  
                                vbtab & strCommand & vbtab & _  
                                vbcrlf & vbcrlf & "with the CLI Task Scheduler.", _  
                                boolLog_Screen, boolLog_File  
         objShell.Run strCommand, 0, True  
           
         Set objShell = Nothing  
     End Sub  
     
     
     
     '============================  
     'Remove_Task_CLI  
     '============================  
     Sub Remove_Task_CLI(TaskName, strCommand)  
         'Created: Feb 9th 2009  
         '  
         'Revisions:  
         '(Feb 9th 2009) - Writing Function  
         'Description: Remove a task using Vista's CLI Task Scheduler  
          '  
          'INPUT: strCommand -> A string  
          '  
         Dim objShell  
         'Dim TaskName  
           
         'TaskName = Split(strCommand,"\")(UBound(Split(strCommand,"\")))  
         'TaskName = Replace(TaskName,".","_")  
         Set objShell = WScript.CreateObject("WScript.Shell")     
           
         'Now we are going to forcefully end the task and delete it.  
         strCommand = objShell.ExpandEnvironmentStrings("%systemroot%") & _  
                          "\system32\schtasks.exe /End /TN " & TaskName  
         Log_Event "About to End the Task: " & vbcrlf & vbcrlf & _  
                                vbtab & strCommand, _  
                                boolLog_Screen, boolLog_File  
         objShell.Run strCommand, 0, True  
           
         wscript.sleep 5000  
           
         strCommand = objShell.ExpandEnvironmentStrings("%systemroot%") & _  
                          "\system32\schtasks.exe /Delete /F /TN " & TaskName  
         Log_Event "About to Delete the Task: " & vbcrlf & vbcrlf & _  
                           vbtab & strCommand, _  
                           boolLog_Screen, boolLog_File  
         objShell.Run strCommand, 0, True  
           
         Set objShell = Nothing  
     End Sub  
     
     
     
     '============================  
     'Is_UAC_Enabled  
     '============================  
     Function Is_UAC_Enabled (strComputer)  
         'Created: Nov 25th 2008  
         '  
         'Revisions:  
         '(Nov 25th 2008) - Writing Function  
         '  
          'Description: Call to see if Vista's UAC Enabled?  
          '  
          'INPUT: strComputer -> A string  
          '                       May contain a computer name or "." for local  
          'Output: Return Value -> True, LUA is Enabled  
          '                     -> False, LUA is NOT Enabled  
          '  
         Const HKLM = &H80000002  
           
         Dim strKeyPath, strEntryName, strValue  
         Dim objRegistry  
         Log_Event "Connecting to / Reading Registry", boolLog_Screen, boolLog_File  
         Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")  
         Is_UAC_Enabled = False  
         strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"  
         strEntryName = "EnableLUA"  
         strValue = ""  
           
         objRegistry.GetDWORDValue HKLM,strKeyPath,strEntryName,strValue   
         Select Case strValue  
             Case 1  
                 Is_UAC_Enabled = True  
             Case 0  
                 Is_UAC_Enabled = False  
             Case Else  
                 Is_UAC_Enabled = False  
         End Select  
     End Function  
     
     
     
     '============================  
     'Run_Command  
     '============================  
     Sub Run_Command(strCommand)  
         'Created: Nov 25th 2008  
         '  
         'Revisions:  
         '(Nov 25th 2008) - Writing Function  
         '(Nov 26th 2008) - Call Cscript Interpreter if command is a script file  
         '                - Make objShell.Run windows visible if boolDebug is True  
         '  
          'Description: Call to see if Vista's UAC Enabled?  
          '  
          'INPUT: strComputer -> A string  
          '                       May contain a computer name or "." for local  
          'Output: Return Value -> True, LUA is Enabled  
          '                     -> False, LUA is NOT Enabled  
          '  
         Dim objShell  
           
         Set objShell = WScript.CreateObject("WScript.Shell")     
         Select Case Lcase(Right(strCommand,4))  
             Case ".vbs"  
                     strCommand = "%systemroot%\system32\cscript.exe " & strCommand  
             Case ".wsf"  
                     strCommand = "%systemroot%\system32\cscript.exe " & strCommand  
             Case ".ps1"  
             Case Else  
         End Select  
           
         'Zero Hides the window and activates another window.   
         'False does not wait for the run window to finish executing  
         Log_Event "About to start: " & vbcrlf & vbcrlf & _  
                                vbtab & strCommand & vbtab & _  
                                vbcrlf & vbcrlf & "without the task scheduler.", _  
                                boolLog_Screen, boolLog_File  
         If boolLog_Screen Then  
             'Run the command in a visible window  
             Log_Event "Running visible", boolLog_Screen, boolLog_File  
             objShell.Run strCommand, 1, True  
         Else  
             'Run the command in a hidden window  
             Log_Event "Running minimized", boolLog_Screen, boolLog_File  
             objShell.Run strcommand, 0, True  
         End If  
         Set objShell = Nothing  
     End Sub  
     
     
     
     '============================  
     'Log_Event  
     '============================  
     Sub Log_Event(ByVal strEvent_Text,ByRef boolLog_To_Screen,ByRef boolLog_To_File)  
         If boolLog_To_Screen Then  
             WScript.Echo strEvent_Text  
         End If  
         If boolLog_To_File Then  
             Err.Clear  
             objLog_File.Writeline Now & vbTab & strEvent_Text  
             If Err.Number <> 0 Then  
                 'Error writing to file. Attempt to close file .  
                 ' set boolLog_To_File = False so no further file writes  
                 ' will occur.  
                 objLog_File.Close  
                 Set objLog_File = Nothing  
                 bool_Log_to_File = False  
                 Err.Clear  
             End IF  
         End If  
     End Sub  
         </script>  
     </job>  
     

    <message edited by turranx on Friday, September 25, 2009 4:22 AM>
    Microsoft Windows 2000 Scripting Guide - The best book for newbie scripters
    http://www.myspace.com/Evil__Overlord
    #2
      turranx

      • Total Posts : 59
      • Scores: 0
      • Reward points : 0
      • Joined: 2/7/2006
      • Location: Cincinnati, OH
      • Status: offline
      Re:Logon Scripts under Vista Thursday, October 01, 2009 10:25 AM (permalink)
      0
      Corrupt task registrations were keeping some users from running their logon scripts.  Here's my solution.

      ~Removing Corrupt Tasks~
      The Task Scheduler GUI is not very forgiving about corrupted tasks. It would appear that a call to "call rootFolder.DeleteTask(strTaskName, 0)" fails if the task's XML file does not exist within "C:\Windows\System32\Tasks".   But at the same time, an attempt to register a task with the same name as contained within "strTaskName" fails because of a registry entry that does exist with the same name.  How to fix this?  Pull out PowerShell.  This will work remotely.

       $TS = new-object -com("Schedule.Service")
       $TS.connect("<Terminal Server Name Here>")
       $RootFolder = $TS.getfolder("\") 
       $RootFolder.DeleteTask("<Task Name Here>",0).  
       


      I don't know what the second parameter means, but zero worked for me.
      Now the task registrations and executions work for my generic test user account.

      Microsoft Windows 2000 Scripting Guide - The best book for newbie scripters
      http://www.myspace.com/Evil__Overlord
      #3

        Online Bookmarks Sharing: Share/Bookmark

        Jump to:

        Current active users

        There are 0 members and 1 guests.

        Icon Legend and Permission

        • New Messages
        • No New Messages
        • Hot Topic w/ New Messages
        • Hot Topic w/o New Messages
        • Locked w/ New Messages
        • Locked w/o New Messages
        • Read Message
        • Post New Thread
        • Reply to message
        • Post New Poll
        • Submit Vote
        • Post reward post
        • Delete my own posts
        • Delete my own threads
        • Rate post

        2000-2012 ASPPlayground.NET Forum Version 3.8
        mbt shoes www.wileywilson.com