Orion9

Joined: 01 Jan 2024 Posts: 1100
|
(Separately) Posted: Wed May 13, 2026 13:43 Post subject: Завершение работы ПК после копирования |
|
|
Автоматическое выключение ПК после завершения копирования или перемещения файлов. Скрипт написан на языке плагина Autorun.
Интерфейс для задания параметров отсутствует. Операция активируется нажатимем Ctrl+Alt+O или Alt+Win+O во время копирования или перемещения файлов (далее просто копирования), окно ТС при этом становится прозрачным. По завершении копирования сохраяется возможность отменить действие в течении 25 секунд. Действие также можно отменить в любой момент копирования повторным нажатием Ctrl+Alt+O или Alt+Win+O.
Операция копирования может быть прервана окном диалога (запрос на перезапись, ошибка копирования и т.д.). В этом случае скрипт ждет 300 секунд перед тем, как выключить ПК. Значение можно изменить в переменной wait_seconds. Некоторая дополнительная информация отображается в заголовке окна копирования. В корне ТС сохраняется лог выключения Shutdown.log — должны быть права на запись в эту папку или путь к файлу лога придется изменить.
 Shutdown.aucfg | Code: | Pragma IncludeOnce
RegisterCommand 81010 "WinShutdown"
# Ctrl+Alt+O
SetHotkeyAction /K:C /K:A /H:O /DM "RunThread" "CopyMonitor"
# Alt+Win+O
SetHotkeyAction /K:A /K:W /H:O /DM "RunThread" "CopyMonitor"
Global h_WinShutdown
Global g_WinShutdown, g_Shutdown = 0
Global g_LogShutdown = COMMANDER_PATH & "\Shutdown.log"
Global o_WinShutdown = Callback("WinShutdownProc", "hwnd;uint;wparam;lparam")
Func WinShutdownProc(hWnd, uMsg, wParam, lParam)
Static WM_CLOSE = 0x0010
If uMsg = WM_CLOSE Then
If DllCall("DestroyWindow", "handle", hWnd) Then
g_Shutdown = 0
EndIf
Return 0
EndIf
Return DllCall("CallWindowProcW", "ptr", g_WinShutdown, _
"hwnd", hWnd, "uint", uMsg, "wparam", wParam, "lparam", lParam)
EndFunc
Func WinShutdown()
Local hIco
Local nTimeOut = 25 # время на отмену операции
# окно уже существует
If h_WinShutdown > 0 Then
If WinGetState(1, h_WinShutdown) Then
SendMessage(h_WinShutdown, 0x0010, 0, 0)
Return
EndIf
h_WinShutdown = 0
Endif
# дескриптор монитора окна ТС
Local hMon = DllCall("MonitorFromWindow", "hwnd", AUTORUN_TCHANDLE, "dword", 2)
# информация о масштабировании экрана
Local nMonScale = 0, nTextScale
DllCall("Shcore.dll\GetScaleFactorForMonitor", "hwnd", hMon, "dword*", @nMonScale)
If nMonScale < 100 Then nMonScale = 100
# информация о размере текста
RegRead nTextScale "HKCU\Software\Microsoft\Accessibility" "TextScaleFactor" 100
nTextScale = Round(nTextScale/100,2)
Local nWidth = Round(3*nMonScale*nTextScale,0)
# создание окна прогресс-бара
h_WinShutdown = DllCall("CreateWindowExW", _
"dword", 0, _
"wstr", "msctls_progress32", _
"wstr", "", _
"dword", 0x00C80000, _
"int", 200, "int", 100, "int", Round(Scale(300)*nTextScale,0), "int", Scale(50), _
"handle", , _
"handle", 0, "handle", 0, "ptr", 0, _
"handle")
# не удалось создать окно
If h_WinShutdown = 0 Then Return 0
# поверх всех окон
WinSetState(30, h_WinShutdown)
# WinAlign(h_WinShutdown, 0, DllCall("GetDesktopWindow"), 0, 100, -100)
# выравнивание по центру рабочего стола
WinAlign(h_WinShutdown, 0, DllCall("GetDesktopWindow"))
# перемещение окна вверх на 50 пикселей
WinSetPos("", -Scale(50), "", "", 1, h_WinShutdown)
# перемещение окна вправо на 50 пикселей
# WinSetPos(Scale(50), "", "", "", 1, h_WinShutdown)
# отображение окна
WinSetState(5, h_WinShutdown)
# установка оконной процедуры
g_WinShutdown = DllCall("SetWindowLong" & (auX64 ? "PtrW" : "W"), _
"hwnd", h_WinShutdown, _
"int", -4, _
"long_ptr", o_WinShutdown.Ptr, "ptr")
Static PBM_SETPOS = 1026, _
PBM_SETRANGE = 1025, _
PBS_MARQUEE = 0x08, _
PBM_SETMARQUEE = 1034, _
WM_GETICON = 0x7f, _
WM_SETICON = 0x80
# установка иконки ТС
hIco = SendMessage(AUTORUN_TCHANDLE, WM_GETICON, 2, 0)
SendMessage(h_WinShutdown, WM_SETICON, 0, hIco)
g_Shutdown = 1
# стиль и позиция прогресс-бара
WinSetStyle(PBS_MARQUEE, 4, h_WinShutdown)
SendMessage(h_WinShutdown, PBM_SETPOS, 0, 0)
# время на отмену
For i = 1 to nTimeOut
SendMessage(h_WinShutdown, PBM_SETPOS, Round(i/nTimeOut*100,0), 0)
WinSetText("Выключение через " & nTimeOut-i & " сек.", h_WinShutdown)
Sleep(900)
If g_Shutdown = 0 Then Break
Next
If g_Shutdown = 0 Then
FileAppend(g_LogShutdown, StrFormat("%s %s Выключение отменено", Date(), Time()))
MsgBox("Выключение ПК отменено", "", 48)
Else
If DllCall("DestroyWindow", "handle", h_WinShutdown) Then h_WinShutdown = 0
FileAppend(g_LogShutdown, StrFormat("%s %s Выключение ПК...", Date(), Time()))
# MsgBox("Выключение ПК", "Тест", 64)
ShellExec("shutdown", "/s /t 0 /f") # /f принудительное закрытие приложений
EndIf
EndFunc
Global g_CopyMonitor = false, g_CopyWndOwner = false, g_DialogWnd = ""
Func CopyMonitor()
Local bWmi = true # показывать байты в заголовке
Local bTransCopyWin = true # прозрачность окна копирования
Local wait_seconds = 300 # время ожидания при появлении окна диалога
Static hCopyWnd = 0
# монитор уже запущен - остановить
If g_CopyMonitor Then
g_CopyMonitor = false
Return
EndIf
# поиск окна копирования
hCopyWnd = WinFind(0, "TDLG2FILEACTIONMIN")
If hCopyWnd = 0 Then
ShowHint("Копирование не запущено", 0, 0, 1000, 1)
WinAlign(LAST_HINT_WINDOW)
Return
EndIf
# текущее состояние монитора
g_CopyMonitor = true
# установка прозрачности окна ТС
WinSetStyle(0x80000, 3)
DllCall("SetLayeredWindowAttributes", "hwnd", AUTORUN_TCHANDLE, _
"ptr", 0, "byte", 192, "dword", 2)
# опциональная прозрачность окна копирования
If bTransCopyWin Then
WinSetStyle(0x80000, 3, hCopyWnd)
DllCall("SetLayeredWindowAttributes", "hwnd", hCopyWnd, _
"ptr", 0, "byte", 192, "dword", 2)
EndIf
# поиск и блокировка кнопки "В фоне"
Local b = WinFind(hCopyWnd, _
(AUTORUN_TCARCH = 32 ? "TButton" : "Button"), (AUTORUN_TCARCH = 32 ? 2 : 1))
WinSetState(21, b)
# параметры подсказки
SetHintParam("ShowHint", "Font", 15, "Arial")
SetHintParam("ShowHint", "BackColor", 0xFF0000)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
ShowHint("Монитор выключения запущен, ожидание завершения копирования", 0, 0, 1000, 1)
# сброс параметров подсказки
SetHintParam("ShowHint", "Reload")
# центрирование подсказки
WinAlign(LAST_HINT_WINDOW)
Local wmi, wmq, txt = WinGetText(hCopyWnd)
# wmi запрос к процессу ТС
wmq = "SELECT IOWriteBytesPersec FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=" & AUTORUN_TCPID
# функция обратного вызова
Local ewp = Callback("IsCopyWndOwner", "hwnd;lparam")
Local hang = 0
# цикл ожидания периодический поиск окна копирования
While hCopyWnd <> 0
g_CopyWndOwner = false
# проверить статус владельца окна копирования
DllCall("EnumWindows", "ptr", ewp.Ptr, "lparam", hCopyWnd)
# записано байт процессом опционально
If bWmi Then wmi = SizeFormat(GetWMIValue("IOWriteBytesPersec", wmq), 1, "G", 2)
WinSetText("Shutdown " & (Not g_CopyWndOwner ? "mode" : "paused for " & hang & " сек.") _
& (Not bWmi ? "" : ": " & wmi), hCopyWnd)
hang = (g_CopyWndOwner ? hang + 1 : 0)
If hang > wait_seconds Then Break
For i = 1 To 10
If Not g_CopyMonitor Then Break
Sleep(100)
Next
If Not g_CopyMonitor Then Break
hCopyWnd = WinFind(0, "TDLG2FILEACTIONMIN")
Wend
Free(ewp)
WinSetText(txt, hCopyWnd)
# разблокирование кнопки "В фоне"
WinSetState(20, b)
# цикл не был прерван повторным нажатием Ctrl+Alt+O
If g_CopyMonitor Then
g_CopyMonitor = false
ShutdownLog(hang)
WinShutdown()
Else
SetHintParam("ShowHint", "Font", 15, "Arial")
SetHintParam("ShowHint", "BackColor", 0xFF0000)
SetHintParam("ShowHint", "Text", 0xFFFFFF)
ShowHint("Монитор выключения остановлен", 0, 0, 1000, 1)
SetHintParam("ShowHint", "Reload")
WinAlign(LAST_HINT_WINDOW)
EndIf
# отключение прозрачности
WinSetStyle(0x80000, 5)
If bTransCopyWin Then WinSetStyle(0x80000, 5, hCopyWnd)
EndFunc
Func IsCopyWndOwner(wnd, lparam)
If Not WinGetState(2, wnd) Then Return 1
Local h = DllCall("GetWindow", "hwnd", wnd, "uint", 4, "hwnd")
If h = lparam Then
g_CopyWndOwner = true
g_DialogWnd = WinGetClass(wnd) & " - " & WinGetText(wnd)
Return 0
EndIf
Return 1
EndFunc
Func ShutdownLog(CopyHang)
Local sLog
Local status = "копирование " & (CopyHang = 0 ? "завершено" :"прервано")
sLog &= auCRLF & auCRLF
sLog &= StrFormat("%s %s Окно выключения ПК\r\n", Date(), Time())
sLog &= StrFormat("%s %s Статус: %s\r\n", Date(), Time(), status)
If CopyHang > 0 Then sLog &= StrFormat("%s %s Диалог: %s\r\n", Date(), Time(), g_DialogWnd)
FileAppend(g_LogShutdown, sLog)
EndFunc
Func GetDPI()
Local DC = DllCall("GetDC", "int", 0)
Local lpy = DllCall("GetDeviceCaps", "handle", DC, "int", 88) # LOGPIXELSX
DllCall("ReleaseDC", "int", 0, "handle", DC)
Return lpy
EndFunc
Func Scale(nValue)
Static dpi = GetDPI()
Return DllCall("MulDiv", "int", nValue, "int", dpi, "int", 96)
EndFunc |
Модуль подключается к autorun.cfg стандартно
| Code: | Pragma Include %COMMANDER_PATH%\Ini\Autorun\Shutdown.aucfg |
Пример файла конфигурации чистого плагина
 autorun.cfg | Code: | Pragma AutorunBlockUnload
LoadLibrary Plugins\Autorun_Tweaks.dll
LoadLibrary Plugins\Autorun_Sysinfo.dll
LoadLibrary Plugins\Autorun_Runtime.dll
LoadLibrary Plugins\Autorun_Process.dll
Pragma Include %COMMANDER_PATH%\wdx\Autorun\Shutdown.aucfg
Pragma AutorunFinalizeSection |
|
|