我正在编写一个批处理脚本,用于从同一文件夹中的MSI文件安装一些应用程序。
当我在命令提示符窗口中编写这些命令时,一切正常,所有命令都能正常工作。
但是当我将它们写入批处理脚本时,突然大多数命令(例如XCOPY
,msiexec
,DISM
会导致错误消息,如:
' XCOPY'不被识别为内部或外部命令,可操作程序或批处理文件。
在谷歌搜索了一段时间后,我看到了很多与环境变量PATH
相关的评论,其中应包含C:\Windows\system32
,并确保其包含在PATH
中。还找到了很多关于编写我已经尝试过的完整路径的答案,但它没有用。
我正在使用Windows Server 2012。
这是我的批处理文件的代码:
@echo off
set path=C:\ rem default path
rem get the path as parameter to the script:
set argC=0
for %%x in (%*) do Set /A argC+=1
if %argC% gtr 0 (set path=%1%)
IF %ERRORLEVEL% NEQ 0 (
echo %me%: something went wrong with input directory
)
echo Destenation: %path%
SETLOCAL ENABLEEXTENSIONS
SET me=%~n0
SET parent=%~dp0
echo %me%: starting installation of Python 2.7 64bit and Apache 64 bit
REM install .net 3.5
DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:installationMediaDrive:\sources\sxs
msiexec /i ".\py\python-2.7.amd64.msi" TARGETDIR=%path%/Python27 /passive /norestart ADDLOCAL=ALL
mkdir %path%\Apache24
XCOPY /e /Q ".\Apache24" %path%\Apache24
答案 0 :(得分:2)
批处理文件看起来应该支持安装目录的可选指定路径作为第一个参数。用于检查此可选文件夹路径是否存在的代码非常混乱。检查可选参数肯定更容易,如下所示。
主要问题是重新定义环境变量PATH
,导致存储在目录%SystemRoot\System32
中的Windows标准控制台应用程序,并且执行时命令解释程序cmd.exe
不再找到其他标准Windows目录批处理文件。
通常,如果此完整文件规范字符串包含空格字符或其中一个字符&()[]{}^=;!'+,`~
,则需要指定要使用双引号括起来的完整路径,文件名和文件扩展名来执行的应用程序。在关于在命令提示符窗口cmd /?
中运行的最后输出帮助页面的最后一段中进行了解释。
但主要是为了让人类用户更容易从命令提示符窗口中手动执行应用程序和脚本,Windows命令解释程序还可以找到自行运行的应用程序或脚本(如果指定没有路径且没有文件扩展名)。 / p>
因此,如果用户只输入xcopy
或批处理文件仅包含xcopy
,则Windows命令解释程序将搜索与模式xcopy.*
匹配的文件,该文件具有文件扩展名,如以分号分隔的环境变量PATHEXT
列表首先在当前目录中,如果在分号分隔的环境变量PATH
列表中的所有目录中没有找到合适的文件。
有3个环境变量PATH
:
系统 PATH
存储在Windows注册表中:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
默认情况下,系统 PATH
中的文件夹路径用于独立于已使用帐户的所有流程。
用户 PATH
存储在Windows注册表中:
HKEY_LOCAL_MACHINE\Environment
用户 PATH
中的文件夹路径默认仅用于使用设置了用户 PATH
的帐户运行的所有进程
本地 PATH
只是在当前活动的运行环境中保留在内存中。
系统和用户 PATH
由Windows连接到单个本地 PATH
进程。
每次进程启动一个新进程(如Windows资源管理器启动Windows命令解释程序以执行批处理文件)时,Windows会为新进程创建当前正在运行的进程的环境表的副本 。因此,无论进程在其自身的环境变量本地副本上发生更改,都不会影响所有其他已在运行的进程。环境变量的局部更改仅对自己的进程有效,并且所有进程都由进程修改其变量启动。
在启动批处理文件时,变量PATH
和PATHEXT
具有在命令提示符窗口中运行时显示的值,该窗口在启动批处理文件时使用的相同用户帐户下打开命令{{1列出名称中不区分大小写的set PATH
开头的所有变量。
现在让我们看一下批处理文件的第二行:
PATH
此行重新定义了本地 set path=C:\ rem default path
环境变量。因此,环境变量PATH
对于执行批处理文件的命令进程有效,并且此批处理文件启动的所有应用程序不再包含PATH
,但现在只包含这个非常奇怪的单个文件夹路径。
C:\Windows\System32;C:\Windows;...
C:\ rem default path
是rem
的内部命令,必须单独写入。在C ++或JavaScript中,批处理代码(例如cmd.exe
)中不存在行注释。有关此命令的帮助,请在命令提示符窗口//
中运行。
在没有安装文件夹路径作为第一个参数的情况下运行批处理文件时,结果是Windows命令解释程序在当前目录中搜索rem /?
,dism.*
和msiexec.*
,因为肯定没有名称为xcopy.*
的目录,在驱动器rem default path
的根目录开头有很多空格/制表符。
结论:使用C:
作为安装文件夹路径的变量名称不是一个好主意。
批处理代码中的另一个错误是使用path
指定批处理文件的第一个参数。这是错误的,因为批处理文件的参数用%1%
,%1
引用,...在命令提示符窗口%2
中运行,以获取有关引用批处理文件的参数的帮助,以及存在的可能性如下面的call /?
用于获取参数0的驱动器和路径,这是批处理文件名,即包含当前正在运行的批处理文件的文件夹的路径。
我建议使用这个批处理代码:
%~dp0
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
@echo off
setlocal EnableExtensions
set "SourcePath=%~dp0"
set "BatchName=%~n0"
if "%~1" == "" (
echo %BatchName% started without an installation folder path.
set "InstallPath=C:\"
goto StartInstalls
)
rem Get installation folder path from first argument
rem of batch file without surrounding double quotes.
set "InstallPath=%~1"
rem Replace all forward slashes by backslashes in case of installation
rem path was passed to the batch file with wrong directory separator.
set "InstallPath=%InstallPath:/=\%"
rem Append a backslash on installation path
rem if not already ending with a backslash.
if not "%InstallPath:~-1%" == "\" set "InstallPath=%InstallPath%\"
:StartInstalls
echo %BatchName%: Installation folder: %InstallPath%
echo/
echo %BatchName%: Installing .NET 3.5 ...
DISM.exe /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:installationMediaDrive:\sources\sxs
echo/
echo %BatchName%: Installing Python 2.7 64-bit ...
%SystemRoot%\System32\msiexec.exe /i "%SourcePath%py\python-2.7.amd64.msi" TARGETDIR="%InstallPath%Python27" /passive /norestart ADDLOCAL=ALL
echo/
echo %BatchName%: Installing Apache 2.4 64-bit ...
mkdir "%InstallPath%Apache24"
%SystemRoot%\System32\xcopy.exe "%SourcePath%\Apache24" "%InstallPath%Apache24\" /C /E /H /I /K /Q /R /Y >nul
endlocal
...有关call /?
,%~dp0
和%~n0
的解释。%~1
dism /?
echo /?
endlocal /?
goto /?
if /?
msiexec /?
rem /?
set /?
setlocal /?
同时阅读
xcopy /?
和setlocal
的确如何运作和endlocal
。最后看看:
Windows服务器的管理员应该扭转在这里和参考页面上写下的所有东西。