Private/Scriptblocks.ps1

$installD365Module = {
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()   
    }
    New-Item -ItemType Directory -Force -Path C:\Install\Log -ErrorAction SilentlyContinue | Out-Null
    Start-Transcript -Path "C:\Install\Log\InstallD365Module.$(get-date -format yyyyMMddhhmmss).log"
    Write-Host "Sleeping for 30 seconds..."
    Start-Sleep -Seconds 30
    Write-Host "Done sleeping..."
    if (Get-Module -Name SetupD365Environment -ListAvailable) {
        Write-Host "Updating module SetupD365Environment..."
        Update-Module -Name SetupD365Environment -Force
    }
    else {
        Write-Host "Installing NuGet..."
        Install-PackageProvider NuGet -Force
        Write-Host "Setting PSGallery to Trusted..."
        Set-PSRepository PSGallery -InstallationPolicy Trusted
        Write-Host "Installing module SetupD365Environment..."
        Install-Module -Name SetupD365Environment -Force
    }
    Stop-Transcript
}

$initializeVm = {
    $ErrorActionPreference = "SilentlyContinue"
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }
    New-Item -ItemType Directory -Force -Path C:\Install\Log -ErrorAction SilentlyContinue | Out-Null
    Start-Transcript -Path "C:\Install\Log\InitVM.$(get-date -format yyyyMMddhhmmss).log"
    Import-Module -Name SetupD365Environment
    if (Get-Module -Name Cloud.Ready.Software.NAV -ListAvailable) {
        Write-Host "Updating module Cloud.Ready.Software.NAV..."
        Update-Module -Name Cloud.Ready.Software.NAV -Force
    }
    else {
        Write-Host "Installing module Cloud.Ready.Software.NAV..."
        Install-Module -Name Cloud.Ready.Software.NAV -Force
    }
    Initialize-CustomAzVm
    Stop-Transcript
}

$downloadBCDVD = {
    Param(
        [Parameter(Mandatory = $false, Position = 3)]
        [string]
        $Version,
        [Parameter(Mandatory = $false, Position = 4)]
        [string]
        $CumulativeUpdate,
        [Parameter(Mandatory = $false, Position = 5)]
        [string]
        $Language
    )
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }
    Start-Transcript -Path "C:\Install\Log\DownloadBC.$(get-date -format yyyyMMddhhmmss).log"
    Import-Module SetupD365Environment
    Write-Host "Version: $Version CU: $CumulativeUpdate Lang: $Language..."
    Receive-BusinessCentralDVD -Version $Version -CumulativeUpdate $CumulativeUpdate -Language $Language
    Stop-Transcript
}

$installBC = {
    Param(
        [Parameter(Mandatory = $false, Position = 1)]
        [string]
        $DownloadDirectory,
        [Parameter(Mandatory = $false, Position = 2)]
        [string]
        $ConfigurationFile,
        [Parameter(Mandatory = $false, Position = 3)]
        [string]
        $LicenseFilename,
        [Parameter(Mandatory = $false, Position = 4)]
        [ValidateSet('13', '14', '15')]
        [string]
        $Version,
        [ValidateSet('App', 'Web')]
        [Parameter(Mandatory = $false, Position = 5)]
        [string]
        $InstallationType = "App",
        [Parameter(Mandatory = $false)]
        [PSCredential]
        $VMCredentials
    )
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }    
    Start-Transcript -Path "C:\Install\Log\InstallBC.$(get-date -format yyyyMMddhhmmss).log"
    # TODO: Remove later >>
    Update-Module -Name SetupD365Environment -Force
    # TODO <<
    Import-Module SetupD365Environment
    Write-Host "Installing Business Central"    
    $InstallArgs = @{        
    }
    if (-not([string]::IsNullOrEmpty($DownloadDirectory))) {
        $InstallArgs.Add('DownloadDirectory', $DownloadDirectory)
    }
    if (-not([string]::IsNullOrEmpty($ConfigurationFile))) {
        $InstallArgs.Add('ConfigurationFile', $ConfigurationFile)
    }
    if (-not([string]::IsNullOrEmpty($LicenseFilename))) {
        $InstallArgs.Add('LicenseFilename', $LicenseFilename)
    }
    if (-not([string]::IsNullOrEmpty($Version))) {
        $InstallArgs.Add('Version', $Version)
    }
    if (-not([string]::IsNullOrEmpty($InstallationType))) {
        $InstallArgs.Add('InstallationType', $InstallationType)
    }
    if (-not([string]::IsNullOrEmpty($VMCredentials))) {
        $InstallArgs.Add('VMCredentials', $VMCredentials)
    }    
    Install-BusinessCentral @InstallArgs
    
    # Set default Service to disabled
    Get-Service | Where-Object { $_.Name -like 'MicrosoftDynamicsNavServer*' } | Set-Service -StartupType Disabled
    Get-Service | Where-Object { $_.Name -like 'MicrosoftDynamicsNavServer*' } | Stop-Service
    Stop-Transcript
}

