MSFT_BizTalkGroupConfig.psm1

enum Ensure { 
    Absent 
    Present 
}

[DscResource()]
class BizTalkGroupConfiguration {
    [DscProperty(Key)]
    [System.String]$Name

    [DscProperty(Mandatory = $true)]
    [System.String]$SqlServerName

    [DscProperty(Mandatory = $true)]
    [System.String]$Databases

    [DscProperty(NotConfigurable)]
    [System.String]$BtsConfigCmdline

    [DscProperty(Mandatory = $true)]
    [System.String]$XmlConfigFile

    [DscProperty(NotConfigurable)]
    [System.String]$SsoBackupFile

    [DscProperty(Mandatory = $true)]
    [Ensure] $Ensure

     [BizTalkGroupConfiguration] Get() {
        Write-verbose "Get TargetResource"
        $result = $this.Test()
        Write-verbose "Tested"
        if ($result) {
            return $this
        }
        else {
            return $this
        }
    }

    [Void] Set() {
        Write-verbose "Set TargetResource"
        Write-Verbose ("Commandline : {0}" -f $this.BtsConfigCmdline)
        Write-Verbose ("Config : {0}" -f $this.XmlConfigFile)
        Write-Verbose ("SqlServer : {0}" -f $this.SqlServerName)
        Write-Verbose ("Databases : {0}" -f $this.Databases)
        
        $result = $this.Test()
      if ($result -eq $false) {
              Switch ($this.Ensure) {
                "Present" { 
                    Write-Verbose "Going to create group"
                    New-Item -ItemType directory -Path C:\TEMP -ErrorAction SilentlyContinue
                    Remove-item 'C:\Temp\BizTalk2016_creategroup.log' -ErrorAction SilentlyContinue
                    $args = ("/l C:\Temp\BizTalk2016_creategroup.log /s {0} /NOPROGRESSBAR" -f  $this.XmlConfigFile)
                    $command = $this.BtsConfigCmdline
                    Write-Verbose $args
                    Write-Verbose $command
                    Start-Process -FilePath $command -ArgumentList $args -Wait
                    Write-Verbose "Create group done"
                    #$global:DSCMachineStatus = 1
                }
                "Absent" { 
                    Write-Verbose "Going to delete group"
                    New-Item -ItemType directory -Path C:\TEMP -ErrorAction SilentlyContinue
                    Remove-item ' C:\Temp\BizTalk2016_deletegroup.log' -ErrorAction SilentlyContinue
                    $args = "/u /l C:\Temp\BizTalk2016_deletegroup.log /NOPROGRESSBAR"
                    $command = $this.BtsConfigCmdline
                    Write-Verbose $args
                    Write-Verbose $command
                    Start-Process -FilePath $command -ArgumentList $args -Wait
                    Write-Verbose "Delete group done"
                    $DatabaseNames = $this.Databases -split "," 
                    $connectionString = "Server=$($this.SqlServerName);Database=Master;Integrated Security=True;"
                    $connection = New-Object System.Data.SqlClient.SqlConnection
                    $connection.ConnectionString = $connectionString
                    $connection.Open()
                    Write-Verbose "Deleting databases"
                    foreach ($DatabaseName in $DatabaseNames ) {
                        $query = ("IF EXISTS(SELECT name FROM sys.databases WHERE name = '{0}') BEGIN alter database [{0}] set single_user with rollback immediate DROP DATABASE [{0}] END" -f $DatabaseName)
                        $command = $connection.CreateCommand()
                        $command.CommandText = $query
                        $command.ExecuteScalar()
                    }
                    Write-Verbose "Databases deleted"
                    $connection.Close()
                    $sqljobs = @("MessageBox_Message_Cleanup_BizTalkMsgBoxDb","Backup BizTalk Server (BizTalkMgmtDb)","MessageBox_UpdateStats_BizTalkMsgBoxDb","MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb","Operations_OperateOnInstances_OnMaster_BizTalkMsgBoxDb","DTA Purge and Archive (BizTalkDTADb)","MessageBox_DeadProcesses_Cleanup_BizTalkMsgBoxDb","MessageBox_Parts_Cleanup_BizTalkMsgBoxDb","Rules_Database_Cleanup_BizTalkRuleEngineDb","Monitor BizTalk Server (BizTalkMgmtDb)","PurgeSubscriptionsJob_BizTalkMsgBoxDb","TrackedMessages_Copy_BizTalkMsgBoxDb","CleanupBTFExpiredEntriesJob_BizTalkMgmtDb")
                    $connectionString = "Server=$($this.SqlServerName);Database=MSDB;Integrated Security=True;"
                    $connection = New-Object System.Data.SqlClient.SqlConnection
                    $connection.ConnectionString = $connectionString
                    $connection.Open()
                    Write-Verbose "Deleting SQL Jobs"
                    foreach($job in $sqljobs)
                    {
                        $query = "
                        DECLARE @jobId binary(16)
                        DECLARE @JOB_NAME SYSNAME = N`'$job`'
                        PRINT `'Checking job `'`'`' + @JOB_NAME + `'`'`'`'
                        IF EXISTS(
                            select 1
                            from msdb.dbo.sysjobs_view job
                                inner join msdb.dbo.sysjobactivity activity on job.job_id = activity.job_id
                            where
                                activity.run_Requested_date is not null
                            and
                                activity.stop_execution_date is null
                            and
                                job.name = @JOB_NAME
                            )
                        BEGIN
                            PRINT `'Stopping job `'`'`' + @JOB_NAME + `'`'`'`'
                            EXEC msdb.dbo.sp_stop_job @JOB_NAME
                        END
                        SELECT @jobId = job_id FROM msdb.dbo.sysjobs WHERE (name = @JOB_NAME)
                        IF (@jobId IS NOT NULL)
                        BEGIN
                            EXEC msdb.dbo.sp_delete_job @jobId, @delete_unused_schedule=1
                            PRINT `'Deleting job `'`'`' + @JOB_NAME + `'`'`'`'
                        END"

                        $command = $connection.CreateCommand()
                        $command.CommandText = $query
                        $command.ExecuteScalar()
                    }
                    $connection.Close()
                    Write-Verbose "SQL Jobs deleted"
                    #$global:DSCMachineStatus = 1
                }
            } 
        }
        else {
            Write-Verbose "System is in desired state."
        }
    }

