在 Azure Automation powershell 脚本中打印来自 SQL 的消息不起作用
Printing messages from SQL in Azure Automation powershell script doesn't work
我创建了一个示例 Azure Automation Powershell Runbook。我正在尝试执行 SQL 命令,然后将来自该命令的消息打印到工作簿输出中。
我的代码取自 Capturing InfoMessage Output from SQL Server using PowerShell,如果我在本地 运行 它就可以工作:
Write-Output "Starting"
$conn = New-Object System.Data.SqlClient.SqlConnection "Data Source=abc.database.windows.net,1433;Initial Catalog=def;Integrated Security=False;User ID=ghj;Password=qwe"
## Attach the InfoMessage Event Handler to the connection to write out the messages
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) Write-Output $event.Message };
$conn.add_InfoMessage($handler);
$conn.FireInfoMessageEventOnUserErrors = $true;
$conn.Open();
$cmd = $conn.CreateCommand();
$cmd.CommandText = "PRINT 'This is the message from the PRINT statement'";
$cmd.ExecuteNonQuery();
$cmd.CommandText = "RAISERROR('This is the message from the RAISERROR statement', 10, 1)";
$cmd.ExecuteNonQuery();
$conn.Close();
Write-Output "Done"
在我 运行 工作簿之后,我看到 Starting
、-1
(来自 ExecuteNotQuery
结果)和 Done
,但没有来自 [=30 的消息=].
Register-ObjectEvent
来自 this answer 也不起作用:
Register-ObjectEvent : Cannot register for the specified event.
An event with the name 'InfoMessage' does not exist. Parameter name: eventName
我做错了什么?
这是我用来获取打印语句的代码:
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = "Server=..."
try {
$connection.Open()
$command = $connection.CreateCommand()
$command.CommandText = "PRINT 'Hello World!';"
Register-ObjectEvent -InputObject $connection -EventName InfoMessage -Action { Write-Host "$($event.SourceEventArgs)" } -SupportEvent
$command.ExecuteNonQuery() | Out-Null
}
catch {
throw $_.Exception.ToString()
}
finally {
$connection.Dispose()
}
在 Azure 自动化中似乎存在在处理程序内部调用 Write-Output
或 Write-Host
的范围问题。将消息设置为处理程序中的全局变量,然后在 ExecuteNonQuery
达到我的目的后调用 Write-Output
。
Write-Output "Starting"
$conn = New-Object System.Data.SqlClient.SqlConnection "Data Source=abc.database.windows.net,1433;Initial Catalog=def;Integrated Security=False;User ID=ghj;Password=qwe"
## Attach the InfoMessage Event Handler to the connection to write out the messages
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) $global:message = $event.Message};
$conn.add_InfoMessage($handler);
$conn.FireInfoMessageEventOnUserErrors = $true;
$conn.Open();
$cmd = $conn.CreateCommand();
$cmd.CommandText = "PRINT 'This is the message from the PRINT statement'";
$cmd.ExecuteNonQuery() | Out-Null;
Write-Output $global:message
$cmd.CommandText = "RAISERROR('This is the message from the RAISERROR statement', 10, 1)";
$cmd.ExecuteNonQuery() | Out-Null;
Write-Output $global:message
$conn.Close();
Write-Output "Done"
如果您需要多条消息,您可以将它们连接到变量。
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) $global:message += $event.Message + "`n"};
但是,无论哪种情况,它们都不会在抛出时引发,而是在查询完成后引发。
编辑:我找到了一个我更喜欢的解决方案并想分享它。在处理程序中使用对象列表...
$events = new-object System.Collections.Generic.List[Object]
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] { param($sender, $event) $events.Add($event) }
...并在 ExecuteNonQuery
循环后写入所有消息
ForEach($event in $events)
{
Write-Output $event.Message
}
我创建了一个示例 Azure Automation Powershell Runbook。我正在尝试执行 SQL 命令,然后将来自该命令的消息打印到工作簿输出中。
我的代码取自 Capturing InfoMessage Output from SQL Server using PowerShell,如果我在本地 运行 它就可以工作:
Write-Output "Starting"
$conn = New-Object System.Data.SqlClient.SqlConnection "Data Source=abc.database.windows.net,1433;Initial Catalog=def;Integrated Security=False;User ID=ghj;Password=qwe"
## Attach the InfoMessage Event Handler to the connection to write out the messages
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) Write-Output $event.Message };
$conn.add_InfoMessage($handler);
$conn.FireInfoMessageEventOnUserErrors = $true;
$conn.Open();
$cmd = $conn.CreateCommand();
$cmd.CommandText = "PRINT 'This is the message from the PRINT statement'";
$cmd.ExecuteNonQuery();
$cmd.CommandText = "RAISERROR('This is the message from the RAISERROR statement', 10, 1)";
$cmd.ExecuteNonQuery();
$conn.Close();
Write-Output "Done"
在我 运行 工作簿之后,我看到 Starting
、-1
(来自 ExecuteNotQuery
结果)和 Done
,但没有来自 [=30 的消息=].
Register-ObjectEvent
来自 this answer 也不起作用:
Register-ObjectEvent : Cannot register for the specified event.
An event with the name 'InfoMessage' does not exist. Parameter name: eventName
我做错了什么?
这是我用来获取打印语句的代码:
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = "Server=..."
try {
$connection.Open()
$command = $connection.CreateCommand()
$command.CommandText = "PRINT 'Hello World!';"
Register-ObjectEvent -InputObject $connection -EventName InfoMessage -Action { Write-Host "$($event.SourceEventArgs)" } -SupportEvent
$command.ExecuteNonQuery() | Out-Null
}
catch {
throw $_.Exception.ToString()
}
finally {
$connection.Dispose()
}
在 Azure 自动化中似乎存在在处理程序内部调用 Write-Output
或 Write-Host
的范围问题。将消息设置为处理程序中的全局变量,然后在 ExecuteNonQuery
达到我的目的后调用 Write-Output
。
Write-Output "Starting"
$conn = New-Object System.Data.SqlClient.SqlConnection "Data Source=abc.database.windows.net,1433;Initial Catalog=def;Integrated Security=False;User ID=ghj;Password=qwe"
## Attach the InfoMessage Event Handler to the connection to write out the messages
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) $global:message = $event.Message};
$conn.add_InfoMessage($handler);
$conn.FireInfoMessageEventOnUserErrors = $true;
$conn.Open();
$cmd = $conn.CreateCommand();
$cmd.CommandText = "PRINT 'This is the message from the PRINT statement'";
$cmd.ExecuteNonQuery() | Out-Null;
Write-Output $global:message
$cmd.CommandText = "RAISERROR('This is the message from the RAISERROR statement', 10, 1)";
$cmd.ExecuteNonQuery() | Out-Null;
Write-Output $global:message
$conn.Close();
Write-Output "Done"
如果您需要多条消息,您可以将它们连接到变量。
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] {param($sender, $event) $global:message += $event.Message + "`n"};
但是,无论哪种情况,它们都不会在抛出时引发,而是在查询完成后引发。
编辑:我找到了一个我更喜欢的解决方案并想分享它。在处理程序中使用对象列表...
$events = new-object System.Collections.Generic.List[Object]
$handler = [System.Data.SqlClient.SqlInfoMessageEventHandler] { param($sender, $event) $events.Add($event) }
...并在 ExecuteNonQuery
循环后写入所有消息
ForEach($event in $events)
{
Write-Output $event.Message
}