Что нового

[Процессы] Обход Singleton, через DllCall (Mutex)

nu3dell

Осваивающий
Сообщения
139
Репутация
24
Создаем скрипт с мутекс именем "test", и необходимо уже 2 скриптом, разблокировать test, что бы при повторном запуске 1 скрипта не было ошибки что уже запущено....
Код:
#include <Misc.au3>
if _Singleton("test",1) = 0 Then
    MsgBox(4096,"Внимание","Текущий скрипт уже запущен")
    Exit
EndIf
MsgBox(4096,"OK","Первый запуск скрипта")

Уверен что нужно использовать DllCall
Примерно так:
Код:
DllCall("kernel32.dll", "int", "OpenMutex", "hwnd", "test")
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
nu3dell

Я немного переделал _Singleton() для своих нужд...
Может, пригодится:

Код:
; В начале скрипта

 If RUNONCE('SNOITALER.NLSPLASH')=0 Then Exit

; Проверка на повторный запуск

 Func RUNONCE($ID)
  Local $MUTEX=DllCall('kernel32.dll','handle','CreateMutexW','ptr',0,'bool',1,'wstr',$ID)
  If @error Then Return SetError(@error,@extended,0)
  Local $ERROR=DllCall('kernel32.dll','dword','GetLastError')
  If @error Then Return SetError(@error,@extended,0)
  If $ERROR[0]=183 Then Return SetError($ERROR[0],$ERROR[0],0)
  Return $MUTEX[0]
 EndFunc
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1,590
Репутация
341
nu3dell
Могли бы и сами в include файл заглянуть
Код:
Func _Singleton($sOccurenceName, $iFlag = 0)
	Local Const $ERROR_ALREADY_EXISTS = 183
	Local Const $SECURITY_DESCRIPTOR_REVISION = 1
	Local $tSecurityAttributes = 0

	If BitAND($iFlag, 2) Then
		; The size of SECURITY_DESCRIPTOR is 20 bytes.  We just
		; need a block of memory the right size, we aren't going to
		; access any members directly so it's not important what
		; the members are, just that the total size is correct.
		Local $tSecurityDescriptor = DllStructCreate("byte;byte;word;ptr[4]")
		; Initialize the security descriptor.
		Local $aRet = DllCall("advapi32.dll", "bool", "InitializeSecurityDescriptor", _
				"struct*", $tSecurityDescriptor, "dword", $SECURITY_DESCRIPTOR_REVISION)
		If @error Then Return SetError(@error, @extended, 0)
		If $aRet[0] Then
			; Add the NULL DACL specifying access to everybody.
			$aRet = DllCall("advapi32.dll", "bool", "SetSecurityDescriptorDacl", _
					"struct*", $tSecurityDescriptor, "bool", 1, "ptr", 0, "bool", 0)
			If @error Then Return SetError(@error, @extended, 0)
			If $aRet[0] Then
				; Create a SECURITY_ATTRIBUTES structure.
				$tSecurityAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
				; Assign the members.
				DllStructSetData($tSecurityAttributes, 1, DllStructGetSize($tSecurityAttributes))
				DllStructSetData($tSecurityAttributes, 2, DllStructGetPtr($tSecurityDescriptor))
				DllStructSetData($tSecurityAttributes, 3, 0)
			EndIf
		EndIf
	EndIf

	Local $handle = DllCall("kernel32.dll", "handle", "CreateMutexW", "struct*", $tSecurityAttributes, "bool", 1, "wstr", $sOccurenceName)
	If @error Then Return SetError(@error, @extended, 0)
	Local $lastError = DllCall("kernel32.dll", "dword", "GetLastError")
	If @error Then Return SetError(@error, @extended, 0)
	If $lastError[0] = $ERROR_ALREADY_EXISTS Then
		If BitAND($iFlag, 1) Then
			Return SetError($lastError[0], $lastError[0], 0)
		Else
			Exit -1
		EndIf
	EndIf
	Return $handle[0]
EndFunc   ;==>_Singleton
 
Автор
nu3dell

nu3dell

Осваивающий
Сообщения
139
Репутация
24
Medic84
А что мне это даст? Если мне нужно обходить Singleton, то есть есть скрипт с Singleton, а вторым скриптом я снимаю Singleton, и теперь уже 1 скрипт можно запускать еще и еще

P.S Там вроде OpenMutex....
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
nu3dell [?]
то есть есть скрипт с Singleton, а вторым скриптом я снимаю Singleton
ну так это передача данных между скриптами. на форуме есть примеры.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Я бы в таком случае сделал так:

