0

I have some powershell which is run by control-M. It run a SQL script and outputs the tables to an email.

What seems to be happening (Only when running through Control-M) is that every other run or so, the first table check is wrong.

When the script runs the first table will always say "Overall checks are" and then "RED", "AMBER", "GREEN" depending on other tables in the script. In SQL it looks like:

IF EXISTS (SELECT 1 FROM @JobTable WHERE NStatus = 'RED')
    OR EXISTS (SELECT 1 FROM @BillingJobTable WHERE NStatus = 'RED')
BEGIN
    select 'Overall checks are RED'
END
ELSE IF EXISTS (SELECT 1 FROM @JobTable WHERE NStatus = 'AMBER')
        OR EXISTS (SELECT 1 FROM @BillingJobTable WHERE NStatus = 'AMBER')
BEGIN
    select 'Overall checks are AMBER'
END
ELSE
BEGIN
    select 'Overall checks are GREEN'
END

If this table says "RED", the subject of the email should say "RED" too, but it's not.

To mention again, this doesn't happen when I run the .ps1 file manually.

Today:

Today

Yesterday and the day before:

Yesterday

Can someone please explain why this is happening and how I can avoid it going forwards?

Here's the .ps1 file, important bits hidden

# Define SQL file path
$sqlFilePath = ".\PCR001.BATCH.Data_Import_Checks.sql"

# Define email information
$smtpServer = ""
$from = ""
$to = ""
$subject = "Import Check"
$htmlBody = ""

# Define SQL connection information
$sqlServer = ""
$sqlDatabase = ""

# Read SQL file contents
$sqlQuery = Get-Content $sqlFilePath | Out-String

# Connect to SQL server and execute query
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection("Server=$sqlServer;Database=$sqlDatabase;Integrated Security=SSPI;")    
$sqlConnection.Open()
$sqlCommand = New-Object System.Data.SqlClient.SqlCommand($sqlQuery, $sqlConnection)
$sqlReader = $sqlCommand.ExecuteReader()

# Get the value of the first row of the first table
$overallChecks = $null
if ($sqlReader.Read()) {
    $overallChecks = $sqlReader.GetValue(0)
}

# Close the reader
$sqlReader.Close()

# Set the subject line based on the value of $overallChecks
if ($overallChecks -eq 'Overall checks are RED') {
    $subject += " - RED"
} elseif ($overallChecks -eq 'Overall checks are AMBER') {
    $subject += " - AMBER"
} else {
    $subject += " - GREEN"
}

# Reopen the reader and create HTML table for each result set
$sqlReader = $sqlCommand.ExecuteReader()
$tableNumber = 1
do {
    # Add a one-line space between tables
    if ($tableNumber -gt 1) {
        $htmlBody += "<br>"
    }

    # Create table header
    $htmlBody += "<table style='border-collapse: collapse;'>"
    $htmlBody += "<tr><th style='border: 1px solid black; font-weight: bold;'>"
    $htmlBody += $sqlReader.GetName(0)
    for ($i = 1; $i -lt $sqlReader.FieldCount; $i++) {
        $htmlBody += "</th><th style='border: 1px solid black; font-weight: bold;'>"
        $htmlBody += $sqlReader.GetName($i)
    }
    $htmlBody += "</th></tr>"

    # Create table rows
    while ($sqlReader.Read()) {
        $htmlBody += "<tr>"
        for ($i = 0; $i -lt $sqlReader.FieldCount; $i++) {
            $htmlBody += "<td style='border: 1px solid black;'>"
            if ($sqlReader.GetName($i) -eq "InputXml") {
                $xml = $sqlReader.GetValue($i)
                if ($xml -eq [System.DBNull]::Value) {
                    $htmlBody += "NULL"
                } else {
                    $htmlBody += [System.Security.SecurityElement]::Escape($xml.ToString())
                }
            } elseif ($sqlReader.GetFieldType($i) -eq [System.DateTime]) {
                $htmlBody += $sqlReader.GetDateTime($i).ToString('yyyy-MM-dd HH:mm:ss.fff')
            } else {
                $htmlBody += $sqlReader.GetValue($i)
            }
            $htmlBody += "</td>"
        }
        $htmlBody += "</tr>"
    }

    # Close table
    $htmlBody += "</table>"
    $tableNumber++
} while ($sqlReader.NextResult())

# Close SQL connection and dispose reader
$sqlConnection.Close()
$sqlReader.Dispose()

# Send email with HTML body
Send-MailMessage -SmtpServer $smtpServer -From $from -To $to -Subject $subject -BodyAsHtml $htmlBody
mklement0
  • 382,024
  • 64
  • 607
  • 775
Badja
  • 857
  • 1
  • 8
  • 33
  • 1
    There is an intrinsic error/race condition in your logic by calling `.ExecuteReader()` twice, and hence running the SQL script twice. There is no guarantee both calls have the same result set(s), so unless your script guarantees this in some way (which would be hard, as the database state would also have to not change) it is always at least theoretically possible to get the results you observe. Rewriting things so `.ExecuteReader()` is called only once doesn't guarantee your problems go away, but would at least make them easier to reason about. – Jeroen Mostert May 22 '23 at 12:36
  • @JeroenMostert Thanks for that. I'll work on it. Sadly I don't think it's fully related, as with some of the records in the table it's looking at something from midnight. So if it's RED one minute it'll be RED the next. Good insight though – Badja May 22 '23 at 13:40

0 Answers0