IE8 未知的运行时错误

IE8 未知的运行时错误,这个真的很难发现问题的根源!!发现用IE调js真的蛋疼。诶,而且IE和FF Chrom等等标准都不一样。其他浏览器都可以,唯独IE不行,无语。现在说下问题怎么解决的。



在用 Javascript 更改 HTML 代码的时候,经常会用到某个对象的 innerHTML。在读写标签内的代码或字符串时非常方便。

但 IE 对这个属性的支持不太好,经常容易报出 “未知的运行时错误”,而同样的操作,在 FireFox 和 Opera 下面就都没问题。

到百度和 Google 查了下,发现是 IE 浏览器下,对 <table>、<tbody> 和 <tr> 等标签的 innerHTML 属性进行写操作时会报错。

应该是 IE 处理不当造成的。

目前没有很好的解决办法,只能采取改变 HTML 结构的方式,也就是说,不要对 <table> 等标签应用这个属性,改为对 <div>、<span> 和 <p> 等标签,就没问题了。

比如,运行下面的代码会报错:

<table border="0" cellspacing="0" cellpadding="0" id="Container">
<tr>
<td>Hello Leakon!</td>
</tr>
</table>
<script type="text/javascript">
document.getElementById('Container').innerHTML = '
<tr><td>Good morning!</td></tr>';
</script>

改变一下实现方式,就没问题了:

<div id="Container">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td>Hello Leakon!</td>
</tr>
</table>
</div>
<script type="text/javascript">
document.getElementById('Container').innerHTML = '
<table border="0" cellspacing="0" cellpadding="0"><tr><td>Good morning!</td></tr></table>';
</script>

One Response to “设置 innerHTML 属性 导致 未知的运行时错误 IE bug”


