Show message after script runs with row count - sql-server

I have the following PowerShell script that works fine. However, when it is run it flashes up and away very quickly.
How could I display a message if the $rowsAffected is greater/equal to 1 and a different message if $rowsAffected is 0 and have it stay on screen until enter is pressed or the window is closed?
#Create SQL Connection
$con = New-Object "System.Data.SqlClient.SQLConnection"
#Set Connection String
$con.ConnectionString = ("Data Source=.\SQL2017;Initial Catalog=DatabaseName;user id=test;password=test;")
$con.Open()
#run query
$sqlcmd = New-Object "System.Data.SqlClient.SqlCommand"
$sqlcmd.Connection = $con
$sqlcmd.CommandTimeout = 30
$sqlcmd.CommandText = "UPDATE Execution SET Execution = 1"
$rowsAffected = $sqlcmd.ExecuteNonQuery()
$con.Close()

This looks to do the trick.
If ($rowsAffected -ge 1)
{
"Your request for the file has been successfully submitted and will be processed in the next few minutes. "
pause
}
else
{
"ERROR! No file was found. Please contact support"
pause
}

Related

PowerShell System.Data.SqlClient.SqlConnection shows no error but also no result

This script runs without any problems for a SQL Server connection:
[string] $connectionString = "Server=$server;Database=$database;Integrated Security = False; User ID = $uid; Password = $pwd;"
$sqlConn = New-Object System.Data.SqlClient.SqlConnection
$sqlConn.ConnectionString = $connectionString
$sqlConn.Open()
Write-Host "The connection is $($sqlConn.State)"
$command = $sqlConn.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$sqlConn.Close();
Write-Host "The connection is $($sqlConn.State)"
$table = new-object “System.Data.DataTable”
$table.Load($result)
But only with that result
The connection is Open
The connection is Closed
I have tried many proper SQL queries which run in Management Studio without any problems. Any hint how to properly execute and maybe check the SQL connection?
The $result variable is a SqlDataReader. You need to leave the connection open when loading the data table from the reader:
$sqlConn.Open()
Write-Host "The connection is $($sqlConn.State)"
$command = $sqlConn.CreateCommand()
$command.CommandText = $query
$table = new-object “System.Data.DataTable”
$result = $command.ExecuteReader()
$table.Load($result)
$sqlConn.Close();
Write-Host "The connection is $($sqlConn.State)"
Consider simplifying using a SqlDataAdapter:
$dataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter($query, $connectionString)
$table = new-object “System.Data.DataTable”
$dataAdapter.Fill($table)

How to safely update database using powershell syntax?

I have a PowerShell script which runs safely up to the point of an update. I connect to the database and can read from it, however, I have trouble updating.
Here is a copy of the error message I receive:
"Exception calling "ExecuteNonQuery" with "0" argument(s): "There is already an open DataReader associated with this Command which must be closed first."
At C:\xxx\xxx\ToolsController.ps1:37 char:5
+ $InnerCommand.ExecuteNonQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException"
FYI: I posted this before and this is an update to the previous question.
Any help at all would be greatly appreciated.
I have tried attaching the variable at the end of the string i.e '..+$varibale'
also tried #" "# and I have gotten the same result.
$Global:Server = "server"
$Global:Database = "db"
$Global:u = "un"
$Global:p = "pw"
[string]$Query = "SELECT * FROM [dbo].[jobs] WHERE [Run] = 0"
try{
$ConnectionString = "server=$Server;Integrated Security=true;database=$Database;user id=$u;password=$p"
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
}
catch{
"Failed to connect SQL Server"
}
$Command = $Connection.CreateCommand()
$InnerCommand = $Connection.CreateCommand()
$Command.CommandText = $Query
$jobs = $Command.ExecuteReader()
while ($jobs.Read()){
switch($jobs["Script"]){
15
{
$traverse = $jobs["Frequency"] - 1
While ($traverse -ge 0) {
c:\xx\xx\batch $jobs["Date"]
$traverse--
}
"Updating Database...."
$Query2 = "UPDATE [dbo].jobs SET [Run] = 1 WHERE [ID] = $jobs['ID']" <------Error here.
$InnerCommand.CommandText = $Query2
$InnerCommand.ExecuteNonQuery()
"Updating Completed!"
}
}
}
$Connection.Close()
$Connection.Dispose()
Write-Host "Connection Closed"
Add MultipleActiveResultSets=True to the connection string. This will allow interleaving of UPDATE statements while reading from the data reader.

