Печать сообщений из SQL в сценарии powershell службы автоматизации Azure не работает

Я создал образец Runbook Powershell службы автоматизации Azure. Я пытаюсь выполнить команду SQL, а затем распечатать сообщения из этой команды в вывод рабочей книги.

Мой код взят из Захват вывода InfoMessage из SQL Server с помощью 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, но не сообщения от SQL.

Register-ObjectEvent из этот ответ тоже не работает:

Register-ObjectEvent : Cannot register for the specified event. 
An event with the name 'InfoMessage' does not exist. Parameter name: eventName

Что я делаю неправильно?


person Mikhail Shilkov    schedule 29.01.2018    source источник
comment
Мне кажется, эта команда предназначена для выполнения команд в sqlserver $cmd.CommandText   -  person TheGameiswar    schedule 29.01.2018
comment
вы должны использовать Write-Outputчто-то вроде этого Write-Output "Output inside of function"   -  person TheGameiswar    schedule 29.01.2018
comment
Да, я пытаюсь выполнять команды в SQL Server и использую Write-Output в приведенном выше коде.   -  person Mikhail Shilkov    schedule 29.01.2018
comment
Вы говорите, что but not messages from SQL я не вижу причин, по которым они должны быть напечатаны на панели вывода.   -  person TheGameiswar    schedule 29.01.2018
comment
Если вам нужны сообщения от sql, одним из способов было бы назначить вывод cmd.execute без запроса или использовать сохраненный процесс с некоторым выходным параметром и назначить его выходному объекту   -  person TheGameiswar    schedule 29.01.2018
comment
Ссылки, на которые я ссылаюсь, говорят, как SqlInfoMessageEventHandler используется для обработки информационных событий, и я вызываю Write-Output из обработчика. Дана хранимая процедура, и у нее нет выходных параметров, она просто делает PRINT вызовов. Выход ExecuteNonQuery равен -1   -  person Mikhail Shilkov    schedule 29.01.2018


Ответы (2)


Кажется, в службе автоматизации Azure есть проблема с вызовом Write-Output или Write-Host внутри обработчика. Установка сообщения в глобальную переменную в обработчике, а затем вызов Write-Output после ExecuteNonQuery сработали для моих целей.

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
}
person Andy Funk    schedule 02.02.2018
comment
Фантастический. Я рвал на себе волосы с помощью Azure, пока наконец не нашел этот ответ. - person Uber Schnoz; 15.06.2018
comment
Кто-нибудь знает, почему Write-Output не работает? Было бы здорово получить эти результаты в реальном времени. - person LucasM; 17.06.2018

Вот код, который я использую для получения операторов печати:

$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()
}
person gvee    schedule 29.01.2018
comment
Вы запускаете его из службы автоматизации Azure? Где вы видите текст, напечатанный Write-Host? Ваш код ничего не печатает в моей книге автоматизации Runbook (ни с Write-Output) - person Mikhail Shilkov; 29.01.2018
comment
@Mikhail в своем коде вы (в настоящее время) назначаете вывод ExecuteNonQuery переменной; поэтому Write-Host/Output, скорее всего, будет поглощен этим. - person gvee; 29.01.2018
comment
Просто изменил его, чтобы ничего не назначать. Он печатает -1 два раза, больше ничего. Изменил свой образец соответственно. - person Mikhail Shilkov; 29.01.2018