functions/SetJobSteps.ps1
Function Set-JobSteps { <# .Synopsis Delete steps of a SQL Agent Job and re-create. .Description Steps for SQL Agent Job will be deleted and re-created to match the settings in the xml file. .Parameter sqlServer The SQL Connection that SQL Agent Job is on. .Parameter root The XML Object .Example $SqlConnectionString = "data source = .; initial catalog = master; trusted_connection = true;" $JobManifestXmlFile = "C:\Reports\Our_First_Job.xml" $SqlConnection = Connect-SqlConnection -ConnectionString $SqlConnectionString [xml] $_xml = [xml] (Get-Content -Path $JobManifestXmlFile) $x = Get-Xml -XmlFile $_xml $sqlAgentJob = Set-Job -SqlServer $SqlConnection -root $x Set-JobSteps -SqlServer $SqlConnection -root $x -job $SqlAgentJob Disconnect-SqlConnection -SqlDisconnect $SqlConnection #> [CmdletBinding()] param ( [Microsoft.SqlServer.Management.Smo.SqlSmoObject] [ValidateNotNullorEmpty()] $SqlServer, [System.Xml.XmlLinkedNode] [ValidateNotNullorEmpty()] $root, [Microsoft.SqlServer.Management.Smo.Agent.AgentObjectBase] [ValidateNotNullorEmpty()] $job ) #clear steps and always re-create $job.RemoveAllJobSteps() $job.Refresh() #re-create steps; defaults for properties are created at first $Steps = $root.Steps foreach ($step in $Steps.ChildNodes) { try { $StepName = $step.Name $JobStep = New-Object ('Microsoft.SqlServer.Management.Smo.Agent.JobStep') ($job, $StepName) $JobStep.Create() Write-Verbose "Blank step $StepName Created" -Verbose $job.Refresh() } catch { throw $_.Exception } finally { if ($null -ne $JobStep) { Remove-Variable -Name "JobStep" } } } foreach ($step in $Steps.ChildNodes) { #Question: huh? Why re-enter the loop? #Answer: We need to create all job steps up front so that we can set on success or on fail accordingly #eg if step succeeds and user wants to use "GoToStep" on Action, then have to get ID of step they want to go to from "OnSuccessStep" #same applies to Failures { try { $JobStep_Properties = $job.JobSteps | Where-Object { $_.Name -eq $step.Name } $StepName = $Step.Name $JobStep_Properties.SubSystem = $step.SubSystem if ($Step.RunAs) { $RunAs = $Step.RunAs.Include if (Test-Path variable:$RunAs) { [string]$value = Get-Variable $RunAs -ValueOnly Write-Verbose ('Setting variable: {0} = {1}' -f $update, $value) -Verbose foreach ($element in $step.SelectNodes("/Job/Steps/Step/RunAs") | Where-Object { $_.Include -eq $RunAs }) { $element.Name = $value } } else { throw ('RunAs Account is not set in the current scope for step {0} (but are defined in the xml): {1}' -f $StepName, $RunAs.Include) } $JobStep_Properties.ProxyName = $Step.RunAs.Name } if ($step.OnSuccessAction -eq "GoToStep") { $OnSuccessGoToStepId = Get-GoToStepId -JobObject $job -GoToJobStep $step.OnSuccessStep $JobStep_Properties.OnSuccessAction = $step.OnSuccessAction $JobStep_Properties.OnSuccessStep = $OnSuccessGoToStepId } else { $JobStep_Properties.OnSuccessAction = $step.OnSuccessAction } if ($step.OnFailAction -eq "GoToStep") { $OnFailGoToStepId = Get-GoToStepId -JobObject $job -GoToJobStep $step.OnFailStep $JobStep_Properties.OnFailAction = $step.OnFailAction $JobStep_Properties.OnFailStep = $OnFailGoToStepId } else { $JobStep_Properties.OnFailAction = $step.OnFailAction } $JobStep_Properties.RetryAttempts = $step.RetryAttempts $JobStep_Properties.RetryInterval = $step.RetryInterval if ($step.subsystem -eq "TransactSql") { $JobStep_Properties.DatabaseName = $step.DatabaseName } if ($step.SubSystem -eq "Ssis") { Write-Verbose "Setting SSIS Server for step." $keys = $($step.SsisServer) foreach ($var in $keys) { $update = $var.Include if (Test-Path variable:$update) { [string]$value = Get-Variable $update -ValueOnly Write-Verbose ('Setting variable: {0} = {1}' -f $update, $value) -Verbose foreach ($element in $step.SelectNodes("/Job/Steps/Step/SsisServer") | Where-Object { $_.Include -eq $update }) { $element.Name = $value } } else { $missingVariables += $update } } if ($missingVariables.Count -gt 0) { throw ('Ssis Server is not set in the current scope (but are defined in the xml): {0}' -f ($missingVariables -join " `n")) } $thisSsisServer = $step.SsisServer.Name $step = Set-IscVariables -SsisStep $Step Write-Verbose "Step $stepName is a Ssis step. Connecting to SSIS Instance to verify the catalog exists. If it does will assume everything else required exists." -Verbose $script = "SELECT 'exists' FROM ssisdb.CATALOG.folders folder INNER JOIN ssisdb.CATALOG.projects project on project.folder_id = folder.folder_id WHERE folder.NAME = '$($Step.SsisServerDetails.SsisServerCatalogFolder)' AND project.name = '$($Step.SsisServerDetails.SsisServerCatalogProject)'" $checkSsisExists = $SqlServer.ConnectionContext.ExecuteScalar($script) # if ($checkSsisExists -ne "exists") { # $msg = "Either Folder " + $Step.SsisServerDetails.SsisServerCatalogFolder + " or Project " + $Step.SsisServerDetails.SsisServerCatalogProject + " does not exist. Cannot fill variables for ssisCommand correctly. Please deploy all SSIS Projects first " # Write-Verbose $msg -Verbose # Throw $msg; # } $script = "SELECT er.reference_id FROM ssisdb.CATALOG.environment_references er INNER JOIN ssisdb.CATALOG.projects p ON p.project_id = er.project_id WHERE er.environment_name = '$($Step.SsisServerDetails.SsisServerCatalogEnvironment)' AND p.NAME = '$($Step.SsisServerDetails.SsisServerCatalogProject)'" Write-Host $script try { $environmentReference = $SqlServer.ConnectionContext.ExecuteScalar($script) } catch { throw $_.Exception } try { $ssisCommand = @" /ISSERVER "\"\SSISDB\$($Step.SsisServerDetails.SsisServerCatalogFolder)\$($Step.SsisServerDetails.SsisServerCatalogProject)\$($Step.SsisServerDetails.SsisServerCatalogPackage)\"" /SERVER "\"$($thisSsisServer)\"" /ENVREFERENCE $environmentReference /Par "\"`$ServerOption::LOGGING_LEVEL(Int16)\"";1 /Par "\"`$ServerOption::SYNCHRONIZED(Boolean)\"";True /CALLERINFO SQLAGENT /REPORTING E "@ Write-Host "This is the ssiscommand" Write-Host $ssisCommand $JobStep_Properties.Command = $ssisCommand } catch { throw $_.Exception } } else { $JobStep_Properties.Command = $step.Command } $JobStep_Properties.Alter() $JobStep_Properties.Refresh() Write-Verbose "Successfully Updated properties for Step $StepName." -Verbose } catch { throw $_.Exception } finally { if ($null -ne $JobStep) { Remove-Variable -Name "JobStep" Remove-Variable -Name "JobStep_Properties" } } } } |