0

我有一系列由 TFS 代理运行的 PowerShell 脚本是构建过程的一部分。它们在多个服务器(Windows Server 2012 R2)上运行,这些服务器将一系列 DACPAC 发布到给定的数据库集。最近我将所有 TFS 构建代理更新到最新版本(TFS 2018

今天我注意到我的构建过程中的这些服务器之一不再运行,特别是由于“System.StackOverflowException”错误(非常适合这个站点),它无法运行“SqlPackage.exe”。

通过手动运行 power shell 脚本可以重现同样的问题,但仅在这台服务器上,所有其他服务器都可以正常运行。脚本如下所示:

$arguments = '/a:Publish /pr:"' + $scriptPath + $database + ".publish.xml" + '" /sf:"' + $dacPac + '" /tcs:"Data Source=' + $servername + ';Persist Security Info=True;User ID=' + $username + ';Password=' + $password + ';Pooling=False;MultipleActiveResultSets=False;Connect Timeout=60;Encrypt=False;TrustServerCertificate=True"'

Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\130\SqlPackage.exe" -ArgumentList $arguments -NoNewWindow -PassThru -Wait

手动运行时,调试的异常是:

Microsoft.SqlServer.TransactSql.ScriptDom.dll 中出现“System.StackOverflowException”类型的未处理异常

我真的不确定这台服务器上的什么配置会导致这种问题。资源方面,服务器非常强大,有大量可用内存,其他服务器运行得很好。我尝试了各种版本的“SqlPackage”(13, 14),但似乎没有任何效果。我已经换掉了 DacPac,但这似乎也不起作用......

有没有人见过这个问题?什么样的服务器配置会导致此类问题?

更新 1:嗯,只需切换到新的“14.0”、“SqlPackage.exe”,现在我在所有机器上都安装了它,我想知道它是否与任何真实的 dll 有关,例如我在SSDT中安装的那些。

实际上现在我想到这个,我认为这个问题是在我第一次安装 VS 2017 时在服务器上开始的,我想知道这是否对“SqlPackage.exe”有影响?

我还发现了这个有趣的帖子,我想知道我是否可以通过这种方式解决它...

4

1 回答 1

0

我从来没有想出如何为“SqlPackage”解决这个问题,我们最终创建了自己的包部署控制台应用程序并通过控制台应用程序(“DacpacDeployUtility”)调用它:

static int Main(string[] args)
{
    try
    {
        string destinationServer = args[0];
        string destinationDatabase = args[1];
        string userID = args[2];
        string password = args[3];
        string publishFileFullPath = args[4];
        string dacpacFileFullPath = args[5];

        SetupRegistryQueryExecutionTimeout();
        PublishDacpacSimple(destinationServer, destinationDatabase, userID, password, publishFileFullPath, dacpacFileFullPath);

        return 0; //where 0 = success
    }
    catch (Exception ex)
    {
        Console.WriteLine("Error in Main: " + ex.Message + "\n" + ex.StackTrace);

        for (int i = 0; i < args.Length; i++)
        {
            Console.WriteLine("Value in args[" + i + "]: " + (i == 3 ? "**********" : args[i]));
        }

        Console.WriteLine("Failed to publish dacpac.");

        //Return error state
        return 1;
    }
}

private static void SetupRegistryQueryExecutionTimeout()
{
    //Fixes an annoying issue with slow sql servers: https://stackoverflow.com/a/26108419/2912011
    RegistryKey myKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\12.0\\SQLDB\\Database", true);
    if (myKey != null)
    {
        myKey.SetValue("QueryTimeoutSeconds", "0", RegistryValueKind.DWord);
        myKey.Close();
    }

    myKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\14.0\\SQLDB\\Database", true);
    if (myKey != null)
    {
        myKey.SetValue("QueryTimeoutSeconds", "0", RegistryValueKind.DWord);
        myKey.Close();
    }

    myKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\15.0\\SQLDB\\Database", true);
    if (myKey != null)
    {
        myKey.SetValue("QueryTimeoutSeconds", "0", RegistryValueKind.DWord);
        myKey.Close();
    }
}

private static void PublishDacpacSimple(string destinationServer, 
    string destinationDatabase, 
    string userID, 
    string password, 
    string publishFileFullPath, 
    string dacpacFileFullPath)
{
    string connectionString = BuildConnectionString(destinationServer, destinationDatabase, userID, password);

    XmlDocument xdoc = new XmlDocument();

    xdoc.Load(publishFileFullPath);

    DacServices ds = new DacServices(connectionString);
    using (DacPackage package = DacPackage.Load(dacpacFileFullPath))
    {
        var options = new DacDeployOptions();                
        
        options.CommandTimeout = 600;              

        ds.Message += (object sender, DacMessageEventArgs eventArgs) => Console.WriteLine(eventArgs.Message.Message);

        ds.Deploy(package, destinationDatabase, true, options);
    }
}

然后在 PowerShell 脚本中调用它:

$DacPacDeployerPath = """" + $scriptPath + "..\..\..\DacpacDeployUtility\bin\release\EBMDacpacDeployUtility.exe"""

$Output = Start-Process -FilePath $DacPacDeployerPath -ArgumentList $arguments -NoNewWindow -PassThru -Wait
于 2019-03-21T15:24:24.727 回答