保存&由于断电而自动关闭之前自动关闭打开Excel 2007文件

时间:2015-04-24 21:41:12

标签: windows excel vbscript uac psexec

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

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

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,runas,vmrum(远程机器是VM),甚至还有Task Scheduler来解决这个问题。我甚至想出了如何确定远程VM上登录用户的会话号,以便我可以将其传递给psexec,以便它可以与远程VM用户交互运行。关闭警告消息在远程VM活动用户的桌面上正确显示。但我总是得到429错误 - 除非我使用远程VM的本地管理员帐户(这是工作组,而不是域,BTW)在本地和远程计算机上登录。我最初认为它可能是一个psexec问题,但我现在认为它是Office 2007或Windows 7 UAC权限问题(感谢Harry Johnston回答我原来的帖子):

  使用PSExec在虚拟机上运行WScript文件时,

GetObject()429错误   机

在发出关机之前,有没有办法在远程计算机上保存打开的Excel文件?我不相信Office AutoSave。我的客户的数据太重要了,不能在断电或由于无法正常使用AutoSave而丢失。

2 个答案:

答案 0 :(得分:0)

如果你正常关机,Word等人会弹出对话框。正常关闭仅仅是程序关闭的请求,任何程序都可以取消它。强制程序终止时。

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

taskkill /s computername /im excel.exe

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

答案 1 :(得分:0)

这个问题的简短回答是我在远程计算机上运行的vbscript没有在远程计算机的登录用户的安全上下文中运行因为这个,Office 2007将不允许在以下代码行中从Excel.Application ActiveX组件创建objXL对象(因此429错误消息" ActiveX组件无法创建对象"): / p>

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

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

  1. 未激活远程过程调用(RPC)引擎
  2. 启用了UAC远程访问限制
  3. 应用程序必须在登录用户的Windows 7会话中运行
  4. 解决第一个问题需要在远程计算机上启用RPC Engine。为此,您必须配置和启动四(4)个Windows服务并配置注册表项以启用远程 RPC。配置注册表项以启用远程RPC,如下所示:

    HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \控制\的TerminalServer

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

    应按如下方式配置四个Windows服务:

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

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

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

    但是我怎样才能使用远程机器登录用户的登录凭据(假设我有办法获取凭据;稍后会详细介绍)在安全上下文中执行我的vbscript如果远程计算机的UAC远程访问限制首先拒绝我访问远程计算机,则登录用户?我能让它工作的唯一方法是关闭远程机器的UAC远程访问限制。这不是一个微不足道的决定,因为关闭UAC远程访问限制会打开远程机器进行环回攻击。"但是如果我要让远程机器的登录用户的安全上下文中的PSEXEC在远程机器上运行我的vbscript,我别无选择。要关闭UAC远程访问限制,请在远程计算机上修改以下注册表项

    HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ CurrentVersion \政策\系统

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

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

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