This category page is part of a series of Professional PowerShell SMO Recipes. You can find an index of all recipes on the main SMO Recipes page, and if you want to learn more about each recipe and see some sample screenshots, click on its category page.
These scripts were created and tested on Windows 8.1 with PowerShell v4 and SQL Server 2014, though most recipes should work with earlier versions of SQL Server. PowerShell v3 and above is required for many of the recipes. If you have a recipe request, leave a comment and I'll see what I can do. This cookbook will be continuously built, as I work more with SMO.
Recipe Categories
SQL Agent
I’m starting a new project that uses SQL Agent extensively, so this section is likely to grow. By the way, if you aren’t familiar with SQL Server credentials and Agent Proxies, consider reading up on it. You may find this feature useful.
Is SQL Server Agent running?
1 2 3 4 5 6 |
# $agentrunning returns $true or $false [void][Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") $server = New-Object Microsoft.SqlServer.Management.Smo.Server "sqlservername\instance" $sql = "SELECT 1 as running FROM master.dbo.sysprocesses WHERE LEFT(program_name, 8) = 'SQLAgent'" $count = $server.databases['master'].ExecuteWithResults($sql).Tables.Rows.Count if ($count -gt 0) { $agentrunning = $true } else { $agentrunning = $false } |
1 2 3 4 5 6 7 |
# Or, alternatively... [void][Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") $server = New-Object Microsoft.SqlServer.Management.Smo.Server "sqlservername\instance" if ($server.JobServer -eq $null) { $agentrunning = $false } else { try { $null = $server.JobServer.script(); $agentrunning = $true } catch { $agentrunning = $false } } |
Find failed jobs
1 2 3 4 |
[void][Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") $server = New-Object Microsoft.SqlServer.Management.Smo.Server "sqlservername\instance" $jobs = $server.jobserver.jobs $jobs | Where-Object { $_.lastRunOutcome -eq "Failed" } | Select-Object OriginatingServer, Name, LastRunDate |
Create Scheduled T-SQL based SQL Server Agent Job
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# This script creates a job named Sample Job with one step. This step executes # some T-SQL on the specified SQL Server. It creates one step and schedules # the job to run every day at 4:15 am. Failures are written to the Event Log. # I also threw in an extra sample schedule. $sqlserver = "sqlserver" $jobname = "Sample Job" $sqlcommand = "select @@VERSION" $database = "master" [void][Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") $server = New-Object Microsoft.SqlServer.Management.Smo.Server $sqlserver $jobserver = $server.JobServer if (!$jobserver[$jobname]) { $job = New-Object Microsoft.SqlServer.Management.SMO.Agent.Job($jobServer, $jobname) $job.Description = "This job doesn't do much." $job.OwnerLoginName = "sa" $job.Category = "Database Maintenance" $job.EmailLevel = [Microsoft.SqlServer.Management.SMO.Agent.CompletionAction]::OnFailure $job.EventLogLevel = [Microsoft.SqlServer.Management.SMO.Agent.CompletionAction]::OnFailure $job.PageLevel = [Microsoft.SqlServer.Management.SMO.Agent.CompletionAction]::Never $job.Create() $stepname = "Step 1" $jobstep = New-Object Microsoft.SqlServer.Management.SMO.Agent.JobStep($job, $stepname) $jobstep.Command = $sqlcommand $jobstep.OnSuccessAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithSuccess $jobstep.OnFailAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithFailure $jobstep.Create() $job.ApplyToTargetServer("(local)") $jobstep.DatabaseName = $database $jobstep.DatabaseUserName = "sa" $schedulename = "Daily at 4:15 am" $now = Get-Date -format "MM/dd/yyyy" $schedule = New-Object Microsoft.SqlServer.Management.SMO.Agent.JobSchedule($job, $schedulename) $schedule.FrequencyTypes = [Microsoft.SqlServer.Management.SMO.Agent.FrequencyTypes]::Daily $schedule.FrequencyInterval = 1 $timespan = New-TimeSpan -hours 4 -minutes 15 $schedule.ActiveStartTimeofDay = $timespan $schedule.ActiveStartDate = $now $schedule.Create() <# every half hour on Saturday, starting at 12:00 am $schedulename = "Another schedule example" $schedule = New-Object Microsoft.SqlServer.Management.SMO.Agent.JobSchedule($job, "$schedulename") $schedule.FrequencyTypes = [Microsoft.SqlServer.Management.SMO.Agent.FrequencyTypes]::Weekly $schedule.FrequencyInterval = [Microsoft.SqlServer.Management.SMO.Agent.WeekDays]::Saturday $schedule.FrequencyRecurrenceFactor = 1 $schedule.FrequencySubDayTypes = [Microsoft.SqlServer.Management.SMO.Agent.FrequencySubDayTypes]::Minute $schedule.FrequencySubDayInterval = 30 $schedule.ActiveStartDate = $now $schedule.ActiveStartTimeofDay = New-TimeSpan $schedule.Create() #> } |
Create credential, proxy account, and job to run local PowerShell scripts
Want to run PowerShell scripts within SQL Agent but not use SQLPS? This script creates a credential (which can be skipped if the SQL Agent account has necessary access), sets up a CmdExec proxy, then creates a job that uses the new credential. The job has one step which executes a script located on the SQL Server at C:\Scripts\Test-Example.ps1
If the account you’re adding does not have a login on the server, it will be added. If the account you’re adding does not have sysadmin access, it will be added to the Proxy Principal list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
$sqlserver = "sqlserver" $jobname = "Sample Job" $script = "C:\Scripts\Test-ExampleScript.ps1" $sqlcredentialname = "PowerShell Proxy Account" $description = "Proxy account for users to run job steps in command shell." [void][Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") $server = New-Object Microsoft.SqlServer.Management.Smo.Server $sqlserver $jobserver = $server.JobServer $subsystem = [Microsoft.SqlServer.Management.Smo.Agent.AgentSubSystem]::CmdExec $msg = "Enter the credential username and password." $credential = $Host.UI.PromptForCredential("Credential username and password",$msg,"$env:userdomain\$env:username",$env:userdomain) $sqlcredential = New-Object Microsoft.SqlServer.Management.SMO.Credential($server, $sqlcredentialname) $username = $credential.UserName $password = $credential.Password $newcredential = $sqlcredential.Create($username,$password) $login = $server.Logins[$username] if ($login -eq $null) { $login = new-object Microsoft.SqlServer.Management.Smo.Login($server,$username) $login.LoginType = "WindowsUser" $login.Credential = $sqlcredentialname $login.Create($password) } $proxy = new-object Microsoft.SqlServer.Management.Smo.Agent.ProxyAccount($jobserver,$sqlcredentialname) $proxy.credentialName = $sqlcredentialname $proxy.Description = "This account is used to execute PowerShell scripts locally." $proxy.isEnabled = $true $proxy.Create() $proxy.AddSubSystem($subsystem) if (!$login.IsMember("sysadmin")) { $proxy.AddLogin($username) $proxy.Alter() } $job = New-Object Microsoft.SqlServer.Management.SMO.Agent.Job($jobServer, $jobname) $job.Description = "This job executes a local PowerShell Script." $job.OwnerLoginName = "sa" $job.Category = "Database Maintenance" $job.EmailLevel = [Microsoft.SqlServer.Management.SMO.Agent.CompletionAction]::OnFailure $job.EventLogLevel = [Microsoft.SqlServer.Management.SMO.Agent.CompletionAction]::OnFailure $job.PageLevel = [Microsoft.SqlServer.Management.SMO.Agent.CompletionAction]::Never $job.Create() $stepname = "Step 1" $jobstep = New-Object Microsoft.SqlServer.Management.SMO.Agent.JobStep($job, $stepname) $jobstep.Command = "powershell.exe $script" $jobstep.Subsystem = $subsystem $jobstep.OnSuccessAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithSuccess $jobstep.OnFailAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithFailure $jobstep.ProxyName = $sqlcredentialname $jobstep.Create() $job.ApplyToTargetServer("(local)") |
Leave a Reply