Что нового

Помогите перехватить завершение работы Windows

Игорь В

Новичок
Сообщения
20
Репутация
0
Версия AutoIt: v3.

Описание:

Я ещё новичок в AutoIT. Мне надо как-то реализовать перехват выключения компьютера через меню "Пуск". Тут вроде где-то есть подобная тема, но там не то, что мне надо. Там было написано о запрете выключения компьютера в том случае, если вставлен компакт-диск. А мне надо блокировать выключение компьютера совсем в других условиях.
Я делаю свою программу в очень простой среде разработки - Алгоритм 2.5, а чтобы там работать, вообще не нужно учить языки программирования. А там нет многого из того, что можно сделать в AutoIT. Вот мне надо реализовать вот что:
Когда пользователь нажимает Пуск->Выключение компьютера, потом выбирает "Выключение" или "Перезагрузка", проверяем, есть ли файл MkXXov0P31CQq1o6SBsdw==.tmp во временной папке пользователя. Если его там нет, выключать компьютер можно. Если его там нет, проверяем текст, который содержится в файле, который будет виден при открытии через Блокнот. Если там содержится текст f5kuDrmNRqJO0oTOMVUjhw==, то выключать компьютер можно, в остальных случаях - нельзя. При выключении компьютера выводить такое сообщение:
"Выключить компьютер в данный момент нельзя, так как к нему подключены другие пользователи."
У меня стоит Windows XP, я делаю серверную программу, через которую пользователи как-раз будут подключаться к моему компьютеру и скачивать с него файлы, доступ к которым я им предоставлю.

Примечания:

Можете даже не выкладывать сюда сам файл скрипта, просто скиньте сюда код, я его скопирую в текстовый редактор, сохраню скрипт и откомпилирую.
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Как реализовать перехват я не подскажу, но можно пойти немного иным путём:
Хитрыми твиками прячем кнопку завершения работы (вроде это возможно), пишем свой собственный выключатель и кидаем на рабочий стол. а он в свою очередь будет принимать решение выключать или нет.
Shutdown (1 ); завершение работы
Shutdown (2 ); перезагрузка
 

VladUs

Скриптер
Сообщения
621
Репутация
181
http://autoit-script.ru/index.php/topic,4304.msg31036.html#msg31036
 
Автор
И

Игорь В

Новичок
Сообщения
20
Репутация
0
Мне тут главное прочитать текст из файла. Имя файла и его текст я писал в описании, читайте повнимательнее.
 
Автор
И

Игорь В

Новичок
Сообщения
20
Репутация
0
Потому что мне непонятно как это сделать, даже когда я прочитал другую тему с тем же содержанием. А так нужно прочитать текст из файла, и если текст один, или файла вообще не существует, то выключать компьютер, если текст другой, то не выключать и выводить сообщение об ошибке.
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Игорь В [?]
Если его там нет, выключать компьютер можно. Если его там нет, проверяем текст,
Наверное Если он там есть?
Код:
$sTmpFile =  @TempDir & "\MkXXov0P31CQq1o6SBsdw==.tmp" ; путь к файлу, который отслеживаем
If FileExists ($sTmpFile) = 0 Then ; если файл не существует
	; тут делаем что-то, что типа можно вырубать
	; типа Shutdown (1)
	Exit
Else
	$hTmpFile = FileOpen ($sTmpFile, 0); открываем файл для чтения
	$sTmpFileData = FileRead ($hTmpFile) ; читаем файл целиком
	FileClose ($hTmpFile); закрываем файл
	$iPos = StringInStr ($sTmpFileData, "f5kuDrmNRqJO0oTOMVUjhw=="); проверяем наличие строчки в тексте
	If $iPos = 0 Then ; если строка не найдена, то выключать можно
		; тут делаем что-то, что типа можно вырубать
		; типа Shutdown (1)
		Exit
	Else ; иначе нельзя
		MsgBox (0, "Завершение работы", "Выключать нельзя!")
		Exit
	EndIf
EndIf
 

VladUs

Скриптер
Сообщения
621
Репутация
181
Код:
#Include <WinAPIEx.au3>

$GUI = GUICreate("Test")
GUISetState(@SW_HIDE )

GUIRegisterMsg ( 0x0011, "_Ret" )
_WinAPI_SetProcessShutdownParameters(0x03FF) ; Установить наивысший приоритет на получение сообщения о завершении работы Windows

While 1
    Sleep(100)
WEnd

