Command line Windows批处理文件不等待命令完成

Command line Windows批处理文件不等待命令完成,command-line,windows-installer,Command Line,Windows Installer,我有一个批处理文件,它一启动就存在(以管理员身份运行),不执行其中的命令,但是如果我在命令行中指定它,它运行良好并执行所有命令 下面是其中的内容: start /wait msiexec /x SetupServices.msi /qn /l* "SetupServices.uninstall.log" start /wait msiexec /i SetupServices.msi /qn /l* "SetupServices.install.log" 尝试执行开始/等待msiexec行,

我有一个批处理文件,它一启动就存在(以管理员身份运行),不执行其中的命令,但是如果我在命令行中指定它,它运行良好并执行所有命令

下面是其中的内容:

start /wait msiexec /x SetupServices.msi /qn /l* "SetupServices.uninstall.log"

start /wait msiexec /i SetupServices.msi /qn /l* "SetupServices.install.log"

尝试执行开始/等待msiexec行,如果这不起作用,请再创建两个bat文件,一个名为uninstall.bat,另一个名为install.bat,并使用call将它们串联执行。

pause
语句添加到批处理的末尾,这将阻止控制台窗口关闭,您将能够看到错误消息(如果有)。错误可能是它没有实际运行任何东西就退出的原因。这可能是什么样的错误?找不到SetupServices.msi-我就是这么想的。

(正确答案)

首先,如果批量启动.exe文件,则更安全的做法是在其前面加上“call”。 有时,这是必要的,以确保批次正在等待完成

使用“start”是另一种可能性,但是对于这个简单的用例来说没有必要

您写入命令未执行。所以,很明显,您有另一个问题,而不是“不等待..完成”问题。 看看您新提供的示例,情况就是这样。在管理模式下,您必须提供完整路径。使用我下面的小技巧(“%~dp0”,包括反斜杠),您仍然可以在批处理文件中使用当前目录

大多数情况下,如果管理员权限出现此类问题,则这是“当前目录”路径的问题。具有管理员权限的批处理文件使用它的方式与我们以前使用的方式不同,它不在自己的目录中启动(但主要在System32中)。不依赖CD是编写防弹批处理文件的一个重要问题

下面是一个很好的示例批次,它结合了此处的其他答案,并解决了您案例中的一些可能问题:

call msiexec /i "%~dp0MySetup.msi" /qb /L*v "%~dp0MySetup.log"
echo Returncode: %ERRORLEVEL%
pause
它正确使用当前目录,并假设安装命令行包含日志文件(仅适用于在当前目录中具有写访问权限的情况,如果没有,请为具有写访问权限的日志文件指定路径,如“%TEMP%\MySetup.log”)


注意:请记住真正使用管理员权限启动批处理文件(鼠标右键菜单或打开管理员命令shell之前:)

这超出了问题的范围,但扩展了我关于处理当前目录的回答:这是我建议的每个批处理文件保存其自身路径的开始。其特点是它也适用于UNC路径。“Pushd”会在必要时自动创建新的驱动器号(假设您有一个空闲的26)。当然,您也可以在批处理文件的末尾立即使用“popd”,但稳定命令不依赖于我提到的当前目录,因此最好始终提供完整路径

@echo off
cls
pushd %~dp0
popd
set MYDIR=%CD%
echo Directory of this batch fil: %MYDIR%
然后,您可以从另一个答案中添加msi行,如下所示:

call msiexec /i "%MYDIR%\MySetup.msi" /qb /L*v "%MYDIR%\MySetup.log"
echo Returncode: %ERRORLEVEL%
pause
(备注:对于日志文件路径,您当然是自由的,它不必位于同一目录中。但对于测试/调试很好。在任何情况下,您都必须对您提供给MSI的目录/文件具有写访问权限。)

虽然对于普通的MSI文件,并不总是需要从一开始就使用管理员权限启动批处理,但与过于依赖稍后(可能)出现的MSI UAC相比,这种技术要安全得多(像使用管理员权限启动MSI一样)。
它也与msiexec…/qn一起工作,这很重要(静默安装)。

回到这个问题,我认为“正确的方法”是通过PowerShell

Start-Process -Wait -FilePath msiexec -ArgumentList /i, "setup.msi", /qn, /l*v, "install.log"   
或者在它前面加上
PowerShell;
直接从CMD调用

PowerShell; Start-Process -Wait -FilePath msiexec -ArgumentList /i, "setup.msi", /qn, /l*v, "install.log"
没有黑客和技巧:-)

如果使用参数,则需要窗口标题“

start /wait "Window Title" "MsiExec.exe" /i SetupServices.msi /qn /l* SetupServices.uninstall.log
start /wait "Window Title" "MsiExec.exe" /i SetupServices.msi /qn /l* SetupServices.install.log

我可以这样做,但不应该有一个更直接的方法吗?:-)我以前做过,但这并没有改变任何事情…:(@Ostati您没有看到任何错误吗?请尝试分析批处理中的%ERRORLEVEL%环境变量,添加
echo%ERRORLEVEL%
应该足够了:0表示成功,其他退出代码表示失败,有一个列表。这是我的一个小建议,因为我的第一个答案引起了一些注意(是的,最近有3个ups:-)与我的许多其他答案相比,其中一些答案真的很有用:-)谢谢,你写的所有东西真的帮了我的忙!欢迎光临。我想让感兴趣的读者了解我下面“第二个”答案的扩展,以及创建一个批处理文件的相关技巧,该批处理文件(重新)以管理员权限(UAC)自动启动,而用户(通常没有经验)不需要“以管理员身份启动”或者是这样:这与这里的问题有关,因为显然设置需要管理员权限,并且问题包含两个子问题。