Getting an error when trying to execute powershell code via a SQL Agent job - sql-server

I've setup a SQL Server 2016 agent job that has 2 steps that is executed by the same service account, Step 1 executes an SSIS package that writes 2 files out to a share. Step 2 executes embedded powershell code that combines these 2 files into a single file and creates a file on that same share where the 2 files were created by SSIS. When I execute the job, Step 1, the SSIS package completes successfully and creates the 2 files on this share. But when Step 2 executes I get the error below. Just a point of info, when I run this script locally from my windows 10 box, I have no issues.
I guess my question is, if SSIS can execute successfully with the same service account can this be a permissions issue for powershell scripts? I'm not a server admin so if this is a stupid questions please forgive my ignorance. Any help/direction anyone can provide would be appreciated.
Message
Executed as user: XXX\sqlsvc02. The job script encountered the following errors. These errors did not stop the script: A job step received an error at line 12 in a PowerShell script. The corresponding line is 'Get-Content $pathCounts, $pathDetails | Set-Content $outFile'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Cannot find path '\xxx\shared\MonthlyReports\BoundPoliciesAddedAtFaultEndorsementWithin10Days_Counts.csv' because it does not exist. ' A job step received an error at line 12 in a PowerShell script. The corresponding line is 'Get-Content $pathCounts, $pathDetails | Set-Content $outFile'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Cannot find path '\xxx\shared\MonthlyReports\BoundPoliciesAddedAtFaultEndorsementWithin10Days_Details.csv' because it does not exist. '. Process Exit Code 0. The step succeeded.
Here is my powershell script:
# Define variables
$path = '\\xxx\shared\MonthlyReports'
$pathCounts = Join-Path -Path $path -ChildPath 'BoundPoliciesAddedAtFaultEndorsementWithin10Days_Counts.csv'
$pathDetails = Join-Path -Path $path -ChildPath 'BoundPoliciesAddedAtFaultEndorsementWithin10Days_Details.csv'
$date = Get-Date
$dateStr = $date.ToString("yyyyMM")
# Define combined file name
$outFile = Join-Path $path -ChildPath("BoundPoliciesAddedAtFaultEndorsementsWithin10Days_" + $dateStr + ".csv")
# Execute combine files code
Get-Content $pathCounts, $pathDetails | Set-Content $outFile
Here is an image of what Step #2 looks like:

Related

Powershell script invoked by SQL Agent works differently

I have a pretty simple powershell script (to convert .xlsx files to .xls) like below:
$files = Get-ChildItem "C:\MyFolder\*.xlsx"
foreach ($file in $files) {
$Filepath = Get-Item -Path $file
$NewFilepath = Join-Path -path $Filepath.directory.fullname -ChildPath
"$($Filepath.basename).xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false #or false
$Excel.displayalerts = $false
$Workbook = $Excel.Workbooks.Open("$Filepath".fullname,
[Type]::Missing,$true)
$Workbook.SaveAs("$NewFilepath",56)
#https://technet.microsoft.com/en-us/library/ff730962.aspx
$Workbook.Close()
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Remove-Variable Excel
Remove-Item $Filepath
}
If I run this script from powershell directly it works just as expected. I mean for each .xlsx file it creates a new .xls file and removes given .xlsx file.
But when I invoke it by SQL Agent all the .xlsx files are simply removed with no creation corresponding .xls files.
SQL Job step
Type: Powershell
Run as: SQL Server Agent service account (checked folder permissioned and is full control)
Command: powershell -File "C:\MyScripts\MyConvertToXls.ps1"
The job does not fail. But when I go to the step execution details I can see the following message:
Message
Executed as user: ServiceAccount. ...rors did not stop the script:
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: 'Sorry, we couldn't find .
Is it possible it was moved, renamed or deleted? '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is:
'At C:\MyScripts\MyConvertToXls.ps1:16 char:1 + $Workbook = $Excel.Workbooks.Open("$Filepath".fullname,[Type]::Missin ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (:) [], COMException '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: ' + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: ' '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: 'You cannot call a method on a null-valued expression. '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: 'At C:\MyScripts\MyConvertToXls.ps1:18 char:1 '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: '+ $Workbook.SaveAs("$NewFilepath",56) '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: '+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'. Correct the script and reschedule the job.
The error information returned by PowerShell is: ' + CategoryInfo : InvalidOperation: (:) [], RuntimeException '
A job step received an error at line 1 in a PowerShell script. The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: ' + FullyQualifiedErrorId : InvokeMethodOnNull '
A job step received an error at line 1 in a PowerShell script. The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: ' '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"... Process Exit Code 0. The step succeeded.
A PowerShell job step type expects a script but it looks like you are specifying the OS command powershell -File "C:\MyScripts\MyConvertToXls.ps1" to invoke the script.
Try a Operating System (CmdExec) job step type to invoke the command. Alternatively, paste the script into the PowerShell job step instead of running the external script.
I had same error, and found this solution.
You need to create folder Desktop
C:\Windows\System32\config\systemprofile\Desktop for 32 bit machine
C:\Windows\SysWOW64\config\systemprofile\Desktop for 64 bit machine
It's amaizing but it works

