kschwarz Posted February 9, 2011 Share Posted February 9, 2011 I have a service written with Autoit and that is working correctly and started under Local System account. This service starts another AutoIt application that generates a Tray Menu but the TrayIcon is not being shown in the Notification Area. When I run this application from my account the Tray Icon is shown and I can access the menu items accordingly. Is there any way to make the Tray Icon be shown when running as Local System account? Another question: The above described Tray Menu has an Menu Item that starts another application. Note that the Tray Menu application is running under Local System Account. Is there any way to start that application with the account of the user that is selecting (clicking) that Menu Item? Thanks, Klaus Link to comment Share on other sites More sharing options...
AdamUL Posted February 9, 2011 Share Posted February 9, 2011 When you installed the service did you set it to interact with the desktop as it shows in the AutoIt Wiki FAQ?RegWrite("HKLM\SYSTEM\CurrentControlSet\Services\[ServiceName]", "Type", "REG_DWORD", 0x110)Adam Link to comment Share on other sites More sharing options...
kschwarz Posted February 10, 2011 Author Share Posted February 10, 2011 When you installed the service did you set it to interact with the desktop as it shows in the AutoIt Wiki FAQ? RegWrite("HKLM\SYSTEM\CurrentControlSet\Services\[ServiceName]", "Type", "REG_DWORD", 0x110) Adam I have made the change in the service settings to include the option to interact with the desktop and it is now showing the Icon. Thanks What about the question abaout starting another application from the Service Tray Manu as the user that makes this selection instead of starting it as Local System? Any hint? Klaus Link to comment Share on other sites More sharing options...
AdamUL Posted February 10, 2011 Share Posted February 10, 2011 (edited) Glad I could help. Now about your other problem, here is an idea that I would use.Try using Run in the script with SCHTASK, with /create, to create a scheduled task to run under the current logged in user using /ru. Then you could use /run with /u to run the task with the currently logged in username. Depending on how often the process is used you can leave the scheduled task and use /query to see if the task exist, /run with /u to run it each time, and /delete to delete the tasks when the script closes. I have not fully tested this, but at least it give you some ideas and a direction to go.There is one catch, @UserName will not work in creating the task, since @UserName is the user running the script, which is SYSTEM, and not the currently logged in user. Here is a small function and example script to get the currently logged in user. This function does not have detailed WMI Error handling, so you will need to add it.FileWriteLine("test.txt", "Current User: " & @UserName) FileWriteLine("test.txt", "User Logged in: " & _CurrentUserLoggedIn()) Func _CurrentUserLoggedIn($sHostName = Default) Local $oWMIService, $oComputers, $oComputer If $sHostName = Default Then $sHostName = "." $oWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sHostName & "\root\cimv2") If Not IsObj($oWMIService) Then Return SetError(2, 1, "") $oComputers = $oWMIService.ExecQuery("Select * from Win32_ComputerSystem") For $oComputer in $oComputers If $oComputer.UserName = "" Then Return SetError(1, 0, "") Else Return $oComputer.UserName EndIf Next EndFuncCompile this script and set it as a scheduled task to run under SYSTEM. You will see SYSTEM as the "Current User", but "User Logged In" will not be SYSTEM. It will be the currently logged in user. Edit: typosEdit: Changed _CurrentUserLoggedIn function to return "" instead of 0 on error.Adam Edited February 11, 2011 by AdamUL Link to comment Share on other sites More sharing options...
kschwarz Posted February 14, 2011 Author Share Posted February 14, 2011 (edited) I have made the change in the service settings to include the option to interact with the desktop and it is now showing the Icon. ThanksWhat about the question abaout starting another application from the Service Tray Manu as the user that makes this selection instead of starting it as Local System? Any hint?KlausIt worked on Windows XP but on Windows 7 the icon did not show up.Any idea? Edited February 14, 2011 by Klaus Link to comment Share on other sites More sharing options...
AdamUL Posted February 14, 2011 Share Posted February 14, 2011 This has to do with Session 0 isolation that was first implemented in Windows Vista. Here is a discussion about it on MSDN. You can try running it in Windows XP compatibility mode. Adam Link to comment Share on other sites More sharing options...
kschwarz Posted February 24, 2011 Author Share Posted February 24, 2011 Glad I could help. Now about your other problem, here is an idea that I would use.Try using Run in the script with SCHTASK, with /create, to create a scheduled task to run under the current logged in user using /ru. Then you could use /run with /u to run the task with the currently logged in username. Depending on how often the process is used you can leave the scheduled task and use /query to see if the task exist, /run with /u to run it each time, and /delete to delete the tasks when the script closes. I have not fully tested this, but at least it give you some ideas and a direction to go.There is one catch, @UserName will not work in creating the task, since @UserName is the user running the script, which is SYSTEM, and not the currently logged in user. Here is a small function and example script to get the currently logged in user. This function does not have detailed WMI Error handling, so you will need to add it.<snip>Compile this script and set it as a scheduled task to run under SYSTEM. You will see SYSTEM as the "Current User", but "User Logged In" will not be SYSTEM. It will be the currently logged in user. Edit: typosEdit: Changed _CurrentUserLoggedIn function to return "" instead of 0 on error.AdamThank you Adam, for your suggestion. I will give it a try. Sorry for the delayed answer.Klaus Link to comment Share on other sites More sharing options...
kschwarz Posted February 28, 2011 Author Share Posted February 28, 2011 (edited) Adam, I have tryed your _CurrentUserLoggedIn() function and it worked on Windows 7, but WMI could not be accessed using WmiRM that is not available in "Windows Server 2003 with SP1, Windows Server 2003, Windows XP, and Windows 2000". On "Windows XP SP3" it returns Current User : myusername User Logged in: domainname\myusername On "Windows XP x64 SP2" it returns Current User : myusername User Logged in: domainname\myusername But On "Windows Server 2003 SP1" it returns Current User : myusername User Logged in: Is there another way to obtain the Username? Could you help me with this? Thanks, Klaus Edited February 28, 2011 by Klaus Link to comment Share on other sites More sharing options...
kschwarz Posted March 1, 2011 Author Share Posted March 1, 2011 Thank you Adam, for your suggestion. I will give it a try. Sorry for the delayed answer.KlausI have tryed the Task Scheduler hint on Windows 7 and it worked perfectly. But when I have tryed it on a Windows XP x64 machine it is always asking for the "run as password". See whole message bellow:Please enter the run as password for domain\username: WARNING: When the run as password is empty, the scheduled task may not run because of the security policy. WARNING: The scheduled task "TaskName" has been created, but may not run because the account information could not be set.And the Eventlog shows "Unknown user name or bad password". The user exists and as I am not giving the password it is failing.Seems this procedure does not work on versions prior to Windows 7 (or Vista perhaps).Any remindings, hints, etc?Klaus Link to comment Share on other sites More sharing options...
rover Posted March 1, 2011 Share Posted March 1, 2011 Another question: The above described Tray Menu has an Menu Item that starts another application. Note that the Tray Menu application is running under Local System Account. Is there any way to start that application with the account of the user that is selecting (clicking) that Menu Item?Thanks,KlausKlausI've not used this UDF, but it may be what you are looking for.Elevate Your Script to the SYSTEM AccountThese two functions in particular._ImpersonateUserStart()_ImpersonateUserEnd()or this?Run a Process as Limited User DropMyRights replacement I see fascists... Link to comment Share on other sites More sharing options...
AdamUL Posted March 2, 2011 Share Posted March 2, 2011 Klaus,Sorry of the late replay. Way too many projects running concurrently. Here are two more versions of _CurrentUserLoggedIn. This one uses PsLoggedOn by Sysinternals. PsLoggedOn must be in the script directory or the system path. Func _CurrentUserLoggedIn($sComputer = @ComputerName) ;Uses PsLoggedOn.exe. ;Use #include <Constants.au3> if $STDOUT_CHILD is used somewhere else in the script. Const $STDOUT_CHILD = 2 ;Comment out if #include <Constants.au3> is used. $sPSLoggedOnOutputHeader1 = "Connecting to Registry of \\" & $sComputer & "..." $sPSLoggedOnOutputHeader2 = "loggedon v1.33 - See who's logged on" & @CRLF & "Copyright ¬ 2000-2006 Mark Russinovich" & @CRLF & "Sysinternals - www.sysinternals.com" & @CRLF $iPIDPSLoggedOn = Run('psloggedon -x \\' & $sComputer, '', @SW_HIDE, $STDOUT_CHILD) If @error Then Return SetError(2, 1, "") ProcessWaitClose($iPIDPSLoggedOn) $sPSLoggedOnOutput = StringStripWS(StdoutRead($iPIDPSLoggedOn), 3) If Not StringInStr($sPSLoggedOnOutput, "Error opening HKEY_USERS") Then $sPSLoggedOnOutput = StringReplace($sPSLoggedOnOutput, $sPSLoggedOnOutputHeader1, "") $sPSLoggedOnOutput = StringReplace($sPSLoggedOnOutput, $sPSLoggedOnOutputHeader2, "") $sPSLoggedOnOutput = StringReplace($sPSLoggedOnOutput, "Users logged on locally:" & @CRLF, "") $sPSLoggedOnOutput = StringReplace($sPSLoggedOnOutput, "NT AUTHORITY\LOCAL SERVICE" & @CRLF, "") $sPSLoggedOnOutput = StringReplace($sPSLoggedOnOutput, "NT AUTHORITY\NETWORK SERVICE" & @CRLF, "") $sPSLoggedOnOutput = StringReplace($sPSLoggedOnOutput, "NT AUTHORITY\SYSTEM" & @CRLF, "") $sPSLoggedOnOutput = StringStripWS($sPSLoggedOnOutput, 3) If StringInStr($sPSLoggedOnOutput, "Users logged on via resource shares:") Then $sPSLoggedOnOutput = StringLeft($sPSLoggedOnOutput, StringInStr($sPSLoggedOnOutput, "Users logged on via resource shares:") - 1) If StringInStr($sPSLoggedOnOutput, "No one is logged on via resource shares.") Then $sPSLoggedOnOutput = StringLeft($sPSLoggedOnOutput, StringInStr($sPSLoggedOnOutput, "No one is logged on via resource shares.") - 1) $sPSLoggedOnOutput = StringStripWS($sPSLoggedOnOutput, 3) Else Return SetError(1, 2, "") EndIf Return $sPSLoggedOnOutput EndFuncThis one searches the Registry. I had to modify the DLL call in _Security__LookupAccountSid because it only had one parameter, for SID, and there was not one for System. This caused problems when checking for local accounts on a remote computer. I renamed the function _Security__LookupAccountSidEx, and it is included below the function.expandcollapse popup#include <Security.au3> Func _CurrentUserLoggedIn($sComputer = @ComputerName) ;Uses Registry. ;Uses #include <Security.au3> ;Uses _Security__LookupAccountSidEx see below. ;Uses #include <Array.au3> for testing. $iSIDCount = 1 While 1 $sUserSID = RegEnumKey("\\" & $sComputer & "\HKEY_USERS", $iSIDCount) Switch @error Case 1, 2, 3 Return SetError(1, 2, "") Case -1 ExitLoop EndSwitch If StringLen($sUserSID) > 8 And Not StringInStr($sUserSID, "_Classes") Then ;~ $vUserAcct = _Security__LookupAccountSid($sUserSID) ;Will not pull Local Accounts from a Remote PC. $vUserAcct = _Security__LookupAccountSidEx($sUserSID, $sComputer) ;Will now pull Local Accounts from a Remote PC. If IsArray($vUserAcct) Then ;~ _ArrayDisplay($vUserAcct, $sComputer) ;For Testing Return $vUserAcct[1] & "\" & $vUserAcct[0] EndIf EndIf $iSIDCount += 1 WEnd Return SetError(1, 0, "") EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: _Security__LookupAccountSidEx ; Description ...: Retrieves the name of the account for a SID ; Syntax.........: _Security__LookupAccountSidEx($vSID,[, $sSystem = ""]) ; Parameters ....: $vSID - Either a binary SID or a string SID ; $sSystem - Name of the system. This string can be the name of a remote computer. If this string is blank, ; +the account name translation begins on the local system. If the name cannot be resolved on the local system, ; +this function will try to resolve the name using domain controllers trusted by the local system. ; Return values .: Success - Array with the following format: ; |$aAcct[0] - Account name ; |$aAcct[1] - Domain name ; |$aAcct[2] - SID type, which can be one of the following values: ; | 1 - Indicates a user SID ; | 2 - Indicates a group SID ; | 3 - Indicates a domain SID ; | 4 - Indicates an alias SID ; | 5 - Indicates a SID for a well-known group ; | 6 - Indicates a SID for a deleted account ; | 7 - Indicates an invalid SID ; | 8 - Indicates an unknown SID type ; | 9 - Indicates a SID for a computer ; Failure - 0 ; Author ........: Paul Campbell (PaulIA) ; Modified.......: Adam Lawrence (AdamUL) ; Remarks .......: ; Related .......: _Security__LookupAccountName, _Security__GetAccountSid ; Link ..........: @@MsdnLink@@ LookupAccountSid ; Example .......: ; =============================================================================================================================== Func _Security__LookupAccountSidEx($vSID, $sSystem = "") Local $pSID, $aAcct[3] If IsString($vSID) Then Local $tSID = _Security__StringSidToSid($vSID) $pSID = DllStructGetPtr($tSID) Else $pSID = $vSID EndIf If Not _Security__IsValidSid($pSID) Then Return SetError(-1, 0, 0) ;~ Local $aResult = DllCall("advapi32.dll", "bool", "LookupAccountSidW", "ptr", 0, "ptr", $pSID, "wstr", "", "dword*", 256, "wstr", "", "dword*", 256, "int*", 0) ;Original DLL call. Local $aResult = DllCall("advapi32.dll", "bool", "LookupAccountSidW", "wstr", $sSystem, "ptr", $pSID, "wstr", "", "dword*", 256, "wstr", "", "dword*", 256, "int*", 0) ;Added $sSystem parameter and change to type "wstr". If @error Then Return SetError(@error, @extended, 0) If Not $aResult[0] Then Return 0 Local $aAcct[3] $aAcct[0] = $aResult[3] ; Name $aAcct[1] = $aResult[5] ; Domain $aAcct[2] = $aResult[7] ; SNU Return $aAcct EndFunc ;==>_Security__LookupAccountSidExFor the Windows XP x64 problem, check the permissions on the Scheduled Tasks folder to make sure the user has rights to it, as noted in kb883273. See if that fixes the problem. If not, then I would also check out the that rover mentioned above, also look at the function _CreateProcessAsUser in that UDF. With _CreateProcessAsUser, you can execute a command line, so you might be able to start the processes you need, in the user context that you need, without using SCHTASK. I haven't fully tested it, but you could give it a try.Hope this helps,Adam Link to comment Share on other sites More sharing options...
kschwarz Posted March 3, 2011 Author Share Posted March 3, 2011 Klaus,Sorry of the late replay. Way too many projects running concurrently. Here are two more versions of _CurrentUserLoggedIn. This one uses PsLoggedOn by Sysinternals. PsLoggedOn must be in the script directory or the system path. <snipped>This one searches the Registry. I had to modify the DLL call in _Security__LookupAccountSid because it only had one parameter, for SID, and there was not one for System. This caused problems when checking for local accounts on a remote computer. I renamed the function _Security__LookupAccountSidEx, and it is included below the function.<snipped>For the Windows XP x64 problem, check the permissions on the Scheduled Tasks folder to make sure the user has rights to it, as noted in kb883273. See if that fixes the problem. If not, then I would also check out the that rover mentioned above, also look at the function _CreateProcessAsUser in that UDF. With _CreateProcessAsUser, you can execute a command line, so you might be able to start the processes you need, in the user context that you need, without using SCHTASK. I haven't fully tested it, but you could give it a try.Hope this helps,AdamHi Adam and rover, I will be giving a try to the new _CurrentUserLoggedIn and the _CreateProcessAsUser functions, but it will take some time because of priority changes. I will let you know if it worked for me or not.Thanks, Klaus Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now