Home  |  Articles  |  Scripts  |  Consultancy  |  FAQs  |  Links

 

Using PowerShell to Script out Replication on SQL Server 2005/SQL Server 2008

Article by Paul Ibison

Introduction

Like most admins, at some stage I used to play around with VBScript and really found it useful for little admin tasks like file manipulation. As far as replication goes it isn't hugely useful, but I did post up a really simple script a few years back to help automate scripting out replication. This can be done in SSMS by right-clicking the replication folder, but it is impossible in straightforward TSQL. Scripting out the replication setup is an essential part of your DR setup so it has to be done somehow, and generally I like to have a scheduled job to run my VBScript file. In SQL Server 2008 I noticed that in SSMS there is often a context-sensitive menu option to start PowerShell, so this is clearly the way to go in the future. If you have never heard of PowerShell, then don't panic because it hasn't really taken off just yet, but judging by its ubiquitous presence in SSMS we can safely say it's going to be pretty much essential at some stage. So, what is it? Well, it's basically a command-line interface to .NET. The syntax is pretty quirky and proprietary, and takes a bit of getting used to, but once you're there, the scripts are powerful and can easily interact with SMO or RMO APIs. So, the most likely reason as Replication Administrators that we might want to use PowerShell is to script out replication publications....

Scripting out Replication

I've included my own script below. It can be used to script out the entire set of merge and transactional publications to a text file. You'll need to run the Powershell script on a server which already has the Powershell library installed - Windows Server 2008 by default, otherwise download and install from Microsoft. To make your life easier, I'd use PowerGUI as a more friendly interface for the whole thing - you can set breakpoints, look at the value of variables etc and generally learn more quickly. I won't go through the script line by line - I have commented the code so you can see what it is doing at each stage. Simply give it a whirl. It will prompt you for the parameters and it'll even run if you ignore the prompts so it's pretty foolproof.

#Load command-line parameters - if they exist
param ([string]$sqlserver, [string]$filename)

#Reference RMO Assembly
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Replication") | out-null
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Rmo") | out-null

function errorhandler([string]$errormsg)
{
    writetofile (
"Replication Script Generator run at: " + (date)) $filename 1
    writetofile (
"[Replication Script ERROR] " + $errormsg) $filename 0
    write-host(
"[Replication Script ERROR] " + $errormsg) -Foregroundcolor Red
}

function writetofile([string]$text, [string]$myfilename, [int]$cr_prefix)
{
   
if ($cr_prefix -eq 1) { "" >> $myfilename }
   
$text >> $myfilename
}

function initializefile([string]$myfilename)
{
   
"" > $myfilename
}

trap {errorhandler($_); Break}

#Deal with absent parameters
[string] $hostname=hostname
if ($sqlserver -eq "") {$sqlserver = read-host -prompt "Please enter the server name or leave blank for Hostname"}
if ($filename -eq "")  {$filename = read-host -prompt "Please enter the file name (eg 'c:\ReplicationBackupScript.txt')..."}
if ($sqlserver -eq "")   {$sqlserver = $hostname}
if ($filename -eq "")   {$filename = "c:\ReplicationBackupScript.txt"}

$repsvr=New-Object "Microsoft.SqlServer.Replication.ReplicationServer" $sqlserver

Clear-host

initializefile
$filename

# if we don't have any replicated databases then there's no point in carrying on
if ($repsvr.ReplicationDatabases.Count -eq 0)
{
    writetofile (
"Replication Script Generator run at: " + (date)) $filename 0
    writetofile
"ZERO replicated databases on $sqlserver!!!" $filename 1
    EXIT
}

# similarly, if we don't have any publications then there's no point in carrying on
[int] $Count_Tran_Pub = 0
[
int] $Count_Merge_Pub = 0

foreach($replicateddatabase in $repsvr.ReplicationDatabases)
{
       
$Count_Tran_Pub = $Count_Tran_Pub + $replicateddatabase.TransPublications.Count
       
$Count_Merge_Pub = $Count_Merge_Pub + $replicateddatabase.MergePublications.Count
}

if (($Count_Tran_Pub + $Count_Merge_Pub) -eq 0)
{
    writetofile (
"Replication Script Generator run at: " + (date)) $filename 0
    writetofile
"ZERO Publications on $sqlserver!!!" $filename 1
    EXIT
}