    [bool] Test() {
        Write-verbose "Test TargetResource"
        $installfolder = (Get-ItemProperty 'HKLM:\Software\Microsoft\BizTalk Server\3.0\').InstallPath
        $this.BtsConfigCmdline = ("{0}Configuration.exe" -f $installfolder)
        $datestring = (Get-Date).ToString("s").Replace(":","-") 
        $this.SsoBackupFile = "C:\Program Files\Common Files\Enterprise Single Sign-On\sso_backup_$datestring.bak" 
        $count = 0   
        # check if all files are present
        if (! (Test-Path $this.XmlConfigFile)) {
            throw("XML Config files are not found.")
        }
        if (! (Test-Path $this.BtsConfigCmdline)) {
            throw("Biztalk Configuration executable was not found.")
        }
        # Read the existing configuration file
        $inputConfig = $this.XmlConfigFile
        $backuplocation = $this.SsoBackupFile
        [xml]$xmlDoc = Get-Content $inputConfig
        # Modify backup file location :
        [System.Xml.XmlElement]$res = $xmlDoc.SelectSingleNode('//Configuration/Feature/Question/Answer/FILE/Value')
        $res.'#text' = $backuplocation
        # Save the file
        $xmlDoc.Save($inputConfig)
        $DatabaseNames = $this.Databases -split "," 
        $connectionString = "Server=$($this.SqlServerName);Database=Master;Integrated Security=True;"
        $connection = New-Object System.Data.SqlClient.SqlConnection
        $connection.ConnectionString = $connectionString
        $connection.Open()
        foreach ($DatabaseName in $DatabaseNames ) {
            $query = "SELECT Name FROM sysdatabases where Name='{0}'" -f $DatabaseName
            $command = $connection.CreateCommand()
            $command.CommandText = $query
            $queryresult = $command.ExecuteScalar()
            Write-Verbose "Queryresult : $queryresult "
            if ($DatabaseName -like $queryresult) {
                $count = $count + 1
                Write-Verbose "Exists : $DatabaseName"
            }
            else {
                Write-Verbose "Not Exists : $DatabaseName"
            }
        }
        $connection.Close()
        if (($count -gt 0) -and ($count -ne $DatabaseNames.Length)) {
            throw("Number of databases do not match. Possible incorrect state.")
        }
        if ($count -eq $DatabaseNames.Length) {
            Write-Verbose "All databases are found."
            if ($this.Ensure -eq [Ensure]::Present) {
                Write-Verbose "Ensure Present"
                return $true
            }
            else {
                Write-Verbose "Ensure Absent"
                return $false
            }
        }
        else {
            Write-Verbose "None of the databases are found."
            if ($this.Ensure -eq [Ensure]::Present) {
                Write-Verbose "Ensure Present"
                return $false
            }
            else {
                Write-Verbose "Ensure Absent"
                return $true

            }
        }
        return $false
    }
}