Problem executing REMOTE powershell script using WinSCP via SQL Server Agent Job

On SQL Server 2016 I have setup a job that executes a powershell script that resides on a remote app server. When I execute the powershell script via the app server using the Powershell ISE app my script works without issue. When I had setup the job and enter this command:
powershell.exe -ExecutionPolicy Bypass -file "\\serverapp1\c$\coverageverifier_scripts\SFTP_CoverageVerifier.ps1" in Step 1.
When I look at the VIEW HISTORY I see the error below but I cannot figure out why the script now cannot load the file or assembly.
Any help/direction would be appreciated. Here is the error:
The job script encountered the following errors. These errors did not stop the script: A job step received an error at line 1 in a PowerShell script. The corresponding line is 'powershell.exe -ExecutionPolicy Bypass -File "\empqaapp1\c$\coverageverifier_scripts\SFTP_CoverageVerifier.ps1"'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Add-Type : Could not load file or assembly '
Here is my powershell script as well:
# Load WinSCP .NET assembly
#Add-Type -Path "WinSCPnet.dll"
Add-Type -Path (Join-Path $PSScriptRoot "WinSCPnet.dll")
# Declare variables
$date = Get-Date
$dateStr = $date.ToString("yyyyMMdd")
# Define $filePath
$filePath = "C:\coverageverifier_scripts\TEST_cvgver.20190121.0101"
# Write-Output $filePath
# Set up session options for VERISK TEST/ACCEPTANCE SFTP SERVER
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "secureftpa.iso.com"
UserName = "account"
Password = "pw"
SshHostKeyFingerprint = "ssh-rsa 1111 xxx/xxxxxxxxx+3wuWNIkMY5GGgRObJisCPM9c9l7yw="
}
$session = New-Object WinSCP.Session
$session.ExecutablePath = "C:\WinSCP\WinSCP.exe"
try
{
# Connect
$session.Open($sessionOptions)
# Transfer files
$session.PutFiles($filePath,"/").Check()
}
finally
{
$session.Dispose()
Your Add-Type call does not include the path to the WinSCPnet.dll.
If you have the WinSCPnet.dll in the same folder as your PowerShell script, use this syntax:
Add-Type -Path (Join-Path $PSScriptRoot "WinSCPnet.dll")
Or use a full path.
See also Loading assembly section in WinSCP .NET assembly article on Using WinSCP .NET Assembly from PowerShell.

Can't start script on remote server from shared resources

I'm trying to write a script in Power Shell to connect to a remote server and execute a .bat file. Since I wanted to do this for more than one server I thought I could place the .bat file on another server which shares ist resources and call it from there, but that does not work. When I place the .bat file in my temp folder and execute it via the script it works. However trying to execute it from the shared resources does not. Why is that?
Note: I can manually start the process via the Task-Manager that starts the .bat file in the shared resources and it works.
script:
$CompName = "myotherserver"
$cred = get-credential
$process = get-wmiobject -query "SELECT * FROM Meta_Class WHERE __Class = 'Win32_Process'" -namespace "root\cimv2" -computername $CompName -credential $cred
$results = $process.Create( "cmd.exe `/c \\mysharedresc\temp\started.bat" )
started.bat:
echo started > c:\temp\started.txt
If you need more annotations or Information please ask for it.
Edit: Working means for me it creates the started.txt in C:\temp. Not working means it does not (but in this case there is no error given.)

PowerShell Output

So, I am fairly new to PowerShell and need to create a script to rename the computers in our office. That portion of the script works. The part I am having trouble with is the output.
I have this set in task scheduler, but when it runs I do not see if the rename was successful. Below is my script and below that is what goes into the text file.
start-transcript -path C:\Users\abhagwandin.SENECA\Desktop\RenameResults.txt
$CSV = Import-Csv "C:\Users\abhagwandin.SENECA\Desktop\Computer Desktop Names Test.csv" -Header OldName, NewName
Foreach ($name in $CSV)
{
write-output $name
netdom renamecomputer $name.OldName /newname: $name.NewName /userd: admin /passwordd: pass /usero: admin /passwordo: pass /reboot /force
}
stop-transcript
-------------------------------------------------------------------------------
**********************
Windows PowerShell Transcript Start
Start time: 20150520154216
Username :
Machine : (Microsoft Windows NT 6.1.7601 Service Pack 1)
**********************
Transcript started, output file is C:\Users\abhagwandin.SENECA\Desktop\RenameRe
sults.txt
OldName NewName
------- -------
JFLAHNYCD1 JFLAHERTY
**********************
Windows PowerShell Transcript End
End time: 20150520154218
**********************
You know that renaming a computer through a cmdline command in powershell instead of using the built in cmdlets can give problems with the output if you don't parse the output (and preferably create a new object for it)?
Why don't you use rename-computer or the rename() method of the win32_computersystem wmi class? Both can be used remotely so you don't even have to schedule tasks that way.
Just create an input file with the current name and the desired names and use a loop to process them.

Powershell from SQL Server Agent Job doesn't recognize ConvertTo-CSV

UPDATE: Modified the script to work within the bounds of PS1 as required by SQLPS.
Changed:
IF($property.Value -match $regex){
$currentBadLine = (ConvertTo-Csv $_ -NoTypeInformation -Delimiter $delimiter);
$badLines += $currentBadLine[1,2]
};
To:
IF($property.Value -match $regex){
$badLines += $_ | Select-Object | ft -autoSize;
};
Prints a new header for each bad line, but it's not the end of the world and not worth the effort to prevent.
I have a Powershell script that pre-processes CSV files before they have a chance to screw up my data imports.
On two servers in a row now I have confirmed that the PS Major Version at least 2, and that the following code snippet runs fine in Powershell ISE. The purpose of the code is to read in each line of the CSV, and then loop through the columns looking for the regex pattern in the $regex variable. When it finds one I want it to keep track of the error before fixing it so I can write an error log later before outputting a cleaned up file ready for import.
%{
Foreach($Property in $_.PSObject.Properties){
IF($property.Value -match $regex){
$currentBadLine = (ConvertTo-Csv $_ -NoTypeInformation -Delimiter $delimiter);
$badLines += $currentBadLine[1,2]
};
$property.Value = $property.Value -replace $regex;
}
$_
}
But once I put that code into an agent job the agent complains:
'The term 'ConvertTo-Csv' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and
try again. '
The question then is this: Is the Agents Powershell subsystem using a different version of Powershell than the rest of the system? If so, how do I find out which version the Subsystem is using and if possible upgrade it so I can fix this.
The server is running:
Windows Server 2008 R2 Enterprise
PS Major version 2, Minor 0 Build -1 revision -1
SQL Server 2008 R2 SP1 10.5.2500.0 64 bit
Thanks!
Yes, proper PowerShell support isn't really implemented until SQL Server 2012 (an even that is a bit flakey as to what cmdlets it supports)
In 2008 and R2 the agent's powershell implementation is actually a minishell, created by the now (thankfully) deprecated make-shell.exe utility, which only allows v1 cmdlets to run, and disallows the use of Add-PSSnapin so you can't add anymore cmdlets.
To get proper powershell support, you either need to shell out and call an external script, or run the job as a windows scheduled task rather than an agent job.
The following article explains a lot about why powershell support in 2008 R2 doesn't work like you think it should:
The Truth about SQLPS and PowerShell V2
One work-around: Export-CSV to a file, then Get-Content from the file.
$rows = ,(New-Object PSObject -prop #{a=7; b='stuff';});
$rows +=,(New-Object PSObject -prop #{a=77; b='more';});
#To run from SQL Job, change from this:
$csvrows = $rows | ConvertTo-CSV -NoType | % {$_.Replace('"','')};
write-output $csvrows;
#to this:
$rows | Export-CSV -NoType "C:\Temp\T.csv"
$csvrows = (Get-Content "C:\Temp\T.csv") | % {$_.Replace('"','')};
write-output $csvrows;

Resources