在 PowerShell 5 中检索 SQL Server InfoMessages

Lea*_*hao 4 sql-server powershell

以下 PowerShell 函数在 PowerShell 2 上正常工作,但现在我正在 PowerShell 5 上对其进行测试,但无法使其工作。它旨在自动化备份恢复测试。但是由于 SQL Server 备份相关任务使用消息而不是返回记录集,因此我不得不添加一个add_InfoMessage带有处理程序的。

我想我可以做到,Invoke-Sqlcmd -Verbose但我更喜欢这种方法。

我还搜索了如何使用 SMO 进行操作,但一无所获

function Restore-Test {
    param (
        [string[]] $bkpPath,
        [string[]] $testServer
    )
    $message = "Inicio: " + (get-date);
    $message += "`nArchivo: " + $bkpPath;
    $message += "`nTestServer: " + $testServer;
    $connString = "Server=" + $testServer + ";Database=master;Integrated Security=SSPI;";
    $commandString = "print 'Message from MSSQL!';";
    #$commandString = "DBA_TOOLS.dbo.sp_RestoreTest N'" + $bkpPath + "'";
    $conn = New-Object System.Data.SqlClient.SqlConnection $connString;
    $conn.Open();
    $cmd = $conn.CreateCommand(); 
    $cmd.CommandText = $commandString ; 
    $handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) $message += "`n" + $event.Message };
    $conn.add_InfoMessage($handler); 
    $conn.FireInfoMessageEventOnUserErrors = $true;
    $cmd.CommandTimeout = 0;
    $cmdResult = $cmd.ExecuteNonQuery();
    $conn.Close();
    $message += "`nExecution result: " + $cmdResult + "`nFinalizacion: " + (get-date);

    return $message;
}
export-modulemember -function Restore-Test
Run Code Online (Sandbox Code Playgroud)

小智 5

您将无法以您尝试的方式捕获打印语句。处理程序旨在将语句输出到控制台,而不是实际捕获它。

这将导致消息写入控制台,但您永远(至少我的测试)无法将其附加到您的$message变量中。我不记得这像在 PowerShell 2.0 中那样工作,但我不再有该版本可供尝试。

$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) Write-Host $event.Message };
Run Code Online (Sandbox Code Playgroud)

现在为什么这已经改变了,我还没有找到。如果我这样做了,我会尽量记住来更新这篇文章。


Lea*_*hao 5

我终于意识到问题是变量范围。解决方法是将其定义为全局$global:message = ""并在具有相同引用的事件处理程序中使用它:

$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) $global:message += "`n" + $event.Message };
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我尝试过Invoke-Sqlcmd -Verbose,但它遇到了 SQL 错误的问题。

你可以这样做:

$message = ""
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
$serverInstance = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $testServer
$ps = [PowerShell]::Create() 
$com = $ps.AddCommand( "Invoke-Sqlcmd" )
$com.AddParameter( "ServerInstance", $serverInstance ) | Out-Null
$com.AddParameter( "Query", $commandString ) | Out-Null
$com.AddParameter( "QueryTimeout", 0 ) | Out-Null
$com.AddParameter( "OutputSqlErrors", $True ) | Out-Null
$com.AddParameter( "IncludeSqlUserErrors") | Out-Null
$com.AddParameter( "SeverityLevel", 0) | Out-Null
$com.AddParameter( "Verbose" )  | Out-Null
$sqlret += $ps.Invoke()  #| Out-Null
$ps.Streams.Verbose | % { $message += "`n" + $_.Message }
$ps.Streams.Error   | % { $message += "`n" + $_.Exception.Message }
Run Code Online (Sandbox Code Playgroud)