Batch file 为什么';以管理员身份运行';更改(有时)批处理文件';谁的当前目录?
我有一个批处理文件,它与我要Batch file 为什么';以管理员身份运行';更改(有时)批处理文件';谁的当前目录?,batch-file,process,windows-7,working-directory,Batch File,Process,Windows 7,Working Directory,我有一个批处理文件,它与我要xcopy的文件位于同一目录中。但由于某些原因,找不到该文件 我认为当前目录总是批处理文件所在的位置 我以管理员身份运行批处理文件。这发生在Windows 7 64位桌面计算机上 批处理文件: @ECHO OFF XCOPY /y "File1.txt" "File2.txt" PAUSE 错误: File not found - File1.txt 0 File(s) copied 错误消息是非常自解释的。找不到文件file1.txt 由于文件名不包含绝对路径,
xcopy
的文件位于同一目录中。但由于某些原因,找不到该文件
我认为当前目录总是批处理文件所在的位置
我以管理员身份运行批处理文件。这发生在Windows 7 64位桌面计算机上
批处理文件:
@ECHO OFF
XCOPY /y "File1.txt" "File2.txt"
PAUSE
错误:
File not found - File1.txt
0 File(s) copied
错误消息是非常自解释的。找不到文件
file1.txt
由于文件名不包含绝对路径,系统将尝试在当前目录中查找它。您当前的目录不包含此文件
您的误解是当前目录不是包含bat文件的目录。这是两个不相关的概念
通过在bat文件中添加这两个命令,可以轻松地进行检查
echo BAT directory is %~dp0
echo Current directory is %CD%
您可以注意到它们是不同的,最后一个反斜杠的附加方式与否存在细微的差异
因此,有两种方法来解决这个问题
pushd %~dp0
XCOPY /y "File1.txt" "File2.txt"
popd
XCOPY /y "%~dp0File1.txt" "%~dp0File2.txt"
%SystemRoot%\System32\cmd.exe /C "%1" %*
使用上下文菜单项启动批处理文件时,哪个目录是当前工作目录取决于当前用户的用户帐户控制(UAC)设置 这可以通过以下小批量文件
C:\Temp\Test.bat
来演示:
@echo Current directory is: %CD%
@pause
已在用户帐户控制设置中选择 默认-仅当程序试图更改我的计算机时通知我
- 当我更改Windows设置时不通知我
HKEY_CLASSES_ROOT\batfile\shell\runasuser\command
此注册表项不包含用于执行批处理文件的默认字符串。取而代之的是带有CLSID的字符串值DelegateExecute
{ea72d00e-4960-42fa-ba92-7792a7944c1d}
结果是打开一个对话框窗口,标题为“用户帐户控制”,文本为:
是否允许以下程序对此计算机进行更改
程序名称:Windows命令处理器已验证的发布者:Microsoft Windows 用户确认后,Windows会临时打开一个新的用户会话,就像在命令行上使用时一样 在这个新的用户会话中,当前的工作目录是
%SystemRoot%\System32
,此时使用默认的注册表项字符串执行Windows注册表中定义的命令
HKEY_CLASSES_ROOT\batfile\shell\runas\command
HKEY_CLASSES_ROOT\batfile\shell\runas\command
即:
%SystemRoot%\System32\cmd.exe /C "%1" %*
因此,将打开一个控制台窗口,标题为C:\Windows\System32\cmd.exe,其中有两行:
Current directory is: C:\Windows\System32
Press any key to continue . . .
点击任意键后,批处理执行完成,从而关闭cmd.exe
,从而关闭用户会话
但已在用户帐户控制设置中选择 不要在任何时候通知我
- 程序尝试安装软件或对我的计算机进行更改
- 我更改Windows设置
XCOPY /y "%~dp0File1.txt" "%~dp0File2.txt"
%SystemRoot%\System32\cmd.exe /C "%1" %*
根据密钥的默认字符串
HKEY_CLASSES_ROOT\batfile\shell\runas\command
HKEY_CLASSES_ROOT\batfile\shell\runas\command
在当前用户会话中
结果是打开一个控制台窗口,其标题也是C:\Windows\System32\cmd.exe,但窗口中显示的是:
Current directory is: C:\Temp
Press any key to continue . . .
父进程(Windows资源管理器作为桌面)的当前工作目录用于执行批处理文件,因为在这种情况下不需要切换到其他用户会话
在他的回答中已经发布了两种可能的解决方案,我在这里复制了这两种解决方案,并做了一些小的改进(
pushd
,目录用双引号括起来),并添加了第三种解决方案
pushd "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
popd
cd /D "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
这也适用于UNC路径。在命令提示窗口中运行pushd/?
,以了解为什么这也适用于UNC路径%SystemRoot%\System32\xcopy.exe "%~dp0File1.txt" "%~dp0File2.txt" /Y
pushd "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
popd
cd /D "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
这不适用于UNC路径,因为默认情况下,命令解释器cmd不支持将UNC路径作为当前目录,有关详细信息,请参见示例为了完整性和模糊性,我添加了另一个解决方案,确认在Windows 8.1下工作,并希望在其他地方工作,因为它依赖于文档化的功能: 您可以更改
runas
命令定义键HKEY\u CLASSES\u ROOT\batfile\shell\runas\command
和HKEY\u CLASSES\u ROOT\cmdfile\shell\runas\command
into
%SystemRoot%\System32\cmd.exe /S /C "(for %%G in (%1) do cd /D "%%~dpG") & "%1"" %*
当使用runas
动词(分别为“以管理员身份运行”菜单项)启动时,将导致bat
或cmd
文件在其包含目录中启动
添加到原始命令的操作:
去掉cmd/S
/C
枚举其单个条目,对于%%G in(%1)do
参数, 使其可作为循环体中的%1
进行扩展;这封信是随意的,但有些可能是“保留的”%%G
扩展到%%~dpG
的d河和p路径,~平铺去除引号(如果存在),这就是为什么我们显式地将它们添加回去%%G
更改D驱动器和目录tcd/D