批处理文件:“环境变量未定义”

5

我正在处理一个调用外部批处理文件并传递一系列命令的Java程序。批处理文件中有一个循环,如下所示:

set paramCount=0
for %%x in (%*) do (
    set /A paramCount+=1
    set list[!paramCount!]=%%x
)

参数是一堆存储为字符串的目录,格式如下:
String[] commands = {"cmd.exe",
                     "/C",
                     "C:\Users\user\Documents", 
                     "C:\Users\user\Pictures", 
                     "C:\Users\user\Videos"}

如您所见,我的for循环应该循环遍历传递给批处理文件(% *)的参数列表,并在脚本内模拟数组(因为命令数组中的前两个元素用于启动命令进程,只留下要循环遍历的目录)。这个程序之前一直运行良好,直到几天前,我突然开始收到以下错误:

Environment variable list[ not defined

我完全没有更改批处理文件,但是它似乎毫无原因地停止了工作。如果需要的话,以下是必要信息:我正在使用流程生成器来运行该过程:

ProcessBuilder pb = new ProcessBuilder(commands);
Process p = pb.start();

据说在批处理文件中使用这种数组语法是可以的,所以我不确定为什么它不能接受。如果您能提供任何帮助,我将不胜感激。在处理这个程序时,我遇到了很多障碍,虽然我已经能够解决其中90%的问题,但剩下的10%开始让我发疯了!谢谢!
编辑:我重新编写了循环,并添加了一些回显命令以使调试更容易。但是,当我运行批处理文件时,虽然没有输出回显,但我仍然会收到相同的错误提示。
@echo off
setlocal enableDelayedExpansion
set paramCount=0
for %%x in (%*) do (
    echo !paramCount!
    echo %%x
    set list[!paramCount!]=%%x
    set /A paramCount=paramCount+1
)

我忘记提到的是,当我在Eclipse中运行Java时,程序可以正常工作;它正确调用了批处理文件,一切正常。直到我将项目导出为可运行的JAR文件并尝试运行该文件时,错误才会出现。
编辑2: 再次查看我的批处理文件代码后(我写了一段时间),我发现只有一行看起来可能会导致这个问题。奇怪的是,我使用了一个几乎相同的代码示例来模拟它,长时间以来它一直没有出现错误。它是一个循环,旨在循环遍历第一个循环创建的“数组”列表的元素:
for /F "tokens=2 delims==" %%d in ('set list[') do (
    set /A paramCount+=1
    set _dir=%%d
    set _dir=!_dir:"=!
    if NOT "%%d"=="nul" set "dirs[!paramCount!]=!_dir!"
)

正如你所看到的,第一行有一个段落写着set list[,这对我来说看起来很奇怪。然而,就像我之前提到的那样,它在相当长的一段时间内都能正常运行。


这个答案可能会有所帮助:https://dev59.com/62kw5IYBdhLWcg3wDWTL#10167990 - user180100
感谢您提供链接。不幸的是,我不太确定它能帮助我解决这个特定问题。我正在使用延迟展开以确保 !!s 起作用。我确保 %...% 和 !...! 被正确使用,并且顺序正确。问题似乎与 paramCount 有关,因为它似乎只读取变量的 list[ 部分而不是整个变量("list[<number>]")。不太确定是什么原因导致这种情况。 - DerStrom8
此时真正让我困惑的是为什么它突然停止接受。我根本没有做任何更改。我在原帖中也忘了提到一些事情,就是当我从Eclipse运行时,它可以正常工作。只有当我将项目导出为可运行的JAR文件时,才会出现错误。 - DerStrom8
@mihai_mandis - set /a parmCount+=1 完全没有问题。它不可能是问题的源头,我认为这是增加值的首选方式,但这主要是风格问题。 - dbenham
@derstrom8 - 或许传递的参数存在某些异常,最终导致了错误。假设参数值是动态的。 - dbenham
显示剩余4条评论
3个回答

1
你发布的代码无法产生该错误消息。你的脚本中必须有其他代码导致了该错误。
只有没有等号的SET语句才可能导致该错误。在解析和展开后,有问题的语句必须类似于以下之一:
set list[
set "list[
set "list["

实际上,如果引号错位,即使存在=也会出现错误。例如,以下代码会出现错误,因为最后一个"之后的所有文本都被忽略:
set "list["1]=value

"

1]=value出现在最后一个"之后并被忽略,只剩下set "list["

您可以考虑启用ECHO,以便精确定位错误消息发生的位置。然后,您需要弄清楚在该点可能导致错误的条件。

"

回应问题中的“编辑2”更新

在新发布的代码中,IN()语句几乎可以确定是生成错误消息的地方。它表明,在执行FOR / F循环时,列表“array”未定义。问题是为什么?需要查找以下内容:

  • 是否有任何东西阻止了早期定义列表“array”的FOR循环运行?

  • 您确定参数已正确传递到脚本中吗?如果没有参数,则不会有数组。

  • 是否有任何东西在第二个FOR循环有机会执行之前取消定义数组?

我建议您加入一些诊断ECHO语句以帮助调试。例如,在定义数组的循环之前立即添加ECHO 1ST LOOP之前以确保正在到达循环。或者在脚本开头添加ECHO ARGS =%*以确保参数已正确传递。祝您好运! :-)


奇怪的是,删除@echo off语句并没有帮助。控制台窗口中除了错误消息之外什么也没有显示。至于您提出的其他建议,我已经非常仔细地检查了我的代码,但我没有发现任何不合适的地方。然而,我确实看到一个语句看起来不对劲,但我使用了与另一个来源相同的语法,而且它已经运行了很长时间。这是另一个for循环,它循环遍历在我已经发布的循环中创建的列表"array"。我将在第二次编辑中将其添加到原始帖子中。 - DerStrom8
这是我用来参考编写循环的线程链接:https://dev59.com/GWMl5IYBdhLWcg3wXWAT#18480952 - DerStrom8
根据您的更新,我在程序的开头放置了一个echo(echo测试),但错误立即出现,而从未将“testing”打印到控制台。我已经检查了Java代码,以确保传递给进程构建器的所有命令都是正确的。我还尝试了echo %*,但没有运气。错误会立即出现。如果那样能够工作,我肯定已经缩小范围了,因为我尝试在代码的各个区域放置了echo调试语句。然而,它们中没有一个被打印出来,这就是我在这里发布问题的原因。 - DerStrom8
好的,请原谅我的愚蠢。我完全忘记了我从旧的批处理文件中制作了一个exe,并且那就是我一直在运行的-这个exe。所以每次我编辑bat文件时,exe都保持不变。我将进行更多的“侦探工作”,但这次会使用批处理文件进行测试=P - DerStrom8

0

我尝试了下面的代码,当从命令行调用时,它对我有效。

@echo off
setlocal enabledelayedexpansion

set paramCount=0

for %%x in (%*) do (
    set /A paramCount=!paramCount!+1
    set list[!paramCount!]=%%x
)
echo !list[1]!
echo !list[2]!
echo !list[3]!

很不幸,我仍然遇到问题。我已经重新排列了循环中的一些代码,并添加了一些“echo”命令来查看发生了什么。我已经在原始帖子中编辑了代码。 - DerStrom8

0

我在评论中提到过,但我想发一篇答案,为了任何其他人的疑问:

如先前所述,该程序在Eclipse中运行良好,批处理文件被调用并按预期运行。然而,在对批处理文件进行一些更改之前,我已从中创建了.exe文件,并且显然正在运行.exe文件而不是.bat文件。这是我犯下的一个非常愚蠢的错误,问题是由批处理文件先前版本中的一些错误引起的。如果我记得正确,那个错误是因为“数组元素”为空。所以我最终做了一个检查,以确保在对其进行操作之前它不是空的。以下是我目前正在使用的代码,它按预期工作:

@echo off
setlocal ENABLEDELAYEDEXPANSION
set /A paramCount=-3
for %%x in (%*) do (
    set list[!paramCount!]=%%x
    set /A paramCount=paramCount+1
)
set argA=%list[-3]%
set argB=%list[-2]%
set argC=%list[-1]%
for /F "tokens=2 delims==" %%a in ('set list[-') do SET "%%a="
set list[-3]=""
set list[-2]=""
set list[-1]=""
set paramCount=0
for /F "tokens=2 delims==" %%d in ('set list[') do (
    if not "%%d"=="" (
        set _dir=%%d
        set _dir=!_dir:"=!
        if NOT "%%d"=="nul" set "dirs[!paramCount!]=!_dir!" 
    ) 
    set /A paramCount+=1 )

感谢大家的回答!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接