<think>我们遇到了“IE自动化错误”,这通常是由于IE浏览器与VBA自动化交互时出现问题。根据经验,这类错误可能由多种原因引起,包括但不限于: 1. IE安全设置阻止了自动化 2. 页面元素未加载完成就进行操作 3. 网络问题导致页面加载失败 4. 浏览器弹出窗口(如证书错误、登录超时等) 5. 浏览器版本与VBA不兼容 在之前优化的代码中,我们已经加入了多种稳定性措施,但错误仍然发生。下面将提供一套综合解决方案,包括错误预防和错误处理。 ### 解决方案:分层次错误处理 我们将从以下三个层面处理该问题: 1. **预防层**:增强代码健壮性,避免错误发生 2. **检测层**:实时监控异常状态 3. **恢复层**:错误发生后的自动恢复机制 以下是具体实现代码: ```vba ' === 增强版错误处理主过程 === Private Sub CommandButton1_Click() On Error GoTo FatalErrorHandler Dim maxRetries As Integer: maxRetries = 3 Dim retryCount As Integer: retryCount = 0 RetryPoint: On Error GoTo SubErrorHandler retryCount = retryCount + 1 ' === 主抓取流程 === ' ... [此处插入之前的优化代码] ... ' 如果执行到这里,表示成功完成 GoTo CleanExit SubErrorHandler: ' 处理可恢复的错误 Dim errMsg As String errMsg = "尝试 " & retryCount & "/" & maxRetries & " 时发生错误: " & Err.Description LogError errMsg ' 检查是否需要重试 If retryCount < maxRetries Then ' 执行恢复操作 If Not ResetIEAutomation() Then GoTo FatalErrorHandler End If Resume RetryPoint Else ' 重试次数用尽,升级为致命错误 Err.Raise Err.Number, Err.Source, "重试次数用尽: " & Err.Description End If Exit Sub FatalErrorHandler: ' 处理不可恢复的错误 Dim fatalMsg As String fatalMsg = "致命错误: " & Err.Description & vbCrLf & _ "错误代码: " & Err.Number & vbCrLf & _ "请检查网络连接或联系管理员。" MsgBox fatalMsg, vbCritical LogError fatalMsg CleanExit: ' ... [清理代码] ... End Sub ' === IE自动化重置函数 === Private Function ResetIEAutomation() As Boolean On Error Resume Next Static ieApp As Object ' 步骤1:尝试关闭现有IE实例 If Not ieApp Is Nothing Then ieApp.Quit Set ieApp = Nothing End If ' 步骤2:清理残留进程 KillIEProcesses ' 步骤3:重建IE实例 Set ieApp = CreateObject("InternetExplorer.Application") If ieApp Is Nothing Then ResetIEAutomation = False Exit Function End If ' 配置新实例 With ieApp .Silent = True .Visible = True .Navigate "about:blank" Do While .Busy Or .readyState <> 4 DoEvents Loop End With ResetIEAutomation = True End Function ' === 终止残留IE进程 === Private Sub KillIEProcesses() On Error Resume Next Dim wmiService As Object, processes As Object Set wmiService = GetObject("winmgmts:\\.\root\cimv2") Set processes = wmiService.ExecQuery("SELECT * FROM Win32_Process WHERE Name='iexplore.exe'") Dim proc As Object For Each proc In processes proc.Terminate 0 Next End Sub ' === 增强版错误日志 === Private Sub LogError(message As String) On Error Resume Next Dim fso As Object, logFile As Object Set fso = CreateObject("Scripting.FileSystemObject") ' 日志文件路径 Dim logPath As String logPath = ThisWorkbook.Path & "\automation_error.log" ' 追加写入日志 Set logFile = fso.OpenTextFile(logPath, 8, True) ' 8=追加模式 logFile.WriteLine "[" & Now & "] " & message logFile.Close End Sub ``` ### 关键错误处理点 1. **分层错误处理**: - `SubErrorHandler`:处理可恢复错误(如元素未找到) - `FatalErrorHandler`:处理不可恢复错误(如网络中断) 2. **自动化重置**: - 彻底终止现有IE实例 - 清理残留进程 - 重建新IE实例 3. **进程级清理**: - 使用WMI查询终止所有`iexplore.exe`进程 - 避免残留进程影响后续操作 ### 常见错误代码及处理方案 | 错误代码 | 原因 | 解决方案 | |----------|-----------------------|------------------------------| | 462 | 远程服务器不可用 | 重置IE实例,检查网络连接 | | 91 | 对象变量未设置 | 增强对象存在性检查 | | 424 | 需要对象 | 添加前置条件验证 | | -2147417851 | 自动化服务器不能创建对象 | 清理IE进程,重置IE设置 | | -2147467259 | 操作超时 | 增加超时时间,优化等待逻辑 | ### 预防性措施 1. **IE设置调整**: ```vba ' 自动调整IE设置 Private Sub AdjustIESettings() ' 禁用保护模式(需要管理员权限) SetKeyValue "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3", "2500", 0, "REG_DWORD" ' 禁用弹出窗口阻止程序 SetKeyValue "HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\New Windows", "PopupMgr", 0, "REG_DWORD" End Sub ``` 2. **元素操作保护**: ```vba ' 安全元素操作函数 Function SafeSetValue(doc As Object, id As String, value As String) On Error Resume Next Dim elem As Object Set elem = doc.getElementById(id) If Not elem Is Nothing Then elem.Value = value SafeSetValue = True Else SafeSetValue = False End If End Function ``` 3. **网络状态检测**: ```vba ' 检查网络连接 Function CheckInternetConnection() As Boolean On Error Resume Next Dim objHttp As Object Set objHttp = CreateObject("MSXML2.XMLHTTP") objHttp.Open "HEAD", "http://www.microsoft.com", False objHttp.Send CheckInternetConnection = (objHttp.Status = 200) End Function ``` ### 部署建议 1. **分步实施**: - 首先部署错误处理框架(分层处理) - 然后添加自动化重置功能 - 最后实现预防性措施 2. **日志分析**: - 定期检查`automation_error.log` - 根据日志优化特定错误处理 3. **用户通知**: - 在致命错误时提供详细指引 - 建议用户检查IE安全设置 §§相关问题§§ 1. 如何避免VBA自动化中的对象未设置错误(Error 91)? 2. 在IE自动化中,处理证书错误弹窗的最佳方法是什么? 3. 如何在不使用管理员权限的情况下调整IE安全设置? 4. VBA中如何实现跨工作簿的错误日志记录? 5. 除了终止进程,还有哪些方法可以清理残留的IE实例?</think>### 解决"IE自动化错误"的全面方案 在VBA中处理IE自动化错误需要系统性的方法。以下是完整的解决方案,包含错误预防、检测和恢复机制: ```vba ' === 增强的IE自动化错误处理框架 === Private Sub CommandButton1_Click() On Error GoTo GlobalErrorHandler Dim ie As Object Set ie = CreateObject("InternetExplorer.Application") ' === 错误预防层 === If Not PrepareIEEnvironment(ie) Then MsgBox "IE环境初始化失败", vbCritical Exit Sub End If With ie .Visible = True ' === 安全导航 === If Not SafeNavigate(ie, "https://logincas.tp-link.com:8443/login?service=http://bugzilla.tp-link.com/", 30) Then MsgBox "导航到登录页面失败", vbExclamation GoTo CleanExit End If ' === 安全表单处理 === Dim doc As Object Set doc = .Document ' 用户名输入 If Not SetElementValueSafely(doc, "username", Sheets("account").Range("A3").Value) Then MsgBox "无法设置用户名", vbExclamation GoTo CleanExit End If ' 密码输入 If Not SetElementValueSafely(doc, "password", Sheets("account").Range("B3").Value) Then MsgBox "无法设置密码", vbExclamation GoTo CleanExit End If ' === 安全提交 === If Not SafeFormSubmit(ie, doc) Then MsgBox "表单提交失败", vbExclamation GoTo CleanExit End If ' === 登录后处理 === If Not SafeNavigate(ie, Sheets("account").Range("B1").Value, 120) Then MsgBox "导航到目标页面失败", vbExclamation GoTo CleanExit End If ' === 表格处理 === ProcessBuglistTable .Document, Sheets("Bugzilla") End With CleanExit: SafeCleanup ie Exit Sub GlobalErrorHandler: Dim errMsg As String errMsg = "自动化错误: " & Err.Number & vbCrLf & Err.Description & vbCrLf & vbCrLf errMsg = errMsg & "发生位置: " & GetCallStack() ' 根据错误类型提供解决方案 Select Case Err.Number Case -2147352319 ' 自动化错误 errMsg = errMsg & "解决方案:" & vbCrLf errMsg = errMsg & "1. 检查IE安全设置是否允许自动化" & vbCrLf errMsg = errMsg & "2. 确保页面完全加载后再操作" & vbCrLf errMsg = errMsg & "3. 尝试增加等待时间" Case 462 ' 远程服务器不存在 errMsg = errMsg & "解决方案:" & vbCrLf errMsg = errMsg & "1. 检查网络连接" & vbCrLf errMsg = errMsg & "2. 确认目标URL可用" & vbCrLf errMsg = errMsg & "3. 重启IE实例" Case Else errMsg = errMsg & "未知错误,请收集日志并联系管理员" End Select ' 保存错误日志 LogError errMsg MsgBox errMsg, vbCritical, "自动化错误" Resume CleanExit End Sub ' === IE环境准备 === Private Function PrepareIEEnvironment(ie As Object) As Boolean On Error Resume Next PrepareIEEnvironment = False ' 检查IE版本 Dim ieVersion As String ieVersion = GetIEVersion() If Val(ieVersion) < 11 Then MsgBox "IE版本过低(" & ieVersion & "),请升级到IE11或更高版本", vbExclamation Exit Function End If ' 配置IE设置 With ie .Silent = True .Visible = True .Navigate "about:blank" ' 等待初始化完成 If Not WaitForCondition(ie, "readyState = 4", 10) Then MsgBox "IE初始化超时", vbExclamation Exit Function End If End With PrepareIEEnvironment = True End Function ' === 安全导航函数 === Private Function SafeNavigate(ie As Object, url As String, timeout As Integer) As Boolean On Error GoTo ErrorHandler ' 检查是否已在目标页面 If InStr(ie.LocationURL, url) > 0 Then SafeNavigate = True Exit Function End If ' 执行导航 ie.Navigate url ' 等待导航完成 If WaitForCondition(ie, "readyState = 4 AND Not Busy", timeout) Then ' 额外检查页面是否完全加载 SafeNavigate = CheckPageLoaded(ie.Document) Exit Function End If ErrorHandler: SafeNavigate = False End Function ' === 安全表单提交 === Private Function SafeFormSubmit(ie As Object, doc As Object) As Boolean On Error GoTo ErrorHandler ' 尝试多种提交方式 Dim form As Object Set form = doc.forms(0) ' 方式1:直接调用submit方法 form.submit ' 等待提交响应 If WaitForCondition(ie, "LocationURL Like '*bugzilla*'", 15) Then SafeFormSubmit = True Exit Function End If ' 方式2:模拟点击提交按钮 Dim submitButton As Object Set submitButton = doc.querySelector("input[type='submit']") If Not submitButton Is Nothing Then submitButton.Click If WaitForCondition(ie, "LocationURL Like '*bugzilla*'", 15) Then SafeFormSubmit = True Exit Function End If End If ErrorHandler: SafeFormSubmit = False End Function ' === 安全元素操作 === Private Function SetElementValueSafely(doc As Object, elementName As String, value As String) As Boolean On Error GoTo ErrorHandler Dim element As Object Dim attempts As Integer: attempts = 0 Do While attempts < 3 Set element = Nothing ' 尝试多种定位方式 Set element = doc.getElementById(elementName) If element Is Nothing Then Set element = doc.getElementsByName(elementName)(0) If element Is Nothing Then Set element = doc.querySelector("[name='" & elementName & "']") If Not element Is Nothing Then element.Value = value SetElementValueSafely = True Exit Function Else ' 等待元素出现 Application.Wait Now + TimeValue("00:00:01") attempts = attempts + 1 End If Loop ErrorHandler: SetElementValueSafely = False End Function ' === 增强的页面检查 === Private Function CheckPageLoaded(doc As Object) As Boolean On Error Resume Next CheckPageLoaded = False ' 检查文档状态 If doc.readyState <> "complete" Then Exit Function ' 检查是否有错误信息 Dim errorElement As Object Set errorElement = doc.querySelector(".error, .errormessage") If Not errorElement Is Nothing Then LogError "页面包含错误信息: " & errorElement.innerText Exit Function End If ' 检查是否有安全警告 If InStr(1, doc.title, "Certificate", vbTextCompare) > 0 Then LogError "检测到证书警告: " & doc.title Exit Function End If CheckPageLoaded = True End Function ' === 错误日志记录 === Private Sub LogError(message As String) On Error Resume Next Dim fso As Object, ts As Object Set fso = CreateObject("Scripting.FileSystemObject") ' 创建日志目录 Dim logPath As String logPath = Environ("TEMP") & "\BugzillaAutomation\" If Not fso.FolderExists(logPath) Then fso.CreateFolder logPath ' 写入日志文件 Set ts = fso.OpenTextFile(logPath & "error_log_" & Format(Now, "yyyymmdd") & ".txt", 8, True) ts.WriteLine "[" & Now & "] " & message ts.Close ' 保存当前页面用于调试 If Not ActiveDocument Is Nothing Then SaveHTMLForDebugging ActiveDocument, logPath & "debug_" & Format(Now, "hhmmss") & ".html" End If End Sub ' === 调用堆栈追踪 === Private Function GetCallStack() As String On Error Resume Next GetCallStack = "" ' 获取最近的调用位置 Dim i As Long For i = 1 To 5 GetCallStack = GetCallStack & " > " & Application.Caller(i) Next i If GetCallStack = "" Then GetCallStack = "未知位置" End Function ' === IE版本检测 === Private Function GetIEVersion() As String On Error Resume Next Dim wsh As Object Set wsh = CreateObject("WScript.Shell") GetIEVersion = wsh.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version") If Err.Number <> 0 Then GetIEVersion = "未知" End If End Function ' === 增强的清理过程 === Private Sub SafeCleanup(ie As Object) On Error Resume Next ' 尝试正常退出 If Not ie Is Nothing Then If TypeName(ie) = "InternetExplorer" Then If Not ie.Document Is Nothing Then ie.Quit End If End If Set ie = Nothing End If ' 强制终止残留进程 Dim wmi As Object, processes As Object, process As Object Set wmi = GetObject("winmgmts:\\.\root\cimv2") Set processes = wmi.ExecQuery("SELECT * FROM Win32_Process WHERE Name='iexplore.exe'") For Each process In processes process.Terminate Next End Sub ``` ### 常见IE自动化错误及解决方案 | 错误代码 | 错误描述 | 解决方案 | |----------------|------------------------------|--------------------------------------------------------------------------| | -2147352319 | 自动化服务器不能创建对象 | 1. 检查IE安全设置<br>2. 禁用保护模式<br>3. 添加网站到信任站点 | | 462 | 远程服务器不存在或不可用 | 1. 检查网络连接<br>2. 确认URL正确<br>3. 重启IE进程 | | 91 | 对象变量未设置 | 1. 添加对象存在性检查<br>2. 增加等待时间<br>3. 使用错误处理保护 | | 424 | 需要对象 | 1. 检查DOM元素选择器<br>2. 添加重试机制<br>3. 验证页面是否完全加载 | | -2147467259 | 操作超时 | 1. 增加超时时间<br>2. 优化页面加载检测<br>3. 减少页面复杂性 | | 70 | 没有权限 | 1. 以管理员身份运行Excel<br>2. 调整IE安全区域设置<br>3. 修改注册表权限 | ### 预防性措施 1. **IE设置调整**: ```vba ' 自动调整IE设置(需要管理员权限) Private Sub AdjustIESettings() Dim wsh As Object Set wsh = CreateObject("WScript.Shell") ' 禁用保护模式 wsh.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\2500", 0, "REG_DWORD" ' 允许跨域访问 wsh.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\1400", 0, "REG_DWORD" ' 禁用弹出窗口阻止程序 wsh.RegWrite "HKCU\Software\Microsoft\Internet Explorer\New Windows\PopupMgr", "no", "REG_SZ" End Sub ``` 2. **证书错误处理**: ```vba ' 自动接受证书错误 Private Sub HandleCertificateError(ie As Object) On Error Resume Next Dim doc As Object Set doc = ie.Document ' 检查证书错误页面 If InStr(1, doc.title, "Certificate", vbTextCompare) > 0 Then Dim link As Object Set link = doc.getElementById("overridelink") If Not link Is Nothing Then link.Click Application.Wait Now + TimeValue("00:00:02") End If End If End Sub ``` 3. **DOM就绪检测**: ```vba ' 增强的DOM就绪检测 Private Function IsDOMReady(doc As Object) As Boolean On Error Resume Next IsDOMReady = False ' 检查文档状态 If doc.readyState <> "complete" Then Exit Function ' 检查关键元素是否存在 If doc.body Is Nothing Then Exit Function If doc.getElementById("container") Is Nothing Then Exit Function ' 检查是否有JavaScript错误 Dim scripts As Object Set scripts = doc.getElementsByTagName("script") For Each s In scripts If InStr(1, s.innerText, "error", vbTextCompare) > 0 Then Exit Function End If Next IsDOMReady = True End Function ``` ### 部署建议 1. **分阶段部署**: - 首先添加全局错误处理框架 - 然后实现关键功能的安全版本 - 最后添加预防性措施 2. **测试计划**: ```vba ' 自动化测试套件 Private Sub RunAutomationTests() TestNavigation "https://logincas.tp-link.com:8443/login" TestLogin "testuser", "testpass" TestTableExtraction TestErrorHandling End Sub ``` 3. **监控与改进**: ```vba ' 性能监控 Private Sub MonitorPerformance() Dim startTime As Double startTime = Timer ' 执行自动化操作... LogPerformance "MainProcess", Timer - startTime End Sub ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值