Func _Ret()
 If FileExists("C:\File.Txt") Then ; Если файл существует, то выключить комп., если нет , то не выкл.
    $i = 1
    Return $i
 Else
    $i = 0
    Return $i
 EndIf
EndFunc
 
Автор
И

Игорь В

Новичок
Сообщения
20
Репутация
0
У меня в итоге получился вот такой код:
Код:
$sTmpFile =  @TempDir & "\MkXXov0P31CQq1o6SBsdw==.tmp" 
If FileExists ($sTmpFile) = 0 Then 
      #Include <Chek.au3>

OnAutoItExitRegister('_Quit')

_WinAPI_EmptyWorkingSet()

While 1
    Sleep(1000)
WEnd
    Exit
Else
    $hTmpFile = FileOpen ($sTmpFile, 0) 
    $sTmpFileData = FileRead ($hTmpFile) 
    FileClose ($hTmpFile)
    $iPos = StringInStr ($sTmpFileData, "f5kuDrmNRqJO0oTOMVUjhw==")
    If $iPos = 0 Then 
  #Include <Chek.au3>

OnAutoItExitRegister('_Quit')

_WinAPI_EmptyWorkingSet()

While 1
    Sleep(1000)
WEnd
        Exit
    Else ; А тут что писать?
        MsgBox (0, "Сообщение от IntServer", "Выключать компьютер в данный момент нельзя, так как к нему ещё подключены пользователи. Подождите, пока они закончат свою работу, или сообщите им, что Вы отключаетесь, потом повторите попытку.")
        Exit
    EndIf
EndIf

Я тут заголовок и текст сообщения поменял на свой. Ну а так тут впринципе кое-что непонятно. А ошибки есть тут?
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Просто каша.... :shok:
Что это? #Include <Chek.au3>
почему оно повторяется несколько раз в коде?
Инклуды принято указывать в самом начале скрипта.
Где функция? OnAutoItExitRegister('_Quit')
Вижу Вы вообще не имеете представления о правилах написания скриптов?

Попытаюсь объединить свой пример с кодом VladUs...
 
Автор
И

Игорь В

Новичок
Сообщения
20
Репутация
0
Да. И тем более, я только сегодня установил AutoIT, и к программированию не имею никакого отношения, а своё ПО делаю в конструкторах программ, где вообще никаких скриптов писать не надо. А на AutoIT перехожу потому, что там в тех конструкторах программ нет возможности перехватить кнопку завершения работы системы в меню "Пуск", а это в данный момент мне нужно.
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Игорь В, посмотрите это видео: shutdownstop.rar (не пугайтесь EXE, это флешка)
Так ли он должен работать?
Если всё устраивает, то с Вас пиво :beer:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
К сожалению, начиная с Vista, отменить завершение Windows программным способом нельзя.
 
Автор
И

Игорь В

