Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
63 / 48 / 12
Регистрация: 28.12.2014
Сообщений: 270

Перезагрузке/завершении работы/смены пользователя операционной системы

26.01.2021, 13:56. Показов 1520. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Есть консольное приложение на VB6. Требуется корректно завершить выполнение задач приложения при перезагрузке/завершении работы/смены пользователя операционной системы. Для этих целей используются оконные сообщения wm_queryendsession, wm_endsession, рассылаемые окнам при работе restart manager’a. Для основных задач нужны message loop и таймер. Для перехвата сообщений wm_queryendsession, wm_endsession нужен доступ к функции окна или хук на очередь. Для того, чтобы не создавать окно, используется скрытое окно рантайма класса ThunderRT6Main, оно субклассируется для перехвата сообщений wm_queryendsession, wm_endsession. Между сообщениями wm_queryendsession и wm_endsession может быть, как я это понимаю только сообщение, отправленное с помощью синхронной функции, ожидающей результат обработки, низко приоритетные сообщения, отправленные между двумя вышеописанными сообщениями не обрабатываются, из-за их высокого приоритета. Message loop при sendmessage вообще не исполняется, управление переходит напрямую в функцию окна. После обработки сообщения wm_endsession, не видно, чтобы ещё какой-то код выполнялся, нет нормального выхода их message loop. Приложение, будто бы терминируется после возврата результата обработки wm_endsession, более кода не выполняется. Так ли это или нет? Может специфика vb. Спасибо.
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Option Explicit
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function EnumThreadWindows Lib "user32" (ByVal dwThreadId As Long, ByVal lpfn As Long, ByVal lParam As Long) As Long
Private Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As msg) As Long
Private Declare Function GetMessage Lib "user32" Alias "GetMessageA" (lpMsg As msg, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Private Declare Sub PostQuitMessage Lib "user32" (ByVal nExitCode As Long)
Public Sub Main()
    Dim lngRetval As Long, strURL As String, _
        lnghSession As Long, lngContexValue As Long, lnghRequest As Long, lnghSendRequest As Long, _
        strRetVal As String, lnghTimerQueue As Long, lnghTimer As Long, udtMSG As msg, lngTimerId As Long, _
        lngFuncPtr As Long
    lngRetval = EnumThreadWindows(GetCurrentThreadId(), AddressOf basModule.EnumThreadWndProc, 0&)
    If (mlnghWnd <> 0&) Then
        lngTimerId = SetTimer(mlnghWnd, 1&, 15000, 0&)
        mlngFuncPtr = SetWindowLong(mlnghWnd, GWL_WNDPROC, AddressOf basModule.WindowProc)
    End If
    Do
        lngRetval = GetMessage(udtMSG, 0&, 0&, 0&)
        If (lngRetval = -1&) Then
            
        Else
    
            Select Case udtMSG.message
                Case WM_QUIT
                    Exit Do
                Case WM_QUERYENDSESSION
                    
                Case WM_ENDSESSION
                    
            End Select
            DispatchMessage udtMSG
        End If
    Loop
End Sub
Public Function EnumThreadWndProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
    Dim lngRetval As Long, strBuff As String
    strBuff = Strings.String$(255&, vbNullChar)
    lngRetval = GetClassName(hwnd, strBuff, Len(strBuff))
    If (Strings.InStr(1&, strBuff, "ThunderRT6Main") <> 0&) Then
        mlnghWnd = hwnd
    Else
        EnumThreadWndProc = True
    End If
End Function
Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case uMsg
        Case WM_TIMER
            
        Case WM_QUERYENDSESSION
            
        Case WM_ENDSESSION
            PostQuitMessage 0&
    End Select
    WindowProc = CallWindowProc(mlngFuncPtr, hwnd, uMsg, wParam, lParam)
End Function
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.01.2021, 13:56
Ответы с готовыми решениями:

Выбор версии операционной системы MS-DOS для работы в среде QBASIC
Здравствуйте, помогите определиться с выбором версии операционной системы MS-DOS для языка QBASIC. Версия DOS должна быть не ниже версии...

Bsod при перезагрузке/завершении работы
Есть машина на Windows server 2008 R2 SP1. Если подключиться к ней по VGA, то видно, что при перезагрузке намертво зависает на экране с...

Определение операционной системы пользователя
Подскажите, как можно определить операционную систему пользователя, какая винда стоит?

5
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
27.01.2021, 00:47
Так не следует делать:
When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system. The exit value returned to the system must be the wParam parameter of the WM_QUIT message.
У тебя в коде когда вызов уходит из Main обратно в рантайм еще используется очередь сообщений. В общем так неправильно + нужно снимать сабклассинг.
В простейшем варианте можно сделать так:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
. . .
 
Private mbCloseLoop As Boolean
 
. . .
 
    Do
    
        lngRetval = GetMessage(udtMSG, 0&, 0&, 0&)
 
. . .
 
    Loop Until mbCloseLoop
    
    SetWindowLong mlnghWnd, GWL_WNDPROC, mlngFuncPtr
 
 
. . .
 
Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case uMsg
 
. . .
            
        Case WM_ENDSESSION
        
            mbCloseLoop = True
            Exit Function
            
    End Select
    
    WindowProc = CallWindowProc(mlngFuncPtr, hwnd, uMsg, wParam, lParam)
    
End Function
2
63 / 48 / 12
Регистрация: 28.12.2014
Сообщений: 270
27.01.2021, 08:30  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
У тебя в коде когда вызов уходит из Main обратно в рантайм
В том то и дело, что не вижу, чтобы управление уходило из Main. В норме так и должно быть, когда приложение завершается обычным образом, но в моем представлении после возврата wm_endsession, процесс терминируется внешне. В документации по поводу завершения работы windows специфики не описано, кроме:
WM_ENDSESSION message
The application need not call the DestroyWindow or PostQuitMessage function when the session is ending.
Если вызвать PostQuitMessage, как это сделано у меня из оконной функции, то wm_quit в очередь потока ложиться, но не обрабатывается message loop, т.к. приложение к этому моменту завершено, т.е. его отправка ничего не меняет. Отсутствие необходимости вызова для окон DestroyWindow, наводит на мысль о нестандартном contol flow.

Цитата Сообщение от The trick Посмотреть сообщение
нужно снимать сабклассинг.
Опять же при нормальном завершении процесса - да, но в данном случае, разницы нет, процесс завершен. В обычном случае, продолжает существовать.

Впринцепе, clean up можно в любом случаем произвести корректно. Остальное оставить так, как наблюдается. Либо использовать winDbg, чтобы посмотреть что за пределами user mode приложения происходит?
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
27.01.2021, 11:47
Цитата Сообщение от IDK Посмотреть сообщение
В том то и дело, что не вижу, чтобы управление уходило из Main.
Возможно в твоей версии рантайма сабклассируемое окно просто вызывает ExitProcess, но это вряд ли. С чего такая уверенность что не уходит из Main? Где застревает тогда?

Цитата Сообщение от IDK Посмотреть сообщение
Если вызвать PostQuitMessage, как это сделано у меня из оконной функции, то wm_quit в очередь потока ложиться, но не обрабатывается message loop, т.к. приложение к этому моменту завершено, т.е. его отправка ничего не меняет. Отсутствие необходимости вызова для окон DestroyWindow, наводит на мысль о нестандартном contol flow.
Не нужно так делать, PostQuitMessage тут не нужен. Можно послать любое другое сообщение, либо сделать флаг как я скинул выше в примере. Рантайм может еще требовать прокачки сообщений, а ты его запрещаешь.

Цитата Сообщение от IDK Посмотреть сообщение
Опять же при нормальном завершении процесса - да, но в данном случае, разницы нет, процесс завершен. В обычном случае, продолжает существовать.
Я у себя проверил, у меня с правками что я скинул выше - все нормально отрабатывает.
1
63 / 48 / 12
Регистрация: 28.12.2014
Сообщений: 270
27.01.2021, 13:47  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
Возможно в твоей версии рантайма сабклассируемое окно просто вызывает ExitProcess, но это вряд ли. С чего такая уверенность что не уходит из Main? Где застревает тогда?
Про ExitProcess сразу подумал, но нет.
Уверенность из-за лога. Исполнение в бинарнике логируется. После обработки wm_endsession в субклассированной функции более код приложения не выполняется. Если нужно выполнить какие-то действия, то их нужно в данном случае выполнять до обработки сообщения wm_endsession, так показывает практика. Есть подозрение, что это поведение по дизайну windows, в каком-то смысле похоже на аварийное завершение процесса.
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
27.01.2021, 14:23
IDK, не может такого быть. Смотри в отладчике что у тебя происходит.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.01.2021, 14:23
Помогаю со студенческими работами здесь

Выполнение кода при завершении работы системы
Возникла необходимость выполнить код при завершении работы системы, как это можно сделать? какие методы или технологии использовать? ...

Завершение работы операционной системы
Уважаемые форумчане! Накопился ряд вопросов, которые требуют комментариев профессионалов: 1. Столкнулся с такой ситуацией - после...

Основы работы операционной системы ThreadX
Добрый день! Объясните пожалуйста основы работы операционной системы ThreadX: как работает переключение между потоками, очереди,...

Функция для блокировки системы и смены пользователя
Доброго времени суток. В моем распоряжении есть коды для выполнения задач связаных с завершением работы сеанса ПК на vb.net. Эти...

Выбор операционной системы для полупрофессиональной/профессиональной работы со звуком
Хотел поинтересоваться - какую систему выбирают опытные люди для работы со звуком? Ну хотя бы из трех общеизвестных? Windows, Linux или...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru