rhci 发表于 2017-9-24 12:59:30

关于程序检测,防止重复运行的求助。[已解决]

本帖最后由 rhci 于 2017-9-25 09:52 编辑

借鉴论坛下载更新代码,打包了一个基于web服务的更新软件,现在问题是,该软件如果重复运行,就会卡住,等待很久以后才会弹出报错窗口,并结束,求助,能否在代码里写入检测自身是否重复运行。源码共享如下:#NoTrayIcon
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#PRE_Icon=C:\windows\system32\SHELL32.dll
#PRE_Outfile=upload.exe
#PRE_Outfile_x64=upload64.exe
#PRE_Compression=4
#PRE_Compile_Both=y
#PRE_UseX64=y
#PRE_Res_Comment=后台文件更新系统
#PRE_Res_Description=BIST-FILE-SYS
#PRE_Res_Fileversion=1.0.0.2
#PRE_Res_LegalCopyright=RX
#PRE_Res_requestedExecutionLevel=None
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <WinAPI.au3>
#include <WinAPIProc.au3>
;~ #Include <Array.au3>
Global $UpSize = 0, $FlieSize, $aUpFile = [], $upme = False
Global $sUpUrl = IniRead("upload.ini", "Config", "up", "")
If FileExists(@ScriptDir & "\upload.ini") Then

        Else
                IniWrite(@ScriptDir & "\upload.ini", "Config", "up", "http://文件服务器IP/wmv/")
       
        EndIf
       
       

GUICreate("正在下载最新资源", 240, 100)
GUICtrlCreateLabel("进度", 5, 13, 30, 20)
$progressbar1 = GUICtrlCreateProgress(35, 10, 200, 20)
$gxmsg = GUICtrlCreateLabel("正在读取更新文件...", 5, 43, 230, 50, 0x01)
GUISetState()

Local $hDownload = InetGet($sUpUrl & 'updata.ini', @TempDir & "\updata.ini", 16+1, 1);下载更新校验文件
Do
    Sleep(250)
Until InetGetInfo($hDownload, 2)    ; 检查下载是否完成.
Local $aData = InetGetInfo($hDownload);获取所有信息.
InetClose($hDownload);关闭句柄, 释放资源.