Новичок
Сообщения
20
Репутация
0
ynbIpb, exe-файл не открывается что-то. Причём никакого сообщения не выводится, просто не открывается, и всё тут. :(
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
перезалил чистый SWF shutdownstop_swf.rar
скорее всего нужно установить это:
http://get.adobe.com/ru/flashplayer/otherversions/
(выбрать версию для IE)
 
Автор
И

Игорь В

Новичок
Сообщения
20
Репутация
0
Да вроде бы всё нормально работает, только ответ вместо Блокнота тут будет давать моя программа, которую я ещё пока не доделал, вот вчера тестировал связь между двумя компьютерами со своим другом. Я недавно ещё писал php-скрипт, он совсем небольшой. Программа будет отвечать без всяких сообщений, то есть пользователь не будет видеть, что ему программа выдаст. Она невидимым для пользователя образом просто откроет страницу http://intsoft.16mb.com/status.php?s=off и всё. Ну это к скрипту AutoIT уже не относится. А "хитрая строка" в "хитром файле" - это цифра 0, только зашифрованная. Я её шифровал с помощью своей собственной программы для шифрования текстов, которую я месяц назад сделал. Ну эта "хитрая строка" является идентификатором количества пользователей, подключенных к моему компьютеру через мою программу. Файл как-раз и будет закидывать в папку Temp моя программа автоматически, без скрипта. А скрипт в свою очередь уже будет всё проверять при завершении работы.
Кстати, а можно ли сделать так, чтобы скрипт не отображался в трее? Я его потом буду в EXE-файл компилировать, я не хочу, чтобы его видел пользователь. Пользователь будет видеть только мою программу, а скрипта видеть не должен.
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
блокнот тут вообще не при делах. Это просто для наглядности обработки сообщения, которое посылается системой всем окнам. Я хотел показать, что наш скрипт получает это сообщение раньше всех.
Вот финальная версия:
Код:
#NoTrayIcon ; не показывать иконку в трее
;защита от запуска двух копий 
If WinExists("Zxh3vfjklfjk4lgf4kgf") Then Exit 
AutoItWinSetTitle("Zxh3vfjklfjk4lgf4kgf")
; проверка версии ОС
If @OSVersion <> "WIN_XP" Then ; если не XP, то сообщаем и выходим
	MsgBox (16, "Ошибка!", "Это приложение работает только на Windows XP")
	Exit
EndIf

$sTmpFile = @TempDir & "\MkXXov0P31CQq1o6SBsdw==.tmp" ; путь к файлу, который отслеживаем
$sMsgTxt = "Выключать компьютер в данный момент нельзя, так как к нему ещё подключены пользователи." & @CRLF _ 
& "Подождите, пока они закончат свою работу, или сообщите им, что Вы отключаетесь, потом повторите попытку."
$WM_QUERYENDSESSION = 0x0011 ; сообщение Windows о завершении работы
$FIRST_SHUTDOWN_RANGE = 0x03FF ; значение, наивысший приоритет на получение сообщения о завершении работы
$iMsgFlg = 0 ;флаг, который определяет показывать месаджбок или нет

$hGui = GUICreate ("shutdown_stop"); создаём гуй, который будет ловить сообщение
GUISetState (@SW_HIDE, $hGui); скрываем его, ибо он нам не нужен

GUIRegisterMsg ($WM_QUERYENDSESSION, "_Shutdown"); ожидаем сообщения от системы, и выполняем указанную функцию
_WinAPI_SetProcessShutdownParameters($FIRST_SHUTDOWN_RANGE); устанавливаем приоритет

While 1 ; бесконечный цикл, в ожидании сообщения.
    Sleep(100); пауза, чтобы не грузить процесс
	If $iMsgFlg = 1 Then _msgbox() ; если флаг стал равен 1, запускаем функцию отображения месаджа
WEnd

; наша функция, обрабатывающая сообщение
Func _Shutdown ($hWndGUI, $MsgID)
	If FileExists ($sTmpFile) = 0 Then ; если файл не существует, то
		Return 1 ; возвращаем 1, тоесть разрешаем завершение работы
	EndIf
	$hTmpFile = FileOpen ($sTmpFile, 0); открываем файл для чтения
	$sTmpFileData = FileRead ($hTmpFile) ; читаем файл целиком
	FileClose ($hTmpFile); закрываем файл
	$iPos = StringInStr ($sTmpFileData, "f5kuDrmNRqJO0oTOMVUjhw=="); проверяем наличие строчки в тексте
	If $iPos = 0 Then ; если строка не найдена, то выключать можно
		Return 1 ; возвращаем 1
	EndIf
	$iMsgFlg = 1 ; выставляем флаг месаджбокса 1, значит показать его
	Return 0 ; возвращаем ноль, значит выключать нельзя
EndFunc

; наша функция, отображающая месаджбокс
Func _msgbox()
	MsgBox (48, "Сообщение от IntServer", $sMsgTxt)
	$iMsgFlg = 0 ; после показа месаджа, выставляем флаг опять в ноль
EndFunc

; функция из библиотеки WinAPIEx_3.3 от Yashied
Func _WinAPI_SetProcessShutdownParameters($iLevel, $fDialog = 0)

	Local $Ret = DllCall('kernel32.dll', 'int', 'SetProcessShutdownParameters', 'dword', $iLevel, 'dword', Not $fDialog)

	If (@error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Return 1
EndFunc   ;==>_WinAPI_SetProcessShutdownParameters
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
ynbIpb,
ИМХО, надо бы еще в начале заблокировать Диспетчер задач и реестр, а перед выходом разблокировать.
Код:
;блокировать:
RegWrite('HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System', 'DisableTaskMgr', 'REG_DWORD', '1')
RegWrite('HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System', 'DisableRegistryTools', 'REG_DWORD', '1')
;разблокировать 1 на 0 поменять
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
Ну я думаю это не для вандалов, которые всеми путями хотят выключить комп (они его тогда и из розетки выдернут).
А для адекватных пользователей, которые увидят сообщение и успокоятся.
 
Верх