$generalizeVM = {
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }    
    Start-Transcript -Path "C:\Install\Log\GeneralizeVM.$(get-date -format yyyyMMddhhmmss).log"
    Write-Host "Generalizing VM. "
    Write-Host "About to call 'Sysprep.exe /generalize /oobe /shutdown /quiet'"
    Stop-Transcript
    $sysprep = 'C:\Windows\System32\Sysprep\Sysprep.exe'
    $arg = '/generalize /oobe /shutdown'
    Start-Process -FilePath $sysprep -ArgumentList $arg    
}

$writeProperties = {
    param(
        [Parameter(Mandatory = $false, Position = 1)]
        [string]
        $VMName,
        [Parameter(Mandatory = $false, Position = 2)]
        [string]
        $ScaleSetName,
        [Parameter(Mandatory = $true, Position = 3)]
        [string]
        $ResourceGroupName,
        [Parameter(Mandatory = $true, Position = 4)]
        [string]
        $StorageAccountName,
        [Parameter(Mandatory = $true, Position = 5)]
        [string]
        $KeyVaultName,
        [Parameter(Mandatory = $true, Position = 6)]
        [string]
        $StorageTableNameSetup,
        [Parameter(Mandatory = $true, Position = 7)]
        [string]
        $StorageTableNameEnvironments,
        [Parameter(Mandatory = $true, Position = 8)]
        [string]
        $StorageTableNameEnvironmentDefaults,
        [Parameter(Mandatory = $true, Position = 9)]
        [string]
        $StorageTableNameInfrastructureData
    )
    $targetFolder = 'C:\Install\AutoUpdate'
    New-Item -ItemType Directory -Path $targetFolder -ErrorAction SilentlyContinue | Out-Null
    $fullscriptpath = Join-Path $targetFolder 'Properties.ps1'
    
    $content = "
    `$VMName = '$VMName'
    `$ScaleSetName = '$ScaleSetName'
    `$ResourceGroupName = '$ResourceGroupName'
    `$StorageAccountName = '$StorageAccountName'
    `$KeyVaultName = '$KeyVaultName'
    `$StorageTableNameSetup = '$StorageTableNameSetup'
    `$StorageTableNameEnvironments = '$StorageTableNameEnvironments'
    `$StorageTableNameEnvironmentDefaults = '$StorageTableNameEnvironmentDefaults'
    `$StorageTableNameInfrastructureData = '$StorageTableNameInfrastructureData'
    "
    
    Set-Content -Path $fullscriptpath -Value $content
}

$createUpdateScheduledTask = {
    $targetFolder = 'C:\Install\AutoUpdate'
    New-Item -ItemType Directory -Path $targetFolder -ErrorAction SilentlyContinue | Out-Null
    
    $fullscriptpath = Join-Path $targetFolder 'AutoUpdate.ps1'
    
    $scriptblock = {
        try {
            Stop-Transcript | out-null
        }
        catch {
            $error.clear()
        }
        Start-Transcript -Path "C:\Install\Log\AutoUpdate.$(get-date -format yyyyMMddhhmmss).log"        
        if (Get-Module -Name SetupD365Environment -ListAvailable) {
            Update-Module -Name SetupD365Environment -Force
        }
        else {
            Install-Module -Name SetupD365Environment -Force
        }
        Import-Module -Name SetupD365Environment
        Test-CustomNetworkAvailable
        #if ((Set-CustomNetworkSettings) -eq $true) {
        # Write-Host "Updated network settings. Restarting machine..."
        # Restart-Computer -Force
        # return
        #}
        . ("C:\Install\AutoUpdate\Properties.ps1")
        $Instance = $false
        if (-not([string]::IsNullOrEmpty($VMName))) {
            $ObjectName = $VMName
        }
        else {
            $ObjectName = $ScaleSetName
            $Instance = $true
        }
        Start-CustomVMUpdate -ObjectName $ObjectName -IsScaleSet:$Instance -ResourceGroupName $ResourceGroupName -StorageAccountName $StorageAccountName -KeyVaultName $KeyVaultName -StorageTableNameSetup $StorageTableNameSetup -StorageTableNameEnvironments $StorageTableNameEnvironments -StorageTableNameEnvironmentDefaults $StorageTableNameEnvironmentDefaults -StorageTableNameInfrastructureData $StorageTableNameInfrastructureData
        Stop-Transcript
    }
    
    Set-Content -Path $fullscriptpath -Value $scriptblock
    
    $action = New-ScheduledTaskAction -Execute 'Powershell.exe' `
        -Argument "-NoProfile -WindowStyle Hidden -ExecutionPolicy Unrestricted -File `"$fullscriptpath`""
    $trigger = New-ScheduledTaskTrigger -AtStartup
    $taskPrinicpal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType  ServiceAccount -RunLevel Highest
    Register-ScheduledTask -Action $action -Trigger $trigger -Principal $taskPrinicpal -TaskName "CustomAutoUpdate" -Description "Update Azure Machine" | Out-Null   
}

$invokeAutoUpdate = {    
    . ("C:\Install\AutoUpdate\AutoUpdate.ps1")
}

$setNetConnectionProfile = {    
    $restartNecessary = $false
    foreach ($netConProfile in Get-NetConnectionProfile) {
        if ($netConProfile.NetworkCategory -ne 'Private') {
            Set-NetConnectionProfile -Name $netConProfile.Name -NetworkCategory Private
            $restartNecessary = $true
        }        
    }
    foreach ($profile in Get-NetConnectionProfile | Where-Object { $_.InterfaceAlias -like 'Ethernet*' }) {
        Set-DnsClientServerAddress -InterfaceIndex $profile.InterfaceIndex -ServerAddresses ("10.0.0.4") # TODO: Change to DC IP
    }
    if ($restartNecessary) {
        Restart-Computer -Force
    }    
}

$enableRemoting = {    
    Enable-PSRemoting -Force
    Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -RemoteAddress Any
    Set-NetFirewallRule -Name "WINRM-HTTP-In-TCP-PUBLIC" -LocalAddress Any
}

$waitForNetwork = {
    $done = $false
    $success = $false
    $noOfTries = 0
    $StartDate = (Get-Date)    
    while (-not($done)) {
        try {
            $noOfTries
            if (Test-NetConnection) {
                $done = $true
                $success = $true
            }
            else {
                Start-Sleep -Seconds 1
            }
        }
        catch {
            # Do nothing
        }
        $noOfTries++
        if ($noOfTries -ge 50) {
            # 50 tries max
            $done = $true
        }
        $duration = New-TimeSpan -Start $StartDate -End (Get-Date)
        if ($duration.Seconds -ge 180) {
            # Wait 3 Minutes max
            $done = $true
        }
    }
    if (-not($success)) {
        Write-Host "Checked Test-NetConnection $noOfTries times, without success."
    }
}

$saveDiagInformation = {
    $filename = "C:\Install\Log\DiagnoseInformation.$(get-date -format yyyyMMddhhmmss).log"
    "Output from: Get-NetIPConfiguration -All" | Out-File -FilePath $filename -Append
    "========================================" | Out-File -FilePath $filename -Append
    Get-NetIPConfiguration -All | Out-File -FilePath $filename -Append
    "========================================" | Out-File -FilePath $filename -Append
    "Output from: Get-NetConnectionProfile" | Out-File -FilePath $filename -Append
    "========================================" | Out-File -FilePath $filename -Append
    Get-NetConnectionProfile | Out-File -FilePath $filename -Append
    "========================================" | Out-File -FilePath $filename -Append
    "Output from: Get-Service | Format-Table -AutoSize" | Out-File -FilePath $filename -Append
    "========================================" | Out-File -FilePath $filename -Append
    Get-Service | Format-Table -AutoSize | Out-File -FilePath $filename -Append
    "========================================" | Out-File -FilePath $filename -Append
}

$configureSqlServer = {
    param(        
        [Parameter(Mandatory = $true)]
        [string]
        $SqlUser,
        [Parameter(Mandatory = $true)]
        [string]
        $SqlPass
    )
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }
    New-Item -ItemType Directory -Force -Path C:\Install\Log -ErrorAction SilentlyContinue | Out-Null
    Start-Transcript -Path "C:\Install\Log\SqlConfig.$(get-date -format yyyyMMddhhmmss).log"
    $scriptBlock = {
        param(        
            [Parameter(Mandatory = $true)]
            [string]
            $SqlUser,
            [Parameter(Mandatory = $true)]
            [string]
            $SqlPass
        )
        $assemblylist =   
        "Microsoft.SqlServer.Management.Common",  
        "Microsoft.SqlServer.Smo",  
        "Microsoft.SqlServer.Dmf ",  
        "Microsoft.SqlServer.Instapi ",  
        "Microsoft.SqlServer.SqlWmiManagement ",  
        "Microsoft.SqlServer.ConnectionInfo ",  
        "Microsoft.SqlServer.SmoExtended ",  
        "Microsoft.SqlServer.SqlTDiagM ",  
        "Microsoft.SqlServer.SString ",  
        "Microsoft.SqlServer.Management.RegisteredServers ",  
        "Microsoft.SqlServer.Management.Sdk.Sfc ",  
        "Microsoft.SqlServer.SqlEnum ",  
        "Microsoft.SqlServer.RegSvrEnum ",  
        "Microsoft.SqlServer.WmiEnum ",  
        "Microsoft.SqlServer.ServiceBrokerEnum ",  
        "Microsoft.SqlServer.ConnectionInfoExtended ",  
        "Microsoft.SqlServer.Management.Collector ",  
        "Microsoft.SqlServer.Management.CollectorEnum",  
        "Microsoft.SqlServer.Management.Dac",  
        "Microsoft.SqlServer.Management.DacEnum",  
        "Microsoft.SqlServer.Management.Utility"  
  
        foreach ($asm in $assemblylist) {  
            $asm = [Reflection.Assembly]::LoadWithPartialName($asm)  
        }
        $s = new-object ('Microsoft.SqlServer.Management.Smo.Server') $env:computername
        $s.Name
        $s.LoginMode
        $s.Settings.LoginMode = [Microsoft.SqlServer.Management.SMO.ServerLoginMode]::Mixed
        $s.Alter()
        Get-Service -Name MSSQLSERVER | Restart-Service -Force
        $SQLLogin = [Microsoft.SqlServer.Management.Smo.Login]::New($s, $SqlUser)
        $SQLLogin.LoginType = [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin
        $SQLLogin.PasswordPolicyEnforced = $False
        $SQLLogin.Create((ConvertTo-SecureString $SqlPass -AsPlainText -Force))
        $svrole = $s.Roles | where { $_.Name -eq 'sysadmin' };
        $svrole.AddMember($SqlUser);

        function Get-ComputerMemory {
            $mem = Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum
            return ($mem.Sum / 1MB);
        }
        
        function Get-SQLMaxMemory { 
            $memtotal = Get-ComputerMemory
            $min_os_mem = 2048 ;
            if ($memtotal -le $min_os_mem) {
                Return $null;
            }
            if ($memtotal -ge 8192) {
                $sql_mem = $memtotal - 2048
            }
            else {
                $sql_mem = $memtotal * 0.8 ;
            }
            return [int]$sql_mem ;  
        }
        
        function Set-SQLInstanceMemory {
            param (
                [string]$SQLInstanceName = ".", 
                [int]$maxMem = $null, 
                [int]$minMem = 0
            )
         
            if ($minMem -eq 0) {
                $minMem = $maxMem
            }
            [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
            $srv = New-Object Microsoft.SQLServer.Management.Smo.Server($SQLInstanceName)
            if ($srv.status) {
                Write-Host "[Running] Setting Maximum Memory: $($srv.Configuration.MaxServerMemory.RunValue)"
                Write-Host "[Running] Setting Minimum Memory: $($srv.Configuration.MinServerMemory.RunValue)"
         
                Write-Host "[New] Setting Maximum Memory to: $maxmem"
                Write-Host "[New] Setting Minimum Memory to: $minmem"
                $srv.Configuration.MaxServerMemory.ConfigValue = $maxMem
                $srv.Configuration.MinServerMemory.ConfigValue = $minMem   
                $srv.Configuration.Alter()
            }
        }
        Set-SQLInstanceMemory -maxMem (Get-SQLMaxMemory)
    }
    try {        
        $VMCredentials = New-Object System.Management.Automation.PSCredential ("$($env:computername)\$SqlUser", (ConvertTo-SecureString $SqlPass -AsPlainText -Force))
        #Enter-PSSession -ComputerName $env:computername -Credential $VMCredentials
        $session = New-PSSession -ComputerName $env:computername -Credential $VMCredentials
        #Invoke-Command -computername $env:computername -Credential $VMCredentials -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass
        #Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass
        Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass -Session $session
        Write-Host "Configuring Firewall..."
        #Enabling SQL Server Ports
        New-NetFirewallRule -DisplayName "SQL Server" -Direction Inbound -Protocol TCP -LocalPort 1433 -Action allow | Out-Null
        New-NetFirewallRule -DisplayName "SQL Admin Connection" -Direction Inbound -Protocol TCP -LocalPort 1434 -Action allow | Out-Null
        New-NetFirewallRule -DisplayName "SQL Database Management" -Direction Inbound -Protocol UDP -LocalPort 1434 -Action allow | Out-Null
        New-NetFirewallRule -DisplayName "SQL Service Broker" -Direction Inbound -Protocol TCP -LocalPort 4022 -Action allow | Out-Null
        New-NetFirewallRule -DisplayName "SQL Debugger/RPC" -Direction Inbound -Protocol TCP -LocalPort 135 -Action allow | Out-Null
        #Enabling SQL Analysis Ports
        New-NetFirewallRule -DisplayName "SQL Analysis Services" -Direction Inbound -Protocol TCP -LocalPort 2383 -Action allow | Out-Null
        New-NetFirewallRule -DisplayName "SQL Browser" -Direction Inbound -Protocol TCP -LocalPort 2382 -Action allow | Out-Null
        #Enabling Misc. Applications
        New-NetFirewallRule -DisplayName "SQL Server Browse Button Service" -Direction Inbound -Protocol UDP -LocalPort 1433 -Action allow | Out-Null
        #Exit-PSSession
        $session | Remove-PSSession
    }
    catch {
        # Do nothing
    }
    Stop-Transcript
}

$configureSqlServerDomain = {
    param(        
        [Parameter(Mandatory = $true)]
        [string]
        $SqlUser,
        [Parameter(Mandatory = $true)]
        [string]
        $SqlPass,
        [Parameter(Mandatory = $true)]
        [string]
        $DomainName
    )
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }
    New-Item -ItemType Directory -Force -Path C:\Install\Log -ErrorAction SilentlyContinue | Out-Null
    Start-Transcript -Path "C:\Install\Log\SqlConfigDomain.$(get-date -format yyyyMMddhhmmss).log"
    $scriptBlock = {
        param(        
            [Parameter(Mandatory = $true)]
            [string]
            $SqlUser,
            [Parameter(Mandatory = $true)]
            [string]
            $SqlPass,
            [Parameter(Mandatory = $true)]
            [string]
            $DomainName
        )
        $assemblylist =   
        "Microsoft.SqlServer.Management.Common",  
        "Microsoft.SqlServer.Smo",  
        "Microsoft.SqlServer.Dmf ",  
        "Microsoft.SqlServer.Instapi ",  
        "Microsoft.SqlServer.SqlWmiManagement ",  
        "Microsoft.SqlServer.ConnectionInfo ",  
        "Microsoft.SqlServer.SmoExtended ",  
        "Microsoft.SqlServer.SqlTDiagM ",  
        "Microsoft.SqlServer.SString ",  
        "Microsoft.SqlServer.Management.RegisteredServers ",  
        "Microsoft.SqlServer.Management.Sdk.Sfc ",  
        "Microsoft.SqlServer.SqlEnum ",  
        "Microsoft.SqlServer.RegSvrEnum ",  
        "Microsoft.SqlServer.WmiEnum ",  
        "Microsoft.SqlServer.ServiceBrokerEnum ",  
        "Microsoft.SqlServer.ConnectionInfoExtended ",  
        "Microsoft.SqlServer.Management.Collector ",  
        "Microsoft.SqlServer.Management.CollectorEnum",  
        "Microsoft.SqlServer.Management.Dac",  
        "Microsoft.SqlServer.Management.DacEnum",  
        "Microsoft.SqlServer.Management.Utility"  
  
        foreach ($asm in $assemblylist) {  
            $asm = [Reflection.Assembly]::LoadWithPartialName($asm)  
        } 
        $s = new-object ('Microsoft.SqlServer.Management.Smo.Server') $env:computername        
        Get-Service -Name MSSQLSERVER | Restart-Service -Force
        $SQLLogin = [Microsoft.SqlServer.Management.Smo.Login]::New($s, "$DomainName\$SqlUser")
        $SQLLogin.LoginType = [Microsoft.SqlServer.Management.Smo.LoginType]::WindowsUser
        $SQLLogin.PasswordPolicyEnforced = $False
        $SQLLogin.Create((ConvertTo-SecureString $SqlPass -AsPlainText -Force))
        $svrole = $s.Roles | where { $_.Name -eq 'sysadmin' };
        $svrole.AddMember("$DomainName\$SqlUser");
    }
    try {        
        $VMCredentials = New-Object System.Management.Automation.PSCredential ("$($env:computername)\$SqlUser", (ConvertTo-SecureString $SqlPass -AsPlainText -Force))
        #Enter-PSSession -ComputerName $env:computername -Credential $VMCredentials
        $session = New-PSSession -ComputerName $env:computername -Credential $VMCredentials
        #Invoke-Command -computername $env:computername -Credential $VMCredentials -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass
        #Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass
        Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass, $DomainName -Session $session
        #Exit-PSSession
        $session | Remove-PSSession
    }
    catch {
        # Do nothing
    }
    Stop-Transcript
}

$restoreSqlDemoDatabase = {
    param(        
        [Parameter(Mandatory = $true)]
        [string]
        $SqlUser,
        [Parameter(Mandatory = $true)]
        [string]
        $SqlPass,
        [Parameter(Mandatory = $true)]
        [string]
        $DomainName
    )
    try {
        Stop-Transcript | out-null
    }
    catch {
        $error.clear()
    }
    New-Item -ItemType Directory -Force -Path C:\Install\Log -ErrorAction SilentlyContinue | Out-Null
    Start-Transcript -Path "C:\Install\Log\SqlRestoreDemoDatabase.$(get-date -format yyyyMMddhhmmss).log"
    $scriptBlock = {
        param(        
            [Parameter(Mandatory = $true)]
            [string]
            $SqlUser,
            [Parameter(Mandatory = $true)]
            [string]
            $SqlPass,
            [Parameter(Mandatory = $true)]
            [string]
            $DomainName
        )
        $assemblylist =   
        "Microsoft.SqlServer.Management.Common",  
        "Microsoft.SqlServer.Smo",  
        "Microsoft.SqlServer.Dmf ",  
        "Microsoft.SqlServer.Instapi ",  
        "Microsoft.SqlServer.SqlWmiManagement ",  
        "Microsoft.SqlServer.ConnectionInfo ",  
        "Microsoft.SqlServer.SmoExtended ",  
        "Microsoft.SqlServer.SqlTDiagM ",  
        "Microsoft.SqlServer.SString ",  
        "Microsoft.SqlServer.Management.RegisteredServers ",  
        "Microsoft.SqlServer.Management.Sdk.Sfc ",  
        "Microsoft.SqlServer.SqlEnum ",  
        "Microsoft.SqlServer.RegSvrEnum ",  
        "Microsoft.SqlServer.WmiEnum ",  
        "Microsoft.SqlServer.ServiceBrokerEnum ",  
        "Microsoft.SqlServer.ConnectionInfoExtended ",  
        "Microsoft.SqlServer.Management.Collector ",  
        "Microsoft.SqlServer.Management.CollectorEnum",  
        "Microsoft.SqlServer.Management.Dac",  
        "Microsoft.SqlServer.Management.DacEnum",  
        "Microsoft.SqlServer.Management.Utility"  
  
        foreach ($asm in $assemblylist) {  
            $asm = [Reflection.Assembly]::LoadWithPartialName($asm)  
        } 
        $path = "C:\Install\DVD"
        $bakFile = ((Get-ChildItem -Path $path -Filter "*.bak" -Recurse) | Select-Object -First 1)
        $backupFile = $bakFile.FullName
        $server = New-Object Microsoft.SqlServer.Management.Smo.Server $env:ComputerName

        $backupDevice = New-Object Microsoft.SqlServer.Management.Smo.BackupDeviceItem($backupFile, 'File')
        $smoRestore = New-Object Microsoft.SqlServer.Management.Smo.Restore

        $DataPath = if ($server.Settings.DefaultFile.Length -gt 0 ) { $server.Settings.DefaultFile } else { $server.Information.MasterDBLogPath }
        $LogPath = if ($server.Settings.DefaultLog.Length -gt 0 ) { $server.Settings.DefaultLog } else { $server.Information.MasterDBLogPath }

        $smoRestore.Devices.Add($backupDevice)
        $smoRestoreDetails = $smoRestore.ReadBackupHeader($server)
        $smoRestore.Database = $smoRestoreDetails.Rows[0]["DatabaseName"]
        $smoRestoreFiles = $smoRestore.ReadFileList($server)

        foreach ($File in $smoRestoreFiles) {
            #Create relocate file object so that we can restore the database to a different path
            $smoRestoreFile = New-Object( "Microsoft.SqlServer.Management.Smo.RelocateFile" )
  
            #the logical file names should be the logical filename stored in the backup media
            $smoRestoreFile.LogicalFileName = $File.LogicalName
 
            $smoRestoreFile.PhysicalFileName = $( if ($File.Type -eq "L") { $LogPath } else { $DataPath } ) + "\" + [System.IO.Path]::GetFileName($File.PhysicalName)
            $smoRestore.RelocateFiles.Add($smoRestoreFile)
        }

        Restore-SqlDatabase -ServerInstance $env:ComputerName -Database $smoRestore.Database -BackupFile $backupFile -RestoreAction Files -ReplaceDatabase -RelocateFile $smoRestore.RelocateFiles
    }
    try {        
        $VMCredentials = New-Object System.Management.Automation.PSCredential ("$($env:computername)\$SqlUser", (ConvertTo-SecureString $SqlPass -AsPlainText -Force))
        $session = New-PSSession -ComputerName $env:computername -Credential $VMCredentials        
        Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $SqlUser, $SqlPass, $DomainName -Session $session
        $session | Remove-PSSession
    }
    catch {
        # Do nothing
    }
    Stop-Transcript
}

$installChoco = {
    param(        
        [Parameter(Mandatory = $false)]
        [string[]]
        $Packages
    )
    Set-ExecutionPolicy Bypass -Scope Process -Force
    Write-Host "Installing Chocolatey..."
    Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
    $chocoPath = "C:\ProgramData\chocolatey\bin\choco.exe"
    foreach ($package in $packages){
        Write-Host "Install Chocolatey-Package $package..."
        & $chocoPath install -y $package
    }    
    Write-Host "Done"
}