找回密码
 加入
搜索
查看: 3767|回复: 12

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

  [复制链接]
发表于 2010-12-24 09:01:44 | 显示全部楼层 |阅读模式
本帖最后由 happytc 于 2010-12-24 09:35 编辑

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

是不是Windows创建进程时,一定会是先运行的程序PID的值一定比后运行的程序小
若是这样,就好解决上面的问题了。
 楼主| 发表于 2010-12-24 09:06:42 | 显示全部楼层
本帖最后由 happytc 于 2010-12-24 09:40 编辑

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

本来还想用winapi函数来得到当前进程的:_WinAPI_GetCurrentProcessID()
 楼主| 发表于 2010-12-24 09:49:05 | 显示全部楼层
这个问题,也让我明白了_WinAPI_GetCurrentProcess函数返回的是伪handle,不是真的。
难怪我试了那么久,总是有问题呢,还得用DllCall里用这个pseudo handle来得到real handle
发表于 2010-12-24 09:52:03 | 显示全部楼层
 楼主| 发表于 2010-12-24 10:01:22 | 显示全部楼层
回复 4# 78391493
呵,这个解决方法也相当不错的,谢了!
发表于 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[0][0] < 1 Then Exit
For $i = 1 To $var[0][0]
        If $var[$i][0] = @ScriptName Then ;ExitLoop(1)
                If StringInStr(_WinAPI_GetCommandLineFromPID($var[$i][1]),@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[0], "int", 0, "ptr", DllStructGetPtr($PBI), "int", DllStructGetSize($PBI), "int", 0)
        Local $dw = DllStructCreate("ptr")
        DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], "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[0], "ptr", DllStructGetData($dw, 1) + 0x40, "ptr", DllStructGetPtr($unicode_string), "int", DllStructGetSize($unicode_string), "ptr", 0)
        Local $Ret = DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], "ptr", DllStructGetData($unicode_string, "String"), "wstr", 0, "int", DllStructGetData($unicode_string, "Length") + 2, "int*", 0)
        DllCall("kernel32.dll", 'int', 'CloseHandle', "hwnd", $ret1[0])
        If $Ret[5] Then Return $Ret[3] ; 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[3]
        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] <> 0) ; $call[0] <> 0 is success
EndFunc   ;==>__GetPrivilege_SEDEBUG
 楼主| 发表于 2010-12-24 18:40:29 | 显示全部楼层
谢谢了,研究一下,非常不错!看起来很复杂的样子,现在我是简单地这样做的
$PIDCurrentProgram = _WinAPI_GetCurrentProcessID()
$CurrentProgramName = _ProcessGetName($PIDCurrentProgram)
$PIDList = ProcessList($CurrentProgramName)

If $PIDList[0][0] > 1 Then 
        Exit
EndIf
发表于 2010-12-24 19:12:28 | 显示全部楼层
#include <lsasecur.au3>
_SeSingletoEx(1) ; 同一时间内,允许运行指定次数的AU3程序。


lsasecur.au3 - http://www.autoitx.com/thread-20442-1-1.html
发表于 2010-12-25 13:33:42 | 显示全部楼层
认真学习了
发表于 2010-12-25 16:41:04 | 显示全部楼层
回复 7# happytc

$PIDCurrentProgram = @AutoItPID

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

        If $PIDList[0][0] > 1 Then
                Exit
        EndIf
       
EndIf
发表于 2010-12-25 16:49:33 | 显示全部楼层
本程序要绝对运行(忽略不同位置的同名程序)
首先要对进程中的同名程序做路径检测
是我的名称、我的路径
则退出……本程序已经运行
否则,运行
!
发表于 2010-12-25 17:18:18 | 显示全部楼层
用bat
tasklist /fo csv
到文件
再用for读取。这样简单点吧
 楼主| 发表于 2010-12-25 22:32:28 | 显示全部楼层
谢谢pusofalse, _ddqs.等的热心帮助。让我在这一个问题中学到很多au3的东西。
以前没有学过au3的东西,脚本主要用perl和ahk,现在因要写一篇文章(关于深入对比au3和ahk的)
所以不得不硬着头皮学auit。不过,学着学着,学出兴趣来了,感觉au3比ahk的优点很是明显,当然弱点也显然
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-10-2 18:21 , Processed in 0.102775 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表