Что нового

Универсальная функция для предотвращения повторного запуска программы

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Данная функция выполняет следующие действия:
  • Завершает выполнение программы в случае ее повторного запуска.
  • Активирует доступное окно программы, если таковое имеется.
  • Посылает основной программе собщение WM_COPYDATA с указанными данными (опционально).
Если основное окно программы недоступно, например вызван MsgBox() с блокировкой родительского окна, то будет активировано первое доступное дочернее окно, в данном случае MsgBox(). WM_COPYDATA посылается только в основное окно ($sTitle). Для большей уникальности, я рекомендую в конец заголовка основного окна добавлять символ с кодом 160 (можно несколько):

Код:
$sTitle = "My GUI" & Chr(160)


$sUnique - это постоянный уникальный идентификатор вашей программы. Я обычно использую для его генерации функцию _WinAPI_CreateGUID().

Код:
#Include <APIConstants.au3>
#Include <GUIConstants.au3>
#Include <WinAPIEx.au3>

Global Const $GUI_NAME = 'My Program'
Global Const $GUI_TITLE = $GUI_NAME & Chr(160)
Global Const $GUI_GUID = 'C58B53BB-B613-47BD-8E84-60795C9A6A03'

_AppSingleton($GUI_TITLE, $GUI_GUID)

$hForm = GUICreate($GUI_TITLE, 400, 400)
$Button = GUICtrlCreateButton('About', 165, 366, 70, 23)
GUISetState()

While 1
    $ID = GUIGetMsg()
    Switch $ID
		Case 0
			ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button
            _WinAPI_ShellAboutDlg('About', 'About ' & $GUI_NAME, 'Anything.', _WinAPI_ExtractIcon(@AutoItExe, 0), $hForm)
    EndSwitch
WEnd

Func _AppSingleton($sTitle, $sUnique, $tCopyData = 0)

	Local $PID, $hRoot, $List, $State, $Result

	$hRoot = WinGetHandle($sUnique)
	If Not $hRoot Then
		AutoItWinSetTitle($sUnique)
		Return
	EndIf
	$PID = WinGetProcess($hRoot)
	If $PID > -1 Then
		$List = _WinAPI_EnumProcessWindows($PID, 0)
		If Not IsArray($List) Then
			Exit
		EndIf
	EndIf
	For $i = 1 To $List[0][0]
		If _WinAPI_GetWindowText($List[$i][0]) = $sTitle Then
			$State = WinGetState($List[$i][0])
			If BitAND($State, 4) Then
				If BitAND($State, 2) Then
					WinActivate($List[$i][0])
				EndIf
				If IsDllStruct($tCopyData) Then
					$Result = DllCall('user32.dll', 'int', 'SendMessage', 'hwnd', $List[$i][0], 'uint', $WM_COPYDATA, 'hwnd', 0, 'struct*', $tCopyData)
					If (@Error) Or (Not $Result[0]) Then
						; Nothing
					EndIf
				EndIf
			Else
				For $j = 1 To $List[0][0]
					If (_WinAPI_GetWindowText($List[$j][0])) And (_WinAPI_GetAncestor($List[$j][0], $GA_ROOTOWNER) = $List[$i][0]) Then
						WinActivate($List[$j][0])
						ExitLoop
					EndIf
				Next
			EndIf
			ExitLoop
		EndIf
	Next
	Exit
EndFunc   ;==>_AppSingleton
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Мне в одном проекте нужно было временное предотвращение повторного запуска. Первая копия, к примеру, начала процесс обновления, поэтому нужно было запрещать запуск других копий, а как только обновление завершено, то разрешать. И вот такой вот возможности Вкл/Выкл очень не хватало для стандартного _Singleton.

А по теме, хорошая функция получилась у вас :smile:
 
Верх