From: Sarah M. Weinberger on 4 Jul 2010 22:19 Hi All, I found out that the problem is not just "my problem", but rather one that anyone who creates VB6 based applications (possibly C# and VB.Net too from what I am read on one post) suffer. I found a tool, RMTool.exe, which Microsoft distributes as part of the Windows Vista Qualification Test Tools. I got lucky to even find that. That is what Microsoft evidently uses for both Windows Vista and Windows 7. The tool allows a user to test the restart functionality. You simply use a command line similar to the following just substituting the PID for the application being tested. You can get the PID by going to the Windows Task Manager and then "View | Select Columns" and then checking the box to view PID (first entry). "C:\Program Files\Microsoft\Logo Testing Tools for Windows\Restart Manager\x86\rmtool.exe" -p 7256 -R I created a simple VB6 project. When I say simple. I am not kidding. I did not even change names. My first attempt was a plain Project1.exe applet. I added nothing to the form, no background code. I saved and clicked on make. I then got the process ID and ran the line above. Guess what? VB6 failed. I ran the test against NotePad and that worked like a charm. I suspect that all Microsoft applications work. VB6 based ones do not. STEP 2: I added subclassing. I deciced to try some subclassing, as that was recommended. I took my plain vanila application and added the following. By the way, I only added the two message box statements later to see if I am even getting the messages called. I am not, but I am getting ahead of myself. -------------------------- New Subclassing Module: -------------------------- Option Explicit Public glPrevWndProc As Long Public Const GWL_WNDPROC = (-4) Public Const WM_QUERYENDSESSION = &H11 Public Const WM_ENDSESSION = &H16 Public Const ENDSESSION_LOGOFF = &H80000000 Public Const ENDSESSION_CRITICAL = &H40000000 Public Const ENDSESSION_CLOSEAPP = &H1 Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public Function pMyWindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long 'Process the WM_QUERYENDSESSION message. We need to process this message for Windows 7 compatibility issues. Select Case uMsg Case WM_ENDSESSION MsgBox "Inside WM_ENDSESSION", vbOKOnly, App.ProductName pMyWindowProc = 0 Exit Function Case WM_QUERYENDSESSION 'Assume a standard response to start. pMyWindowProc = 1 'TRUE, Allow the system to end gracefully. MsgBox "Inside WM_QUERYENDSESSION", vbOKOnly, App.ProductName 'Handle the specific sub-message. Select Case lParam Case ENDSESSION_LOGOFF 'Fall through and take the default action. Case ENDSESSION_CRITICAL 'Fall through and take the default action. Case ENDSESSION_CLOSEAPP 'Fall through and take the default action. Case Else 'Fall through and take the default action. End Select Exit Function Case WM_ENDSESSION End Select 'Pass back all unprocessed messages to the original procedure associated with the form. pMyWindowProc = CallWindowProc(glPrevWndProc, hWnd, uMsg, wParam, lParam) End Function -------------------------- Form1 Code -------------------------- Option Explicit Private Sub Form_Load() 'Subclass Main Form: We want to process windows messages. glPrevWndProc = SetWindowLong(Me.hWnd, GWL_WNDPROC, AddressOf pMyWindowProc) End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) 'Stops the form from intercepting Window's messages by resetting the default procedures associated with the form. Call SetWindowLong(Me.hWnd, GWL_WNDPROC, glPrevWndProc) End Sub -------------------------- Here is a run from NotePad: A working scenario: ----------------------------------------------------------------------------------------------------------------------- Note: PID 6564 was of a running NotePad.exe. All tests done on Microsoft Windows Vista. C:\>"C:\Program Files\Microsoft\Logo Testing Tools for Windows\Restart Manager\x86\rmtool.exe" -p 6564 -R Starting Session StartSession() returned 0 SUCCESS: StartSession() Session Key: ebcedc00899770428fa4f29c7338f7f0??� Registering file RegisterResources() returned 0 SUCCESS: RegisterResources() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 6640, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:6564, type 1, stat 1) - Notepad () Shuting down applications SUCCESS: RmShutdown() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 6640, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:6564, type 1, stat 2) - Notepad () Restarting Applications SUCCESS: RmRestart() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 6640, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:6564, type 1, stat 2) - Notepad () Ending Session EndSession() returned 0 SUCCESS: EndSession() ----------------------------------------------------------------------------------------------------------------------- Here is from a failed VB6 application (with or without subclassing and with or without a Form_QueryUnload): ----------------------------------------------------------------------------------------------------------------------- C:\>"C:\Program Files\Microsoft\Logo Testing Tools for Windows\Restart Manager\x86\rmtool.exe" -p 1516 -R Starting Session StartSession() returned 0 SUCCESS: StartSession() Session Key: bc96075ed55ce64caab5da4fd8c4f67f!!� Registering file RegisterResources() returned 0 SUCCESS: RegisterResources() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 2124, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:1516, type 1, stat 1) - Project1.exe () Shuting down applications *** FAILURE ***: RmShutdown() Ending Session EndSession() returned 0 SUCCESS: EndSession() ----------------------------------------------------------------------------------------------------------------------- Usually I hit Ctrl+C to break the RMTool execution after the "Shuting down applications" line, as the timeout is hugely long. The application usually winds up hanging and needs to be forcefully shutdown, but that depends on whether or not RMTool is broken and the like. I found out by adding in the MsgBox statements that the message handler, when using RMTool.exe never gets the WM_QUERYENDSESSION or the WM_ENDSESSION. VB6 never gets the Form_QueryUnload or Form_Unload. Further testing without RMTool reveals that Form_QueryUnload comes after the WM_QUERYENDSESSION message. Summary: VB6, which is a form based programming language, has some sort of issue complying with Microsoft Restart Manager requiremment for Windows Vista and Windows 7. Out of sheer curiosity I decided to try a Visual Studio 2010 VB.Net executable with no code or form items added, WindowsApplication1.exe. I did not even change the names. The test was a success, so Visual Studio 2010 VB.Net passes the Restart Manager test with flying colors. Sadly, VB6 does not. Here is the result of my test. ----------------------------------------------------------------------------------------------------------------------- C:\>"C:\Program Files\Microsoft\Logo Testing Tools for Windows\Restart Manager\x86\rmtool.exe" -p 4108 -R Starting Session StartSession() returned 0 SUCCESS: StartSession() Session Key: f09a4c7bb7adbf488a9b9ec883f93527??g Registering file RegisterResources() returned 0 SUCCESS: RegisterResources() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 8156, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:4108, type 1, stat 1) - WindowsApplication1 () Shuting down applications SUCCESS: RmShutdown() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 8156, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:4108, type 1, stat 2) - WindowsApplication1 () Restarting Applications SUCCESS: RmRestart() Getting affected apps. RmGetList() needs 1 structs, reboot reasons 0, returned 0xea SUCCESS: Allocating RM_PROCESS_INFO array SUCCESS: GetAffectedApps() My PID: 8156, Affected Apps: 1, needed 1, reboot reasons 0 PID(1:4108, type 1, stat 2) - WindowsApplication1 () Ending Session EndSession() returned 0 SUCCESS: EndSession() ----------------------------------------------------------------------------------------------------------------------- I need to get VB6 to work with Microsoft's Restart Manager. Any thoughts? Like I said, anyone developing a VB6 based application will suffer this problem as me. Sorry for being long winded, but there was a lot of information to impart. Thanks in advance, Sarah
|
Pages: 1 Prev: Happy Sabbath! Next: Windows 7 Qualification and VB6 (RMTool) - The SOLUTION |