newuser 发表于 2010-8-10 09:18:39

[已解决]打补丁的问题?

本帖最后由 newuser 于 2010-8-16 15:24 编辑

这是从源码区提出的代码,觉得还是在'提问交流'区问比较好.
我的问题是这样的:
我有个Update目录里存放的是补丁文件,而且确实存在补丁文件,因为之前他们都已打过,那么我现在将它改名以确保他与从注册表里枚举的所有打过的补丁名不同,我在执行该脚本,还是一闪而过,没有打补丁的过程啊?#include <GUIConstantsEx.au3>
#include <IE.au3>
#include <ButtonConstants.au3>
#include <ListViewConstants.au3>
#include <ProgressConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <file.au3>
#include <array.au3>
DirCreate(@ScriptDir & "\Update")
$PatchsFileDownDirctory=@ScriptDir & "\Update"
Dim $FixedPatchsRegPath="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix"
Dim $FixedPatchsListPath=@ScriptDir & "\FixedPatchsList.ini"
Dim $i
FileOpen($FixedPatchsListPath,8) ;8表示如果指定打开目录不存在那么强制建立它!
While 1
        $i +=1
        $Var=RegEnumKey($FixedPatchsRegPath,$i)
        If @error <>0Then ExitLoop
        FileWriteLine($FixedPatchsListPath,$Var & @CRLF);将枚举出的值逐行写入到指定的ini文件中       
WEnd
$PatchsListFile=FileRead($FixedPatchsListPath)
;MsgBox(0,'',$patchslistfile)
FileClose($FixedPatchsListPath)       
;创建打补丁主程序界面
$Form1 = GUICreate("局域网补丁更新工具", 401, 301, 373, 184)
$Group1 = GUICtrlCreateGroup("", 5, 60, 290, 230)
$Label1 = GUICtrlCreateLabel("安装进度:", 16, 234, 64, 20)
GUICtrlSetFont(-1, 10, 400, 0, "MS Sans Serif")
$Progress1 = GUICtrlCreateProgress(80, 230, 209, 20);创建1个进度条显示补丁安装过程
$Label2=GUICtrlCreateLabel("补丁状态",15,265,65,15)
GUICtrlSetColor(-1,0x008000)
GUICtrlSetFont(-1,8.5,400,0,"Arial")
$message="本机已存在的安全补丁:" & $i-1 & "个"
$Label3=GUICtrlCreateLabel($message,80,265,240,15);用于显示补丁不同安装时期的信息状态
$ListView1 = GUICtrlCreateListView("计数|安全标示名称|安装状态", 5, 65, 290, 155)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button1 = GUICtrlCreateButton("安装补丁", 312, 96, 73, 33, 0)
;;$Button2 = GUICtrlCreateButton("退出", 312, 224, 73, 33, 0)
GUICtrlCreateLabel("按Win+C键强制退出安装!",314, 224, 73, 33)
GUICtrlSetColor(-1, 0x008000)
GUICtrlSetFont(-1, 8.5, 400, 0, "Arial")
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState(@SW_SHOW)

While 1
      $nMsg = GUIGetMsg()
      Select
                Case $nMsg = $GUI_EVENT_CLOSE
                        Exit
                Case $nMsg = $Button1
                        Update()
      EndSelect
WEnd
       