If $aData Then
        ;下载校验文件成功,分析校验数据
        $gengxin = getcrc32()
        If $gengxin <> '' Then
                gengxin()
        EndIf
        FileDelete(@TempDir & "\updata.ini")
        DirRemove (@ScriptDir & "\Rxtemp\")
Else
        MsgBox(0,"", '更新文件失败,请检查并修改配置文件.')

        ShellExecute("upload.ini", "", @ScriptDir, "edit");
EndIf

Func gengxin()
        GUICtrlSetState($progressbar1, 16)
        $updataname = StringSplit($gengxin, ',')
        $zdx = MylBytes($UpSize)
        $FlieSize_A = StringSplit($FlieSize, ',')
        GUICtrlSetData($gxmsg, '更新文件总大小 ' & $zdx)
        $gxbegin = TimerInit()
        Local $yxz = 0, $nD = 5, $hDownload[$nD], $down[$nD], $nF = 1; $nD = (线程数),
        For $i = 1 To $updataname Step $nD
                $fdx = 0
                For $j = 0 To $nD - 1
                        If $i + $j <= $updataname Then
                                $fdx += $FlieSize_A[$i + $j];InetGetSize($gxurl & $updataname[$i + $j])
                                $url = $sUpUrl & StringReplace($updataname[$i + $j], '\', '/')
                                $saveurl = @ScriptDir & "\Rxtemp\" & $updataname[$i + $j]
                                $saveurl_tmp = StringMid($saveurl, 1, StringInStr($saveurl, '\', 0, -1))
                                If Not FileExists($saveurl_tmp) Then DirCreate($saveurl_tmp)
                                $hDownload[$j] = InetGet($url, $saveurl, 1, 1)
                                $nF = $i
                        Else
                                $hDownload[$j] = ''
                        EndIf
                Next
                Do
                        For $t = Int(100 / $UpSize) To 100
                                Sleep(300)
                                $dif = TimerDiff($gxbegin)
                                $s = Round($dif / 1000)
                                For $j = 0 To $nD - 1
                                        If $hDownload[$j] <> '' Then
                                                $down[$j] = InetGetInfo($hDownload[$j], 0)
                                        Else
                                                $down[$j] = 0
                                        EndIf
                                Next
                                $s1 = getsize($down) + $yxz
                                $s3 = Round($s1 / $s)
                                If $s3 < 0 Then $s3 = 0 & 'k'
                                $stime = Round(($UpSize - $s1) / ($s3))
                                If $stime < 0 Then $stime = ""
                                $t = ($s1 / $UpSize) * 100
                                GUICtrlSetData($progressbar1, $t)
                                GUICtrlSetData($gxmsg, '总计需要下载 ' & $zdx & @LF & '已经下载 ' _
                                               & MylBytes($s1) & @LF & '下载速度 ' & MylBytes($s3) & '/s' & @LF & '剩余时间 ' & $stime & '秒')
                                If getsize($down) = $fdx Then ExitLoop
                        Next
                Until getsize($down) = $fdx
                For $j = 0 To $nD - 1
                        If $hDownload[$j] <> '' Then
                                $yxz += InetGetInfo($hDownload[$j], 0)
                                InetClose($hDownload[$j])
                        EndIf
                Next
        Next
        If $nF < $updataname Then
                For $i = $nF To $updataname
                        $fdx = $FlieSize_A[$i];InetGetSize($gxurl & $updataname[$i])
                        $url = $sUpUrl & StringReplace($updataname[$i], '\', '/')
                        $saveurl = @ScriptDir & "\Rxtemp\" & $updataname[$i]
                        $saveurl_tmp = StringMid($saveurl, 1, StringInStr($saveurl, '\', 0, -1))
                        If Not FileExists($saveurl_tmp) Then DirCreate($saveurl_tmp)
                        $shDownload = InetGet($url, $saveurl, 1, 1)
                        Do
                                For $t = Int((InetGetInfo($shDownload, 0) + $yxz) / $UpSize * 100) To 100
                                        Sleep(300)
                                        $dif = TimerDiff($gxbegin)
                                        $s = Round($dif / 1000)
                                        $s1 = InetGetInfo($shDownload, 0) + $yxz
                                        $s3 = Round($s1 / $s)
                                        If $s3 < 0 Then $s3 = 0 & 'k'
                                        $stime = Round(($UpSize - $s1) / ($s3))
                                        If $stime < 0 Then $stime = ""
                                        $t = ($s1 / $UpSize) * 100
                                        GUICtrlSetData($progressbar1, $t)
                                        GUICtrlSetData($gxmsg, '总计需要下载 ' & $zdx & @LF & '已经下载 ' _
                                                        & MylBytes($s1) & @LF & '下载速度 ' & MylBytes($s3) & '/s' & @LF & '剩余时间 ' & $stime & '秒')
                                        If InetGetInfo($shDownload, 0) = $fdx Then ExitLoop
                                Next
                        Until InetGetInfo($shDownload, 2)
                        $yxz = $yxz + (InetGetInfo($shDownload, 0))
                        InetClose($shDownload)
                Next
        EndIf
        For $i = 1 To $updataname
                If $updataname[$i] = 'rxsetup.exe' Then
                        $upme = True
                Else
                        $move = FileMove(@ScriptDir & "\Rxtemp\" & $updataname[$i], @ScriptDir & "\" & $updataname[$i], 9)
                        If $move <> 1 Then
                                Exit MsgBox(0, '', $updataname[$i] & '文件下载失败!')                               
                        EndIf
                EndIf
        Next
        GUICtrlSetData($gxmsg, '')
        GUICtrlSetState($progressbar1, 32)
        If $upme = True Then
                GUICtrlSetData($gxmsg, '更新自身!')
                Sleep(500)
                Run(@ComSpec & ' /c ping 127.0.0.1 -n 1&copy ' & @ScriptDir & '\Rxtemp\rxsetup.exe ' & @ScriptFullPath & '&' & @ScriptFullPath & ' up&Del ' & @ScriptDir & '\Rxtemp\rxsetup.exe', @ScriptDir, @SW_HIDE)
                Exit
        Else
                GUICtrlSetData($gxmsg, '自身更新成功!')
        EndIf
EndFunc   ;==>gengxin

Func getsize($Array)
        Dim $size = 0
        For $i = 0 To UBound($Array) - 1
                $size += $Array[$i]
        Next
        Return $size
EndFunc

Func getcrc32()
        Dim $file_crc32
        $file = FileOpen(@TempDir & "\updata.ini", 0)
        While 1
                $Line = FileReadLine($file)
                If @error = -1 Then ExitLoop
                $filename = StringSplit($Line, '=')
                If Not @error Then
                        $CheckCrc32 = StringSplit($filename, '|')
                        If Not @error Then
                        If $filename = 'rxsetup.exe' Then
                                $CRC32 = _CRC32ForFile(@ScriptName)
                                If $CRC32 <> $CheckCrc32 Then
                                        $file_crc32 &= $filename & ","
                                        $FlieSize &= $CheckCrc32 & ","
                                        $UpSize += $CheckCrc32
                                EndIf
                        Else
                                $CRC32 = _CRC32ForFile($filename)
                                If $CRC32 <> $CheckCrc32 Then
                                        $file_crc32 &= $filename & ","
                                        $FlieSize &= $CheckCrc32 & ","
                                        $UpSize += $CheckCrc32
                                EndIf
                        EndIf
                        EndIf
                EndIf
        WEnd
        FileClose($file)
        $FlieSize = StringTrimRight($FlieSize, 1)
        Return StringTrimRight($file_crc32, 1)
EndFunc

Func MylBytes($lBytes)
        If $lBytes < 1024 Then
                Return ($lBytes & "b")
        ElseIf $lBytes < 1048576 Then
                Return Round($lBytes / 1024, 2) & "k"
        ElseIf $lBytes < 536870912 Then
                Return Round($lBytes / (1024 ^ 2), 2) & "M"
        Else
                Return Round($lBytes / (1024 ^ 3), 2) & "G"
        EndIf
EndFunc   ;==>_MylBytes

; #FUNCTION# ;===============================================================================
;
; Name...........: _CRC32ForFile
; Description ...: Calculates CRC32 value for the specific file.
; Syntax.........: _CRC32ForFile ($sFile)
; Parameters ....: $sFile - Full path to the file to process.
; Return values .: Success - Returns CRC32 value in form of hex string
;                        - Sets @error to 0
;                  Failure - Returns empty string and sets @error:
;                  |1 - CreateFile function or call to it failed.
;                  |2 - CreateFileMapping function or call to it failed.
;                  |3 - MapViewOfFile function or call to it failed.
;                  |4 - RtlComputeCrc32 function or call to it failed.
; Author ........: trancexx
;
;==========================================================================================
Func _CRC32ForFile($sFile)
        Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFileW", _
                        "wstr", $sFile, _
                        "dword", 0x80000000, _ ; GENERIC_READ
                        "dword", 1, _ ; FILE_SHARE_READ
                        "ptr", 0, _
                        "dword", 3, _ ; OPEN_EXISTING
                        "dword", 0, _ ; SECURITY_ANONYMOUS
                        "ptr", 0)
        If @error Or $a_hCall = -1 Then
                Return SetError(1, 0, "")
        EndIf
        Local $hFile = $a_hCall
        $a_hCall = DllCall("kernel32.dll", "ptr", "CreateFileMappingW", _
                        "hwnd", $hFile, _
                        "dword", 0, _ ; default security descriptor
                        "dword", 2, _ ; PAGE_READONLY
                        "dword", 0, _
                        "dword", 0, _
                        "ptr", 0)
        If @error Or Not $a_hCall Then
                DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile)
                Return SetError(2, 0, "")
        EndIf
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile)
        Local $hFileMappingObject = $a_hCall
        $a_hCall = DllCall("kernel32.dll", "ptr", "MapViewOfFile", _
                        "hwnd", $hFileMappingObject, _
                        "dword", 4, _ ; FILE_MAP_READ
                        "dword", 0, _
                        "dword", 0, _
                        "dword", 0)
        If @error Or Not $a_hCall Then
                DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
                Return SetError(3, 0, "")
        EndIf
        Local $pFile = $a_hCall
        Local $iBufferSize = FileGetSize($sFile)
        Local $a_iCall = DllCall("ntdll.dll", "dword", "RtlComputeCrc32", _
                        "dword", 0, _
                        "ptr", $pFile, _
                        "int", $iBufferSize)
        If @error Or Not $a_iCall Then
                DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile)
                DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
                Return SetError(4, 0, "")
        EndIf
        DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile)
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
        Local $iCRC32 = $a_iCall
        Return SetError(0, 0, Hex($iCRC32))
EndFunc   ;==>_CRC32ForFile

yamakawa 发表于 2017-9-24 14:02:56

回复 1# rhci _Singleton

rhci 发表于 2017-9-24 14:19:38

回复 2# yamakawa


    ...加哪里?怎么弄?举个栗子呗

yamakawa 发表于 2017-9-24 14:31:47

回复 3# rhci
照搬帮助文件的例子#include <Misc.au3>
#include <MsgBoxConstants.au3>

If _Singleton("test", 1) = 0 Then
    MsgBox($MB_SYSTEMMODAL, "警告", "本程序已经在运行!")
    Exit
EndIf
MsgBox($MB_SYSTEMMODAL, "OK", "成功启动!")

rhci 发表于 2017-9-24 14:33:06

回复 4# yamakawa

好吧,大神,告诉我,我应该怎么加入到我上面的代码里?

rhci 发表于 2017-9-24 14:59:19

回复 4# yamakawa


    谢了大神,搞定了

kk_lee69 发表于 2017-9-25 09:35:10

回复 6# rhci
注意版規   搞定了 請修改標題
页: [1]
查看完整版本: 关于程序检测,防止重复运行的求助。[已解决]