happytc 发表于 2010-12-24 09:01:44

[已解决]怎么检测脚本是否存在别的进程?

本帖最后由 happytc 于 2010-12-24 09:35 编辑

比如au3的脚本程序:abc.exe
能否实现在abc.exe运行时先检测是否存在另外一个abc.exe进程,若有,则退出本进程?

是不是Windows创建进程时,一定会是先运行的程序PID的值一定比后运行的程序小
若是这样,就好解决上面的问题了。

happytc 发表于 2010-12-24 09:06:42

本帖最后由 happytc 于 2010-12-24 09:40 编辑

简单解决,用用$var = ProcessList("abc.exe")得到的进程列表,然后用$var> 1 就退出本程序

本来还想用winapi函数来得到当前进程的:_WinAPI_GetCurrentProcessID()

happytc 发表于 2010-12-24 09:49:05

这个问题,也让我明白了_WinAPI_GetCurrentProcess函数返回的是伪handle,不是真的。
难怪我试了那么久,总是有问题呢,还得用DllCall里用这个pseudo handle来得到real handle

78391493 发表于 2010-12-24 09:52:03

http://www.autoitx.com/thread-16888-1-1.html

happytc 发表于 2010-12-24 10:01:22

回复 4# 78391493
呵,这个解决方法也相当不错的,谢了!

3mile 发表于 2010-12-24 10:49:11

未作测试,仅作参考。慎用
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#AutoIt3Wrapper_outfile=abc.exe
#AutoIt3Wrapper_UseUpx=n
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <array.au3>
Opt("TrayIconHide", 1)

$var = ProcessList()

If $var < 1 Then Exit
For $i = 1 To $var
        If $var[$i] = @ScriptName Then ;ExitLoop(1)
                If StringInStr(_WinAPI_GetCommandLineFromPID($var[$i]),@ScriptFullPath) Then
                        MsgBox(0, @ScriptDir, "找到的是自己")
                        Exit
                Else
                        MsgBox(0,0,"找到的进程不是自己");这里可以杀掉除自己之外的进程。或者自杀
                EndIf
        EndIf
Next


Func _WinAPI_GetCommandLineFromPID($PID)
        __GetPrivilege_SEDEBUG()
        Local $ret1 = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', BitOR(0x400, 0x10), 'int', False, 'int', $PID)
        Local $tag_PROCESS_BASIC_INFORMATION = "int ExitStatus;ptr PebBaseAddress;ptr AffinityMask;ptr BasePriority;ulong UniqueProcessId;ulong InheritedFromUniqueProcessId;"
        Local $PBI = DllStructCreate($tag_PROCESS_BASIC_INFORMATION)
        DllCall("ntdll.dll", "int", "ZwQueryInformationProcess", "hwnd", $ret1, "int", 0, "ptr", DllStructGetPtr($PBI), "int", DllStructGetSize($PBI), "int", 0)
        Local $dw = DllStructCreate("ptr")
        DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1, "ptr", DllStructGetData($PBI, 2) + 0x10, "ptr", DllStructGetPtr($dw), "int", 4, "ptr", 0)
        Local $unicode_string = DllStructCreate("ushort Length;ushort MaxLength;ptr String")
        DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1, "ptr", DllStructGetData($dw, 1) + 0x40, "ptr", DllStructGetPtr($unicode_string), "int", DllStructGetSize($unicode_string), "ptr", 0)
        Local $Ret = DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1, "ptr", DllStructGetData($unicode_string, "String"), "wstr", 0, "int", DllStructGetData($unicode_string, "Length") + 2, "int*", 0)
        DllCall("kernel32.dll", 'int', 'CloseHandle', "hwnd", $ret1)
        If $Ret Then Return $Ret ; If bytes returned, return commandline...
        Return ""
EndFunc   ;==>_WinAPI_GetCommandLineFromPID

Func __GetPrivilege_SEDEBUG()
        Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes"
        Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & 12 & "]" ; count of LUID structs * sizeof LUID struct
        Local $hToken = _WinAPI_OpenProcessToken($TOKEN_ADJUST_PRIVILEGES)
        $call = DllCall("advapi32.dll", "int", "LookupPrivilegeValue", "str", Chr(0), "str", "SeDebugPrivilege", "int64*", "")
        Local $iLuid = $call
        Local $TP = DllStructCreate($tagTOKENPRIVILEGES)
        Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB"))
        DllStructSetData($TP, "PrivilegeCount", 1)
        DllStructSetData($LUID, "Luid", $iLuid)
        DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED)
        $call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", 0, "ptr", Chr(0), "ptr", Chr(0))
        Return ($call <> 0) ; $call <> 0 is success
EndFunc   ;==>__GetPrivilege_SEDEBUG

happytc 发表于 2010-12-24 18:40:29

谢谢了,研究一下,非常不错!看起来很复杂的样子,现在我是简单地这样做的$PIDCurrentProgram = _WinAPI_GetCurrentProcessID()
$CurrentProgramName = _ProcessGetName($PIDCurrentProgram)
$PIDList = ProcessList($CurrentProgramName)

If $PIDList > 1 Then
        Exit
EndIf

pusofalse 发表于 2010-12-24 19:12:28

#include <lsasecur.au3>
_SeSingletoEx(1) ; 同一时间内,允许运行指定次数的AU3程序。

lsasecur.au3 - http://www.autoitx.com/thread-20442-1-1.html

syhw222 发表于 2010-12-25 13:33:42

认真学习了

_ddqs. 发表于 2010-12-25 16:41:04

回复 7# happytc

$PIDCurrentProgram = @AutoItPID

If @Compiled Then
        $CurrentProgramName = @ScriptName
        $PIDList = ProcessList($CurrentProgramName)

        If $PIDList > 1 Then
                Exit
        EndIf
       
EndIf

_ddqs. 发表于 2010-12-25 16:49:33

本程序要绝对运行(忽略不同位置的同名程序)
首先要对进程中的同名程序做路径检测
是我的名称、我的路径
则退出……本程序已经运行
否则,运行
!

tangh217 发表于 2010-12-25 17:18:18

用bat
tasklist /fo csv
到文件
再用for读取。这样简单点吧

happytc 发表于 2010-12-25 22:32:28

谢谢pusofalse, _ddqs.等的热心帮助。让我在这一个问题中学到很多au3的东西。
以前没有学过au3的东西,脚本主要用perl和ahk,现在因要写一篇文章(关于深入对比au3和ahk的)
所以不得不硬着头皮学auit。不过,学着学着,学出兴趣来了,感觉au3比ahk的优点很是明显,当然弱点也显然
页: [1]
查看完整版本: [已解决]怎么检测脚本是否存在别的进程?