jstump1 Posted March 14, 2012 Posted March 14, 2012 (edited) Hello -I have an energy-saving app that I use on Windows XP that is going to need a couple of modifications to work on Windows Vista, 7, 8, and on.It is an AutoIt app that I run as an interacitve service under the local system account using srvany.exe. The program creates one dialogue box that asks the user if they want to continue working or to shutdown. The app continues to work on Win 7, but the Interactive Services Detection notificaton is a problem. Most users ignore it or don't have a clue what it is, so they never see the msgbox asking if they want to continue working.I read Microsoft's info on this redesign issue - see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx and this whitepaper http://msdn.microsoft.com/en-us/windows/hardware/gg463353.aspxCan anyone tell me if it is possible to redesign my program to use the WTSSendMessage function that Microsoft recommends?I am attaching most of my project, excluding EXEs. If it gets completed I'll post it to the sample scripts forum. This program records info necessary for implementing wake-on-lan (via another autoit script), plus it shuts down PCs using some intelligence and a flexible schedule.TIAJamesEDIT: So it looks like WTSAPI32.DLL is what I am looking for since it contains the function. I'll have to figure out how to call the dll and use the function with it.InstallScheduledShutdown.zip Edited March 14, 2012 by jstump1
jstump1 Posted March 15, 2012 Author Posted March 15, 2012 (edited) To further clarify what I want to accomplish: I want to send a message to the logged-on user asking them to respond OK or cancel. Currently it is done with a msgbox, but I need to do it with a remote desktop function instead. The AutoIt script runs under the localsystem account, so it can't interact with the desktop of the logged on user for windows versions above XP. $UserResponse = MsgBox(1, "Scheduled Power Action", "Your computer is scheduled to " & $UserActionMessage & ". Click CANCEL to keep working.", $ShutDownWindowTimeout) This code instead needs to use dllcall to Wtsapi32.dll. Function called will be WTSSendMessage, on session host computer 'WTS_CURRENT_SERVER_HANDLE', session id 0 (console user). Working with dlls looks a bit over my head. I need some help from someone who can explain how to handle variables, structures, pointers, etc. I don't understand all the variable types and how to match a type in autoit to the types and structure Microsoft documents. I see the documentation, but I do not have understanding yet. Thanks Edited March 15, 2012 by jstump1
jstump1 Posted March 26, 2012 Author Posted March 26, 2012 (edited) OK - So I am starting to figure this out on my own. I'm getting closer, but it still doesn't work on Windows 7. It works OK on XP because the console session id is 0. On windows vista and above it is different. I need help getting dllcall to work for Windows 7. For some reason the below script works OK, except for the DllCall functions. Please help. On XP the DllCall functions do not return a result or @error but the second DllCall works, first one does nothing I can tell. On Win 7 neither DllCall works or returns anything - not even an @ error. $ShutDownWindowTimeout = "30" $UserActionMessage = "SHUTDOWN" $pTitle = DllStructCreate("char Title[32]") MsgBox(0, "DllStructCreate Title", @error) $pMessage = DllStructCreate("char Message[128]") MsgBox(0, "DllStructCreate Message", @error) $pResponse = DllStructCreate("DWORD Response") MsgBox(0, "DllStructCreate Response", @error) $SessionId = DllCall("kernel32.dll", "DWORD", "WTSGetActiveConsoleSessionId") MsgBox(0, "DllCall Kernel32 SessionId,@error", $SessionId & "," & @error) DllStructSetData($pTitle, "Title", "Scheduled Power Action") MsgBox(0, "DllStructSetData Title,@error", DllStructGetData($pTitle, "Title") & "," & @error) DllStructSetData($pMessage, "Message", "Your computer is scheduled to " & $UserActionMessage & ". Click CANCEL to keep working.") MsgBox(0, "DllStructSetData Message,@error", DllStructGetData($pMessage, "Message") & "," & @error) $DllCallResponse = DllCall("wtsapi32.dll","BOOLEAN","WTSSendMessageA","HANDLE","WTS_CURRENT_SERVER_HANDLE","DWORD",$SessionId,"str",DllStructGetData($pTitle, "Title"),"DWORD",DllStructGetSize($pTitle),"str",DllStructGetData($pMessage, "Message"),"DWORD",DllStructGetSize($pMessage),"UINT","1L","DWORD",$ShutDownWindowTimeout,"DWORD",DllStructGetPtr($pResponse),"BOOLEAN","1") MsgBox(0, "DllCall Response,@error", $DllCallResponse,@error) MsgBox(0, "DllCall pointer response", DllStructGetData($pResponse, "Response")) Edited March 26, 2012 by jstump1 My eyes could not even read the text at the original size!
jstump1 Posted April 11, 2012 Author Posted April 11, 2012 OK - I finally solved this. I didn't catch the info in the documentation on DllCall that the result from the function is an array. With that info I was finally able to figure out how to make the API call necessary Example code: #include <WinAPI.au3> $ShutDownWindowTimeout=800 $UserActionMessage = "SHUTDOWN" $pTitle = DllStructCreate("char Title[32]") $pMessage = DllStructCreate("char Message[128]") $pResponse = DllStructCreate("DWORD Response") $KernelCall = DllOpen(@SystemDir & "Kernel32.dll") $SessionId = DllCall($KernelCall, "DWORD", "WTSGetActiveConsoleSessionId") DllClose($KernelCall) DllStructSetData($pTitle, "Title", "Scheduled Power Action") DllStructSetData($pMessage, "Message", "Your computer is scheduled to " & $UserActionMessage & ". Click CANCEL to keep working.") $wtsapiCall = DllOpen(@SystemDir & "Wtsapi32.dll") $SendMessageResult = DllCall($wtsapiCall,"BOOL","WTSSendMessageA","HANDLE","WTS_CURRENT_SERVER_HANDLE","DWORD",$SessionId[0],"str",DllStructGetData($pTitle, "Title"),"DWORD",DllStructGetSize($pTitle),"str",DllStructGetData($pMessage, "Message"),"DWORD",DllStructGetSize($pMessage),"DWORD","1L","DWORD",$ShutDownWindowTimeout,"DWORD",DllStructGetPtr($pResponse),"BOOL","1") MsgBox(0, "WinAPILastError", _WinAPI_GetLastError() & "," & _WinAPI_GetLastErrorMessage()) MsgBox(0, "DllCall Response,@error", $SendMessageResult[0] & "," & $SendMessageResult[1] & "," & $SendMessageResult[2] & "," & $SendMessageResult[3] & "," & $SendMessageResult[4] & "," & $SendMessageResult[5] & "," & $SendMessageResult[6] & "," & $SendMessageResult[7]& $SendMessageResult[8] & "," & $SendMessageResult[9] & "," & $SendMessageResult[10]) MsgBox(0, "DllCall pointer response", DllStructGetData($pResponse, "Response")) DllClose($wtsapiCall)
robinj Posted September 12, 2012 Posted September 12, 2012 Just taking a look at your code because I want a service I am writing to pop up a status message on screen with option to abort. I take it that your code has two components, one running in system account and one under the user account? not able to access you code since zip file is password protected.... Robin
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