Public/Install-SifPreReqs.ps1

#Requires -RunAsAdministrator

$sifPreReqsExist = Get-Variable SifHelperPreReqsExist -Scope global -ErrorAction SilentlyContinue
if (!$sifPreReqsExist) {
    $global:SifHelperPreReqsExist = $false
}

Function Install-SifPreReqs {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param(
        [switch] $Force = $false
    )

    try {
        
        $whatIfSetting = $PSBoundParameters -and $PSBoundParameters.ContainsKey('WhatIf') -and $PSBoundParameters['WhatIf']
        $verboseSetting = $PSBoundParameters -and $PSBoundParameters.ContainsKey('Verbose') -and $PSBoundParameters['Verbose']

        if ($Force) {
            $global:SifHelperPreReqsExist =$false
        }
    
        if ($global:SifHelperPreReqsExist -ne $true) {

            $nugetPackageProvider = Get-PackageProvider -Name NuGet -Force -Verbose:$verboseSetting -ErrorAction Stop
            if (!$nugetPackageProvider) {
                Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Confirm:$false -Verbose:$verboseSetting
            }

            # TODO remove the module imports for PKI and WebAdministration.. should be done in module .PSD1
            if (!(Get-Module PKI)) { Import-Module PKI -ErrorAction Stop -Verbose:$whatIfSetting }

            if (!(Get-Module WebAdministration) -or (!(Get-PSDrive IIS -ErrorAction SilentlyContinue -Verbose:$verboseSetting))) {
                Get-Module WebAdministration | Remove-Module -Force -Confirm:$false
                Import-Module WebAdministration -ErrorAction Stop -Force -Verbose:$verboseSetting
            }

            $SitecoreGalleryUrl = "https://sitecore.myget.org/F/sc-powershell/api/v2"

            if (-not(Get-PSRepository -name SitecoreGallery)) {
                Register-PSRepository -Name SitecoreGallery -SourceLocation $SitecoreGalleryUrl -InstallationPolicy Trusted -Verbose:$verboseSetting
            }

            ("SitecoreInstallFramework", "SqlServer") | ForEach-Object {

                if ((Get-InstalledModule -Name $_ -ErrorAction SilentlyContinue)) {
                    Update-Module $_ -Confirm:$false -Verbose:$verboseSetting
                }
                else {
                    Install-Module $_ -Confirm:$false -AllowClobber -SkipPublisherCheck -Force -Verbose:$verboseSetting
                }

                if (!(Get-Module $_)) {
                    Write-Warning "Module '$_' is not loaded!"
                    Import-Module $_ -Force -Verbose:$verboseSetting
                }
            }

            $dacFxBinPath = $null

            function Get-DacFxPath {

                $dacFxBinPath = $null


                $sqlPackagePath = Get-SQLPackagePath -ErrorAction SilentlyContinue

                if ($sqlPackagePath) {
                    $dacFxBinPath = Split-Path -Path $sqlPackagePath -Parent
                }

                return $dacFxBinPath
            }

            $dacFxBinPath = Get-DacFxPath
            Write-Verbose "dacFxBinPath: $dacFxBinPath"

            function Install-DacFx {

                Write-Verbose "Installing DacFx 17.3"

                function silentInstallMsi {
                    param (
                        [ValidateScript( { Test-Path $_ -IsValid })]
                        [string]$path
                    )
                    $DataStamp = get-date -Format yyyyMMddTHHmmss
                    $file = get-item $path
                    $logFile = '{0}-{1}.log' -f $file.fullname, $DataStamp
                    $MSIArguments = @(
                        "/i"
                        ('"{0}"' -f $file.fullname)
                        "/qn"
                        "/norestart"
                        "/L*v"
                        $logFile
                    )
                    Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow
                }

                $sqlClrTypes = 'https://download.microsoft.com/download/C/0/2/C02DBE78-3265-4779-9AE1-634A4BF1CD6E/EN/SQL140/amd64/SQLSysClrTypes.msi'
                $sqlClrTypesFilename = Split-Path $sqlClrTypes -Leaf
                $sqlClrTypesTempFile = Join-Path $env:TEMP $sqlClrTypesFilename

                $dacFx173 = 'https://download.microsoft.com/download/3/7/F/37F3C5CE-E96B-41AC-B361-27735365AA16/EN/x64/DacFramework.msi'
                $dacFx173Filename = Split-Path $dacFx173 -Leaf
                $dacFx173TempFile = Join-Path $env:TEMP $dacFx173Filename

                # Start-BitsTransfer -Source $sqlClrTypes, $dacFx173 -Destination $sqlClrTypesTempFile, $dacFx173TempFile
                $startTime = Get-Date

                try {
                    Write-Verbose "Downloading $sqlClrTypes to $sqlClrTypesTempFile"

                    Invoke-WebRequest -Uri $sqlClrTypes -OutFile $sqlClrTypesTempFile -UseBasicParsing
                    $endTime = Get-Date
                    $timeTaken = $endTime.Subtract($startTime)
                    Write-Verbose "Time taken: $($timeTaken.TotalSeconds) seconds"
                }
                catch {
                    Write-Error -Message ("Error downloading $sqlClrTypes" + ": $($_.Exception.Message)")
                    throw
                }

                $startTime = Get-Date

                try {
                    Write-Verbose "Downloading $dacFx173 to $dacFx173TempFile"

                    Invoke-WebRequest -Uri $dacFx173 -OutFile $dacFx173TempFile -UseBasicParsing
                    $endTime = Get-Date
                    $timeTaken = $endTime.Subtract($startTime)
                    Write-Verbose "Time taken: $($timeTaken.TotalSeconds) seconds"
                }
                catch {
                    Write-Error -Message ("Error downloading $dacFx173" + ": $($_.Exception.Message)")
                    throw
                }


                # install sql clr types
                silentInstallMsi -path $sqlClrTypesTempFile

                # install dac fx 17.3
                silentInstallMsi -path $dacFx173TempFile

                Write-Verbose "Completed DacFx 17.3 installation."
            }

            $dacVersion = $null

            if ($dacFxBinPath) {
                $dacFxPath = Split-Path $dacFxBinPath -Parent
                $dacVersionPath = Split-Path $dacFxPath -Parent
                $dacVersion = Split-Path $dacVersionPath -Leaf
            }

            if (!$dacVersion -or ($dacVersion -and $dacVersion -ne 140)) {

                Install-DacFx

            }

            $chocoInstallScript = (New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')
            Set-ExecutionPolicy Bypass -Scope Process -Force
            Invoke-Expression $chocoInstallScript
            choco upgrade webdeploy -y -r

            $msDeployKeyName = 'HKLM:\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\3'
            $msDeployKeyProperties = Get-ItemProperty -Path $msDeployKeyName -ErrorAction SilentlyContinue

            if ($msDeployKeyProperties) {

                $dacFxPathKeyProp = $msDeployKeyProperties | Select-Object -ExpandProperty DacFxPath -ErrorAction SilentlyContinue

                if (!$dacFxPathKeyProp) {
                    New-ItemProperty -Path $msDeployKeyName -Name 'DacFxPath' -Value $dacFxBinPath -Force
                }
                else {
                    Set-ItemProperty -Path $msDeployKeyName -Name 'DacFxPath' -Value $dacFxBinPath -Force
                }

                $dacFxDependenciesPathKeyProp = $msDeployKeyProperties | Select-Object -ExpandProperty DacFxDependenciesPath -ErrorAction SilentlyContinue

                if (!$dacFxDependenciesPathKeyProp) {
                    New-ItemProperty -Path $msDeployKeyName -Name 'DacFxDependenciesPath' -Value $dacFxBinPath -Force
                }
                else {
                    Set-ItemProperty -Path $msDeployKeyName -Name 'DacFxDependenciesPath' -Value $dacFxBinPath -Force
                }
            }
            else {
                Write-Warning 'Could not find MSDeploy in registry.'
            }

            choco upgrade urlrewrite -y -r

            $global:SifHelperPreReqsExist = $true
        } else {
            Write-Information 'SIF PreReqs already installed.'
        }

    } finally {        

    }
}