看起来批处理文件应该支持可选指定的安装目录路径作为第一个参数。用于检查此可选文件夹路径是否存在的代码非常混乱。肯定有更简单的方法来检查可选参数,如下所示。
主要问题是重新定义环境变量PATH,这导致Windows 的标准控制台应用程序存储在目录%SystemRoot\System32 中,并且命令解释器cmd.exe 在执行批处理文件时不再找到其他标准Windows 目录。
一般来说,如果这个完整的文件规范字符串包含空格字符或这些字符之一&()[]{}^=;!'+,`~,则需要使用双引号括起来的完整路径、文件名和文件扩展名来指定要执行的应用程序@如在关于在命令提示符窗口中运行的最后一个输出帮助页面上的最后一段 cmd /?。
但主要是为了使人类用户更容易从命令提示符窗口中手动执行应用程序和脚本,如果指定没有路径且没有文件扩展名,Windows 命令解释器也可以找到要自行运行的应用程序或脚本。
因此,如果用户仅输入 xcopy 或批处理文件仅包含 xcopy,Windows 命令解释器将搜索匹配模式 xcopy.* 的文件,该文件扩展名在分号分隔的环境变量列表中定义PATHEXT 在当前目录中的第一个,如果在分号分隔的环境变量 PATH 列表中的所有目录中都没有找到合适的文件。
有3个环境变量PATH:
-
系统 PATH 存储在以下 Windows 注册表中:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
system PATH 中的文件夹路径默认用于独立于所用帐户的所有进程。
-
用户 PATH 存储在以下 Windows 注册表中:
HKEY_LOCAL_MACHINE\Environment
user PATH 中的文件夹路径默认仅用于使用设置了 user PATH 的帐户运行的所有进程。
local PATH 只是在当前正在运行的进程的活动环境中保存在内存中。
system 和 user PATH 由 Windows 连接到单个 local PATH 用于进程。
每当一个进程启动一个新进程(如 Windows Explorer)启动 Windows 命令解释器以执行批处理文件时,Windows 都会为新进程创建当前运行进程的环境表的副本 .因此,无论进程在其自己的环境变量本地副本上发生什么变化,都不会影响所有其他已经运行的进程。对环境变量的局部更改只对自己的进程和由该进程修改其变量所启动的所有进程有效。
在启动批处理文件时,变量PATH 和PATHEXT 的值与在启动批处理文件时使用的相同用户帐户下打开的命令提示符窗口中运行时显示的值相同,命令set PATH 列出所有开始的变量PATH 名称不区分大小写。
现在让我们看一下批处理文件的第二行:
set path=C:\ rem default path
这一行重新定义了 local PATH 环境变量。因此环境变量PATH对执行批处理文件的命令进程有效,并且由该批处理文件启动的所有应用程序不再包含C:\Windows\System32;C:\Windows;...,而是现在只包含这个非常奇怪的单个文件夹路径。
C:\ rem default path
rem 是cmd.exe 的内部命令,必须单独写一行。在 C++ 或 JavaScript 中的 // 等批处理代码中没有行注释。有关此命令的帮助,请在命令提示符窗口中运行 rem /?。
在没有安装文件夹路径作为第一个参数的情况下运行批处理文件时,结果是 Windows 命令解释器仅在当前目录中搜索 dism.*、msiexec.* 和 xcopy.*,因为肯定没有名称为 @ 的目录987654365@ 在驱动器的根目录 C: 开头有很多空格/制表符。
结论:不宜使用path作为安装文件夹路径的变量名。
批处理代码中的另一个错误是使用%1% 指定批处理文件的第一个参数。这是错误的,因为批处理文件的参数使用%1、%2、... 在命令提示符窗口中运行call /? 以获取有关引用批处理文件参数的帮助以及存在哪些可能性,例如%~dp0下面用于获取参数 0 的驱动器和路径,即批处理文件名,即包含当前正在运行的批处理文件的文件夹的路径。
我建议使用这个批处理代码:
@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 /?
也请阅读
最后看看:
Windows 服务器的管理员应该将此处和引用页面上的所有内容都用小指扭转。