SQL Agent - PowerShell step “syntax error” - sql-server

I have a PowerShell block that runs fine in the PowerShell window but when I put the same exact code into SQL Server Agent job step and try to execute it it failed with the following message.
Date 27.6.2015 1:00:00
Log Job History (JobName)
Step ID 1
Server ServerName
Job Name JobName
Step Name Step1
Duration 00:00:00
Sql Severity 0
Sql Message ID 0
Operator Emailed
Operator Net sent
Operator Paged
Retries Attempted 0
Message
Unable to start execution of step 1 (reason: line(46): Syntax error).
The step failed.
Below is the offending code
$text = $table | Where-Object {$_.Pending_Messages -gt $threshold} | Out-String
$html = "<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd""><html xmlns=""http://www.w3.org/1999/xhtml""><head>$style</head><body>$name <br />$warning<br /><br /><table><tr><td>Pending_Messages</td><td>Transaction Profile ID</td><td>Description</td><td>name</td><td>Last Activity</td><td>Address</td><td>Minimum Sent Time</td><td>Awake</td></tr>"
foreach ($Row in $table.Rows) {
if ($($Row[0]) -gt $threshold) { # <--- This is line 46
$ToSend = 1
write-host "value is : $($Row[0])"
$html += "<tr><td>" + $row[0] + "</td><td>" + $row[1] + "</td><td>" + $row[2] + "</td><td>" + $row[3] + "</td><td>" + $row[4] + "</td><td>" + $row[5] + "</td><td>" + $row[6] + "</td><td>" + $row[7] + "</td></tr>"
#break
}
}
What went wrong?

You haven't said what version of SQL Server or Windows OS you're running, but the Agent runs its own version of powershell that's distinct from whatever you may have installed.
On SQL Server 2012, sqlps utility launches PowerShell 2.0
On SQL Server 2008/2008R2, sqlps utility launches PowerShell 1.0
So, you may be using a syntax feature that's only available in a later version of powershell than what your Agent is running, which is why you get the Syntax error message.

Related

Trouble executing SQLPS or PowerShell from T-SQL script using xp_cmdshell

I had originally created a set of scripts to extract the results from a system of dynamic queries to CSV using SQLCMD. However, due to large text fields in the datasets containing a large amount of formatting codes, the CSV files became unwieldly. I then switched to using SQLPS or PowerShell, which did a great job of formatting the output files. Unfortunately, I am unable to get my extract CSV files to save when running the T-SQL file manually from SSMS. I can paste the same output code into SQLPS and it works fine using PowerShell.exe or SQLPS.exe.
I checked file permissions on the extract folder, tried different options for SQLPS and PowerShell, and reviewed the execution in Process Monitor, but I cannot figure out why this will not work.
SET #Cmd = 'sqlps
$FromDate = "' + #FromDate + '";
$ToDate = "' + #ToDate + '";
$IncidentTypeName = "' + #IncidentTypeName + '";
$DateField = "' + #DateField + '";
$QueryType = "' + #QueryType + '";
$PersonTypeID = "' + #PersonTypeID + '";
$var = "FromDate=$FromDate", "ToDate=$ToDate", "IncidentTypeName=$IncidentTypeName", "DateField=$DateField", "QueryType=$QueryType", "PersonTypeID=$PersonTypeID";
invoke-sqlcmd -ServerInstance ' +#Server+ ' -Database ' +#Database+ ' -Username '+#Login+' -Password '+#Password + ' -QueryTimeout 0 ' +
' -InputFile "'+#SqlScriptFolder+#InputFileType+'" -Variable $var | export-csv -Delimiter "," -NoTypeInformation -Path "'+#ExtractFolder+#OutputFile+'.csv"'
print #Cmd
EXEC master..xp_cmdshell #Cmd
My requirements are to extract a standard CSV file, and unfortunately I am trying to leverage the large amount of T-SQL code I put together earlier in the project when working with SQLCMD. It will also need to be an automated process, which is why I was trying to leverage PowerShell or SQLPS. I am using SQL Server 2019 on a dev machine running Windows 10.
Any ideas on this one?
Well, after much research into my crazy process, which I should definitely rewrite to be a PowerShell script (and not use xp_cmdshell), I found the solution, which is to
escape the " (double-quotes) with a \ (backslash)
replace the carriage returns and newlines using SET #Cmd = REPLACE(REPLACE(#Cmd, NCHAR(13), N''), NCHAR(10), N' ');
from invoke-sqlcmd-doesnt-work-when-used-with-xp-cmdshell

SQL Server PowerShell error Get-ChildItem

I try to get backup from SQL databases with this PowerShell code:
Set-Location "SQLSERVER:\SQL\computer\distance\Databases"
foreach ($database in (Get-ChildItem)) {
$dbName = $database.Name
Backup-SqlDatabase -Database $dbName -BackupFile "E:\bu\$dbName"
}
In a virtual server it works.
When I go to SQLSERVER:\SQL\computer\distance\Databases location and take ls
it show my databases and sucessfully takes backups.
But in another server in my workplace it gives this error:
Get-ChildItem : SQL Server PowerShell provider error: Failed to read child items.
[Failed to connect to server computer\instance. --> Login failed for user
'work\sql'.]
At line:1 char:23
+ ForEach($database in (Get-ChildItem))
+ ~~~~~~~~~~~~~
+ CategoryInfo : ReadError: (SQLSERVER:\SQL\...\instance\Databases:SqlPath) [Get-ChildItem], GenericProviderException
+ FullyQualifiedErrorId : CannotReadChildItems,Microsoft.PowerShell.Commands.GetChildItemCommand
and when in SQLSERVER:\SQL\computer\distance\Databases directory I do ls it gives this error:
ls : SQL Server PowerShell provider error: Failed to read child items. [Failed to
connect to server computer\instance. --> Login failed for user 'work\sql'.]
At line:1 char:1
+ ls
+ ~~
+ CategoryInfo : ReadError: (SQLSERVER:\SQL\...\instance\Databases:SqlPath) [Get-ChildItem], GenericProviderException
+ FullyQualifiedErrorId : CannotReadChildItems,Microsoft.PowerShell.Commands.GetChildItemCommand
computer\instance: I changed for this example.

