Windows更新安装时出现对象错误,脚本在新系统驱动安装时崩溃
问题描述
我的AutoIt代码此前运行正常,但在新操作系统上安装驱动时发生崩溃,报错信息为 "The requested action with this object has failed",崩溃位置在$session_download.Download处。尽管代码中包含错误处理逻辑,但触发错误时并未弹出预期的错误提示框。
相关代码如下:
Func download_and_install() Local $session_install Local $hide_stat Local $result Local $reboot = False Local $session_download ; 检查更新数组是否存在 If Not IsArray($arr_updates) Then log_this("Update array doesn't exist, restarting update phase.") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf Local $obj_coll log_this("创建更新会话。") Local $obj_sess = ObjCreate("Microsoft.Update.Session", $sys_info[1]) If @error Then log_this("创建对象出错,重启函数。") Return EndIf #Region 下载更新 log_this("创建更新下载器。") $session_download = $obj_sess.CreateUpdateDownloader() If @error Then MsgBox(0, "结果", "下载错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf log_this("开始下载更新。") $arr_updates[0][1] = 1 For $c = 1 To $arr_updates[0][0] log_this('处理单个更新下载') ; 跳过未选中的更新,按需隐藏 log_this("隐藏更新") If $arr_updates[$c][3] = 0 Then If $prog_update[3][1] = 1 And $prog_update[4][1] = 1 Then $hide_stat = $arr_updates[$c][5].IsHidden If Not $hide_stat Then $arr_updates[$c][5].IsHidden = True EndIf ContinueLoop EndIf sleep(10000) log_this("更新数据") update_install_data() log_this("创建集合") $obj_coll = ObjCreate("Microsoft.Update.UpdateColl") If @error Then log_this("创建对象出错,重启函数。") Return EndIf log_this("添加更新到集合") $obj_coll.Add($arr_updates[$c][5]) If @error Then MsgBox(0, "结果", "下载错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf log_this("为下载会话绑定集合 ") $session_download.Updates = $obj_coll If @error Then MsgBox(0, "结果", "下载错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf log_this("执行下载会话 ") $session_download.Download If @error Then MsgBox(0, "结果", "下载错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf $arr_updates[0][4] += 1 log_this("下载完成") Next log_this("更新下载完成。") #EndRegion 下载更新 #Region 安装更新 log_this("创建更新安装器。") Local $session_install = $obj_sess.CreateUpdateInstaller() If @error Then MsgBox(0, "结果", "安装错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf log_this("开始安装更新。") $arr_updates[0][1] = 2 For $d = 1 To $arr_updates[0][0] log_this("处理单个更新安装") ; 跳过未选中的更新 If $arr_updates[$d][3] <> 1 Then ContinueLoop sleep(10000) log_this("更新数据") update_install_data() log_this("创建集合") $obj_coll = ObjCreate("Microsoft.Update.UpdateColl") If @error Then log_this("创建对象出错,重启函数。") Return EndIf log_this("添加更新到集合") $session_install.Updates = $obj_coll If @error Then MsgBox(0, "结果", "安装错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf log_this("为安装会话绑定集合") $obj_coll.Add($arr_updates[$d][5]) If @error Then MsgBox(0, "结果", "安装错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf log_this("执行安装会话") $result = $session_install.Install If @error Then MsgBox(0, "结果", "安装错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf If $result.RebootRequired Then $reboot = True $arr_updates[0][5] += 1 log_this("安装完成") Next $prog_update[9][1] += $arr_updates[0][5] IniWrite($path_progress, "Update", "UpdatesInstalled", $prog_update[9][1]) log_this("更新安装完成。") #EndRegion 安装更新 If $prog_update[3][1] = 1 Then $prog_update[1][1] = 7 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Else log_this("重启后将再次检查更新。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) EndIf If $reboot Then log_this("需要重启。") If $prog_overall[3][1] = "Next" Then allow_exe(1, 0) log_this("正在重启系统。") If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization", "NoLockScreen") = 0 Then RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization", "NoLockScreen", "REG_DWORD", 1) EndIf If IniRead($path_progress, "Overall", "Restart", "") = "Yes" Then IniWrite($path_progress, "Overall", "Restart", "No") EndIf ; 读取INI文件中的当前值 Local $restarts = IniRead($path_progress, "AditionalConfig", "Restarts", "0") ; 转换为整数并加1 If Int($restarts) < 10 Then $restarts = Int($restarts) + 1 IniWrite($path_progress, "AditionalConfig", "Restarts", String($restarts)) Shutdown(6) Exit Else IniWrite($path_progress, "AditionalConfig", "Restarts", "0") $prog_update[1][1] = 7 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) EndIf EndFunc ;==>download_and_install
问题排查与修复方案
1. 错误处理失效的核心原因
AutoIt的@error无法捕获所有COM对象抛出的异常,$session_download.Download这类COM方法的错误需要专门的COM错误捕获机制处理,原代码仅依赖@error会导致错误被遗漏。
2. 修复错误捕获逻辑
在函数开头添加COM错误监听,替换原有的@error判断:
; 在download_and_install函数开头添加 ObjEvent("AutoIt.Error", "ComErrorHandler") ; 新增全局错误处理函数 Func ComErrorHandler() Local $err = ObjEvent(@ERROR, "") log_this("COM错误详情: " & $err.windescription & " | 错误代码: " & Hex($err.number)) MsgBox(0, "下载失败", "错误信息: " & $err.windescription) $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Exit EndFunc
3. 新系统兼容性适配
- 确认新系统未精简Windows Update组件:部分定制系统会移除
Microsoft.Update.Session依赖的服务,可通过运行services.msc检查Windows Update服务是否正常运行。 - 强制以管理员权限运行脚本:驱动安装和更新操作需要高权限,可在脚本开头添加
#RequireAdmin声明。 - 验证更新对象有效性:新系统中部分更新的属性可能变更,可在添加到集合前增加判断:
If Not IsObj($arr_updates[$c][5]) Then log_this("无效的更新对象,跳过: " & $c) ContinueLoop EndIf
4. 修复安装阶段的顺序错误
原安装代码中先绑定空集合到安装器,再添加更新,会导致安装器无法获取有效更新,调整顺序如下:
; 正确顺序:先添加更新到集合,再绑定到安装器 $obj_coll.Add($arr_updates[$d][5]) If @error Then MsgBox(0, "结果", "安装错误。") $prog_update[1][1] = 4 IniWrite($path_progress, "Update", "Phase", $prog_update[1][1]) Return EndIf $session_install.Updates = $obj_coll
内容的提问来源于stack exchange,提问作者Ice
相关产品推荐
相关产品推荐

