保存并关闭 在因断电关机前自动打开 Excel 2007 个文件

Save & Close Open Excel 2007 Files Automatically BEFORE Shutdown Due To Power Loss

我花了好几天的时间试图找到一种方法来在 shutdown.exe 或 psshutdown.exe 发布之前保存用户打开的 Excel 2007 文件。我正在使用 Windows 7 Pro 64 位机器 w/UAC 启用,包括远程限制。我不想绕过这些安全措施。

我已经开发了可以完成这项工作的 vbscript,但它只能在本地 运行s。代码如下:

Option Explicit
'--------------------------------------------------

'*** Dimension Local Variables ***
Dim objXL, msg, i, WshShell, strShutdownMessage, strMsg

'*** Enable Error Handling ***
On Error Resume Next

'*** Display Server Emergency and Computer Shutdown Message ***
Set WshShell = WScript.CreateObject("WScript.Shell") 'Creates an instance of the Windows Scripting Host shell (WshShell)
'--- Popup Message - Automatically Closes After 15 Seconds ---
'--- (the "4112" nType value is the sum of 16 - Critical window type + 4096 - display on top!!)
WshShell.Popup "AN UNEXPECTED SERVER EMERGENCY HAS OCCURRED." & Chr(13) & Chr(13) &_
"THIS COMPUTER WILL AUTOMATICALLY SHUT DOWN 30 SECONDS FROM WHEN THIS MESSAGE DISAPPEARS.  " &_
"PLEASE SAVE YOUR DATA AND CLOSE ALL OPEN APPLICATIONS IMMEDIATELY!", 15, "SERVER EMERGENCY SHUTDOWN WARNING!",4112

'*** Debugging Exit ***
'WScript.quit

'*** Wait 30 Seconds Before Saving Data, Closing Applications, and Shutting Down Computer ***
WScript.Sleep 30000

'*** Set Excel Object Variable ***
Set objXL = GetObject( , "Excel.Application")

'*** Trap Error And Shutdown Computer If No Open Excel Workbooks ***
If Err.Number > 0 Then 'No open Excel workbooks
 'MsgBox ("ErrorLevel ... = " & Err.Number)
 'Wscript.quit
 WshShell.run("c:\windows\system32\shutdown.exe /f /s") 'Run shutdown command
End If

'*** Save Data And Close Each Open Excel Workbook ***
For Each i In objXL.Workbooks 'Close each open Excel workbook
 i.Save
 i.Close
Next

'*** Shutdown Computer ***
WshShell.run("c:\windows\system32\shutdown.exe /f /s")

我遇到的问题是当代码执行以下语句时抛出 429 错误:

Set objXL = GetObject( , "Excel.Application")

我已尝试 psexec、运行as、vmrum(远程机器是虚拟机),甚至任务计划程序来解决这个问题。我什至想出了如何确定远程 VM 上登录用户的会话号,这样我就可以将它传递给 psexec,这样它就可以 运行 与远程 VM 用户交互。关机警告消息正确显示在远程 VM 活动用户的桌面上。但我总是收到 429 错误 - 除非我使用远程 VM 的本地管理员帐户登录本地和远程计算机(顺便说一句,这是一个工作组,而不是域)。我最初认为这可能是一个 psexec 问题,但我现在认为它是 Office 2007 或 Windows 7 UAC 权限问题(感谢 Harry Johnston 对我原来 post 的回答) :

GetObject() 429 Error When Using PSExec To Run WScript File On Virtual Machine

有什么方法可以在发出关机命令之前将打开的 Excel 文件保存在远程机器上?我不信任 Office AutoSave。我客户的数据非常重要,不能因为停电或无法正确使用自动保存而丢失。

如果您正常关机,Word 等会弹出对话框。正常关机只是要求程序关闭,任何程序都可以取消它。当强制程序终止时。

因此在客户端中正常关闭 excel。他们会得到一个对话。他们也可以取消它。 taskkill 命令行程序可以做到这一点。

taskkill /s computername /im excel.exe

如果他们拒绝关闭,您可以使用 /f 标志强制关闭。

这个问题的简短回答是远程机器上 运行 的 vbscript 没有 运行 在远程机器的登录用户的安全上下文中. 因此,Office 2007 不允许在以下代码行中从 Excel.Application ActiveX 组件(因此出现 429 错误消息,"ActiveX component cannot create object")创建 objXL 对象:

