Windows applications are sent the WM_QUERYENDSESSION message at shutdown. Applications can return TRUE to indicate that they can be closed, or FALSE to indicate that they should not be closed (e.g., because doing so would cause the user to lose data or destroy a CD being burned). Does PowerBasic handle this message. If so, can PowerBasic perform a specific action, specifically write a registry key or run an external program when it receives WM_QUERYENDSESSION
Announcement
Collapse
No announcement yet.
Does PowerBasic handle WM_QUERYENDSESSION
Collapse
X
-
I assume you mean the PowerBasic Compiler as opposed to the Console Compiler. What is Afaik?
Can this be done with the console? The result I need is a program that just sits there silently and then either erases a key or runs Regedit to erase a key when Windows exits. I know this can be done with Group Policy or some shareware programs but they won't do. It also has to silently do a little other housekeeping but I think I can handle that.
Last time I used PowerBasic it was called QuickBasic.
Comment
-
You need to use CreateWindow/CreateWindowEx or a dialog resource to create a hidden window in order to capture the message, as you do not have access to the console window handler. Subclassing the console could also be done I suppose, although it's more complex and you don't really need the console.
Search source code forum for PBCC examples of CreateWindow or dialog box creation. Also see #CONSOLE OFF (sp?) in the PB help file.
PS> PowerBASIC has never been called QuickBasic, that was a Microsoft product. It was called TurboBASIC in the 80's.Last edited by Kev Peel; 30 Oct 2008, 02:14 PM.
Comment
-
Ah yes, my bad. It was so far ahead of Quickbasic it was incredible. It started teaching me structured programming and assembly. Back then the screen write routines were so incredibly slow that you could whatch the characters arrive. I wrote a program which called an assembly language routine to poke the screen... no one could believe it when a complete screen of text would pop up.
After using the subprogram features, when I graduated to FORTH where structured programming is the only way its possible, I had no problems.
Since its been so long since I have used PowerBasic and am not at all familiar with the program or documentation, do you think maybe you could be a bit more specific? Exactly how does PB handle a WM_QUERYENDSESSION message? I was hoping that it would be similar to error handling where I could jump to a subroutine.
Would it be easier to use PB9? I suppose there would be no objection as I'm sure I could hide the window at least until shutdown.Last edited by Guest; 30 Oct 2008, 02:42 PM.
Comment
-
Welcome (back)
The compiler itself does not enforce this new method, but Windows. This is the hurdle many programmers face transitioning from DOS. My advice would to get a good book (Charles Petzold's 'Programming Windows' is a good one, although the samples are in C).
Basically, you provide Windows with a function (which would be a 'callback') and Windows calls the function periodically to send the messages ('events') through to your app. This is part of the 'event driven' model of Windows.
I just don't have time to write an example at the moment (sorry), but here is some code from Michael Mattias that creates a Window and callback in PBCC:
Progress Bar Dialog for PB/CC programs
Would it be easier to use PB9?
If you already have PB/WIN 9 then YES! It would be extremely easy with PB/WIN DDT statements and there are plenty of sample DDT projects that are supplied with the compiler.Last edited by Kev Peel; 30 Oct 2008, 02:46 PM.
Comment
-
See http://msdn.microsoft.com/en-us/library/aa376890(VS.85).aspx and http://msdn.microsoft.com/en-us/library/ms700677(VS.85).aspx.
A WM_QUERYENDSESSION message is sent to a callback function (see http://www.powerbasic.com/support/he.../callbacks.htm) in PBWin or a user defined WindowProc (see http://msdn.microsoft.com/en-us/library/ms633573(VS.85).aspx) in PBCC.Sincerely,
Steve Rossell
PowerBASIC Staff
Comment
-
With PB/CC maybe SetConsoleCtrlHandler() with a callback function looking for CTRL_LOGOFF_EVENT might be useful.Michael Mattias
Tal Systems (retired)
Port Washington WI USA
[email protected]
http://www.talsystems.com
Comment
-
Originally posted by Thomas Bonge View PostThen if its ok I am going to ... re-ask the question in the PBC forum.
Comment
-
Try this out.
Code:#COMPILE EXE #DIM ALL %CCWIN = 1 #INCLUDE "WIN32API.INC" FUNCTION WINMAIN (BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _ BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG DIM hWnd AS LOCAL DWORD DIM cWnd AS LOCAL WndClassEX DIM szName AS LOCAL ASCIIZ * 12 DIM tMSG AS LOCAL tagMSG szName = "QSessionEnd" cWnd.cbSize = SIZEOF(cWnd) cWnd.lpfnWndProc = CODEPTR(WndProc) cWnd.lpszClassName = VARPTR(szName) cWnd.hbrBackground = GETSTOCKOBJECT(%LTGRAY_BRUSH) REGISTERCLASSEX cWnd hWnd = CREATEWINDOW ( szName, "QSessionEnd", %WS_DISABLED, 0, 0, 0, 0, %HWND_DESKTOP, %NULL, hInstance, BYVAL %NULL ) SHOWWINDOW hWnd, %SW_HIDE WHILE GETMESSAGE(tMsg, %NULL, 0, 0) TRANSLATEMESSAGE tMsg DISPATCHMESSAGE tMsg WEND END FUNCTION FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _ BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG IF wMsg = %WM_QUERYENDSESSION THEN 'wParam = 0 = Shutdown Windows Dialog Box PRINT TIME$ & ": Prevented ShutDown. (" & FORMAT$(wParam) & ")" FUNCTION = 0 EXIT FUNCTION END IF FUNCTION = DEFWINDOWPROC(hWnd&, wMsg&, wParam&, lParam&) END FUNCTION
LOCAL MyEMail AS STRING
MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")
Comment
-
Thank you so much for posting this. Unfortunately I don't know what to do with it. It'sw not clear if it should be compiled with PB or PBCC but I qassumed PBCC because it references "WIN32API.INC." I tried both and although I could eventually compile both, the Debug-Run of both gave errors. I assume that it presents aq DOS screen then when you try to reboot it cancels the reboot and prints a message to the screen. Assembled with PBCC it gives the blank screen, no message, and crashes on run. Compiled with PB it gives the same blank screen, no message, no crash, but the computer reboots fine.
What am I doing wrong?
Comment
-
It was meant for CC. It compiled and ran (normal and debug) without issue for me. When I ran the compiled executable it prevented the shutdown. I'm not quite sure what the problem could be. Microsoft has a page that provides further detail into WM_QUERYENDSESSION @ http://msdn.microsoft.com/en-us/libr...90(VS.85).aspx . Maybe this could provide insight?
I use this code in a small program I made that sits in the system tray and prevents shutdown until it is closed.LOCAL MyEMail AS STRING
MyEmail = STRREVERSE$("53pmohtj") & CHR$(64) & STRREVERSE$("liamg") & CHR$(46) & STRREVERSE$("moc")
Comment
-
Code:#DIM ALL #COMPILE EXE #INCLUDE "win32api.inc" FUNCTION PBMAIN SetConsoleCtrlHandler CODEPTR(ConsoleHandler), 1 WAITKEY$ SetConsoleCtrlHandler CODEPTR(ConsoleHandler), 0 END FUNCTION FUNCTION ConsoleHandler(BYVAL dwEvent AS DWORD) AS LONG 'these will all terminate the program SELECT CASE dwEvent CASE %CTRL_C_EVENT PRINT "Ctrl-C pressed" CASE %CTRL_BREAK_EVENT PRINT "Ctrl-Break pressed" CASE %CTRL_CLOSE_EVENT PRINT "[x] Close pressed" CASE %CTRL_LOGOFF_EVENT PRINT "User logging off or restarting" CASE %CTRL_SHUTDOWN_EVENT PRINT "System shutting down" END SELECT ? "Press a key to exit console handler" WAITKEY$ END FUNCTION
The world is full of apathy, but who cares?
Comment
-
John's code needs only slight modification to compile and run with PBWin804 / 9 (replace Print w/ MsgBox).
Here's a version that has the option to resume the shutdown process (after writting to the registry or whatever).
The extra code is mostly C&P from PB's sample utility code "Restart.bas". (Plus a check to see if it was shutdown or a logoff that caused the WM_QUERYENDSESSION. - Quicker testing to resume a logoff!)
Code:#COMPILE EXE #DIM ALL #INCLUDE "WIN32API.INC" ' < First three functions are from PB sample "Restart.bas" - Mods for Shut down / LogOff. %SHTDN_REASON_FLAG_USER_DEFINED = &H40000000 FUNCTION IsNt () AS LONG LOCAL tOsVersion AS OSVERSIONINFO tOsVersion.dwOSVersionInfoSize = SIZEOF(tOsVersion) IF GetVersionEx(tOsVersion) THEN FUNCTION = (tOsVersion.dwPlatformId = %VER_PLATFORM_WIN32_NT) END IF END FUNCTION '------------------/IsNt FUNCTION AdjustToken () AS LONG LOCAL hToken AS DWORD LOCAL tokenProcess AS TOKEN_PRIVILEGES ' Get the privilege token for this process. - keep in hToken IF ISFALSE OpenProcessToken(GetCurrentProcess(), %TOKEN_ADJUST_PRIVILEGES OR %TOKEN_QUERY, hToken) THEN EXIT FUNCTION END IF ' Get the value of the shutdown privilege. IF LookupPrivilegeValue(BYVAL %NULL, "SeShutdownPrivilege", tokenProcess.Privileges(0).pLuid) THEN ' Enable the shutdown privilege for this process. tokenProcess.PrivilegeCount = 1 tokenProcess.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED FUNCTION = AdjustTokenPrivileges(hToken, %FALSE, tokenProcess, 0, BYVAL %NULL, BYVAL %NULL) END IF CloseHandle hToken END FUNCTION '------------------/AdjustTken FUNCTION ResumeShutDown(BYVAL LogOff AS LONG) AS LONG IF IsNT() THEN IF ISFALSE AdjustToken() THEN MSGBOX "Could not obtain shutdown privilege." EXIT FUNCTION END IF END IF ' If you're using Windows XP or later, you may want to provide a shutdown ' reason code in the second parameter. See the Reason.inc file for codes. ' The major reason code should be ORed with the minor reason code. ' eg %SHTDN_REASON_FLAG_USER_DEFINED = &H40000000 IF LogOff = 0 THEN IF ISFALSE ExitWindowsEx(%EWX_SHUTDOWN OR %EWX_FORCEIFHUNG, %SHTDN_REASON_FLAG_USER_DEFINED) THEN MSGBOX "Shutdown failed." END IF ELSE IF ISFALSE ExitWindowsEx(%EWX_LOGOFF, 0) THEN MSGBOX "Shutdown failed." END IF END IF END FUNCTION '------------------/ResumeShutDown ' John Thompson. [URL]http://www.powerbasic.com/support/pbforums/showthread.php?p=300964#post300964[/URL] ' with some mods FUNCTION WINMAIN (BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _ BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG DIM hWnd AS LOCAL DWORD DIM cWnd AS LOCAL WndClassEX DIM szName AS LOCAL ASCIIZ * 12 DIM tMSG AS LOCAL tagMSG szName = "QSessionEnd" cWnd.cbSize = SIZEOF(cWnd) cWnd.lpfnWndProc = CODEPTR(WndProc) cWnd.lpszClassName = VARPTR(szName) cWnd.hbrBackground = GETSTOCKOBJECT(%LTGRAY_BRUSH) REGISTERCLASSEX cWnd hWnd = CREATEWINDOW ( szName, "QSessionEnd", %WS_DISABLED, 0, 0, 0, 0, %HWND_DESKTOP, %NULL, hInstance, BYVAL %NULL ) SHOWWINDOW hWnd, %SW_HIDE WHILE GETMESSAGE(tMsg, %NULL, 0, 0) TRANSLATEMESSAGE tMsg DISPATCHMESSAGE tMsg WEND END FUNCTION '------------------/WinMain FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _ BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG DIM Res AS LONG STATIC ThisProc, LogOff AS LONG IF wMsg = %WM_QUERYENDSESSION THEN IF ThisProc = 0 THEN ThisProc = %TRUE ' Test for resume shutdown LogOff = IIF(lParam AND %ENDSESSION_LOGOFF = %ENDSESSION_LOGOFF, 1, 0) MSGBOX TIME$ & ": Prevented ShutDown. (" & FORMAT$(wParam) & ")" PostMessage hWnd, %WM_USER + 1000, 0, 0 FUNCTION = 0 ' Stop the shutdown process EXIT FUNCTION END IF END IF IF wMsg = %WM_USER + 1000 THEN ' Here you could do those other things, then.. Res = MSGBOX ("Resume Shutdown / LogOff?", %MB_YESNO OR %MB_SYSTEMMODAL _ ' / logoff OR %MB_ICONWARNING OR %MB_DEFBUTTON2, "Ready to quit?") IF Res = %IDYES THEN ResumeShutDown (LogOff) ELSE ThisProc = 0 LogOff = 0 END IF END IF FUNCTION = DEFWINDOWPROC(hWnd&, wMsg&, wParam&, lParam&) END FUNCTION '------------------/WndProc
Rgds, Dave
Comment
-
'Here's a slightly modified vesion of the previous post..
Code:#COMPILE EXE #DIM ALL #INCLUDE "WIN32API.INC" ' < First three functions are from PB sample "Restart.bas" - Shut down / LogOff. %SHTDN_REASON_FLAG_USER_DEFINED = &H40000000 FUNCTION IsNt () AS LONG LOCAL tOsVersion AS OSVERSIONINFO tOsVersion.dwOSVersionInfoSize = SIZEOF(tOsVersion) IF GetVersionEx(tOsVersion) THEN FUNCTION = (tOsVersion.dwPlatformId = %VER_PLATFORM_WIN32_NT) END IF END FUNCTION '------------------/IsNt FUNCTION AdjustToken () AS LONG LOCAL hToken AS DWORD LOCAL tokenProcess AS TOKEN_PRIVILEGES ' Get the privilege token for this process. - keep in hToken IF ISFALSE OpenProcessToken(GetCurrentProcess(), %TOKEN_ADJUST_PRIVILEGES OR %TOKEN_QUERY, hToken) THEN EXIT FUNCTION END IF ' Get the value of the shutdown privilege. IF LookupPrivilegeValue(BYVAL %NULL, "SeShutdownPrivilege", tokenProcess.Privileges(0).pLuid) THEN ' Enable the shutdown privilege for this process. tokenProcess.PrivilegeCount = 1 tokenProcess.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED FUNCTION = AdjustTokenPrivileges(hToken, %FALSE, tokenProcess, 0, BYVAL %NULL, BYVAL %NULL) END IF CloseHandle hToken END FUNCTION '------------------/AdjustTken FUNCTION ResumeShutDown(BYVAL LogOff AS LONG) AS LONG IF IsNT() THEN IF ISFALSE AdjustToken() THEN MSGBOX "Could not obtain shutdown privilege." EXIT FUNCTION END IF END IF ' If you're using Windows XP or later, you may want to provide a shutdown ' reason code in the second parameter. See the Reason.inc file for codes. ' The major reason code should be ORed with the minor reason code. ' eg %SHTDN_REASON_FLAG_USER_DEFINED = &H40000000 IF LogOff = 0 THEN IF ISFALSE ExitWindowsEx(%EWX_SHUTDOWN OR %EWX_FORCEIFHUNG, %SHTDN_REASON_FLAG_USER_DEFINED) THEN MSGBOX "Shutdown failed." END IF ELSE IF ISFALSE ExitWindowsEx(%EWX_LOGOFF, 0) THEN MSGBOX "Shutdown failed." END IF END IF END FUNCTION '------------------/ResumeShutDown ' John Thompson. [URL]http://www.powerbasic.com/support/pbforums/showthread.php?p=300964#post300964[/URL] ' with some mods FUNCTION WINMAIN (BYVAL hInstance AS LONG, BYVAL hPrevInstance AS LONG, _ BYVAL lpCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG DIM hWnd AS LOCAL DWORD DIM cWnd AS LOCAL WndClassEX DIM szName AS LOCAL ASCIIZ * 12 DIM tMSG AS LOCAL tagMSG szName = "QSessionEnd" cWnd.cbSize = SIZEOF(cWnd) cWnd.lpfnWndProc = CODEPTR(WndProc) cWnd.lpszClassName = VARPTR(szName) cWnd.hbrBackground = GETSTOCKOBJECT(%LTGRAY_BRUSH) REGISTERCLASSEX cWnd hWnd = CREATEWINDOW ( szName, "QSessionEnd", %WS_DISABLED, 0, 0, 0, 0, %HWND_DESKTOP, %NULL, hInstance, BYVAL %NULL ) SHOWWINDOW hWnd, %SW_HIDE WHILE GETMESSAGE(tMsg, %NULL, 0, 0) TRANSLATEMESSAGE tMsg DISPATCHMESSAGE tMsg WEND END FUNCTION '------------------/WinMain FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _ BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG DIM Res AS LONG STATIC ThisProc, LogOff AS LONG IF wMsg = %WM_QUERYENDSESSION THEN IF ThisProc = 0 THEN ThisProc = %TRUE ' Test for resume shutdown LogOff = IIF(lParam AND %ENDSESSION_LOGOFF = %ENDSESSION_LOGOFF, 1, 0) ' MSGBOX TIME$ & ": Prevented ShutDown. (" & FORMAT$(wParam) & ")" ' ** moved msgbox PostMessage hWnd, %WM_USER + 1000, 0, 0 FUNCTION = 0 ' Stop the shutdown process EXIT FUNCTION END IF END IF IF wMsg = %WM_USER + 1000 Then MSGBOX TIME$ & ": Prevented ShutDown." ' ** ' Here you could do those other things, then.. Res = MSGBOX ("Resume Shutdown / LogOff?", %MB_YESNO OR %MB_SYSTEMMODAL _ ' / logoff OR %MB_ICONWARNING OR %MB_DEFBUTTON2, "Ready to quit?") IF Res = %IDYES THEN ResumeShutDown (LogOff) ELSE ThisProc = 0 LogOff = 0 END IF END IF FUNCTION = DEFWINDOWPROC(hWnd&, wMsg&, wParam&, lParam&) END FUNCTION '------------------/WndProc
(It receives %WM_QUERYENDSESSION itself?) and the Session End process isn't halted.
With the modification the hidden window "QSessionEnd" keeps working until you elect to resume the shutdown / logoff process.Last edited by Dave Biggs; 24 Nov 2008, 08:47 AM.Rgds, Dave
Comment
Comment