如何将参数转义为在 VS 构建后事件中运行的 PS 脚本的空格



Update 1:

再次仔细查看输出后,我有点想通了。 通过在右括号和引号之间添加尾随空格,它可以工作:

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersion.ps1" "$(ProjectDir) " "$(TargetDir) "

我怀疑PowerShell以某种方式解释了)"

有没有更优雅的方法来解决这个问题?

更新 2

这很奇怪。我有另一个脚本可以进行清理,并在)"之间分配空间,如下所示:

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersionCleanup.ps1" "$(ProjectDir)"

但是,添加尾随空格会导致它失败,因为它在内部将文件名附加到路径,因此路径将不正确。

如果有人理解这一点,我很乐意接受解释作为正确答案!


源语言:

我在 VisualStudio 中有以下预构建命令,我想用它来从 Git 标签注入版本:

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersion.ps1" $(ProjectDir) $(TargetDir)

如果路径 $(SolutionDir( 不包含空格(然后也会出现在 $(ProjectDir( 或 $(TargetDir(中(,则此方法工作正常。

当路径 $(SolutionDir( 确实包含空格时,脚本似乎按预期启动,但参数未正确传递,我无法弄清楚如何在 PS 脚本的参数中转义它们。

我尝试添加 sing"、三重""和 ',它给出以下内容(每个 PS 命令尝试不同的方法来转义空格(:

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersion.ps1" $(ProjectDir) $(TargetDir)

参数[0]:

D:\VisualStudio

参数[1]:

项目\software_git_repo\程序编辑器\

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersion.ps1" "$(ProjectDir)" "$(TargetDir)"

BS: 参数[0]:

D:\VisualStudio Projects\software_git_repo\ProgramEditor" D:\VisualStudio

BS: args[1]:

项目\software_git_repo\程序编辑器\bin\调试">

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersion.ps1" """$(ProjectDir)""" """$(TargetDir)"""

BS: 参数[0]:

"D:\VisualStudio

BS: args[1]:

项目\software_git_repo\程序编辑器">

powershell -ExecutionPolicy ByPass -File "$(SolutionDir)BuildScriptsInjectGitVersion.ps1" '$(ProjectDir)' '$(TargetDir)'  

BS: 参数[0]:

'D:\VisualStudio

BS: args[1]:

项目\software_git_repo\程序编辑器\'

行为:

echo ProjectDir:
echo $(ProjectDir)
echo TargetDir:
echo $(TargetDir)

我得到:

项目目录:

D:\VisualStudio Projects\software_git_repo\ProgramEditor\

目标目录:

D:\VisualStudio Projects\software_git_repo\ProgramEditor\bin\Debug\

当 VS 目录宏在引号参数中展开时,请注意意外的转义引号。


包含路径的脚本参数应用引号括起来,以避免在路径包含空格时被解释为多个参数。因此,在Visual Studio的预构建/构建后事件命令行中,以下内容似乎是合理的:

powershell.exe -file "$(SolutionDir)script.ps1" -projectDirectory "$(ProjectDir)"

但是指定目录的宏值总是包含一个尾随的反斜杠;所以当它们展开时,行变成,例如:-

powershell.exe -file "C:sln pathscript.ps1" -projectDirectory "C:sln pathproject"

。其中尾随 \" 是转义字符,被解释为参数值的一部分,该值以 -

C:\sln 路径\项目">

溶液

在我的情况下,修复是在要转义的目录宏之后插入一个额外的反斜杠而不是引号,这会恢复预期的参数值并防止任何后续参数的混乱:-

powershell.exe -file "$(SolutionDir)script.ps1" -projectDirectory "$(ProjectDir)"

虽然不是很直观。如果我错过了更明显的东西,请告诉我......

我注意到的一件事是 $(SolutionDir( 之后有一个额外的反斜杠。 我正在使用VS2017,我认为$(SolutionDir(一直有一个反斜杠。 不过不知道。

我的解决方案文件夹中有一个创建 json 配置文件的.bat。 我的后期生成事件如下所示。

call "$(SolutionDir)CreateConfigurationJson.bat" "$(TargetDir)mySettings.json"
{"ProjectName":"$(ProjectName)"}

"$(TargetDir)mySettings.json"是.bat文件的第一个参数

{"ProjectName":"$(ProjectName)"}是第二个参数。

无需转义字符。 希望这有帮助。

蝙蝠文件的代码是:

echo off
set filePath=%1
break>%filePath%
set json=%2
echo %json% >>%filePath%

感谢您@tranquil_tarn的出色回答! 我挣扎着与BATCH +Powershell逃离地狱好几个小时。 在这里发布最终代码,希望能帮助某人。

溶液

@ECHO OFF
cls
echo .SYNOPSIS
echo    Allows prebuild to be Powershell, instead of BATCH. (You'll thank me later)
echo    Specifically this example shows passing in VisualStudio (ProjectDir) variable AND correctly handles spaces in the path.
echo .DESCRIPTION
echo    Call prebuild.ps1 and pass in built-in VS Variables: https://learn.microsoft.com/en-us/visualstudio/ide/reference/pre-build-event-post-build-event-command-line-dialog-box?view=vs-2022
echo    Use powershell best-practices named parameters rather than positional to avoid positional-unmatched errors.
echo    If Username '$(User)' is blank DO NOT include the Switch at all to avoid powershell errors

REM TASK1: Check a variable for blank/empty and only include the Param if not empty
SET "user=$(User)"
IF [%user%]==[] (
echo "userParam is blank"
) ELSE (
SET "userParam=-User:%user%"
)
echo "userParam: %userParam%" 
REM TASK2: Warning: (ProjectDir) in VisualStudio ends in a slash, which when expanded, results in escaped quote ' at end of line
REM if you DO NOT include the quotes, then spaces in path will break it.  if you DO include quotes then it gets escaped.
REM solution is to include an extra slash at the end, resulting in double backslash \ which escapes down to single backslash ''... whew! 
REM 'see https://stackoverflow.com/questions/52205117/how-to-escape-spaces-the-parameters-to-a-ps-script-running-in-vs-post-build-even/64146880#64146880'
cd "$(ProjectDir)"
SET cmd1=powershell -NoProfile -ExecutionPolicy Unrestricted -Command ^
".prebuild.ps1 -ProjectDir:'$(ProjectDir)' -Conf:'$(Configuration)' -ProjectName:'$(ProjectName)' %userParam% "
REM For debugging, view the command (including escaped strings) before calling it.
echo %cmd1%
call %cmd1%

最新更新