functions/Install-DbaReports.ps1

Function Install-DbaReports
{
  <#
      .SYNOPSIS
      Installs both the server and client components for dbareports. To install only the client component, use Install-DbaReportsClient.

      .DESCRIPTION
      Installs the following on the specified SQL server:
    
      Database with all required tables, stored procedures, extended properties etc.
      Adds the executing account (SQL Agent account if no proxy specified) as dbo to the database
      Proxy/Credential (if required)
      Agent Category ("dbareports collection jobs")
      Agent Jobs
      Job Schedules
      Copies PowerShell files to SQL Server or shared network directory

      - If the specified database does not exist, you will be prompted to confirm that the script should create it.
      - If no Proxy Account is specified, you will be prompted to create one automatically or accept that the Agent ServiceAccount has access
      - If no InstallDirectory is specified, the SQL Server's backup directory will be used by default
      - If no LogFileDirectory is specified, InstallDirectory\logs will be used

      Installs the following on the local client
    
      Config file at Documents\WindowsPowerShell\Modules\dbareports\dbareports-config.json
    
      The config file is pretty simple. This is for Windows (Trusted) Authentication
    
      {
      "Username": null,
      "SqlServer": "sql2016",
      "InstallDatabase": "dbareports",
      "SecurePassword": null
      }
    
      And the following for SQL Login
      {
      "Username": "sqladmin",
      "SqlServer": "sql2016",
      "InstallDatabase": "dbareports",
      "SecurePassword": "01000000d08c9ddf0115d1118c7a00c04fc297eb010000etcetc"
      }

      Or alternative Windows credentials
      {
      "Username": "ad\\dataadmin",
      "SqlServer": "sqlcluster",
      "InstallDatabase": "dbareports",
      "SecurePassword": "01000000d08c9ddf0115d1118c7a00c04fc297eb010000etcetc"
      }
    
      Note that only the account that created the config file can decrypt the SecurePassword
    
      .PARAMETER SqlServer
      The SQL Server Instance that will hold the dbareports database and the agent jobs

      .PARAMETER SqlCredential
      Allows you to login to servers using SQL Logins as opposed to Windows Auth/Integrated/Trusted.

      .PARAMETER InstallDatabase
      The name of the database that will hold all of the information that the agent jobs gather. Defaults to dbareports

      .PARAMETER InstallPath
      The folder that will hold the PowerShell scripts that the Agent Jobs call and the logfiles for the agent jobs. The Agent account or Proxy must have access to this folder.
    
      If no InstallPath is specified, the SQL Server's default backup directory is used.

      .PARAMETER LogFileFolder
      The folder where the logs from the Agent Jobs will be written. Defaults to the "logs" folder in the Installpath directory.

      .PARAMETER LogFileRetention
      The number of days to keep the Log Files defaults to 30 days

      .PARAMETER JobPrefix
      The Prefix that gets added to the Agent Jobs defaults to dbareports

      .PARAMETER JobCategory
      The category for the Agent Jobs. Defaults to "dbareports collection jobs"
    
      .PARAMETER TimeSpan
      By default, the jobs are scheduled to execute daily unless NoJobSchedule is specified. The default time is 04:15. To change the time, pass different timespan.

      $customtimespan = New-TimeSpan -hours 22 -minutes 15

      This would set the schedule the jobs for 10:15 PM.
    
      .PARAMETER ReportsFolder
      The folder where the report samples will be stored on the client (?)

      .PARAMETER NoDatabaseObjects
      A switch which will not update or create the database and its related objects

      .PARAMETER NoJobs
      A switch which will not install the Agent Jobs

      .PARAMETER NoPsFileCopy
      A switch which will not copy the PowerShell scripts

      .PARAMETER NoJobSchedule
      A switch which will not schedule the Agent Jobs

      .PARAMETER NoConfig
      A switch which will not create the json config file on the local machine.

      .PARAMETER NoAlias
      A switch which means the script will not create an alias for the dbareports server

      .PARAMETER NoShortcut
      A switch which means the script will not create a shortcut on the desktop

      .PARAMETER Force
      A switch to force the installation of dbareports. This will drop and recreate everything and all of your data will be lost. "Use the force wisely DBA"

      .PARAMETER Confirm
      Prompts you for confirmation before executing the command.

      .PARAMETER WhatIf
      This doesnt work as install is too dynamic. Show what would happen if the cmdlet was run.
      .NOTES
      dbareports PowerShell module (https://dbareports.io, SQLDBAWithABeard.com)
      Copyright (C) 2016 Rob Sewell

      This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

      This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

      You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

      .LINK
      https://dbareports.io/Install-DbaReports

      .EXAMPLE
      Install-DBAreports -SqlServer sql2016

      Installs the dbareports database on SQL2016 and uses all defaults. Will not output to screen but will log to a log file in C:\Users\$ENV:USERNAME\Documents\WindowsPowerShell\Modules\dbareports\dbareports_install_DATE.txt

      .EXAMPLE
      Install-DBAreports -SqlServer sql2016 -InstallPath \\fileshare\share\sql

      Installs the dbareports database on the server sql2016 and the powershell script files at \\fileshare\share\sql Will not output to screen but will log to a log file in C:\Users\$ENV:USERNAME\Documents\WindowsPowerShell\Modules\dbareports\dbareports_install_DATE.txt

      .EXAMPLE
      Install-DBAreports -SqlServer sql2016 -InstallPath \\fileshare\share\sql -Verbose

      Installs the dbareports database on the server sql2016 and the powershell script files at \\fileshare\share\sql Will output to screen and will log to a log file in C:\Users\$ENV:USERNAME\Documents\WindowsPowerShell\Modules\dbareports\dbareports_install_DATE.txt
  #>

  [CmdletBinding(SupportsShouldProcess = $true)] 
  [OutputType([String])]
  Param (
    [parameter(Mandatory = $true, ValueFromPipeline = $true)]
    [Alias("ServerInstance", "SqlInstance")]
    [object]$SqlServer,
    [PSCredential]$SqlCredential,
    [Alias("Database")]
    [string]$InstallDatabase = "dbareports",
    [string]$InstallPath,
    [string]$JobPrefix = "dbareports",
    [string]$LogFileFolder,
    [int]$LogFileRetention = 30,
    [string]$ReportsFolder,
    [switch]$NoDatabaseObjects,
    [switch]$NoJobs,
    [switch]$NoPsFileCopy,
    [switch]$NoJobSchedule,
    [switch]$NoConfig,
    [switch]$NoShortcut,
    [switch]$NoAlias,
    [string]$JobCategory = "dbareports collection jobs",
    [timespan]$TimeSpan = $(New-TimeSpan -hours 4 -minutes 15),
    [switch]$Force
  )
    
  DynamicParam { if ($SqlServer) 
    {
      return (Get-ParamSqlProxyAccount -SqlServer $SqlServer -SqlCredential $SqlCredential) 
    }
  }
    
  BEGIN
  {
    try    
    {
      $docs = [Environment]::GetFolderPath("MyDocuments")
      $Date = Get-Date -format yyyyMMddhhmmss
      if((Test-Path "$docs\WindowsPowerShell\Modules\dbareports\") -eq $false)
      {
        If ($PSCmdlet.ShouldProcess("Creating Module Folder")) 
        { 
          New-Item "$docs\WindowsPowerShell\Modules\dbareports" -ItemType Directory -ErrorAction Stop
        }
      }
      If ($PSCmdlet.ShouldProcess("Creating LogFile")) 
      { 
        $LogFile = New-Item "$docs\dbareports_install_$Date.txt" -ItemType File -ErrorAction Stop
      }
    }
    catch
    {
      Write-Warning "Failed to create log file please see error below"
      Write-Error $_
      Write-Output "You can find the install log here $($Logfile.FullName)- IF it managed to create it!"
      break

    }
    $LogFilePath = $LogFile.FullName
    Write-Output "Log filepath for install is $LogFilePath"

    Function Add-DatabaseObjects
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()  
      # Schema Setup
      Write-Log -path $LogFilePath  -message "Creating schemas" 
      try
      {
        $schemanames = $sourceserver.Databases[$InstallDatabase].Schemas.Name
        $schemas = Get-ChildItem -Path "$parentPath\setup\database\Security\Schemas\*.sql"
                
        foreach ($filename in $schemas.Name)
        {
          $schemaname = $filename.Replace(".sql", "") # .TrimEnd doesn't work.
                    
          if ($schemanames -contains $schemaname)
          {
            Write-Log -path $LogFilePath  -message "Schema $schemaname already exists. Skipping." -Level Warn
            Continue
          }
                    
          Write-Log -path $LogFilePath  -message "Creating schema $schemaname" -Level Info 
          $file = Get-ChildItem -Path "$parentPath\setup\database\Security\Schemas\$filename"
          $sql = Get-Content -Path $file -Raw
          If ($PSCmdlet.ShouldProcess("Executing $filename against $installdatabase on $($sourceserver.name)")) 
          { 
            $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
          }
        }
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Schema could not be created. - $_" -Level Error 
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
            
      # Extended Properties Setup
      Write-Log -path $LogFilePath  -message "Creating extended properties" -Level info
      try
      {
        $propertynames = $sourceserver.Databases[$InstallDatabase].ExtendedProperties.Name
        $properties = Get-ChildItem -Path "$parentPath\setup\database\Extended Properties\*.sql"
                
        foreach ($filename in $properties.Name)
        {
          $name = $filename.Replace(".sql", "") # .TrimEnd doesn't work.
                    
          if ($propertynames -contains $name)
          {
            Write-Log -path $LogFilePath  -message "Extended Property $name already exists. Skipping." -Level Warn
            Continue
          }
                    
          Write-Log -path $LogFilePath  -message "Creating Extended Property $name" -Level Info
          $file = Get-ChildItem -Path "$parentPath\setup\database\Extended Properties\$filename"
          $sql = Get-Content -Path $file -Raw
          If ($PSCmdlet.ShouldProcess("Executing $filename against $installdatabase on $($sourceserver.name)")) 
          { 
            $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
          }
        }
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Extended Properties could not be created. - $_" -Level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }            
      # Table setup
      ## SHOULD THIS HAVE A NESTED TRY CATCH?
      Write-Log -path $LogFilePath  -message "Creating tables" -Level Info
      $tablenames = $sourceserver.Databases[$InstallDatabase].Tables.Name
      # FUnction to create the tables using the SQL Files
      function New-Table
      {
        [CmdletBinding(SupportsShouldProcess = $true)] 
        Param([object]$tables) 
        try
        {    
          foreach ($filename in $tables)
          {
            $table = $filename.Replace(".sql", "") # .TrimEnd didn't work :()
            $schema = $table.Split(".")[0]
            $tablename = $table.Split(".")[1]
                    
            if ($tablenames -contains $tablename)
            {
              Write-Log -path $LogFilePath  -message "$table already exists. Skipping." -Level Warn
              continue
            }
                    
            Write-Log -path $LogFilePath  -message "Creating table $tablename" -Level info
            $file = Get-ChildItem -Path "$parentPath\setup\database\Tables\$filename"
            $sql = Get-Content -Path $file -Raw
            If ($PSCmdlet.ShouldProcess("Executing $filename against $installdatabase on $($sourceserver.name)")) 
            { 
              $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
            }
          }
        }
        catch
        {
          Write-Log -path $LogFilePath  -message "Failed to create table $table - $_" -Level Error
          Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
          throw
        }

      }
      try
      {
        ## Create tabels with PKs first
        $first = 'info.serverinfo.sql', 'dbo.InstanceList.sql', 'info.Databases.sql', 'dbo.Clients.sql'
        Write-Log -path $LogFilePath  -message "Creating the first tables $first"
        New-Table -tables $first -ErrorAction Stop
      } 
      catch
      {
        Write-Log -path $LogFilePath  -message "Couldn't create the First tables - $_" -Level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        throw
      }
      try
      {
        ## Create the rest of the tables
        $therest = (Get-ChildItem -Path "$parentPath\setup\database\Tables\*.sql" | Where-Object {
            $_.Name -notin $first 
        }).Name
        Write-Log -path $LogFilePath  -message "Creating the rest of the tables $therest"
        New-Table -tables $therest -ErrorAction Stop
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Couldn't create the rest of the tables - $_" -Level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        throw
      }
            
      # Stored procedure Setup
      Write-Log -path $LogFilePath  -message  "Creating initial stored procedures" -Level Info    

      try
      {
        $procnames = $sourceserver.Databases[$InstallDatabase].StoredProcedures.Name
        $procs = Get-ChildItem -Path "$parentPath\setup\database\StoredProcedures\*.sql"
                
        foreach ($filename in $procs.Name)
        {
          $procname = $filename.Split(".")[1]
                    
          if ($procnames -contains $procname)
          {
            Write-Log -path $LogFilePath  -message "Procedure $procname already exists. Skipping." -Level Warn
            Continue
          }
                    
          Write-Log -path $LogFilePath  -message "Creating procedure $procname" -Level info
          $file = Get-ChildItem -Path "$parentPath\setup\database\StoredProcedures\$filename"
          $sql = Get-Content -Path $file -Raw
          If ($PSCmdlet.ShouldProcess("Executing $filename against $installdatabase on $($sourceserver.name)")) 
          { 
            $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
          }
        }
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Stored procedures could not be created. - $_" -Level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
    }
        
    Function Add-BulkInsertSprocs
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()
      $notriggers = 'dbo.NotEntered.sql'
      $tables = Get-ChildItem -Path "$parentPath\setup\database\Tables\*.sql" | Where-Object {
        $notriggers -notcontains $_.Name 
      }
            
      # Gotta hard refresh
      $sourceserver.Databases[$InstallDatabase].Tables.Refresh()
      $alltables = $sourceserver.Databases[$InstallDatabase].Tables
            
      $tvpnames = $sourceserver.Databases[$InstallDatabase].UserDefinedTableTypes.Name
            
      foreach ($table in $tables.BaseName)
      {
        $schema = $table.Split(".")[0]
        $tablename = $table.Split(".")[1]
                
        $tvptable = $alltables | Where-Object {
          $_.Schema -eq $schema -and $_.Name -eq $tablename 
        }
                
        if ($null -eq $tvptable)
        {
          Write-Log -path $LogFilePath  -message "Can't find $schema.$tablename. Moving on." -Level Warn
          Continue
        }
                
        $tvpname = "tvp_$tablename"
                
        if ($tvpnames -contains $tvpname)
        {
          Write-Log -path $LogFilePath  -message "TVP $schema.tvp_$tablename already exists. Skipping TVP and Stored Procedure" -Level Warn
          Continue
        }
                
        # Use the table definition to create a type
        $script = $tvptable.Script()
        $script = $script.Replace("IDENTITY(1,1) NOT NULL", "")
        $script = $script.Replace("IDENTITY(1,1) NOT NULL", "")
        $script = $script.Replace(") ON [PRIMARY]", "")
        $script = $script.Replace("TEXTIMAGE_ON [PRIMARY]", "")
        $split = ($script -Split "CREATE TABLE \[$schema\]\.\[$tablename\]\(")
        $script = $split[$split.getupperbound(0)]
                
        $sql = "CREATE TYPE $schema.tvp_$tablename AS TABLE ($script, [U] bit)"
                
        try
        {                    
          Write-Log -path $LogFilePath   -message "Creating user defined table type $schema.tvp_$tablename" -Level Info
          If ($PSCmdlet.ShouldProcess("Executing TVP SQL against $installdatabase on $($sourceserver.name)")) 
          {
            $results = $sourceserver.Databases[$InstallDatabase].ExecuteWithResults($sql)
          }
        }
        catch
        {
          Write-Log -path $LogFilePath  -message "Can't create TVP type for $table in the $InstallDatabase database on $($sourceserver.name). - $_" -Level Error
          Write-Log -path $LogFilePath  -message "$sql " -Level Error
          Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
          Continue
        }
                
        $sql = "SELECT COLUMN_NAME as columnNames FROM INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = '$schema' AND TABLE_NAME = '$tablename'"
                
        try
        {
          $results = $sourceserver.Databases[$InstallDatabase].ExecuteWithResults($sql)
        }
        catch
        {
          Write-Log -path $LogFilePath  -message "Can't get column list from $table in the $InstallDatabase database on $($sourceserver.name). - $_" -Level Error
          Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
          throw
        }
                
        $pkcolumn = Get-IdentityColumn $table
        if ($null -eq $pkcolumn)
        {
          Write-Log -path $LogFilePath  -message "No IDENTITY column found on $tablename. Skipping." -Level Warn
          Continue
        }
                
        $onebyone = @()
                
        foreach ($column in $results.Tables.ColumnNames)
        {
          if ($column -ne $pkcolumn)
          {
            $onebyone += "[a].[$column] = [b].[$column]"
          }
        }
                
        $onebyone = $onebyone -join ","
        $allcolumns = ($results.Tables.ColumnNames | Where-Object {
            $_ -ne $pkcolumn 
        }) -join "],["
        $allcolumns = "[$allcolumns]"
                
        $procname = "$schema.usp_$tablename"
        $sql = "CREATE PROCEDURE $procname
          @TVP $schema.tvp_$tablename READONLY
          AS
          BEGIN
          INSERT INTO $schema.$tablename ($allcolumns)
          SELECT $allcolumns FROM @TVP WHERE [U] = 0
                                
          UPDATE a SET
          $onebyone
          FROM @tvp b JOIN $schema.$tablename a on a.$pkcolumn = b.$pkcolumn
          WHERE [U] = 1
        END"

        try
        {
          Write-Log -path $LogFilePath  -message "Creating procedure $procname" -Level Info
          $results = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
        }
        catch
        {
          Write-Log -path $LogFilePath  -message "Can't create stored procedure for $table in the $InstallDatabase database on $($sourceserver.name). - $_" -Level Error
          Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
          throw
        }
      }
    }
        
    Function Add-Jobs
    {
      if ($jobprefix -ne "dbareports")
      {
        $jobprefix = "$jobprefix - dbareports"
      }
            
      if ($null -eq $ProxyAccount) 
      { 
        $ProxyAccount = "None" 
      }
            
      if ($InstallPath.StartsWith("\\"))
      {
        $JobFilePath = "Microsoft.PowerShell.Core\FileSystem::$InstallPath"
        $JobCommand = "powershell.exe -ExecutionPolicy Bypass"
      }
      else
      {
        #$JobFilePath = [regex]::Escape($InstallPath)
        $JobFilePath = $InstallPath
        $JobCommand = "powershell.exe -ExecutionPolicy Bypass . "
      }
            
      $diskusage = @{
        JobName = "$jobprefix - Disk Usage"
        Description = "This job will run a PowerShell script to gather the disk usage from the servers in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\DiskSpace.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $AgentJobDetail = @{
        JobName = "$jobprefix - Agent Job Results"
        Description = "This job will return all the agent job information about the servers in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\AgentJobDetail.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $AgentJobServer = @{
        JobName = "$jobprefix - Agent Job Server"
        Description = "This job will return all the agent job information about the servers in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\AgentJobServer.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $dbinfo = @{
        JobName = "$jobprefix - Database Information"
        Description = "This job will return all the database information from the Servers in the dbo.InstanceList table in the $InstallDatabase database.It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\Databases.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $winserver = @{
        JobName = "$jobprefix - Windows Server Information"
        Description = "This job will return information about the servers listed in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\ServerOSInfo.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $sqlserverinfo = @{
        JobName = "$jobprefix - SQL Server Information"
        Description = "This job will return information about the SQL Servers listed in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder\$InstallDatabaseSQLInfoUpdate_"
        Command = "$JobCommand '$JobFilePath\SQLInfo.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $suspectpages = @{
        JobName = "$jobprefix - Suspect Pages"
        Description = "This job will run a PowerShell script to gather the suspect pages from the msdb database from the servers listed in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder\$InstallDatabaseSuspectPagesUpdate_"
        Command = "$JobCommand '$JobFilePath\SuspectPages.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $logcleanup = @{
        JobName = "$jobprefix - Log File Cleanup"
        Description = "This job will run a PowerShell script to gather the suspect pages from the msdb database from the servers listed in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder\$InstallDatabaseSuspectPagesUpdate_"
        Command = "$JobCommand '$JobFilePath\cleanlogs.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $testaccess = @{
        JobName = "$jobprefix - Test Access to Servers and Log Directory"
        Description = "This job will run a PowerShell script to gather the Alerts from the servers listed in the dbo.InstanceList table in the $InstallDatabase database. It will log to $LogFileFolder"
        Command = "$JobCommand '$JobFilePath\Alerts.ps1'"
        Subsystem = 'PowerShell'
      }
            
      $historicaldbsize = @{
        JobName = "$jobprefix - Historical Database Size"
        Description = "This job will archives database size information from the Servers in the dbo.InstanceList table in the $InstallDatabase database.It will log to $LogFileFolder."
        Subsystem = "TransactSql"
        Command = "INSERT INTO [Info].[HistoricalDBSize]
          SELECT [DatabaseID]
          ,[DB].[InstanceID]
          ,[DB].[Name]
          ,[DateChecked]
          ,[SizeMB]
          ,[SpaceAvailableKB]
          FROM [$InstallDatabase].[Info].[Databases] DB JOIN [$InstallDatabase].[dbo].[InstanceList] IL ON IL.[InstanceID] = [DB].[InstanceID]
          WHERE [Environment] = 'Production'
          AND [DB].[Inactive] = 0
        AND [Status] NOT LIKE 'Offline%'"

      }
            
      $setdbinactive = @{
        LogFileFolder = $LogFileFolder
        Category = $JobCategory
        OwnerLoginName = $OwnerLoginName
        JobName = "$jobprefix - Check for and Label Inactive Databases"
        Description = "Sets the inactive field of database in info.Databases to 1 (true) when dbareports has been unable to contact/update from it for 3 days."
        Subsystem = "TransactSql"
        Command = "UPDATE [Info].[Databases] SET [Inactive] = 1 WHERE [DatabaseID] in (SELECT [DatabaseID]
          FROM [$InstallDatabase].[Info].[Databases]
          JOIN [dbo].InstanceList ON [$InstallDatabase].[Info].[Databases].[InstanceID] = [dbo].[InstanceList].[InstanceID]
          WHERE [DateChecked] < dateadd(DAY,-3,getdate())
          AND [InstanceList].[Inactive] = 0
        AND [InstanceList].[Inactive] = 0)"

      }
            
      $LogFileErrors = @{
        JobName = "$jobprefix - Log File Errors"
        Description = "This job will scrape all the log files and add the Errors and Warnings to the LogFileErrorMessages table in the $InstallDatabase database.It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\LogFileErrorMessages.ps1'"
        Subsystem = 'PowerShell'
      }

      $Alerts = @{
        JobName = "$jobprefix - Alerts"
        Description = "This job will scrape all the log files and add the Errors and Warnings to the LogFileErrorMessages table in the $InstallDatabase database.It will log to $LogFileFolder."
        Command = "$JobCommand '$JobFilePath\Alerts.ps1'"
        Subsystem = 'PowerShell'
      }

      $jobnames = $sourceserver.JobServer.Jobs.Name
            
      $hasharray = @()
      $hasharray += $diskusage
      $hasharray += $AgentJobDetail
      $hasharray += $AgentJobServer
      $hasharray += $dbinfo
      $hasharray += $winserver
      $hasharray += $sqlserverinfo
      $hasharray += $suspectpages
      $hasharray += $logcleanup
      $hasharray += $historicaldbsize
      $hasharray += $setdbinactive
      $hasharray += $testaccess
            $hasharray += $LogFileErrors 
      $hasharray += $Alerts
      
      foreach ($hash in $hasharray)
      {
        $jobname = $hash.JobName
                
        if ($jobnames -contains $jobname)
        {
          Write-Log -path $LogFilePath  -message "$jobname already exists. Skipping." -Level Warn
          Continue
        }
                
        Write-Log -path $LogFilePath  -message "Creating job $jobname" -Level Info
                
        $temphash = @{
          LogFileFolder = $LogFileFolder
          Category = $JobCategory
          OwnerLoginName = $OwnerLoginName
          ProxyAccount = $ProxyAccount
          JobName = $jobname
          SubSystem = $Hash.SubSystem
          Description = $hash.Description
          Command = $hash.Command
        }
                
        if ($jobname -eq $historicaldbsize.JobName -or $jobname -eq $setdbinactive.JobName)
        {
          # T-SQL can't support a proxy account
          $temphash.Remove('ProxyAccount')
        }
                
        Add-DbrAgentJob @temphash
      }
    }
        
    Function Copy-PsFiles
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()
      if ($InstallPath.StartsWith("\\") -eq $true)
      {
        # Make the directories
        Write-Log -path $LogFilePath  -message "Creating the directory for the PowerShell Files at $InstallPath" -Level Info
        If ($PSCmdlet.ShouldProcess("Creating $InstallPath Directory")) 
        { 
          $null = New-Item -ItemType Directory $InstallPath -Force
        }
        If ($PSCmdlet.ShouldProcess("Creating Logs Folder")) 
        {
          $null = New-Item -ItemType Directory "$InstallPath\logs" -Force
        }
        # Copy the files
        $sourcedir = "$parentPath\setup\powershell"
        Write-Log -path $LogFilePath  -message "Copying everything from $sourcedir to $InstallPath" -Level info
        If ($PSCmdlet.ShouldProcess("Copying PS Files from $sourcedir to $InstallPath")) 
        { 
          Copy-Item "$sourcedir\*.ps1" $InstallPath -Force -ErrorAction Stop
          Copy-Item "$parentPath\functions\Write-Log.ps1" $InstallPath -Force
        }
        Write-Log -path $LogFilePath  -message "All files copied" -Level Info
      }
      else
      {
        # It's local to the SQL Server.
                
        # Is the installer being run on the SQL Server itself?
        if ($Source -ne $env:COMPUTERNAME)
        {
          # Nope, copy files over UNC
          $InstallPath = Join-AdminUnc $Source $InstallPath
        }
                
        try
        {
          # Make the directories
          Write-Log -path $LogFilePath  -message "Creating the directory for the PowerShell Files at $InstallPath" -Level Info
          If ($PSCmdlet.ShouldProcess("Creating Directory $InstallPath")) 
          { 
            $null = New-Item -ItemType Directory $InstallPath -Force -ErrorAction Ignore
          }
          If ($PSCmdlet.ShouldProcess("Creating Logs Folder")) 
          { 
            $null = New-Item -ItemType Directory "$InstallPath\logs" -Force -ErrorAction Ignore
          }
          # Somtimes it takes twice. I don't know why.
          $null = New-Item -ItemType Directory $InstallPath -Force -ErrorAction Ignore
          $null = New-Item -ItemType Directory "$InstallPath\logs" -Force -ErrorAction Ignore
                    
          # copy the files to the admin UNC share
          If ($PSCmdlet.ShouldProcess("Copying PS Files from $parentPath\setup\powershell\ to $InstallPath")) 
          { 
            Copy-Item "$parentPath\setup\powershell\*.ps1" $InstallPath -Force
            Copy-Item "$parentPath\functions\Write-Log.ps1" $InstallPath -Force
          }
          Write-Log -path $LogFilePath  -message "All files copied" -Level Info
        }
        catch
        {
          Write-Log -path $LogFilePath  -message "Can't create files on $InstallPath. Check to ensure you have permissions to do so or run the installer locally. - $_" -Level error
          Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        }
      }
            
      # Do the replaces
      Write-Log -path $LogFilePath  -message  "Customizing files for this installation" -Level Info
      try
      {
        $files = Get-ChildItem "$InstallPath\*.ps1"
      }
      catch
      {
        Write-Log -path $LogFilePath  -message  "GCI failed for $installpath - $_" -Level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        break
      }
            
      if ($LogFileFolder.StartsWith("\\"))
      {
        $JobLogPath = "Microsoft.PowerShell.Core\FileSystem::$LogFileFolder"
      }
      else
      {
        $JobLogPath = $LogFileFolder
      }
            
      foreach ($file in $files)
      {
        try
        {
          Write-Log -path $LogFilePath  -message "Updating $file" -Level Info
          $customized = (Get-Content -Raw $file).Replace("--installserver--", $source)
          $customized = $customized.Replace("--installdb--", $InstallDatabase)
          $customized = $customized.Replace("--logdir--", $JobLogPath)
          $customized = $customized.Replace("--logretention--", $LogFileRetention)
          If ($PSCmdlet.ShouldProcess("Updating $file with your estate details")) 
          { 
            $customized | Set-Content $file
          }
        }
        catch
        {
          Write-Log -path $LogFilePath  -message "Failed Updating $file -$_" -Level Error
          Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        }
      }
    }
        
    Function Add-DatabaseAccess
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()
      $execaccount = $sourceserver.JobServer.ServiceAccount
            
      if ($null -ne $ProxyAccount -and $ProxyAccount -ne "None")
      {
        $proxydetails = $sourceserver.JobServer.ProxyAccounts[$ProxyAccount]
        $execaccount = $proxydetails.CredentialIdentity
      }
            
      $db = $sourceserver.Databases[$InstallDatabase]
      if ($null -ne $execaccount)
      {
                if ($null -eq $db.Users[$execaccount])
                {
                    Write-Log -path $LogFilePath  -message "Adding $execaccount to $InstallDatabase as db_owner" -Level Info
                    try
                    {
                        $dbuser = New-Object Microsoft.SqlServer.Management.Smo.User -ArgumentList $db, $execaccount
                        $dbuser.Login = $execaccount
                        If ($execaccount -eq $db.Owner)
                        {
                            write-Log -path $LogFilePath -message "$execaccount is already db_owner in $InstallDatabase" -Level Info;
                        }
                        else
                        {
                            If ($PSCmdlet.ShouldProcess("Creating Database User $execaccount"))
                            {
                                $dbuser.Create()
                            }
                            $dbo = $db.Roles['db_owner']
                            If ($PSCmdlet.ShouldProcess("Adding $execaccount as db owner for $InstallDatabase"))
                            {
                                $dbo.AddMember($execaccount)
                                $dbo.Alter()
                            }
                            Write-Log -path $LogFilePath  -message "Successfully Added $execaccount to $InstallDatabase as db_owner" -Level Info
                        }
                    }
                    catch
                    {
                        Write-Log -path $LogFilePath  "Cannot add $execaccount to $InstallDatabase as db_owner. - $_" -Level Warn
                        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
                        throw
                    }
                }
            }
        }
        
    Function Add-JobSchedule
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()
      $schedulename = "daily dbareports update"
      $now = Get-Date -format "MM/dd/yyyy"
      $sourceserver.JobServer.Jobs.Refresh()
      $dbrjobs = $sourceserver.JobServer.Jobs | Where-Object {
        $_.Category -eq $JobCategory 
      }
      $fiveminutes = New-TimeSpan -hours 0 -minutes 5
            
      foreach ($job in $dbrjobs)
      {
        $jobname = $job.name.Replace("dbareports - ", "")
        Write-Log -path $LogFilePath  -message "Scheduling $jobname for $timespan" -Level Info
                
        $schedulename = "Daily dbareports update - $jobname"
        $schedule = New-Object Microsoft.SqlServer.Management.SMO.Agent.JobSchedule($job, $schedulename)
        $schedule.FrequencyTypes = [Microsoft.SqlServer.Management.SMO.Agent.FrequencyTypes]::Daily
        $schedule.FrequencyInterval = 1
        $schedule.ActiveStartTimeofDay = $timespan
        $schedule.ActiveStartDate = $now
        If ($PSCmdlet.ShouldProcess("Creating Schedule $schedulename")) 
        { 
          try
          {
            $schedule.Create()
          }
          catch
          {
            Write-Log -path $LogFilePath -message "Failed to create schedule $schedulename - $_" -level Error
            Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
          }
        }
        If ($PSCmdlet.ShouldProcess("Adding Schedule $schedulename to Job $($Job.Name)")) 
        { 
          try
          {
            $job.AddSharedSchedule($schedule.id)
            $job.Alter()
          }
          catch
          {
            Write-Log -path $LogFilePath -message "Faield to add Schedule $schedulename to Job $($Job.name)"
            Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
          }

        }
        $timespan = $timespan.Add($fiveminutes)
      }
    }
        
    Function Get-IdentityColumn
    {
      $schema = $table.Split(".")[0]
      $tablename = $table.Split(".")[1]
            
      $sql = "SELECT name FROM $InstallDatabase.sys.columns Where [object_id] = OBJECT_ID('$schema.$tablename') AND is_identity = 1"
            
      try
      {
        Write-Log -path $LogFilePath  -message "Getting column list from $table in the $InstallDatabase on $($sourceserver.name)"
        $identity = $sourceserver.ConnectionContext.ExecuteScalar($sql)
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Can't get column list from $table in the $InstallDatabase database on $($sourceserver.name). - $_" -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        throw                    
      }
            
      return $identity
    }
        
    Function Test-Access
    {
      $paths = $LogFileFolder, $InstallPath
            
      foreach ($path in $paths)
      {
        $folderperms = Test-dbrSqlPath -SqlServer $sqlserver -Path $path
                
        if ($sqlaccount -eq $agentaccount)
        {
          if ($folderperms -eq $false)
          {
            Write-Log -path $LogFilePath  -message "SQL Server Agent Account ($agentaccount) cannot access $path - $_" -level Error
            throw 
          }
        }
      }
    }
        
    Function Add-InstallInfo
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()
      try
      {
        # sp_addextendedproperty
        $sql = "EXEC sp_updateextendedproperty N'dbareports installpath', N'$InstallPath', NULL, NULL, NULL, NULL, NULL, NULL;
        EXEC sp_updateextendedproperty N'dbareports logfilefolder', N'$LogFileFolder', NULL, NULL, NULL, NULL, NULL, NULL"

        If ($PSCmdlet.ShouldProcess("Updating Extended properties for $InstallDatabase")) 
        { 
          $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
        }
        Write-Log -path $LogFilePath  -message "Updated extended properties in the $InstallDatabase database." -level Info
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Could not update extended properties in the $InstallDatabase database. - $_" -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
    }
        
    Function Add-Migration
    {
      [CmdletBinding(SupportsShouldProcess = $true)] 
      param ()
      try
      {
        $upgradeexists = Test-Path "$parentPath\setup\database\UpgradeScripts\*.sql"
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Failed to test for upgrade scritps - $_ " -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
      if ($upgradeexists -eq $false) 
      {
        return 
      }
      try
      {
        $Migrations = Get-ChildItem -Path "$parentPath\setup\database\UpgradeScripts\*.sql"
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Failed to get upgrade scritps - $_ " -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
      try
      {
        $CurrentDBVersion = $sourceserver.Databases[$InstallDatabase].ExtendedProperties['dbareports version'].Value
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Failed to get Current Database version from $InstallDatabase - $_ " -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
      Write-Log -path $LogFilePath  -message "Current database version of $InstallDatabase is $CurrentDBVersion" -level Info
      Write-Log -path $LogFilePath  -message "Upgrading database to $DBVersion" -level Info
      foreach ($Migration in $Migrations)
      {
        $Scriptversion = $Migration.Name.Split(' ')[1]
        while ($Scriptversion -le $DBVersion)
        {
          try
          {
            $file = $Migration.FullName
            $sql = Get-Content -Path $file -Raw
            If ($PSCmdlet.ShouldProcess("Running Migration script $file on $InstallDatabase")) 
            { 
              $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
            }
            Write-Log -path $LogFilePath  -message "Upgrade file $File executed" -level Info
          }
          catch
          {
            Write-Log -path $LogFilePath  -message "$File failed to execute - $_" -level Error
            Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
            break
          }
        }
      }
      Write-Log -path $LogFilePath  -message "Upgraded database to $DBVersion" -level Info
      Write-Log -path $LogFilePath  -message "Setting Extended Property" -level Info
      try
      {
        $sql = "EXEC sp_updateextendedproperty N'dbareports version', N'$DBVersion', NULL, NULL, NULL, NULL, NULL, NULL"
        If ($PSCmdlet.ShouldProcess("Updating Extended properties for $InstallDatabase following migration")) 
        { 
          $null = $sourceserver.Databases[$InstallDatabase].ExecuteNonQuery($sql)
        }
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Failed to update extended property - $_" -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
            
    }
        
    $DBVersion = '0.0.4' # Updates extended property and runs migration scripts for that version
    $parentPath = Split-Path -Parent $PSScriptRoot
    $ProxyAccount = $psboundparameters.ProxyAccount
        
    $sourceserver = Connect-SqlServer -SqlServer $sqlserver -SqlCredential $SqlCredential
    $source = $sourceserver.DomainInstanceName
    $sqlaccount = $sourceserver.ServiceAccount
        
    if ($sourceserver.VersionMajor -lt 10)
    {
      Write-Log -path $LogFilePath  -message "The dbareports database must be installed on SQL Server 2008 and above." -level Warn
      throw
    }
  }
    
  PROCESS
  {
    if ($TimeSpan.Hours -gt 24)
    {
      throw "This is a daily schedule so the hours cannot exceed 24"
      Write-Log -path $LogFilePath  -message "This is a daily schedule so the hours cannot exceed 24" -level Error
    }
        
    # ensure agent is running
    try
    {
      $agent = $sourceserver.EnumProcesses() | Where-Object {
        $_.Program -like '*Agent*' 
      }
    }
    catch
    {
      Write-Log -path $LogFilePath  -message "Failed to gather Agent Process on $($sourceserver.name)"
      Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
    }
    $agentaccount = $sourceserver.JobServer.ServiceAccount
        
    if ($agent.count -eq 0)
    {
      throw "SQL Server Agent does not appear to be running."
      Write-Log -path $LogFilePath  -message "SQL Server Agent does not appear to be running." -level Error
    }
        
    # boom!
    if ($Force -eq $true)
    {
      if ($sourceserver.Databases[$InstallDatabase].Count -ne 0)
      {
        Write-Output "Force specified. Removing everything."
        Write-Log -path $LogFilePath  -message "Force specified. Removing everything." -level Warn
        If ($PSCmdlet.ShouldProcess("Forcing the uninstall of the previous version of dbareports including database")) 
        { 
          Uninstall-DbaReports -Force -ErrorAction SilentlyContinue
        }
      }
    }
        
    # Set installpath if not set
    if ($InstallPath.Length -eq 0)
    {
      $InstallPath = $sourceserver.BackupDirectory
      Write-Log -path $LogFilePath  -message "No install path specified, using SQL instance's backup directory $installpath" -level Warn
      # WE CAN EITHER AUTO SET IT TO BACKUPS OR PROMPT THEM WITH SHOW-SQLSERVERFILESYSTEM?
      # Agree - PROMPT THEM
    }
        
    if ($InstallPath -notlike '*dbareports*')
    {
      # Set full path
      $InstallPath = "$InstallPath\dbareports"
    }
        
    # Set logging folder if not set
    if ($LogFileFolder.Length -eq 0)
    {
      $LogFileFolder = "$InstallPath\logs"
      Write-Log -path $LogFilePath  -message "No log file path specified, using $LogFileFolder" -level Info
    }
        
    # check if database exists
    $sql = "select count(*) as dbcount from master.dbo.sysdatabases where name = '$InstallDatabase'"
    try
    {
      [bool]$dbexists = $sourceserver.ConnectionContext.ExecuteScalar($sql)
    }
    catch
    {
      Write-Log -path $LogFilePath  -message "Failed to check if $installdatabase exists on $($sourceserver.name)"
      Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
    }
        
    if ($dbexists -eq $false)
    {
      if ($Force -eq $false)
      {
        # Prompt to create and then create.
        $title = "The install database, $InstallDatabase, does not exist. Create?"
        $message = "Would you like us to create a database named $InstallDatabase on $sqlserver (Y/N)"
        $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Will continue"
        $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Will exit"
        $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
        $result = $host.ui.PromptForChoice($title, $message, $options, 0)
                
        if ($result -eq 1) 
        { 
          return "FINE!"; 
          Write-Log -path $LogFilePath  -message "User Chose not to Install Database" -level Error
        }
      }
      try
      {
        $sql = "create database [$InstallDatabase]"
        If ($PSCmdlet.ShouldProcess("Creating $InstallDatabase on $($sourceserver.name)")) 
        { 
          $dbexists = $sourceserver.ConnectionContext.ExecuteNonQuery($sql)
        }
        $sourceserver = Connect-SqlServer -SqlServer $sqlserver -SqlCredential $SqlCredential
        ##$jobserver = $sourceserver.jobserver
      }
      catch
      {
        Write-Log -path $LogFilePath  -message "Couldn't create database, sorry. BYE. $_" -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
        throw "Couldn't create database, sorry. BYE."
      }
    }
    else ## If I am right, if the db exists and db version less than version in here run the migration scripts from the current db version to version in this script
    {
      Write-Output "Checking for Migration Scripts"
      Write-Log -path $LogFilePath  -message "Checking for Migration Scripts" -level Info
      Add-Migration
    }
    If ($NoConfig -eq $false)
    {
      $securepassword = $SqlCredential.Password
            
      if ($null -ne $securepassword)
      {
        $securepassword = $securepassword | ConvertFrom-SecureString
      }
            
      $json = @{
        SqlServer = $SqlServer
        InstallDatabase = $InstallDatabase
        Username = $SqlCredential.username
        SecurePassword = $securepassword
      }
      try
      {
        $config = Get-ConfigFileName
      }
      catch
      {    
        Write-Log -path $LogFilePath -message "Failed to get config name - $_ " -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
      Write-Log -path $LogFilePath  -message "Writing config to $config" -level Info
      try
      {
        If ($PSCmdlet.ShouldProcess("Writing config to $config")) 
        { 
          $json | ConvertTo-Json | Set-Content -Path $config -Force
        }
      }
      catch
      {    
        Write-Log -path $LogFilePath -message "Failed to write config to $config - $_ " -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
    }
        
    if ($ProxyAccount.length -eq 0 -and $NoJobs -eq $false)
    {
      $dbrproxy = $sourceserver.JobServer.ProxyAccounts | Where-Object {
        $_.Name -like "*dbareports*" 
      }
            
      if ($null -eq $dbrproxy -and $Force -eq $false)
      {
        $netbiosname = $sourceserver.ComputerNamePhysicalNetBIOS
                
        if ($agentaccount -like 'NT *' -or $agentaccount -like "$netbiosname\*")
        {
          Write-Log -path $LogFilePath  -message "The Agent account, $agentaccount, is a local account. It is *highly unlikely* that it will have permissions to log into other SQL Servers." -level Warn            
        }
                
        # Prompt to create and then create.
        $title = "You haven't specified a proxy account. The SQL Server Agent service account, $agentaccount, must have access to all servers or you can use a proxy account."
        $message = " Would you like to create a proxy now? (Y/N)"
        $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Will use the proxy account"
        $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Will not use the proxy account"
        $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
        $result = $host.ui.PromptForChoice($title, $message, $options, 0)
                
        if ($result -eq 1) 
        {
          Write-Log -path $LogFilePath  -message "User Chose not to create Proxy Account" -level Info 
        }
        if ($result -eq 0)
        {
          Add-DbrCredential
                    
          $sourceserver.JobServer.ProxyAccounts.Refresh()
                    
          $dbrproxy = $sourceserver.JobServer.ProxyAccounts | Where-Object {
            $_.Name -eq "PowerShell Proxy Account for dbareports" 
          }
                    
          if ($null -ne $dbrproxy)
          {
            $ProxyAccount = $dbrproxy.Name
          }
          else
          {
            Write-Log -path $LogFilePath  -message "Proxy Account not found Cannto continue" -level Error
            throw "Proxy account not found. Can't continue."
          }
        }
      }
      elseif ($null -ne $dbrproxy)
      {
        $proxyname = $dbrproxy.Name
                
        # Prompt to create and then create.
        $title = "We found the proxy account '$proxyname' but it was not specified."
        $message = "Would you like to use it for the install? (Y/N)"
        $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Will use the proxy account"
        $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Will not use the proxy account"
        $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
        $result = $host.ui.PromptForChoice($title, $message, $options, 0)
                
        if ($result -eq 1) 
        { 
          Write-Output "FINE!";
          Write-Log -path $LogFilePath  -message "User Chose to use Proxy Account $proxyname" -level Info 
        }
        if ($result -eq 0) 
        { 
          $ProxyAccount = $proxyname 
        }
      }
    }
        
    If ($NoPsFileCopy -eq $false)
    {
      Write-Log -path $LogFilePath  -message "Copying PS Files" -level Info
      Copy-PsFiles
            
      # Get SQL Server to test the access to each path
      Test-Access
    }
        
    If ($NoDatabaseObjects -eq $false)
    {
      Write-Log -path $LogFilePath  -message "Creating SQL Objects" -level Info
      Add-DatabaseObjects
      Write-Log -path $LogFilePath  -message "Creating Stored Procedures and User Defined Table Types" -level Info
      Add-BulkInsertSprocs
      Write-Log -path $LogFilePath  -message "Adding dbareports installation extended info" -level Info
      Add-InstallInfo
    }
        
    If ($NoJobs -eq $false -and $NoDatabaseObjects -eq $false)
    {
      Add-DatabaseAccess
    }
        
    If ($NoJobs -eq $false)
    {
      Write-Log -path $LogFilePath  -message "Creating Jobs" -level Info
      Add-Jobs
    }
        
    If ($NoJobSchedule -eq $false)
    {
      Write-Log -path $LogFilePath  -message "Adding Schedules starting at $TimeSpan" -level Info
      Add-JobSchedule
    }
        
    If ($NoShortcut -eq $false)
    {
      Write-Log -path $LogFilePath  -message "Copying shortcut to desktop" -level Info
      $shortcut = "$parentPath\setup\shortcuts\dbareports.lnk"
      try
      {
        If ($PSCmdlet.ShouldProcess("Adding Shrotcut to Desktop")) 
        { 
          Copy-Item $shortcut $([Environment]::GetFolderPath("Desktop"))
        }
      }
      catch
      {
        Write-Log -Path $LogFilePath "Failed to add shortcut to desktop - $_" -level Error
        Write-Output "Something went wrong - The Beard is sad :-( . You can find the install log here $($Logfile.FullName)"
      }
    }
        
    If ($NoAlias -eq $false)
    {
      Write-Log -path $LogFilePath  -message "Creating a SQL Server alias called dbareports to $sqlserver in registry which requires admin access." -level Info
      Write-Log -path $LogFilePath  -message "This will enable PowerBI to run without additional configuration." -level Info
      New-DbrSqlAlias
    }
        
    Write-Log -path $LogFilePath  -message "Thanks for installing dbareports! Here are the results of Get-DbrConfig:" -level Info        
    $GetConfig = Get-DbrConfig
    Write-Log -path $LogFilePath  -message $GetConfig -Level Info
    Write-Log -path $LogFilePath  -message "You may now run Add-DbrServerToInventory to add a new server to your inventory." -level Info
        
    if ($Force -eq $false)
    {
      # Prompt to create and then create.
      $title = "Actually, we can automatically add $SqlServer to your inventory."
      $message = "Would you like us to add $SqlServer to the inventory now? (Y/N)"
      $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Will continue"
      $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Will exit"
      $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
      $result = $host.ui.PromptForChoice($title, $message, $options, 0)
            
      if ($result -eq 1) 
      { 
        Write-Output "K!" ;
        Write-Log -path $LogFilePath  -message "User Chose not to add $SQLServer to inventory" -Level Info
      }
    }
    else
    {
      $result = 0
    }
        
    if ($result -eq 0)
    {
      Write-Log -path $LogFilePath  -message "Adding $SqlServer to inventory using Add-DbrServerToInventory" -Level Info
      Add-DbrServerToInventory -SqlInstance $sqlserver
    }
  }
    
  END
  {
    $sourceserver.ConnectionContext.Disconnect()
    $title = "Want to review the install log?"
    $message = "Would you like to review the install log now? (Y/N)"
    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Will continue"
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Will exit"
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
    $result = $host.ui.PromptForChoice($title, $message, $options, 0)
            
    if ($result -eq 1) 
    { 
      Write-Output "K!" 
    }
    else
    {
      notepad $LogFilePath
    }
        
  }
}