Func update()
        $message="正在搜索补丁更新文件..."
        GUICtrlSetData($label3,$message)
        Sleep(1000)
        $filelist=_FileListToArray(@ScriptDir & "\Update","*.exe",1);将已下载补丁所在目录里的文件都送到1个数组里
        If @error =1 Then;如果上述操作失败进行相关提示
                MsgBox(16,'提示','Update文件夹或里面的补丁文件不存在,程序无法继续运行!')
                Exit
        EndIf
        Dim $j,$n,$i
        For $j=1 To $filelist
                $array=StringSplit($filelist[$j],"-");对于数组中的文件进行KB段提出
                StringInStr($PatchsListFile,$array);$patchslistfile是前面搜索本机已安装补丁的列表文件
                If @error = 1 Then;有没有打过的补丁就n计数加1,就是计算机上还没有打的补丁数
                        $n += 1
                ElseIf @error = 0 Then
                        msgbox(64, "提示", "没有可安装的补丁,程序将退出!")
                        Exit
                EndIf
        Next
        For $i = 3 To 1 Step -1
                $message = "共需安装" & $n & "个系统补丁," & $i & "秒后开始安装"
                GUICtrlSetData($Label3, $message)
                Sleep(1000)
        Next
        $message = "正在安装..."
        GUICtrlSetData($Label3, $message)
        Dim $wait = 0, $m = 0
        $start = GUICtrlSetData($Progress1, $wait) ;修改进度条的状态
        For $j = 1 To $filelist
                $array = StringSplit($filelist[$j], "-") ;以指定分隔符把字符串拆分成若干子串
                If StringInStr($patchslistfile, $array) = 0 Then ;StringInStr()为检查某个字符串是否含有给定的子串,返回为0未发现
                        $result = RunWait($FixedPatchsListPath & "\" & $filelist[$j] & "/u /z /n /o /q")
                        $m += 1
                        ;ProgressSet(100/$filelist*$i, "已完成"&100/$filelist *$i& " % ")
                        $wait = 100 / $n * $m
                        GUICtrlSetData($Progress1, $wait)
                        $jindu = "已完成: " & Round($wait, 0) & " %"
                        GUICtrlSetData($Label3, $jindu)
                        If $result = 1603 Then
                                $ending = "安装失败"
                        Else
                                $ending = "安装成功"
                        EndIf
                        GUICtrlCreateListViewItem($m & "|" & $array & "|" & $ending, $ListView1) ;在GUI上创建一个 ListView 项目控件
                EndIf
        Next
        $jindu = "已完成: 100%"
        GUICtrlSetData($Label3, $jindu)
        TrayTip("提示", "补丁已安装,请重启电脑!", 6, 1)
EndFunc   ;==>update

newuser 发表于 2010-8-10 09:48:06

回复 1# newuser
该脚本编译后在其他计算机上出现下面问题:

newuser 发表于 2010-8-10 14:14:29

回复 1# newuser

别沉了!

C.L 发表于 2010-8-10 15:58:11

使用非数组变量错误
看了下代码,最可能出错的地方,是这里:
$array=StringSplit($filelist[$j],"-");对于数组中的文件进行KB段提出
StringInStr($PatchsListFile,$array);$patchslistfile是前面搜索本机已安装补丁的列表文件
检查你的这两个数组:$filelist 和 $array ,最可能出错的是$array,如果StringSplit($filelist[$j],"-")没有返回数组,下面的这行就会出错。

newuser 发表于 2010-8-10 16:42:02

回复 4# C.L
2个数组都有数据啊!另外请看我的第一个问题,我将某补丁文件的KB部分改为注册表没有的,怎么没有安装过程啊?

C.L 发表于 2010-8-10 17:15:54

你这段代码在我这里运行测试没有什么问题
除非在=@ScriptDir & "\Update" 没有exe文件时才会出现数组错误。

没有安装过程,一是文件命名错误,另一个可能是因为用了静默安装的代码所致。

xsjtxy 发表于 2010-8-10 17:41:00

你这个脚本不是一点点的问题啊。改了半天才改好。
#include <GUIConstantsEx.au3>
#include <IE.au3>
#include <ButtonConstants.au3>
#include <ListViewConstants.au3>
#include <ProgressConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <file.au3>
#include <array.au3>
DirCreate(@ScriptDir & "\Update")
$PatchsFileDownDirctory=@ScriptDir & "\Update"
Dim $FixedPatchsRegPath="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix"
Dim $FixedPatchsListPath=@ScriptDir & "\FixedPatchsList.ini"
dim $i
update2()
;创建打补丁主程序界面
$Form1 = GUICreate("局域网补丁更新工具", 401, 301, 373, 184)
$Group1 = GUICtrlCreateGroup("", 5, 60, 290, 230)
$Label1 = GUICtrlCreateLabel("安装进度:", 16, 234, 64, 20)
GUICtrlSetFont(-1, 10, 400, 0, "MS Sans Serif")
$Progress1 = GUICtrlCreateProgress(80, 230, 209, 20);创建1个进度条显示补丁安装过程
$Label2=GUICtrlCreateLabel("补丁状态",15,265,65,15)
GUICtrlSetColor(-1,0x008000)
GUICtrlSetFont(-1,8.5,400,0,"Arial")
$message="本机已存在的安全补丁:" & $i-1 & "个"
$Label3=GUICtrlCreateLabel($message,80,265,240,15);用于显示补丁不同安装时期的信息状态
$ListView1 = GUICtrlCreateListView("计数|安全标示名称|安装状态", 5, 65, 290, 155)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button1 = GUICtrlCreateButton("安装补丁", 312, 96, 73, 33, 0)
$Button2 = GUICtrlCreateButton("退出程序", 312, 146, 73, 33, 0)

GUICtrlCreateLabel("按Win+C键强制退出安装!",314, 224, 73, 33)
GUICtrlSetColor(-1, 0x008000)
GUICtrlSetFont(-1, 8.5, 400, 0, "Arial")
GUICtrlSetState(-1, $GUI_DISABLE)

GUICtrlSetOnEvent($Button1, "update")
GUICtrlSetOnEvent($Button2, "quit")
GUISetOnEvent($GUI_EVENT_CLOSE, "quit")
HotKeySet("#c", "quit")
Opt("GUIOnEventMode", 1)
GUISetState(@SW_SHOW)
While 1
sleep(100)
WEnd

func update()
Update2()
Update1()
endfunc

Func update1()
      $message="正在搜索补丁更新文件..."
      GUICtrlSetData($label3,$message)
      Sleep(1000)
        dim $filelist
      $filelist=_FileListToArray(@ScriptDir & "\Update","*.exe",1);将已下载补丁所在目录里的文件都送到1个数组里
      If IsArray($filelist) = 0 Then ;检查变量是否为数据
                MsgBox(16,'提示','Update文件夹或里面的补丁文件不存在,程序无法继续运行!')
        else

      Dim $j,$n=0,$i
      For $j=1 To $filelist
                $array=StringSplit($filelist[$j],"-");对于数组中的文件进行KB段提出
                $yazbd = IniRead($FixedPatchsListPath, "已经安装补丁", $array, "")
                If $yazbd = "" Then;有没有打过的补丁就n计数加1,就是计算机上还没有打的补丁数
                        $n += 1
                EndIf
      Next
        If $n = 0 Then
                msgbox(64, "提示", "没有可安装的补丁,程序将退出!")
                Exit
        endif
      For $i = 3 To 1 Step -1
                $message = "共需安装" & $n & "个系统补丁," & $i & "秒后开始安装"
                GUICtrlSetData($Label3, $message)
                Sleep(1000)
      Next
      $message = "正在安装..."
      GUICtrlSetData($Label3, $message)
      Dim $wait = 0, $m = 0
      $start = GUICtrlSetData($Progress1, $wait) ;修改进度条的状态
      For $j = 1 To $filelist
                $array = StringSplit($filelist[$j], "-") ;以指定分隔符把字符串拆分成若干子串
                If IniRead($FixedPatchsListPath, "已经安装补丁", $array, "") = "" Then
                        $result = RunWait(@ScriptDir & "\Update\" & $filelist[$j] & " /u /z /n /o /q")
                        $m += 1
                        ;ProgressSet(100/$filelist*$i, "已完成"&100/$filelist *$i& " % ")
                        $wait = 100 / $n * $m
                        GUICtrlSetData($Progress1, $wait)
                        $jindu = "已完成: " & Round($wait, 0) & " %"
                        GUICtrlSetData($Label3, $jindu)
                        If $result = 1603 Then
                              $ending = "安装失败"
                        Else
                              $ending = "安装成功"
                        EndIf
                        GUICtrlCreateListViewItem($m & "|" & $array & "|" & $ending, $ListView1) ;在GUI上创建一个 ListView 项目控件
                EndIf
      Next
      EndIf
      $jindu = "已完成: 100%"
      GUICtrlSetData($Label3, $jindu)
      TrayTip("提示", "补丁已安装,请重启电脑!", 6, 1)
EndFunc   ;==>update

func update2()
$i = 0
While 1
      $i +=1
      $Var=RegEnumKey($FixedPatchsRegPath,$i)
      If @error <>0Then ExitLoop
        IniWrite($FixedPatchsListPath, "已经安装补丁", $Var, "1")

WEnd
endfunc

func quit()
exit
endfunc

newuser 发表于 2010-8-11 08:27:31

回复 6# C.L
我确定脚本当前目录下的Update目录下肯定有补丁文件.
Update目录下有1个WindowsServer2003-KB982666-x86-CHS.exe文件,这个是我打过的,我将它重新命名WindowsServer2003-KB982966-x86-CHS.exe,这个是注册表已打补丁目录没有的,执行完毕,提示"没有可安装的补丁,程序将退出",也就是执行的这段代码:StringInStr($PatchsListFile,$array);$patchslistfile是前面搜索本机已安装补丁的列表文件
                If @error = 1 Then;有没有打过的补丁就n计数加1,就是计算机上还没有打的补丁数
                        $n += 1
                ElseIf @error = 0 Then
                        msgbox(64, "提示", "没有可安装的补丁,程序将退出!")
                        Exit
                EndIf
我觉得到这步就应该是进行完了:Update 目录下的补丁文件与机器已打过的补丁的对比,而且是得出"Update目录下的补丁是已经打过"的结果,那么我对补丁修改文件名不就白改了吗?可这也不对啊,难道不是按KB982666这部分进行是否已打补丁的判断吗?
所以看来静默安装那部分代码根本没执行啊!

abc123 发表于 2010-8-11 14:53:12

学习了。这个工具作用不大呀。

C.L 发表于 2010-8-12 03:46:06

本帖最后由 C.L 于 2010-8-12 03:49 编辑

回复 8# newuser

ElseIf @error = 0 Then 那应该是这个判断用得不对,我没认真的看过StringInStr()的error返回值是什么,用这个函数,我一般都是直接用返回值来判断的

newuser 发表于 2010-8-12 08:06:08

回复 7# xsjtxy
不好意思,昨天光缆断了,不过还是有个问题,明明打补丁之前,机器有已打补丁100,使用如下代码又新打了几个,可是再次使用脚本,机器已打补丁还是100?那新打的补丁到哪里去了呢?重新启动依然?!!!弄了大半天也不知道问题在哪?
另外请教,360威势在机器上打补丁的目录在哪里?谢谢!#Region ;**** 参数创建于 ACNWrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <IE.au3>
#include <ButtonConstants.au3>
#include <ListViewConstants.au3>
#include <ProgressConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <file.au3>
#include <array.au3>
Opt("GuiOnEventMode",1)
DirCreate(@ScriptDir & "\Update")
$PatchsFileDownDirctory=@ScriptDir & "\Update"
Dim $FixedPatchsRegPath="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\HotFix"
Dim $FixedPatchsListPath=@ScriptDir & "\FixedPatchsList.ini"
Dim $i
_EnumRegFixedPatchs();枚举计算机已经安装的补丁数


;创建打补丁主程序界面
$Form1 = GUICreate("局域网补丁更新工具", 401, 301, 373, 184)
$Group1 = GUICtrlCreateGroup("", 5, 60, 290, 230)
$Label1 = GUICtrlCreateLabel("安装进度:", 16, 234, 64, 20)
GUICtrlSetFont(-1, 10, 400, 0, "MS Sans Serif")
$Progress1 = GUICtrlCreateProgress(80, 230, 209, 20);创建1个进度条显示补丁安装过程
$Label2=GUICtrlCreateLabel("补丁状态",15,265,65,15)
GUICtrlSetColor(-1,0x008000)
GUICtrlSetFont(-1,8.5,400,0,"Arial")
$message="本机已存在的安全补丁:" & $i-1 & "个"
$Label3=GUICtrlCreateLabel($message,80,265,240,15);用于显示补丁不同安装时期的信息状态
$ListView1 = GUICtrlCreateListView("计数|安全标示名称|安装状态", 5, 65, 290, 155)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button1 = GUICtrlCreateButton("安装补丁", 312, 96, 73, 33, 0)
$Button2 = GUICtrlCreateButton("退出", 312, 146, 73, 33, 0)
GUICtrlCreateLabel("按Win+C键强制退出安装!",314, 224, 73, 33)
GUICtrlSetColor(-1, 0x008000)
GUICtrlSetFont(-1, 8.5, 400, 0, "Arial")
GUICtrlSetState(-1, $GUI_DISABLE)

GUICtrlSetOnEvent($Button1,"_Update")
GUICtrlSetOnEvent($button2,"_Exit")
GUISetOnEvent($GUI_EVENT_CLOSE,"_Exit")
HotKeySet("#c","_Exit")
GUISetState(@SW_SHOW)

While 1
        Sleep(1000)
WEnd
       
Func _Update()
        $message="正在搜索补丁更新文件..."
        GUICtrlSetData($label3,$message)
        Sleep(1000)
       
        Dim $filelist;事先定义好1个一维数组,这个很重要,否则在编译后执行可能出现:使用非法树组问题
        $filelist=_FileListToArray(@ScriptDir & "\Update","*.exe",1);将已下载补丁所在目录里的文件都送到定义好的1维数组里
       
        If @error =1 Then;判断_FileListToArray()是否成功,如 失败进行相关提示并退出
                MsgBox(16,'提示','Update文件夹或里面的补丁文件不存在,程序无法继续运行!')
                Exit
        EndIf
       
        Dim $j,$n=0,$i
        For $j=1 To $filelist
                $array=StringSplit($filelist[$j],"-");对于数组中的文件进行KB段提出
                ;StringInStr($FixedPatchsListPath,$array);$patchslistfile是前面搜索本机已安装补丁的列表文件
                $IsFixedPatch=IniRead($FixedPatchsListPath,"已经安装补丁",$array,"");判断已经下载的补丁是否已经打过
                If $IsFixedPatch="" Then;是未打过的补丁就n计数加1,就是计算机上还没有打的补丁数
                        $n += 1
                EndIf
        Next
        If $n=0 Then
                MsgBox(0,"提示","已下载的目录里没有新补丁可以安装,程序将退出!")
                Exit
        EndIf
        For $i = 3 To 1 Step -1
                $message = "共需安装" & $n & "个系统补丁," & $i & "秒后开始安装"
                GUICtrlSetData($Label3, $message)
                Sleep(1000)
        Next
        $message = "正在安装..."
        GUICtrlSetData($Label3, $message)
        Dim $wait = 0, $m = 0
        $start = GUICtrlSetData($Progress1, $wait) ;修改进度条的状态
        For $j = 1 To $filelist
                $array = StringSplit($filelist[$j], "-") ;以指定分隔符把字符串拆分成若干子串
                If IniRead($FixedPatchsListPath,"已经安装补丁",$array,"") = "" Then
                ;StringInStr()为检查某个字符串是否含有给定的子串,返回为0未发现
                        $result = RunWait($FixedPatchsListPath & "\" & $filelist[$j] & "/u /z /n /o /q")
                        $m += 1
                        ;ProgressSet(100/$filelist*$i, "已完成"&100/$filelist *$i& " % ")
                        $wait = 100 / $n * $m
                        GUICtrlSetData($Progress1, $wait)
                        $jindu = "已完成: " & Round($wait, 0) & " %"
                        GUICtrlSetData($Label3, $jindu)
                        If $result = 1603 Then
                                $ending = "安装失败"
                        Else
                                $ending = "安装成功"
                        EndIf
                        GUICtrlCreateListViewItem($m & "|" & $array & "|" & $ending, $ListView1) ;在GUI上创建一个 ListView 项目控件
                EndIf
        Next
        $jindu = "已完成: 100%"
        GUICtrlSetData($Label3, $jindu)
        TrayTip("提示", "补丁已安装,请重启电脑!", 6, 1)
EndFunc   ;==>update
Func _EnumRegFixedPatchs()
        Dim $i=0
        While 1
                $i +=1
          $Var=RegEnumKey($FixedPatchsRegPath,$i)
          If @error <>0Then ExitLoop
        ;FileWriteLine($FixedPatchsListPath,$Var & @CRLF);向此前已经打开的ini文件中        将枚举出的值逐行写入到指定
             IniWrite($FixedPatchsListPath,"已经安装补丁",$Var,"1")
        WEnd
EndFunc
Func _Exit()
        Exit
EndFunc

newuser 发表于 2010-8-12 11:10:19

回复 11# newuser

灌水漂浮!

the886 发表于 2010-8-14 13:48:23

试试。。。。。。。。。。。。。。。。。。

G,man。 发表于 2010-8-14 17:47:44

{:face (355):}学习下。

devilma 发表于 2010-8-16 22:40:53

{:face (382):}站个位置,学习一下
页: [1] 2
查看完整版本: [已解决]打补丁的问题?