我正在尝试设置一个 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' "

然后以错误结束:



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



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

最佳答案

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



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

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

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/

10-13 08:58
查看更多