functions/Invoke-DBScriptObjects.ps1

function Invoke-DBScriptObjects {
    <#
    .SYNOPSIS
        Generate file-per-object scripts of specified server and database.
 
    .DESCRIPTION
        Generate file-per-object scripts of specified server and database to specified directory. Attempts to create specified directory if not found.
 
    .PARAMETER ServerName
        Specifies the database server hostname.
 
    .PARAMETER Database
        Specifies the name of the database you want to script as objects to files.
 
    .PARAMETER SavePath
        Specifies the directory where you want to store the generated scripts.
 
    .PARAMETER Credentials
        Specifies credentials to connect to the database with. If not supplied then a trusted connection will be used.
 
    .NOTES
        Author: Phil Factor
        Adapted from http://www.simple-talk.com/sql/database-administration/automated-script-generation-with-powershell-and-smo/
        Edits By: Tim Cartwright:
            - Changed to script Service Broker objects.
            - Script into folders per object type and schema, instead of one flat folder
            - Ability to use username and password instead of trusted. Trusted can still be used.
 
        Example directory structure created:
            ├───dbo
            │ ├───StoredProcedures
            │ │ dbo.proc1.sql
            │ │ dbo.proc2.sql
            │ │ ...
            │ ├───Tables
            │ │ dbo.table1.sql
            │ │ dbo.table2.sql
            │ │ ...
            │ └───Views
            │ │ dbo.view1.sql
            │ │ dbo.view2.sql
            │ │ ...
 
 
    .LINK
        https://github.com/tcartwright/tcdbtools
    #>


    #>
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true, Position = 1)]
        [string]$ServerInstance,
        [Parameter(Mandatory = $true, Position = 2)]
        [string[]]$Databases,
        [Parameter(Mandatory = $true, Position = 3)]
        [string]$SavePath,
        [pscredential]$Credentials
    )

    begin {
        $sqlCon = InitSqlObjects -ServerInstance $ServerInstance -Credentials $Credentials
        $SqlCmdArguments = $sqlCon.SqlCmdArguments
        $server = $sqlCon.server

        # create scripter object (used by the function ScriptOutDbObj())
        $scripter = New-Object "Microsoft.SqlServer.Management.Smo.Scripter" $server #create the scripter

        # https://docs.microsoft.com/en-us/dotnet/api/microsoft.sqlserver.management.smo.scriptingoptions?view=sql-smo-160
        $scripter.Options.AllowSystemObjects = $false
        $scripter.Options.AnsiFile = $true
        $scripter.Options.AnsiPadding = $false # true = SET ANSI_PADDING statements
        $scripter.Options.Default = $true
        $scripter.Options.DriAll = $true
        $scripter.Options.Encoding = New-Object "System.Text.ASCIIEncoding"
        $scripter.Options.ExtendedProperties = $true
        $scripter.Options.IncludeDatabaseContext = $false # true = USE <databasename> statements
        $scripter.Options.IncludeHeaders = $false
        $scripter.Options.NoCollation = $false # true = don't script verbose collation info in table scripts
        $scripter.Options.Permissions = $true
        $scripter.Options.ScriptSchema = $true
        $scripter.Options.SchemaQualify = $true
        $scripter.Options.SchemaQualifyForeignKeysReferences = $true
        $scripter.Options.ScriptDrops = $false
        $scripter.Options.ToFileOnly = $true
        $scripter.Options.Triggers = $true
        $scripter.Options.Indexes = $true
        $scripter.Options.XmlIndexes = $true
        $scripter.Options.FullTextIndexes = $true
        $scripter.Options.ClusteredIndexes = $true
        $scripter.Options.NonClusteredIndexes = $true
        $scripter.Options.WithDependencies = $false
        $scripter.Options.ContinueScriptingOnError = $true

        # now get all the object types except extended stored procedures and a few others we don't want
        # by creating a bit flags of the DatabaseObjectTypes enum:
        $objectTypeFlags = [long][Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes]::All -bxor (
            [long][Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes]::Certificate +
            [long][Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes]::DatabaseRole +
            [long][Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes]::ExtendedStoredProcedure +
            [long][Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes]::SqlAssembly +
            [long][Microsoft.SqlServer.Management.Smo.DatabaseObjectTypes]::DatabaseScopedConfiguration
        )
    }

    process {
        foreach ($Database in $Databases) {
            $SqlCmdArguments.Database = $Database
            $db = $server.Databases[$Database]
            $dbSavePath = [System.IO.Path]::Combine($SavePath, $Database)

            if (!(Test-Path -Path $dbSavePath)) {
                Write-Verbose "Creating directory at '$dbSavePath'"
                New-Item $dbSavePath -Type Directory -Force -ErrorAction Stop | Out-Null
            }

            if ($db.Name -ne $Database) {
                Write-Warning "Can't find the database [$Database] in '$ServerInstance'"
                continue
            };

            #get everything except the information schema, system views, and some other extra items
            $objects = $db.EnumObjects($objectTypeFlags) |
            Where-Object {
                $_.Schema -ine "sys" -and
                $_.Name -ine "sys" -and
                $_.Schema -ine "information_schema" -and
                $_.Name -ine "information_schema" -and
                $_.Schema -inotlike "db_*" -and
                $_.Name -inotlike "db_*" -and
                $_.Name -inotlike "sp_*diagram*" -and
                $_.Name -ine "fn_diagramobjects" -and
                $_.Name -ine "sysdiagrams" -and
                $_.Schema -ine "guest" -and
                $_.Name -ine "guest"
            }

            $cnt = 0
            $total = $objects.Count + $db.Triggers.Count + 1
            $activity = "SCRIPTING DATABASE: [$($db.Name)]"

            Write-InformationColored "$activity" -ForegroundColor Yellow

            # write out each scriptable object as a file in the directory you specify
            $objects | ForEach-Object {
                #for every object we have in the datatable.
                $cnt = ScriptOutDbObj -scripter $scripter -dbObj $_ -SavePath $dbSavePath -WriteProgressActivity $activity -WriteProgressCount $cnt -WriteProgressTotal $total
            }

            # Next, script out Database Triggers (DatabaseDdlTrigger) separately because they are not returned by Database.EnumObjects()
            foreach ($trigger in $db.Triggers) {
                $cnt = ScriptOutDbObj -scripter $scripter -dbObj $trigger -SavePath $dbSavePath -WriteProgressActivity $activity -WriteProgressCount $cnt -WriteProgressTotal $total
            }

            $scripter.Options.Permissions = $false
            # also script out the database definition itself
            $cnt = ScriptOutDbObj -scripter $scripter -dbObj $db -SavePath $dbSavePath -WriteProgressActivity $activity -WriteProgressCount $cnt -WriteProgressTotal $total

            Write-Progress -Activity $activity -Completed
            Write-InformationColored "FINISHED $activity" -ForegroundColor Yellow
        }
    }
}