c# - 如何在执行 powershell 脚本的 msdeploy post sync 命令中转义引号?

标签 c# powershell msdeploy cakebuild

我正在尝试设置一个 Cake 任务,该任务将使用 MsDeploy 将 powershell 脚本同步到远程服务器,然后将该脚本作为同步后命令执行。

我面临的问题是在 cake 文件中找到引号和转义符的组合,允许命令一直到 powershell 并正确引用文件路径以允许 powershell 找到脚本;路径中有空格。

这看起来非常困难,因为该命令在运行时要经过一系列的执行。 首先,因为这是用 C# 编写的,所以字符串要么需要逐字记录 (@"command here"),要么将所有内部双引号转义为 \。 .

接下来 Cake 对参数执行了几个操作,尽管在它实际执行之前似乎都没有影响引用和转义之类的操作,此时它使用 C# Process.Start()运行 MsDeploy 可执行文件的静态方法。在我的阅读中,有人建议这种运行命令的方法需要三个双引号才能正确转义,尽管这与我尝试时看到的不一致。

然后一旦在远程机器上 MsDeploy 使用 CMD.exe执行明显不支持单引号的命令,因此需要使用 \" 转义双引号或 "" .

我得到的最接近的是这样的:

Task("InitializeIISApplication")
    .IsDependentOn("InjectVariables") 
    .Does(() => {
        MsDeploy(new MsDeploySettings
        {
            Verb = Operation.Sync,
            RetryAttempts = 3,
            RetryInterval = 10000,
            Source = new FilePathProvider
            {
                Direction = Direction.source,
                Path = MakeAbsolute(File(@".\MyPowershell.ps1")).ToString()        
            },
            Destination = new FilePathProvider
            {
                Direction = Direction.dest,
                Path = File(deployParameters.ApplicationDestinationPath + @"\MyPowershell.ps1").ToString(),
                Username = deployParameters.MsDeployUserName,
                Password = deployParameters.MsDeployUserPassword,
                WebManagementService = deployParameters.DeploymentTargetUrl
            },
            AllowUntrusted = true,
            EnableRules = new List<string> {
                "DoNotDeleteRule"
            },
            PostSyncCommand = new CommandProvider {
                AppendQuotesToPath = false,
                Direction = Direction.dest,
                Path = $"powershell -file '{deployParameters.ApplicationDestinationPath}\\MyPowershell.ps1' ",
            }
        });

        MsDeploy(new MsDeploySettings
        {
            Verb = Operation.Delete,
            Destination = new FilePathProvider
            {
                Direction = Direction.dest,
                Path = File(deployParameters.ApplicationDestinationPath + "\MyPowershell.ps1").ToString(),
                Username = deployParameters.MsDeployUserName,
                Password = deployParameters.MsDeployUserPassword,
                WebManagementService = deployParameters.DeploymentTargetUrl
            },
            AllowUntrusted = true
        });
    });

任务依赖只是设置deployParameters对象。

在启用 Cake 的诊断详细信息的情况下,它会在日志中生成以下命令(为清楚起见添加了新行):

"C:/Program Files/IIS/Microsoft Web Deploy V3/msdeploy.exe"  
-verb:sync   
-source:filePath="Y:/PathToBuildArtifact/Deploy/MyPowershell.ps1"
-dest:filePath="C:/Application - With Spaces/MyPowershell.ps1",wmsvc="https://deploy-server/msdeploy.axd",userName=msdeployuser,password=********
-enableRule:DoNotDeleteRule
-retryAttempts:3
-retryInterval:10000
-allowUntrusted
-postSync:runCommand="powershell -file 'C:\Application - With Spaces\MyPowershell.ps1' "

然后以错误结束:

Warning: Processing -File ''C:/Application' failed: The given path's format is not supported. Specify a valid path for the -File parameter.

我尝试在 postSync 命令中使用双引号的任何变体都会导致此错误:

Error: Unrecognized argument '-'.

如果重要的话,这是在 Bamboo CI 服务器上完成的。

最佳答案

结果很可能是 -file 参数导致了一些奇怪的解析行为。 在命令提示符下调用 powershell -help 会显示以下片段:

Runs the specified script in the local scope ("dot-sourced"), so that the functions and variables that the script creates are available in the current session. Enter the script file path and any parameters. File must be the last parameter in the command, because all characters typed after the File parameter name are interpreted as the script file path followed by the script parameters.

这暗示那里有一些特殊的逻辑。

因此,我改为尝试使用调用运算符 (&) 执行文件,在几次不同的引用尝试之后,我最终得到了以下成功运行的后同步命令:

PostSyncCommand = new CommandProvider {
                Direction = Direction.dest,
                Path = $"powershell \"\"& \"\"\"\"{deployParameters.ApplicationDestinationPath}\\MyPowershell.ps1\"\"\"\" \"\"",
            }

请注意,powershell 之后的所有内容都包含在两个双引号中,第一个用作对 msdeploy 调用的转义,其中的字符串必须有四个引号,第一个和第三个引号用于转义第二个和第四个对 msdeploy 的调用和第二个然后转义第四个以最终调用 powershell。

关于c# - 如何在执行 powershell 脚本的 msdeploy post sync 命令中转义引号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56299189/

相关文章:

powershell - 您如何以编程方式获取所有常用参数的列表?

powershell - 在 Windows 文件共享上设置权限

c# - 使用 WebSocketCollection 对象广播消息期间的错误处理

powershell - 如何限制 Get-ChildItem 搜索的文件(或限制递归深度)?

c# - DISM.exe 返回代码?

visual-studio-lightswitch - 在电灯开关应用程序中扩展部署参数化

visual-studio - Visual Studio 发布 MSdeploy $(SolutionDir)

azure - 如何使用 MSDeploy 扩展将包部署到 Azure Web App? (HTTP header 之一的值格式不正确)

c# - 枚举 DLL 函数?

c# - 图像大小调整性能 : System. 绘图与 System.Windows.Media