Powershell Script Taking Long Time when seems like it shouldnt?

So I have a script that is meant to send some pretty huge (700mb) txt files to an FTP of a service we use that automatically set's our prices across a fleet of domains.
I'm using a bitearray (as found here) to upload it to the site, and I have some very elementary built in error handling as well as some database tie-ins.
If we run these seperately, they move pretty fast. For whatever reason, after the completion of one block, the time until starting another block is CRAZY volatile. Sometimes it's 2 minutes, sometimes the script just sits around for a good 40 minutes before moving to the next block.
I'm sort of assuming the issue is I'm giving the thing more housekeeping than I should be? It's also worth noting that even stopping the script can sometimes take 15 minutes. (Like, If I just hit break on the script in the middle of it running, it can take a good 15-20 minutes to stop)
Also, for what it's worth, the script got MUCH worse in terms of runtime in the last few days. I have no idea what we could have changed to make it start taking so much longer but here we are.
Anyway, any insights would be appreciated.
Notes: I don't clear the content variable when I clear variables, should I?
Should I keep the rs open? I don't think I CAN because I'm connecting to the FTP with different usernames.
Here's the code (I actually have about 12 of the *.txt Blocks, but They're identicle so I've kept it down to three here):
#================================== SETUP BLOCK ==================================#
#get dat email ready
$strpasswd = Get-Content "PASSWORDFILE" | ConvertTo-SecureString
$mycreds = New-Object System.Management.Automation.PSCredential ("EXCHANGEUSER",$strpasswd)
$EmailTo = 'some#email','goes#here'
$EmailFrom = 'EXCHANGEUSER'
$EmailSubject = "CA Feed Issue Undefined Subject"
$emailbody = "Body Not Yet Defined"
$SmtpServer = 'MUHSERVER'
#Opens up database session so we can send queries
$strserver = "Server\MUHDB"
$strdatabase = "logs"
$strusername = "EXCHANGEUSER"
#createsdatabaseconnection
$sqlConnection = new-object System.Data.SqlClient.SqlConnection "server='$strserver';database='$strdatabase';Integrated Security=SSPI; User ID='$strusername'; password='$strpassword'"
$sqlConnection.Open()
#define the defaultquery
$strQuery =
"
INSERT INTO [logs].[dbo].[EventLog] (SourceID, Started, Completed, Result, Context, Machine)
values (50,1500,1500,'NOTEDEFINED','NOTDEFINED','Server\MUHCLIENTMACHINE-CAFeed')
"
#this is how I execute the command
#$sqlCommand = $sqlConnection.CreateCommand()
#$sqlCommand.CommandText = $strquery
#$sqlCommand.ExecuteReader()
#==================================Luna.txt ==================================#
##DEFINE THESE TO CREATE NEW FEEDS
$strFilename = "\\PATH\Luna.txt"
$ftp = [System.Net.FtpWebRequest]::Create("FTPLINK1")
$user = "USERNAME1"
$password = "PASSWORDREDACTED"
# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]$ftp
# build authentication and connection
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$ftp.Credentials = new-object System.Net.NetworkCredential($user,$password)
$ftp.UseBinary = $true
$ftp.UsePassive = $true
$ftp.timeout = -1
#start a timer and error handling
$starttime = (get-date).ToString()
$error.Clear()
# read in the file to upload as a byte array
$content = [System.IO.File]::ReadAllBytes("$strfilename")
$ftp.ContentLength = $content.Length
# get the request stream, and write the bytes into it
$rs = $ftp.GetRequestStream()
$rs.Write($content, 0, $content.Length)
$endtime = (get-date).ToString()
#error handle
if ($error)
{
#Assemble the Query
$sqlresult = "THERE IS AN ERROR, Check the error email for details"
$sqlcontext = ($strfilename + '|' + $content.length + ' bytes')
$strquery =
"INSERT INTO [logs].[dbo].[EventLog] (SourceID, Started, Completed, Result, Context, Machine)
values (50,'$starttime','$endtime','$sqlresult','$sqlcontext','Server\MUHCLIENTMACHINE-CAFEEDSCRIPT')"
#Create Command and Execute.
$sqlCommand = $sqlConnection.CreateCommand()
$sqlCommand.CommandText = $strQuery
$sqlCommand.ExecuteNonQuery()
#Send dem emails
$emailbody = "A file for the CA Feed failed on $strfilename at " + (get-date).ToString() + " with the error '$error[0]'"
$emailsubject = "CA Feed Failed File"
Send-MailMessage -SmtpServer $SmtpServer -to $EmailTo -from $EmailFrom -subject $EmailSubject -Body $emailbody
}
else
{
write-host ("$strfilename" + ' Ran Without Errors')
$sqlresult = "RAN WITHOUT ERRORS"
$sqlcontext = ($strfilename + '|' + $content.length + ' bytes')
$strquery =
"INSERT INTO [logs].[dbo].[EventLog] (SourceID, Started, Completed, Result, Context, Machine)
values (50,'$starttime','$endtime','$sqlresult','$sqlcontext','Server\MUHCLIENTMACHINE-CAFEEDSCRIPT')"
#Create a command object.
$sqlCommand = $sqlConnection.CreateCommand()
$sqlCommand.CommandText = $strQuery
$sqlCommand.ExecuteNonQuery()
}
# be sure to clean up after ourselves and get ready for next block
Clear-Variable -Name starttime,endtime,strfilename,sqlresult,sqlcontext,ftp
$rs.Close()
$rs.Dispose()
#==================================LDE.txt ==================================#
##DEFINE THESE TO CREATE NEW FEEDS
$strFilename = "\\PATH\LDE.txt"
$ftp = [System.Net.FtpWebRequest]::Create("FTPLINK2")
$user = "USERNAME2"
$password = "PASSWORDREDACTED"
# create the FtpWebRequest and configure it
$ftp = [System.Net.FtpWebRequest]$ftp
# build authentication and connection
$ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$ftp.Credentials = new-object System.Net.NetworkCredential($user,$password)
$ftp.UseBinary = $true
$ftp.UsePassive = $true
$ftp.timeout = -1
#start a timer and error handling
$starttime = (get-date).ToString()
$error.Clear()
# read in the file to upload as a byte array
$content = [System.IO.File]::ReadAllBytes("$strfilename")
$ftp.ContentLength = $content.Length
# get the request stream, and write the bytes into it
$rs = $ftp.GetRequestStream()
$rs.Write($content, 0, $content.Length)
$endtime = (get-date).ToString()
#error handle
if ($error)
{
#Assemble the Query
$sqlresult = "THERE IS AN ERROR, Check the error email for details"
$sqlcontext = ($strfilename + '|' + $content.length + ' bytes')
$strquery =
"INSERT INTO [logs].[dbo].[EventLog] (SourceID, Started, Completed, Result, Context, Machine)
values (50,'$starttime','$endtime','$sqlresult','$sqlcontext','Server\MUHCLIENTMACHINE-CAFEEDSCRIPT')"
#Create Command and Execute.
$sqlCommand = $sqlConnection.CreateCommand()
$sqlCommand.CommandText = $strQuery
$sqlCommand.ExecuteNonQuery()
#Send dem emails
$emailbody = "A file for the CA Feed failed on $strfilename at " + (get-date).ToString() + " with the error '$error[0]'"
$emailsubject = "CA Feed Failed File"
Send-MailMessage -SmtpServer $SmtpServer -to $EmailTo -from $EmailFrom -subject $EmailSubject -Body $emailbody
}
else
{
write-host ("$strfilename" + ' Ran Without Errors')
$sqlresult = "RAN WITHOUT ERRORS"
$sqlcontext = ($strfilename + '|' + $content.length + ' bytes')
$strquery =
"INSERT INTO [logs].[dbo].[EventLog] (SourceID, Started, Completed, Result, Context, Machine)
values (50,'$starttime','$endtime','$sqlresult','$sqlcontext','Server\MUHCLIENTMACHINE-CAFEEDSCRIPT')"
#Create a command object.
$sqlCommand = $sqlConnection.CreateCommand()
$sqlCommand.CommandText = $strQuery
$sqlCommand.ExecuteNonQuery()
}
# be sure to clean up after ourselves and get ready for next block
Clear-Variable -Name starttime,endtime,strfilename,sqlresult,sqlcontext,ftp
$rs.Close()
$rs.Dispose()
I don't think anybody is going to debug that code. Your best bet is to find where your issue is. I use a stopwatch like below. set it up strategically:
$SW = [System.Diagnostics.Stopwatch]::new()
$SW.Start()
#Your code block goes here
Write-Host "End of Code block 1"
$SW.Elapsed.TotalSeconds
#Another code block goes here
Write-Host "End of Code block 2"
$SW.Elapsed.TotalSeconds
Now if you are trying to break out and it is taking 15 mins to respond, it is probably stuck doing an operation. It cannot respond until the operation finishes or fails.