How can I get version Information for multiple computers? -Powershell

I am trying to write a script to determine whether or not a server is running MSSQLSERVER or MSSQL$* (some instance of SQL Server) by going through a text file of server names separated by a new line. The code works for the first server and outputs the correct version and engine edition, but for all of the other servers it will only tell me whether or not they running SQL Server, and not output the version and engine edition. What am I doing wrong?
Thanks in advance for any and all help!
Clear-Host
$Name1 = "MSSQLSERVER"
$Name2 = "MSSQL$*"
$computers = Get-Content "E:\computers.txt"
$saveAs = 'E:\SQL_Report.txt'
foreach ($computer in $computers) {
try{
$Service1 = Invoke-Command -ComputerName $computer {Get-Service MSSQLSERVER}
$Service2 = Invoke-Command -ComputerName $computer {Get-Service MSSQL$*}
if($Service1 -Match $Name1 -Or $Service2 -Match $Name2){
"$computer Running MSSQL"
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null
$srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" "$computer"
$srv.Version
$srv.EngineEdition
}
else{
"$computer Not running MSSQL"
}
}
catch{
"$computer, Not Accessable, $_"
continue
}
}
Here is an example of current output:
Database_name1 Running SQL Server
Major Minor Build Revision
10 50 6220 -1
EnterpriseOrDeveloper
Database_name2 Not running SQL Server
Cannot find any service with service name 'MSSQLSERVER'.
+ CategoryInfo : ObjectNotFound: (MSSQLSERVER:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
Database_name3 Running SQL Server
Cannot find any service with service name 'MSSQLSERVER'.
+ CategoryInfo : ObjectNotFound: (MSSQLSERVER:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand

Error "You cannot call a method on a null-valued expression." while taking backup of SQL Files

I want to take backup of a few user databases on SQL Server 2008 R2.
I am running the following script on Powershell v2.0.
#load SQL snap-in
Add-pssnapin SqlServerCmdletSnapin100
Add-pssnapin SqlServerProviderSnapin100
#pull the current date
$date = Get-Date -Format yyyyddMM
#set location of backup files
$directory = "F:\sql\backup"
#Grab the database names
$dbname = dir 'SQLSERVER:\SQL\MyServer\DEFAULT\Databases\MyDataBase' | Select Name
#Backup each user database found.
$dbname | foreach { $_.Name.ToString() } | foreach {$bakfile = "$directory" + $_ + "_" + $date + ".bak";
"Backing up Database: $_"; Invoke-Sqlcmd -SuppressProviderContextWarning -Query
"BACKUP DATABASE $_ TO DISK=N'$bakfile' WITH INIT";
}
But this script shows me the following error in succession:
You cannot call a method on a null-valued expression.
At F:\sql\backup.ps1:40 char:21
+ $dbname | foreach { $_.Name.ToString() } | foreach {$bakfile = "$directory" + $_ ...
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
What exactly is this error?
Where is it occurring?
How to correct this?
what changes should I make if I want to save the backup
file in '.sql' form?
Is there any other simpler way?

extraction data from file.mdf using pyodbc

I have an application for managing pharmacies (just an example ) this application is developed so that it relates to a single pharmacy . This application map on a Micrsoft DBMS MSSDE
each pharmacy generates database file ( pharmacy.mdf , pharmacy_log.mdf )
So after getting these files from different pharmacies, I wrote a script to automate data extraction from these all files
As the application is running, the script do the following tasks:
- Stops the server MSSQL server
- copy the two files from folder files recover and paste them in the path of the application
- Restart the server
- exctract the desired data
the connection with the database in question is using the python pyodbc Module
Once the extraction is run at a certain time pyodbc crash
i gotte this error:
cursor.execute ('select * from Pha.dbo.table_test ')
pyodbc.Error : ( '01000 ',' [ 01000 ] [ Microsoft] [ODBC SQL Server Driver] [ Shared Memory] ConnectionWrite ( ( send () ( 10054 ) ( SQLExecDirectW ) ')
i wrote this code for connection:
log = os.path.join(path,c,"SIC_log.ldf")
mdf = os.path.join(path,c,"SIC.mdf")
print(log)
print(mdf)
subprocess.call('net stop mssqlserver')
time.sleep(2)
os.system('copy "' + log + '" "' + MSSQL_DIR+'"')
os.system('copy "' + mdf + '" "' + MSSQL_DIR+'"')
time.sleep(2)
subprocess.call('net start mssqlserver')
time.sleep(2)
# Open a connection with the database
cnxn = pyodbc.connect('DSN=SIC_ODBC')
time.sleep(2)
extract_clo(cnxn, wb, ws)
cnxn.close()

Resources