Set objXL = GetObject( , "Excel.Application")

然后,挑战是能够弄清楚如何在远程计算机的登录用户的安全上下文中 运行 我的 vbscript(或任何应用程序,就此而言)。我最终选择了 PSEXEC 作为我用来 运行 我在远程机器上的 vbscript 的实用程序。 PSEXEC 有三个问题,我必须处理这些问题才能使我的 vbscript 成功执行而不会出现 429 错误(如果您使用 PSEXEC 以外的东西,您的问题列表可能会有所不同)。 这些问题只存在于远程机器上:

  1. 远程过程调用 (RPC) 引擎未激活
  2. UAC 远程访问限制已启用
  3. 应用程序必须 运行 在登录用户的 Windows 7 会话中

解决第一个问题需要在远程计算机上启用 RPC 引擎。为此,您必须配置并启动四 (4) 个 Windows 服务并配置注册表项以启用 remote RPC。配置注册表项以启用远程 RPC,如下所示:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TerminalServer

  • AllowRemoteRPC ... dword = 1
  • fDenyTSConnections ... dword=0

四个Windows服务应该配置如下:

  • 远程桌面配置服务...手动启动...必须启动
  • 远程桌面服务服务...手动启动...必须启动
  • 远程桌面服务用户模式端口重定向器服务...手动启动..必须启动
  • 远程过程调用服务...自动启动...必须启动

第二个问题,UAC 远程访问限制,阻止任何在 Windows 7 机器上拥有帐户的用户使用 remote PRC(这是PSEXEC 用于 运行 远程计算机上的应用程序的机制)除非使用计算机的内置管理员帐户。 Windows 7 内置管理员帐户不受UAC 远程限制的影响(这解释了为什么我的vbscript 在使用管理员帐户时执行时没有出现429 错误)。但是,所有其他用户帐户都会受到影响。

经过几天的测试,我了解到应用程序只有在 运行 处于远程计算机登录用户的安全上下文中时,才能在远程计算机上成功执行。这意味着 PSEXEC 必须使用远程机器当前登录用户的登录凭据,以便应用程序访问远程机器登录用户的安全上下文,而不抛出 429 错误。 这是帮助我配置此解决方案以解决 429 错误问题的关键学习内容。

但是如果远程机器的 UAC 远程访问限制首先拒绝我访问远程机器?我能让它工作的唯一方法是关闭远程机器的 UAC 远程访问限制。这不是一个微不足道的决定,因为关闭 UAC 远程访问限制会打开远程机器到 "loopback attacks." 但是如果我要让 PSEXEC 到 运行 我在远程机器上的 vbscript,我别无选择在远程计算机的登录用户的安全上下文中。要关闭 UAC 远程访问限制,请在远程计算机上修改以下注册表项

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System

值为“0”(零)启用 UAC 远程限制;值“1”禁用 UAC 远程限制。将此值更改为“1”以禁用 UAC 远程访问限制。这将允许 PSEXEC 访问远程机器,以使用远程机器登录用户的登录凭据 运行 其应用程序负载。

最后也是最具挑战性的问题是如何确定哪个用户在远程计算机上登录,然后使用他们的用户名和密码在登录用户的安全上下文中 运行 PSEXEC。这个问题的解决方案是使用 QWINSTA 查询远程机器上的会话数据。这涉及创建一个 Windows 7 命令 (.cmd) 文件,该文件使用 QWINSTA 询问远程计算机并确定哪个用户名与远程计算机的活动会话以及活动​​会话的 ID 相关联。

使用 Windows 7 .cmd 文件中存在的一系列 DOS 比较(“==”)语句,将 QWINSTA USERNAME 值与远程计算机用户及其密码列表进行比较以确定远程机器的登录用户密码。然后将用户名、密码和会话 ID 作为扩展的 DOS 变量传递给 PSEXEC 语句。然后,PSEXEC 应用程序负载可以 运行 在正确的用户会话中的远程计算机上(这也是一个很难解决的问题),以及登录用户的凭据。它是正确的用户会话和登录用户登录凭据的组合,"connects" PSEXEC 应用程序到登录用户的安全上下文并允许它 运行 而不会生成 429 错误。