Run write-host output while SqlConnection.Open() is running

I would like to have a trailing ..... that expands/grows while I'm running SqlConnection.Open().
I can't figure out how to do this and the output stops when i run the command SqlConnection.Open() until the connection is made then my code proceeds.
I tried a while loop, but the while content does nothing until the actual connection is established or fails, which can take 10 -15 seconds.
$waiting = ".", ".", ".", ".", ".";
Try
{
#write-host -ForegroundColor GREEN "Connecting to SQL Server: $svr"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $svr ;Database = $db; User ID = $uid ;Password = $pwd;"
while (!$SqlConnection.State -eq 'Open')
{
write-host -ForegroundColor GREEN "Connecting to SQL Server: $svr" -NoNewline
ForEach ($p in $waiting) {
Write-Host -ForegroundColor Cyan "`r$p" -NoNewLine
Start-Sleep -Milliseconds 300
}
$SqlConnection.Open()
}
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $Global:SqlConnection
$SqlCmd.CommandText = $UsrSqlQuery
}
You have a single threaded script. Once you call the .Open method, nothing's going to happen until it returns. I think multithreading is the only way you're going to get what you want.
Here's an example of multithreading in PS:
multithreading

Powershell SQL server update query

I'm trying to connect to a Microsoft SQL Database and update any record that the changed field is = to 'x'. I'm able to query the database but when I attempt to do an update I get this error:
Fill : Exception calling "Fill" with "1" argument(s): "Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
This is the script I'm using:
#Create SQL Connection
$con = new-object "System.data.sqlclient.SQLconnection"
#Set Connection String
$con.ConnectionString =(“Data Source=server;Initial Catalog=IDCards;Integrated Security=SSPI”)
$con.open()
$sqlcmd = new-object "System.data.sqlclient.sqlcommand"
$sqlcmd.connection = $con
$sqlcmd.CommandTimeout = 600000
#$sqlcmd.CommandText = “select * from tblPhotoID where changed = 'X'”
$sqlcmd.CommandText = “UPDATE dbo.tblPhotoID SET Changed = '1' WHERE Changed ='X'”
$adapter = New-Object system.data.sqlclient.sqldataadapter ($sqlcmd.CommandText, $con)
$set = New-Object system.data.dataset
$adapter.Fill($set)
There are about 4000 records that would updated currently. The script runs about 30 secs before timing out. I've tried increasing the command timeout and gotten the same results.
Your update statement is not going to return a recordset so there is nothing to fill the dataset. You instead want to try the following:
#Create SQL Connection
$con = new-object "System.data.sqlclient.SQLconnection"
#Set Connection String
$con.ConnectionString =(“Data Source=sb-inft-orange.ads.iu.edu;Initial Catalog=IDCards;Integrated Security=SSPI”)
$con.open()
$sqlcmd = new-object "System.data.sqlclient.sqlcommand"
$sqlcmd.connection = $con
$sqlcmd.CommandTimeout = 600000
$sqlcmd.CommandText = “UPDATE dbo.tblPhotoID SET Changed = '1' WHERE Changed ='X'”
$rowsAffected = $sqlcmd.ExecuteNonQuery()
In your code, you have used $adapter.Fill($set) FYI, It is used to add rows in the DataSet to match those in the data source.Instead you can use $adapter.Update($Set) I think this will solve your problem. Also you can use $sqlcmd.ExecuteNonQuery()
#Create SQL Connection
$con = new-object "System.data.sqlclient.SQLconnection"
#Set Connection String
$con.ConnectionString =(“Data Source=sb-inft-orange.ads.iu.edu;Initial
Catalog=IDCards;Integrated Security=SSPI”)
$con.open()
$sqlcmd = new-object "System.data.sqlclient.sqlcommand"
$sqlcmd.connection = $con
$sqlcmd.CommandTimeout = 600000
$sqlcmd.CommandText = “UPDATE dbo.tblPhotoID SET Changed = '1' WHERE Changed ='X'”
$sqlcmd.ExecuteNonQuery()
$cn = New-Object System.Data.SqlClient.SqlConnection ( "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog.......)
$q = "select ... from .. "
$da = New-Object System.Data.SqlClient.SqlDataAdapter($q, $cn)
$da.SelectCommand.CommandTimeout = 60

Resources