You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:27:02