An interesting issue came across my desk this week. One of our clients has a number of PowerShell tasks running on SQL Server Agent job. One day, the jobs suddenly stopped working due to the error below: [caption id="attachment_104229" align="aligncenter" width="1351"]
[Powershell Task Fails on SQL Server Job[/caption]
Executed as user: NT Service\SQLSERVERAGENT. A job step received an error at line 1 in a PowerShell script. The corresponding line is 'import-module SQLPS'. Correct the script and reschedule the job. The error information returned by PowerShell is: 'File C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\SQLPS\Sqlps.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. File C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\SQLPS\Sqlps.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. '. Process Exit Code -1. The step failed.
Execution policy has different scopes. You can check the settings by running get-executionpolicy -list. If you are running it via the SQL server job agent, then the policy that will apply is process scope. Try checking the policy on PowerShell. Take note of the value and enter the SQLPS module by issuing sqlps command. Notice the change in the Execution Policy for the scope "Process." This is the Execution Policy configured for the SQLPS mini-shell. PowerShell type job steps will run using this policy since it will run inside the SQLPS mini-shell.
Note: If the registry key for the SQLPS execution policy does not exist, you won't be able to load SQLPS and the execution policy for the process scope will toggle to restricted. You would receive an error similar to below:
import-module : File C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\SQLPS\Sqlps.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. At line:1 char:1 + import-module SQLPS + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : SecurityError: (:) [Import-Module], PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand
A quick workaround to the issue without messing around with the policy settings on the server is to bypass the execution policy. You can do this by saving your code into a PowerShell script file and converting the SQL job step into a cmdexec step type and writing it as such: powershell.exe -ExecutionPolicy Bypass ."Script path here" [caption id="attachment_104235" align="aligncenter" width="1483"]
On the left, PowerShell type job step. This will fail if execution policy for SQLPS is set to restricted or does not exist. On the right is the workaround.[/caption]
As mentioned above, if this is a GPO you'll need to get your system admin to change the policy. Even if you change it on the server, the GPO will just change it back. To fix the issue, you'll have to change the policy for SQLPS. SQLPS gets its execution policy from the registry: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.SqlServer.Management.PowerShell.sqlps130
Note: Microsoft.SqlServer.Management.PowerShell.sqlps### the ### will change depending on your SQL server version. You can change the ExecutionPolicy key The default value is RemoteSigned. There may be instances when the key is completely removed, as was the case with our client. To get it working again, you'll need to add the key back to fix SQLPS. Make sure the path value points to your actual sqlps.exe location.
If you ask any decent DBA about running PowerShell tasks through SQL server job as a PowerShell type job step, the advice will always be - don't. PowerShell type steps calls the SQLPS mini-shell and runs your command from there. SQLPS for SQL 2012 and older versions do not play nice with other modules. A better way is to run it as a CmdExec type for a few reasons:
Ready to future-proof your SQL Server investment?