在Windows批处理文件中编写脚本时,有时脚本的正确执行需要使用setlocal命令。我对使用setlocal的主要提示是,我经常为&if语句执行复杂的操作,其中我在代码的该部分中设置了变量值。当我发出命令endlocal时,这些设置会丢失。

到目前为止,我已经通过将变量值回显到setlocal段内的暂存文件中,然后在endlocal之后将值读回到变量中来解决此问题。但是,似乎应该有一个更优雅的解决方案。

如果仅使用一个或多个set语句,建议的答案将提供一种解决问题的简便方法。但是,当放置了setlocal时,链接的答案未提供解决方案,以允许for循环在执行时(而不是进行分析时)正确扩展变量名。在我的情况下,我还有if语句逻辑树,可以对该信息执行进一步的检查,以便set许多不同的可能变量值。链接的解决方案不提供这种情况的解决方案。

该代码应该检查安装软件包的版本号。它是从另一个需要该版本号才能正常运行的脚本中调用的。我们知道该软件包是使用[application] [version number] .msi形式命名的。 [版本号]可以是以下任意一个:

  • 7
  • 7.5
  • 9
  • 9.5
  • 10
  • 10.1

  • 指定目录中可能存在多个安装包,因此仔细检查所有安装包并选择目录中的最高版本很重要。

    我继承并扩展了代码以正确处理10和10.1版本。如果没有setlocal的话还有更好的方法(例如,我考虑过重写以使用case语句),我很乐意看到更好的解决方案。

    但是,我仍然对学习如何将变量传递到setlocal/endlocal段中感兴趣。
    setlocal enabledelayedexpansion
    
    for /f %%a in ('dir /b program*.MSI') do (
        set FileName=%%a
        set tst1=!FileName:~4,3!
        if "!tst1!" == "msi" (
            rem Only true if it has a 1 digit number (e.g. "9")
            set MAIN_VERSION=!FileName:~2,1!
        ) else (
            set tst2=!FileName:~5,3!
            if "!tst2!" == "msi" (
                rem Only true if it has a 2 digit version number (e.g. "10")
                set MAIN_VERSION=!FileName:~2,2!
            ) else (
                ... lots more code ...
            )
        )
    )
    rem Write results out to a file for temporary storage.  This particular
    rem form of echo is required to ensure there are no trailing spaces, CR,
    rem or LF
    echo|set /P ="!MAIN_VERSION!" > %USERPROFILE%\UGV.txt
    
    rem End local variables
    endlocal
    
    rem Read the correct version out of our temporary storage file
    set /p MAIN_VERSION=<%USERPROFILE%\UGV.txt
    

    如何在不使用暂存文件的情况下从Windows批处理脚本MAIN_VERSION/setlocal代码段中传递变量(例如上面的endlocal)?

    最佳答案

    为了在setlocal/endlocal范围内保留变量,存在不同的解决方案。

    这取决于您应该使用哪种情况。

    1)简单

    只能在带简单内容的括号块之外使用,但是可以使用特殊字符!^"产生问题。

    setlocal
    set localVar=something simple
    ...
    (
      endlocal
      set "out=%localVar%"
    )
    set out
    

    2)中

    也可以在块中工作,并且可以处理最多的字符,但是由于!^和换行符/回车符而失败
    if 1==1 (
      setlocal EnableDelayedExpansion
      set "localVar=something medium nasty & "^&"
    
      for /F "delims=" %%V in ("!localVar!") DO (
          endlocal
          set "out=%%V"
      )
    )
    set out
    

    3)高级

    在任何情况下都适用于所有内容
    SO: preserving exclamation marks in variable between setlocals batch

    10-04 12:11