用%〜dp0引用的批处理文件路径有时在更改目录时更改的原因是什么? [英] What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory?

查看:130
本文介绍了用%〜dp0引用的批处理文件路径有时在更改目录时更改的原因是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含以下内容的批处理文件:

I have a batch file with following content:

echo %~dp0
CD Arvind
echo %~dp0

即使更改目录%~dp0后的值也相同. 但是,如果我从CSharp程序运行此批处理文件,则 CD 之后,%~dp0的值将更改.现在它指向新目录.以下是我使用的代码:

Even after changing directory value of %~dp0 is the same. However, if I run this batch file from CSharp program, the value of %~dp0 changes after CD. It now points to new directory. Following is the code that I use:

Directory.SetCurrentDirectory(//Dir where batch file resides);
ProcessStartInfo ProcessInfo;
Process process = new Process();
ProcessInfo = new ProcessStartInfo("mybatfile.bat");
ProcessInfo.UseShellExecute = false;
ProcessInfo.RedirectStandardOutput = true;
process = Process.Start(ProcessInfo);
process.WaitForExit();
ExitCode = process.ExitCode;
process.Close();

为什么通过不同方式执行相同脚本的输出会有差异?

Why is there a difference in output on executing same script by different ways?

我在这里想念什么吗?

推荐答案

这个问题开始了关于这一点的讨论,并进行了一些测试以确定原因.因此,在cmd.exe中进行了一些调试之后……(这是针对 32位Windows XP cmd.exe 的,但是由于该行为在较新的系统版本上是一致的,因此可能使用相同或相似的代码)

This question started the discussion on this point, and some testing was done to determine why. So, after some debugging inside cmd.exe ... (this is for a 32 bit Windows XP cmd.exe but as the behaviour is consistent on newer system versions, probably the same or similar code is used)

在Jeb的答案里面已经说明

Inside Jeb's answer is stated

It's a problem with the quotes and %~0.
cmd.exe handles %~0 in a special way

这里杰布是正确的.

在正在运行的批处理文件的当前上下文中,有一个对当前批处理文件的引用,变量"包含正在运行的批处理文件的完整路径和文件名.

Inside the current context of the running batch file there is a reference to the current batch file, a "variable" containing the full path and file name of the running batch file.

访问变量时,将从可用变量列表中检索其值,但是如果请求的变量为%0,并且已请求某个修饰符(使用了~),则正在运行的批处理引用中的数据使用变量".

When a variable is accessed, its value is retrieved from a list of available variables but if the variable requested is %0, and some modifier has been requested (~ is used) then the data in the running batch reference "variable" is used.

但是~的使用在变量中还有另一个影响.如果用引号将该值引起来,则引号将被删除.代码中有一个错误.它的编码类似于(这里简化为伪代码的汇编程序)

But the usage of ~ has another effect in the variables. If the value is quoted, quotes are removed. And here there is a bug in the code. It is coded something like (here simplified assembler to pseudocode)

value = varList[varName]
if (value && value[0] == quote ){
    value = unquote(value)
} else if (varName == '0') {
    value = batchFullName
}

是的,这意味着在引用批处理文件时,将执行if的第一部分,并且不使用对该批处理文件的完整引用,而是检索到的值是用于引用该批处理的字符串文件时调用它.

And yes, this means that when the batch file is quoted, the first part of the if is executed and the full reference to the batch file is not used, instead the value retrieved is the string used to reference the batch file when calling it.

那会发生什么?如果在调用批处理文件时使用了完整路径,则不会有问题.但是,如果在调用中未使用完整路径,则需要检索批处理调用中不存在的路径中的任何元素.此检索假定相对路径.

What happens then? If when the batch file was called the full path was used, then there will be no problem. But if the full path is not used in the call, any element in the path not present in the batch call needs to be retrieved. This retrieval assumes relative paths.

一个简单的批处理文件(test.cmd)

A simple batch file (test.cmd)

@echo off
echo %~f0

使用test调用时(无扩展名,无引号),我们获得c:\somewhere\test.cmd

When called using test (no extension, no quotes), we obtain c:\somewhere\test.cmd

使用"test"调用时(不带引号),我们获得c:\somewhere\test

When called using "test" (no extension, quotes), we obtain c:\somewhere\test

在第一种情况下,不带引号的情况下,将使用正确的内部值.在第二种情况下,当引用被引用时,用于调用批处理文件("test")的字符串将被取消引用并使用.当我们请求完整路径时,它被认为是对称为test的东西的相对引用.

In the first case, without quotes, the correct internal value is used. In the second case, as the call is quoted, the string used to call the batch file ("test") is unquoted and used. As we are requesting a full path, it is considered a relative reference to something called test.

这就是原因.怎么解决?

This is the why. How to solve?

通过C#代码

  • 请勿使用引号:cmd /c batchfile.cmd

如果需要使用引号,请在批处理文件的调用中使用完整路径.这样,%0包含所有必需的信息.

If quotes are needed, use the full path in the call to the batch file. That way %0 contains all the needed information.

从批处理文件

可以从任何地方以任何方式调用批处理文件.检索当前批处理文件信息的唯一可靠方法是使用子例程.如果使用了任何修饰符(~),则%0将使用内部的变量"来获取数据.

Batch file can be invoked in any way from any place. The only reliable way to retrieve the information of the current batch file is to use a subroutine. If any modifier (~) is used, the %0 will use the internal "variable" to obtain the data.

@echo off
    setlocal enableextensions disabledelayedexpansion

    call :getCurrentBatch batch
    echo %batch%

    exit /b

:getCurrentBatch variableName
    set "%~1=%~f0"
    goto :eof

这将回显以控制当前批处理文件的完整路径,而不管您如何调用文件(带引号或不带引号).

This will echo to console the full path to the current batch file independtly of how you call the file, with or without quotes.

注释:为什么有效?为什么子例程中的%~f0引用返回不同的值?从子例程内部访问的数据不同.当执行call时,将在内存中创建一个新的批处理文件上下文,并使用内部变量"来初始化此上下文.

note: Why does it work? Why the %~f0 reference inside a subroutine return a different value? The data accessed from inside the subroutine is not the same. When the call is executed, a new batch file context is created in memory, and the internal "variable" is used to initialize this context.

这篇关于用%〜dp0引用的批处理文件路径有时在更改目录时更改的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