Скрипт №1 (первый/главный скрипт):
Код:
_FirstRun()

MsgBox(4096, "OK", "Первый запуск скрипта")

Func _FirstRun()
	Local $iPID = IniRead(@ScriptDir & '\Config.ini', 'Main', 'Process', 0)
	
	If ProcessExists($iPID) Then
		MsgBox(4096, "Внимание", "Текущий скрипт уже запущен")
		Exit
	EndIf
	
	IniWrite(@ScriptDir & '\Config.ini', 'Main', 'Process', @AutoItPID)
	OnAutoItExitRegister('_OnExit')
EndFunc

Func _OnExit()
	IniDelete(@ScriptDir & '\Config.ini', 'Main', 'Process')
EndFunc


Скрипт №2 (отключение проверки у первого скрипта):
Код:
;Тут естественно путь до файла конфигурации программы нужно указывать соответствующий
IniWrite(@ScriptDir & '\Config.ini', 'Main', 'Process', 0)
 
Автор
nu3dell

nu3dell

Осваивающий
Сообщения
139
Репутация
24
CreatoR не то, нужно через singleton
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
nu3dell

Попробуйте ещё использовать семафоры:

Код:
#Include <WinAPIEx.au3>
_WinAPI_CreateSemaphore()
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
nu3dell [?]
CreatoR не то, нужно через singleton
не понятно обоснование требования к исполнению. то есть его нет. зачем лезть в дебри, если задача - управлять скриптом через другой скрипт.и неважно какую функцию при этом нужно отменять или запускать.
 
Автор
nu3dell

nu3dell

Осваивающий
Сообщения
139
Репутация
24
CreatoR
Первый скрипт нельзя запустить 2 раза, а вторым скриптом мы сделаем что бы можно было запустить 2 раза

P.S Что вы тут увидели не законного?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
nu3dell [?]
P.S Что вы тут увидели не законного?
дело не в законности :smile:
а в том, что не понятно зачем использовать вызовы функции из библиотеки если обмен данными на запуск или остановку функции между скриптами можно сделать проще
вот один из примеров http://autoit-script.ru/index.php/topic,11757.msg77658.html#msg77658
на форуме есть несколько тем по интеракции между скриптами



Добавлено:
Сообщение автоматически объединено:

вот пример.
для общения между скриптами используем файловую систему
в примере: если нет ключевого файла run.txt, то скрипт нельзя запустить более одного раза.
Код:
#include <Misc.au3>
If FileExists(@ScriptDir & '\run.txt') Then
	MsgBox(0, '', 'запускаем несколько копий')
Else
	_Singleton('1.exe')
	MsgBox(0, '', 'скрипт работает один раз')
EndIf


когда понадобится запустить несколько копий, то второй скрипт создает файл run.txt и уже далее он же запускает первый скрипт (из примера) сколько нужно раз
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
nu3dell [?]
Первый скрипт нельзя запустить 2 раза, а вторым скриптом мы сделаем что бы можно было запустить 2 раза
Ну тогда в чём проблема, пример что я дал как раз это и позволяет.

Что вы тут увидели не законного?
Я разве что то написал про незаконность? :scratch:
 

beliy

Продвинутый
Сообщения
372
Репутация
72
мой вариант, если правильно понял постановку ТЗ:

Код:
#include <Misc.au3>
HotKeySet("{ESC}", "_quit")

While 1
   _checkSingleton()
WEnd


Func _checkSingleton()
   if FileExists (@ScriptDir & "\setting.ini") Then
	  $checkIni = IniRead ( @ScriptDir & "\setting.ini", "singleton", "enable", "Конфигурационный файл поврежден" )
   Else
	  IniWrite(@ScriptDir & "\setting.ini", "singleton", "enable", 1)
	  $checkIni = 1
   EndIf
   if $checkIni = 1 Then
	  if _Singleton("test",1) = 0 Then
		  MsgBox(4096,"Внимание","Текущий скрипт уже запущен")
		 Exit
	  Else
		 MsgBox(4096,"OK","Первый запуск скрипта")
	  EndIf
   EndIf
EndFunc

Func _quit()
    Exit 0
EndFunc


2 скрипт будет просто изменять значение с 1 на 0 в ini-файле
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
beliy [?]
Не очень удачный.
Скрипт постоянно читает файл, это нагрузка на диск, не говоря уже о потреблении памяти.

И он по концепции почти не отличается от предложенных вариантов выше.
 
Верх