【问题标题】:sqlpackage.exe publish fails with no errorsqlpackage.exe 发布失败,没有错误
【发布时间】:2021-08-30 02:46:24
【问题描述】:

我有以下powershell 脚本,它从jenkinswindows server 2019 从属运行:

$sqlpackagepublish = Start-Process -FilePath sqlpackage.exe -ArgumentList '/Action:Publish','/SourceFile:"Database Services\bin\Release\Database Services.dacpac"',"/TargetConnectionString:""Data Source=${Env};Integrated Security=True;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=False;Initial catalog=${Target}""","/p:BlockOnPossibleDataLoss=${Data_loss}" -wait -PassThru -Credential $Cred -RedirectStandardOutput sqlstdout.txt -RedirectStandardError sqlstderr.txt
$sqlpackagepublish.WaitForExit()
$sqlpackagepublish

if ($sqlpackagepublish.ExitCode -eq 0) {
     Get-Content sqlstdout.txt
 }
else {
     echo "An error occurred"
     Get-Content sqlstderr.txt
     exit $sqlpackagepublish.ExitCode
}

但部署失败,sqlstderr.txt 中没有错误,jenkins 日志中也没有任何信息。知道如何调试它吗?

更新

根据以下建议的答案,我尝试了两种方法:

1.

删除-PassThru 参数并读取文件内容。 所以我改变了我的代码如下:

$sqlpackagepublish = Start-Process -FilePath sqlpackage.exe -ArgumentList '/Action:Publish','/SourceFile:"Database Services\bin\Release\Database Services.dacpac"',"/TargetConnectionString:""Data Source=${Env};Integrated Security=True;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=False;Initial catalog=${Target}""","/p:BlockOnPossibleDataLoss=${Data_loss}" -wait -Credential $Cred
$sqlpackagepublish.WaitForExit()
$sqlpackagepublish

但现在我明白了:

You cannot call a method on a null-valued expression.
+ $sqlpackagepublish.WaitForExit()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

强大的 .NET'y 方式

在我最初的问题中,我有以下几行:

$Username = $args[0]
$Password = $args[1]
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
$sqlpackagepublish = Start-Process -FilePath sqlpackage.exe -ArgumentList {args} -wait -PassThru -Credential $Cred

我不明白如何将其添加到您的代码中

【问题讨论】:

    标签: sql-server powershell jenkins windows-server-2019 sqlpackage


    【解决方案1】:

    这就是Start-Process 命令的基本创建方式。 -PassThru 开关将输出重定向到一个对象(在这种情况下为$sqlpackagepublish)。 更多关于Start-Process的信息在这里:https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-5.1

    解决方案很少。

    1. 删除-PassThru 参数并像现在一样读取文件的内容
    2. 更努力,但更强大的 .NET 方式:
    function Start-ProcessExecution
    {
        param (
            [string] $exe,
            [string] $arguments,
            [string] $user,
            [string] $password
        )
        $startInfo = New-Object System.Diagnostics.ProcessStartInfo;
    
        $pass = ConvertTo-SecureString -AsPlainText $password -Force
        $startInfo.UserName = "$user";
        $startInfo.Password = "$pass";
    
        $startInfo.FileName = $exe;
        $startInfo.Arguments = $arguments;
        $startInfo.UseShellExecute = $false;
        $startInfo.RedirectStandardOutput = $true;
        $startInfo.RedirectStandardError = $true;
    
        $process = New-Object System.Diagnostics.Process;
        $process.StartInfo = $startInfo;
    
        $process.Start() | Out-Null;
    
        $output = $process.StandardOutput.ReadToEnd();
        $err = $process.StandardError.ReadToEnd();
    
        $process.WaitForExit();
    
        $obj = [PSCustomObject]@{
            ExitCode = $process.ExitCode
            StdOut = $output
            StdErr = $err
        }
        return $obj;
    }
    
    $exe = "sqlpackage.exe"
    $arguments = [string]::Join(" ", "/Action:Publish", `
        '/SourceFile:"Database Services\bin\Release\Database Services.dacpac"', `
        '/TargetConnectionString:"Data Source=${Env};Integrated Security=True;Persist Security Info=False;Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=False;Initial catalog=${Target}"', `
        '/p:BlockOnPossibleDataLoss=${Data_loss}')
    
    $result = (Start-ProcessExecution -exe $exe -arguments $arguments -user $args[0] -password $args[1])
    $ec = $result.ExitCode;
    
    if ($ec -eq 0) {
        Write-Host "STDOUT:`n$($result.StdOut)";
    }
    else {
        Write-Host "STDERR:`n$($result.StdErr)";
    }
    

    Wrapper 基本上是为了提高可读性,其构造是为了防止在调用 WaitForExit() 后读取大量输出时出现死锁。

    【讨论】:

    • 它看起来更好,但是带有$arguments 的东西不起作用:*** Argument 'BlockOnPossibleDataLoss' has an invalid value: '${Data_loss}'. 并且在我删除它之后,下一个错误是Unable to connect to target server '${Env}'。无论如何,现在我把它写成硬编码并得到了真正的错误,所以我正在努力修复它:)
    • 已编辑答案 :) 它现在应该提供变量。
    • Tnx。还有一件事,我还必须像我原来的问题一样使用-Credential $Cred。你也可以用它来编辑你的答案吗?
    • 再次编辑 :) 您还可以更改函数以允许将凭据传递给它
    • 好的,让我们专注于你的第一个建议 :) 我删除了它,但现在我收到了这个错误:You cannot call a method on a null-valued expression. + $sqlpackagepublish.WaitForExit()
    猜你喜欢
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 2013-08-10
    • 2020-06-28
    • 2017-10-29
    • 2014-03-09
    相关资源
    最近更新 更多