草庐IT

excel - 从Windows批处理脚本以安全模式启动Excel文件,使用默认文件关联

coder 2024-06-18 原文

问题摘要:
我可以在安全模式下从Windows批处理脚本启动Excel文件installer.xlsm,而不提供Excel.exe安装路径吗?
细节
我有一个windows批处理脚本,它可以从远程服务器下载一系列excel加载项的最新版本,将它们放在一个目录(c:\appname\add ins)中,并调用excel文件installer.xlsm。
加载时,installer.xlsm执行VBA宏,该宏卸载旧版本的加载项并安装其新版本。
当前,我使用以下命令启动installer.xlsm:

start "Launching installer file" /wait "<Path to file>\Installer.xlsm"

它的优点在于它使用windows的文件关联来打开excel,而且我不需要提供excel.exe安装路径(多个用户具有不同的计算机映像和ms-office版本)。
现在我想在安全模式下加载installer.xlsm,以确保在installer.xlsm尝试使用外接程序时没有加载任何外接程序,也没有运行任何其他代码。
我知道我可以使用"<PathToExcel>excel" /safemode "<PathToXls>Installer.xlsm",如this answer中所述,但此方法不使用windows的文件关联,并且要求我提供路径。
我们有不同机器图像的用户,使用不同版本的ms office,所以我不想进入硬编码所有可能的excel安装位置。
我能做如下的事情吗:
start "Launching installer file" /wait "<Path to file>\Installer.xlsm /safemode"

我尝试了不同的组合但没有成功。你会怎么做?

最佳答案

首先,我建议阅读Microsoft TechNet关于Application Registration的文章。它解释了应用程序或应用程序套件(如Microsoft Office)的安装程序应如何注册已安装的应用程序,以便其他应用程序可以找到应用程序的可执行文件。
建议在注册表项下创建

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths

一个可执行文件名为excel.exe的子键,默认字符串值是具有完整路径的可执行文件名,还可以选择添加一个名为Path的字符串值,其中仅包含可执行文件的路径。Path字符串可以但大多数不存在,并且可以但不能以反斜杠结尾。
命令start还使用此键查找应用程序,如Where is “START” searching for executables?
各种版本的Microsoft Office的安装程序也在此注册表项下注册excel.exe注册表项。
因此,在Windows Vista和更高版本的Windows上,获取Microsoft Excel安装位置的最简单方法是:
@echo off
for /F "skip=1 tokens=2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe" /ve 2^>nul') do set "ExcelApp=%%~B"
echo ExcelApp=%ExcelApp%
pause

但在Windows XP上,reg.exe的输出不同,因此需要以下批处理代码:
@echo off
for /F "skip=3 tokens=3*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe" /ve 2^>nul') do set "ExcelApp=%%~B"
echo ExcelApp=%ExcelApp%
pause

在为获取包含空格的注册表项的默认字符串的字符串值而编写的批处理代码中,在Read words separated by space & string value also contains space in a batch script上对不同的输出进行了解释。
最好的编码实践是添加额外的代码来处理一个错误情况,比如注册表项根本不存在,因为根本没有安装Microsoft Excel。
但是,使用批处理代码可以分别执行哪些命令启动windows shell函数ShellExecuteEx在命令提示符窗口中使用命令行吗?
start "Launching installer file" "C:\Path to file\Installer.xlsm"

是的,正如下面注释的批处理代码所示。
@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem First query default string value of HKEY_CLASSES_ROOT\.xlsm from registry.
call :GetDefaultRegValue "HKCR\.xlsm"

rem Is there no key HKEY_CLASSES_ROOT\.xlsm or was the default string empty?
if not defined RegValue goto GetFromAppPaths

SET RegValue
rem Get the shell command line used for opening a *.xlsm file.
call :GetDefaultRegValue "HKCR\%RegValue%\shell\open\command"

rem Could the command line not read successfully from Windows registry?
if not defined RegValue goto GetFromAppPaths

SET RegValue
rem The command line contains as first string usually enclosed in double
rem quotes EXCEL.EXE with full path enclosed in double quotes. And there
rem can be even more arguments on the command line which are not needed
rem here. The command line below is used to get just first string of
rem the command line which should be EXCEL.EXE with full path.
for %%I in (%RegValue%) do set "RegValue=%%~I" & goto CheckExcelExistence

rem It is not good when both registry queries above fail. This means
rem either Microsoft Excel is not installed at all or a version of
rem Excel is installed which does not support *.xlsm files like Excel
rem of MS Office 2003, MS Office 2000 or MS Office 97.

rem However, perhaps just *.xlsm is not correct registered and therefore
rem get full path to excel.exe from application registration key.

:GetFromAppPaths
call :GetDefaultRegValue "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe"
if defined RegValue goto CheckExcelExistence

echo Failed to determine installation location of Microsoft Excel.
echo/
endlocal
pause
goto :EOF

:CheckExcelExistence
SET RegValue
rem Remove surrounding double quotes if the Excel executable file name
rem read from Windows registry is still enclosed in double quotes.
set "RegValue=%RegValue:"=%"
if exist "%RegValue%" goto :RunInstall

echo Registered "%RegValue%" does not exist.
echo/
endlocal
pause
goto :EOF

:RunInstall
SET RegValue
ECHO start "Launching installer file" /wait "%RegValue%" "%~dp0Installer.xlsm" /safemode
endlocal
goto :EOF


rem This subroutine queries from Windows registry the default string value of
rem the key passed to the subroutine as first and only parameter and assigns
rem this value to environment variable RegValue. Environment variable RegValue
rem is deleted and therefore is not defined after subroutine exits on failure
rem to get the registry value or when the default value is an empty string.
rem This subroutine works for Windows XP and all later versions of Windows.

:GetDefaultRegValue
set "TypeToken=2"

:Reg3Run
for /F "skip=1 tokens=%TypeToken%*" %%A in ('%SystemRoot%\System32\reg.exe QUERY "%~1" /ve 2^>nul') do (
    if "%%A" == "REG_SZ" (
        if not "%%~B" == "" (
            set "RegValue=%%B"
            goto :EOF
        )
    ) else if "%%A" == "NAME>" (
        set "TypeToken=3"
        goto Reg3Run
    )
)
set "RegValue="
goto :EOF

这个批处理代码只是一个演示。真正找到它时,它不会启动excel。相反,它只输出命令行,该命令行将启动excel,因为start的echo left…在labelRunInstall下面的块中。
此外,此批处理代码包含4行,SET RegValue。这4行只输出从windows注册表成功查询并存储在环境变量RegValue中的字符串值。这4个命令有助于理解执行批处理文件时发生的情况。最后从批处理文件中删除这四条命令行,并删除大写的单个echo。
注意:如果预期的注册表项不存在或其默认值为空字符串,则很容易测试会发生什么情况。只需在以#开头的行的最后一个双引号前插入一个像call :GetDefaultRegValue这样的单个字符,就不会再找到修改后的注册表项。
为了理解使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页。
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
rem /?
setlocal /?
start /?
同时阅读微软关于Using Command Redirection Operators的文章,了解2>nul的解释。重定向运算符>必须用插入符号^转义,以便在windows命令解释器在执行命令之前处理此命令行时,将命令行解释为文本字符,而该命令行在单独的命令进程中执行嵌入的reg.exe命令行。从后台开始。

关于excel - 从Windows批处理脚本以安全模式启动Excel文件,使用默认文件关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45509710/

有关excel - 从Windows批处理脚本以安全模式启动Excel文件,使用默认文件关联的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  7. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  8. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  9. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  10. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

随机推荐