I wrote this function to facilitate me doing SQL Server Migrations, but it does take the agent jobs on one server and writes them to disk as .sql files.
Function Write-SQLAgentJobs([string]$ServerInstance, [string]$ExportPath)
{
#Create Directory if needed.
If((Test-Path -LiteralPath $ExportPath -PathType Container) -eq $false)
{
New-Item -Path $ExportPath -ItemType Container | Out-Null
Write-Debug -Message "$(Get-Date) - Creating Export Path $($ExportPath)"
}
#Get the Additional Modules needed for doing the work.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
$SMO = new-object ('Microsoft.SqlServer.Management.Smo.Server') $ServerInstance
#Build Up Scripter Object...
$Scripter = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($SMO)
$ScriptOptions = New-Object ('Microsoft.SqlServer.Management.Smo.ScriptingOptions')
$Scripter.Options.ScriptDrops = $False
$Scripter.Options.WithDependencies = $False
$Scripter.Options.IncludeHeaders = $True
$Scripter.Options.AppendToFile = $False
$Scripter.Options.ToFileOnly = $True
$Scripter.Options.ClusteredIndexes = $True
$Scripter.Options.DriAll = $True
$Scripter.Options.Indexes = $True
$Scripter.Options.Triggers = $True
$Scripter.Options = $ScriptOptions
ForEach($Job In ($SMO.JobServer.Jobs | Where-Object -FilterScript {$_.name -ne ""}))
{
$JobName = ConvertTo-ValidPath -TestPath ($Job.name)
$FileName = [System.IO.Path]::Combine($ExportPath, "$($JobName).sql")
If((Test-Path -LiteralPath $FileName -PathType leaf) -eq $true)
{
Remove-Item -LiteralPath $FileName -Force -ErrorAction SilentlyContinue | Out-Null
}
$Scripter.Options.FileName = $FileName
$Scripter.Script($Job) | Out-Null
}
}
Function ConvertTo-ValidPath([string]$TestPath)
{
$invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''
$re = "[{0}]" -f [RegEx]::Escape($invalidChars)
Write-Output ($TestPath -replace $re)
}