# if we got this far we know that there are some publications so we'll script them out
# the $scriptargs controls exactly what the script contains
# for a full list of the $scriptargs see the end of this script
$scriptargs = [Microsoft.SqlServer.Replication.scriptoptions]::Creation `
-bor  [Microsoft.SqlServer.Replication.scriptoptions]::IncludeArticles `
-bor  [Microsoft.SqlServer.Replication.scriptoptions]::IncludePublisherSideSubscriptions `
-bor  [Microsoft.SqlServer.Replication.scriptoptions]::IncludeSubscriberSideSubscriptions

writetofile (
"Replication Script Generator run at: " + (date)) $filename 0
writetofile
" PUBLICATIONS ON $sqlserver" $filename 1
writetofile
" TRANSACTIONAL PUBLICATIONS ($Count_Tran_Pub)" $filename 1

foreach($replicateddatabase in $repsvr.ReplicationDatabases)
{
   
if ($replicateddatabase.TransPublications.Count -gt 0)
    {
       
foreach($tranpub in $replicateddatabase.TransPublications)
        {
           
write-host "********************************************************************************" -Foregroundcolor Blue
           
"***** Writing to file script for publication: " + $tranpub.Name
           
write-host "********************************************************************************" -Foregroundcolor Blue
            writetofile
"********************************************************************************" $filename 0
            writetofile (
"***** Writing to file script for publication: " + $tranpub.Name) $filename 0
            writetofile
"********************************************************************************" $filename 0
            [
string] $myscript=$tranpub.script($scriptargs
            writetofile
$myscript $filename 0
        }
    }
}

writetofile
" MERGE PUBLICATIONS ($Count_Merge_Pub)" $filename 1
writetofile
"" $filename 0

foreach($replicateddatabase in $repsvr.ReplicationDatabases)
{
   
if ($replicateddatabase.MergePublications.Count -gt 0)
    {
       
foreach($mergepub in $replicateddatabase.MergePublications)
        {
           
write-host "********************************************************************************" -Foregroundcolor Blue
           
"***** Writing to file script for publication: " + $mergepub.Name
           
write-host "********************************************************************************" -Foregroundcolor Blue
            writetofile
"********************************************************************************" $filename 0
            writetofile (
"***** Writing to file script for publication: " + $mergepub.Name) $filename 0
            writetofile
"********************************************************************************" $filename 0
            [
string] $myscript=$mergepub.script($scriptargs
            writetofile
$myscript $filename 0
        }
    }
}

#Creation Specifies that the generated script is for creating replication objects.
#Deletion Specifies that the script is for deleting a replication object.
#DisableReplicationDB Specifies that the script is a deletion script that disables publishing on a database and removes any agent jobs needed for publishing.
#EnableReplicationDB Specifies that the script is a creation script that enables publishing on a database and creates any agent jobs needed for publishing.
#IncludeAgentProfiles Specifies that the script includes all user-defined replication agent profiles defined on the Distributor.
#IncludeAll Specifies that the script includes all possible replication objects that can exist, which is equivalent to setting all values of ScriptOptions.
#IncludeArticles Specifies that the script includes articles.
#IncludeChangeDestinationDataTypes Specifies that the script includes any user-defined data type mappings. This option is only supported for non-SQL Server Publishers when the IncludeArticles option is enabled. This option is only supported on SQL Server 2005 and later versions.
#IncludeCreateDistributionAgent Specifies that the script includes Distribution Agent jobs.
#IncludeCreateLogreaderAgent Specifies that the script includes Log Reader Agent jobs.
#IncludeCreateMergeAgent Specifies that the script includes Merge Agent jobs.
#IncludeCreateQueuereaderAgent Specifies that the script includes Queue Reader Agent jobs.
#IncludeCreateSnapshotAgent Specifies that the script includes Snapshot Agent jobs.
#IncludeDisableReplicationDB Specifies that the script disables publishing on a database and removes any agent jobs needed for publishing.
#IncludeDistributionPublishers Specifies that the script includes Publishers.
#IncludeEnableReplicationDB Specifies that the script enables publishing on a database and creates any agent jobs needed for publishing.
#IncludeGo Specifies that the script includes the GO command at the end of a batch.
#IncludeInstallDistributor Specifies that the script installs publishing objects at the Distributor.
#IncludeMergeDynamicSnapshotJobs Specifies that the script includes the definition of any existing partitioned snapshot jobs for merge publications with parameterized row filters. This option is only supported for Microsoft SQL Server 2000 and later versions.
#IncludeMergeJoinFilters Specifies that the script includes the definition of all join filters defined for a merge publication.
#IncludeMergePartitions Specifies that the script includes the definition of any existing partitions for merge publications with parameterized row filters. This option is supported for Microsoft SQL Server 2005 and later versions.
#IncludeMergePublicationActivation Specifies that the script includes setting the status of a merge publication to active. This option is supported for SQL Server 2005 and later versions.
#IncludePartialSubscriptions Specifies that the script includes subscriptions to transactional publications that do not subscribe to all articles in the publication.
#IncludePublicationAccesses Specifies that the script includes all logins added to the publication access list (PAL). This option is only supported for publication creation scripts. Deleting a publication automatically removes the PAL.
#IncludePublications Specifies that the script includes publications.
#IncludePublisherSideSubscriptions Specifies that the script includes the registration of all subscriptions at the Publisher.
#IncludePullSubscriptions Specifies that the script includes all pull subscriptions.
#IncludeRegisteredSubscribers Specifies that the script includes the registration of all Subscribers at the Publisher.
#IncludeReplicationJobs Specifies that the script includes the definition of all SQL Server Agent jobs created by replication. This option is supported for SQL Server 2005 and later versions.
#IncludeSubscriberSideSubscriptions
#IncludeUninstallDistributor Specifies that the script uninstalls publishing objects at the Distributor.
#InstallDistributor Specifies a creation script that installs publishing objects at the Distributor.
#None Clears all scripting options.
#UninstallDistributor Specifies a deletion script that uninstalls publishing objects at the Distributor.