clear
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
function Get-INIContent(){
    [CmdletBinding()]
    Param (
    [Parameter(Mandatory=$true, Position=1)]
    [String]$subject, 
    [Parameter(Mandatory=$true, Position=2)]
    [String]$appNam
    )
    Process
    {
        $appVal=''
        $hashAppVal=@{}
        $ischk=$false
        $egurkhaPath=(Get-Item Env:EGURKHA_INSTALL_DIR).value.ToString()
        $tstIniPath=$egurkhaPath+'\agent\config\O365_Prerequisites.ini'
        $iniContent=get-content -Path $tstIniPath
        $isFound=$false
        for($i=0;$i -lt $iniContent.Length;$i++ ){
            if($appNam -eq 'none'){
                if($iniContent[$i].StartsWith('['+$subject) -and (!$iniContent[$i].StartsWith(';'))){ 
                    $ischk=$true
                    #Write-Host '88888 ' $iniContent[$i]
                    $subNam=($iniContent[$i] -split '-')[1]
                    $val=$subNam.Substring(0,($subNam.length-1)).Trim()
                    $i++
                    $key=($iniContent[$i] -split '=')[1]
                    $hashAppVal.Add($key,$val)
                }
            }else{
                if($iniContent[$i].StartsWith('['+$subject) -and (!$iniContent[$i].StartsWith(';'))){ 
                    $i++
                    while($true){
                        try{
                            $iniArr=$iniContent[$i].Split('=')
                            if($appNam -eq $iniArr[0]){
                                $appVal=$iniArr[1]
                                $isFound=$true
                                break;    
                            }
                        }catch{$isFound=$true;break;}
                            $i++  
                    }
                }
                if($isFound){break;}
            }
        }
        if($ischk){
            return $hashAppVal
        }
        else{
            return $appVal
        }
    }
}
function Check-DotNETversion(){
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true, Position=1)]
        [String]$FolderName1, 
        [Parameter(Mandatory=$true, Position=2)]
        [String]$FolderName2,
        [Parameter(Mandatory=$true, Position=3)]
        [String]$ReleaseNo
    )
    Process{
        $getPaths=Get-ChildItem -Path 'HKLM:SOFTWARE\Microsoft\NET Framework Setup\NDP' |select *
        foreach($path in $getPaths){
            if($path.Name.EndsWith($FolderName1)){
                $path1=$path.Name.Replace('HKEY_LOCAL_MACHINE\','HKLM:')
                $secndPaths=Get-ChildItem -Path $path1
                foreach($secPath in $secndPaths){
                    if($secPath.Name.EndsWith($FolderName2)){
                        $getProps=$secPath.Name.Replace('HKEY_LOCAL_MACHINE\','HKLM:')
                        if((Get-ItemProperty $getProps).Release -ge $ReleaseNo){
                            return $true
                        }
                        else{
                            return $false
                        }
                    }
                }
            }
        }
    }
}

$os=[String](Get-WMIObject win32_operatingsystem).Name
$osNam=$os.Substring(0,$os.IndexOf('|')).Trim() #(Microsoft Windows 7 Professional |C:\Windows|\Device\Harddisk0\Partition2)
$csdVersion=(Get-WMIObject win32_operatingsystem).CSDVersion #(Service Pack 1)
$sysType=(Get-WMIObject win32_operatingsystem).OSArchitecture #(64-bit)

Write-Host 'SYSTEM INFO - ' $osNam ' -- ' $csdVersion '--' $sysType

#Set Download Location
$dwnld=Get-INIContent -subject 'Location' -appNam 'Download'
if($dwnld -ne 'none' -and (Test-Path $dwnld)){
    $DownloadLocation=$dwnld   
}else{
    $DownloadLocation = $env:USERPROFILE+'\downloads\O365\'
}
if(!(Test-Path -Path $DownloadLocation)){
    $null=New-Item -ItemType directory -Path $DownloadLocation
}
Write-Host 'Download Location - ' $DownloadLocation

#Set LOG Location
$lgf=Get-INIContent -subject 'Location' -appNam 'Log'
if($lgf -ne 'none' -and (Test-Path $lgf)){
    $logDir=$lgf   
}else{
    $egurkhaPath=(Get-Item Env:EGURKHA_INSTALL_DIR).value.ToString()
    $logDir=$egurkhaPath+'\agent\O365'
}
if(!(Test-Path -Path $logDir)){
    $null=New-Item -ItemType directory -Path $logDir
}
$logFile=$logDir+'\Installation.log'
#Remove-Item -Path $logFile

Function O365-WriteLog{
	Param(
    [String]$writString,
    [String]$LogPath,
    [String]$ReportingName
    )
    $LogPath1=$LogPath.Replace(".log","1.log")
	[string]$date = Get-Date -Format G
    ( "[" + $date + "] - [" + $ReportingName+"]"+" - " + $writString ) | Out-File -FilePath $LogPath -Append
    if ([System.IO.File]::Exists($LogPath) -and (Get-Item $LogPath).length -gt 2mb) {  #if the size of file is greater than 1MB 
        if([System.IO.File]::Exists($LogPath1)){  #if logfile1 already exists, delete logfile1 
            Remove-Item $LogPath1 
        } 
        Rename-Item $LogPath $LogPath1 
    }
}

function Unzip{
    param([string]$zipfile, [string]$outpath)
    #[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
    $shell_app=new-object -com shell.application
    $zip_file = $shell_app.namespace($zipfile)
    $destination = $shell_app.namespace($outpath)
    $destination.Copyhere($zip_file.items())
}

function Chk-OSTypes(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$OSStr       
    )
    Process
    {
        if($OSStr -eq 'AllOS'){
            return $true
        }else{
            $chkOS=$false
            $osArr=$OSStr -split '!'
            foreach($osTyp in $osArr){           
                if($osTyp -match '#' -and $osTyp -notmatch '-'){
                    $osVerArr=$osTyp -split '#'
                    if($osNam -match $osVerArr[0] -and $osNam -match $osVerArr[1]){$chkOS=$true}
                }elseif($osTyp -match '#' -and $osTyp -match '-'){
                    $osVerArr=$osTyp -split '#'
                    $osHyArr=$osVerArr[1] -split '-'
                    if($osNam -match $osVerArr[0] -and $osNam -match $osHyArr[0] -and $csdVersion -match $osHyArr[1]){$chkOS=$true}
                }elseif($osTyp -notmatch '#' -and $osTyp -match '-'){
                    $osVerArr=$osTyp -split '-'
                    if($osNam -match $osVerArr[0] -and $csdVersion -match $osVerArr[1]){$chkOS=$true}
                }else{
                    if($osNam -match $osTyp){$chkOS=$true}
                }
                if($chkOS){
                    return $true
                }
            }
            return $false   
        }
    }
}

function Chk-Registry(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$RegStr       
    )
    Process
    {
        if($RegStr -eq 'NIL'){
            return $true
        }else{
            $regArr=$RegStr -split '#'
            $regValuesArr=$regArr[1] -split '!'
            $regValues=Get-ItemProperty -Path $regArr[0]
            foreach($regValue in $regValuesArr){
                $valArr=$regValue -split '-'
                $regStr=$valArr[0]
                $curval=[int]$regValues."$regStr"
                $val=[int]$valArr[1]
                if(!($curval -ge $val)){
                    return $true
                    break;
                }
            }
            return $false
        }
    }
}


function Proceed-Download(){
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, Position=1)]
        [String]$APPName, 
        [Parameter(Mandatory=$true, Position=2)]
        [String]$APPFile
    )
    Process
    {
        Try{
            if($APPFile -match '#'){
                $arr=$APPFile -split '#'
                $appDst=$arr[0].Substring($arr[0].LastIndexOf('/')+1)
                $dest=$DownloadLocation+$appDst
                if((Get-Host).Version.Major -le 3){
                    $wc=New-Object System.Net.WebClient
                    $wc.DownloadFile($arr[0],$dest)
                }else{
                    $isPresent=Test-Path $dest -PathType Leaf
                    if(!$isPresent){
                        Try{
                            Write-Host $APPName '- Download started...' -ForegroundColor Green
                            O365-WriteLog -writString 'Downloading started' -LogPath $logFile -ReportingName $APPName
                            Start-BitsTransfer -Source $arr[0] -Destination $dest -TransferType Download -Description "Transfering $APPName" -ErrorAction Stop
                            Write-Host $APPName '- Download completed!' -ForegroundColor Green
                            O365-WriteLog -writString 'Downloading completed' -LogPath $logFile -ReportingName $APPName
                        }Catch{
                            Write-Host $APPName '- Download not completed or failed!' -ForegroundColor Green
                            O365-WriteLog -writString 'Downloading not completed or failed' -LogPath $logFile -ReportingName $APPName
                        }
                    }
                }
                Unzip -zipfile $dest -outpath $DownloadLocation
                #$dest=$dest.Replace(".zip",$arr[1])
                #$installHash.Add($dest,$APPName)
            }else{
                $appDst=$APPFile.Substring($APPFile.LastIndexOf('/')+1)
                $dest=$DownloadLocation+$appDst
                if((Get-Host).Version.Major -le 3){
                    $wc=New-Object System.Net.WebClient
                    $wc.DownloadFile($APPFile,$dest)
                }else{
                    $isPresent=Test-Path $dest -PathType Leaf
                    if(!$isPresent){
                        Try{
                            Write-Host $APPName '- Download started...' -ForegroundColor Green
                            O365-WriteLog -writString 'Download started...' -LogPath $logFile -ReportingName $APPName
                            Start-BitsTransfer -Source $APPFile -Destination $dest -TransferType Download -Description "Transfering $APPName" -ErrorAction Stop
                            Write-Host $APPName '- Download completed!' -ForegroundColor Green
                            O365-WriteLog -writString 'Download completed!' -LogPath $logFile -ReportingName $APPName
                        }Catch{
                            Write-Host $APPName '- Download not completed or failed!' -ForegroundColor Green
                            O365-WriteLog -writString 'Download not completed or failed!' -LogPath $logFile -ReportingName $APPName
                        }
                    }
                }       
            }
        }Catch{
                Write-Host "Download Failed" $Exception.Message -ForegroundColor Red
        }
    }      
}

O365-WriteLog -writString '*****************************************************************' -LogPath $logFile -ReportingName 'START'
O365-WriteLog -writString $osNam ' -- ' $csdVersion '--' $sysType -LogPath $logFile -ReportingName 'SYSTEM INFO'
O365-WriteLog -writString $DownloadLocation -LogPath $logFile -ReportingName 'Download Location'

$preDwnldHash=[ordered]@{}
$installHash=[ordered]@{}
$moduleHash=[ordered]@{}

$options=@{}
$options=Get-INIContent -subject 'APPs' -appNam 'none'
$onames =$options.Keys
$chkBxStr=''
$isRunNetwrkAssmnt=$False
######***GUI****#######
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object System.Windows.Forms.Form
$flowlayoutpanel = New-Object System.Windows.Forms.FlowLayoutPanel
$buttonOK = New-Object System.Windows.Forms.Button
$textbox1=New-Object System.Windows.Forms.TextBox
$label1=New-Object System.Windows.Forms.Label
$textbox2=New-Object System.Windows.Forms.TextBox
$label2=New-Object System.Windows.Forms.Label

$textbox3=New-Object System.Windows.Forms.TextBox
$label3=New-Object System.Windows.Forms.Label
$textbox4=New-Object System.Windows.Forms.TextBox
$label4=New-Object System.Windows.Forms.Label
$label5=New-Object System.Windows.Forms.Label

$O365DtlsLbl=New-Object System.Windows.Forms.Label
$O365UsrLbl=New-Object System.Windows.Forms.Label
$O365UsrTxtBx=New-Object System.Windows.Forms.TextBox
$O365PassLbl=New-Object System.Windows.Forms.Label
$O365PassTxtBx=New-Object System.Windows.Forms.TextBox

$compLbl=New-Object System.Windows.Forms.Label
   
$totalvalues = ($onames.count)

$formsize = 290 + (30 * $totalvalues)
$flowlayoutsize = 10 + (30 * $totalvalues)
$buttonplacement = 245 + (30 * $totalvalues)

$script:CheckBoxArray = @()

$form_Load = {
    foreach($user in $onames){
        $DynamicCheckBox = New-object System.Windows.Forms.CheckBox
        $DynamicCheckBox.Margin = '10, 8, 0, 0'
        $DynamicCheckBox.Name = $user
        $DynamicCheckBox.Size = '200, 22'
        $DynamicCheckBox.Text = "" + $user
        $DynamicCheckBox.TextAlign = 'MiddleLeft'
        $flowlayoutpanel.Controls.Add($DynamicCheckBox)
        $script:CheckBoxArray += $DynamicCheckBox
    }       
}
$form.Controls.Add($O365DtlsLbl)
$form.Controls.Add($O365UsrLbl)
$form.Controls.Add($O365UsrTxtBx)
$form.Controls.Add($O365PassLbl)
$form.Controls.Add($O365PassTxtBx)
$form.Controls.Add($label5)
$form.Controls.Add($label1)
$form.Controls.Add($textbox1)
$form.Controls.Add($label2)
$form.Controls.Add($textbox2)
$form.Controls.Add($label3)
$form.Controls.Add($textbox3)
$form.Controls.Add($label4)
$form.Controls.Add($textbox4)
$form.Controls.Add($compLbl)
$form.Controls.Add($flowlayoutpanel)
$form.Controls.Add($buttonOK)
$form.AcceptButton = $buttonOK
$form.AutoScaleDimensions = '8, 17'
$form.AutoScaleMode = 'Font'
$form.ClientSize = "360 , $formsize"
$form.FormBorderStyle = 'FixedDialog'
$form.Margin = '5, 5, 5, 5'
$form.MaximizeBox = $False
$form.MinimizeBox = $False
$form.Name = 'form1'
$form.StartPosition = 'CenterScreen'
$form.Text = 'O365 Prerequisites'
$form.add_Load($($form_Load))
    
$flowlayoutpanel.BorderStyle = 'FixedSingle'
$flowlayoutpanel.Location = '38, 220'
$flowlayoutpanel.Margin = '4, 4, 4, 4'
$flowlayoutpanel.Name = 'flowlayoutpanel1'
$flowlayoutpanel.AccessibleName = 'flowlayoutpanel1'
$flowlayoutpanel.Size = "270, $flowlayoutsize"
$flowlayoutpanel.TabIndex = 1

$O365DtlsLbl.Location="38,15"
$O365DtlsLbl.Anchor="Bottom, Left"
$O365DtlsLbl.Text="&O365 Details :"
$O365DtlsLbl.Size="100,20"

$O365UsrLbl.Location="38,38"
$O365UsrLbl.Anchor="Bottom, Left"
$O365UsrLbl.Text="&Username"
$O365UsrLbl.Size="60,20"

$O365UsrTxtBx.Location="105,38"
$O365UsrTxtBx.Name="O365User"
$O365UsrTxtBx.Size="200,20"
$O365UsrTxtBx.Text="none"

$O365PassLbl.Location="38,67"
$O365PassLbl.Anchor="Bottom, Left"
$O365PassLbl.Text="&Password"
$O365PassLbl.Size="60,20"

$O365PassTxtBx.Location="105,67"
$O365PassTxtBx.Name="O365Pass"
$O365PassTxtBx.Size="200,20"
$O365PassTxtBx.Text="none"
$O365PassTxtBx.PasswordChar='*'

$label5.Location="38,95"
$label5.Anchor="Bottom, Left"
$label5.Text="&Proxy Details :"
$label5.Size="100,20"

$label1.Location="38,118"
$label1.Anchor="Bottom, Left"
$label1.Text="&Host IP"
$label1.Size="60,20"

$textbox1.Location="105,118"
$textbox1.Name="ProxyHost"
$textbox1.Size="120,20"
$textbox1.Text="none"

$label2.Location="228,118"
$label2.Anchor="Bottom, Left"
$label2.Text="&Port"
$label2.Size="25,20"

$textbox2.Location="255,118"
$textbox2.Name="Port"
$textbox2.Size="50,20"
$textbox2.Text="none"

$label3.Location="38,145"
$label3.Anchor="Bottom, Left"
$label3.Text="&Username"
$label3.Size="60,20"

$textbox3.Location="105,145"
$textbox3.Name="ProxyUser"
$textbox3.Size="200,20"
$textbox3.Text="none"

$label4.Location="38,171"
$label4.Anchor="Bottom, Left"
$label4.Text="&Password"
$label4.Size="60,20"

$textbox4.Location="105,171"
$textbox4.Name="ProxyPass"
$textbox4.Size="200,20"
$textbox4.Text="none"
$textbox4.PasswordChar='*'

$compLbl.Location="38,200"
$compLbl.Anchor="Bottom, Left"
$compLbl.Text="&Components to be monitored :"
$compLbl.Size="180,20"

$buttonOK.Anchor = 'Bottom, Right'
$buttonOK.DialogResult = 'OK'
$buttonOK.Location = "135, $buttonplacement"
$buttonOK.Margin = '4, 4, 4, 4'
$buttonOK.Name = 'buttonOK'
$buttonOK.Size = '100, 30'
$buttonOK.TabIndex = 0
$buttonOK.Text = '&OK'

$frmDialog=$form.ShowDialog()
$isChkdOption=$false
foreach($cbox in $CheckBoxArray){
    if($cbox.CheckState -eq 'Checked'){
        $isChkdOption=$true
        $chkBxStr=$chkBxStr+'~'+$options[$cbox.Name]
    }   
}  
Remove-Variable checkbox*
if($frmDialog -eq 'OK' -and $isChkdOption){
    $proxyHost=$textbox1.Text
    $proxyPort=$textbox2.Text
    $proxyUsr=$textbox3.Text
    $proxyPass=$textbox4.Text
    $userName=$O365UsrTxtBx.Text
    $password=$O365PassTxtBx.Text

    $chkVerError=$false
    foreach($opt in $options.Values){
        if($chkBxStr -match $opt){
            $subject='APPs-'+$opt
            $cntNam=$opt+'_ChkDotNetVer'
            $chkVerArr=Get-INIContent -subject $subject -appNam $cntNam
            if($chkVerArr -ne $null -and $chkVerArr -ne '') {
                $verArr=$chkVerArr.Split('~')
                $chkVersion=Check-DotNETversion -FolderName1 $verArr[0] -FolderName2 $verArr[1] -ReleaseNo $verArr[2]
                if($chkVersion -eq $false){
                    $chkVerError=$true
                    $chkSub='APPs-'+$opt;$chkNam=$opt+'_Name'
                    $nam=Get-INIContent -subject $chkSub -appNam $chkNam
                    Write-Host 'Please upgrade your .NET Framework to '$verArr[3]'v to monitor '$nam -ForegroundColor Red
                }
            }
        }  
    }
    if($chkVerError){
        Write-Host 'Error! Exiting...'
        exit
    }
   
    if($userName -ne '' -and $userName -ne $null -and $userName -ne 'none' -and $password -ne '' -and $password -ne $null -and $password -ne 'none'){
        $credential = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $password -asplaintext -force)
    }
    $sessionOption = New-PSSessionOption -SkipRevocationCheck
    if($proxyHost -ne '' -and $proxyHost -ne $null -and $proxyHost -ne 'none' -and $proxyPort -ne '' -and $proxyPort -ne $null -and $proxyPort -ne 'none'){
        $proxyserver='http://'+$proxyHost+':'+$proxyPort
        O365-WriteLog -writString 'Proxy Available in this System '$proxyserver -LogPath $logFile -ReportingName 'SYSTEM'
        [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy($proxyserver)
        if($proxyUsr -ne '' -and $proxyUsr -ne $null -and $proxyUsr -ne 'none' -and $proxyPass -ne '' -and $proxyPass -ne $null -and $proxyPass -ne 'none'){
            O365-WriteLog -writString 'Proxy credentials are Available in this System ' -LogPath $logFile -ReportingName 'SYSTEM'
            $proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $proxyUsr, $(convertto-securestring $proxyPass -asplaintext -force)
            [system.net.webrequest]::defaultwebproxy.credentials =$proxyCred
            [system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
            $sessionOption = New-PSSessionOption -SkipRevocationCheck -ProxyAccessType WinHttpConfig -ProxyAuthentication basic -ProxyCredential $proxyCred
        }
    }

    $moduleNam=Get-InstalledModule
    $availModules=''
    foreach($nam in $moduleNam){
        $availModules=$availModules+'~'+$nam.Name
    }
    
    Try{
        Set-PSRepository -Name PSGallery -InstallationPolicy Trusted -ErrorAction Stop
    }Catch{}

    foreach($opt in $options.Values){
        $subject='APPs-'+$opt
        if($chkBxStr -match $opt){
            if($chkBxStr -match 'SBO'){$isRunNetwrkAssmnt=$true}
            $subject='APPs-'+$opt
            $cntNam=$opt+'_Ins'
            $appsOptArr=Get-INIContent -subject $subject -appNam $cntNam
            $appsOpts=$appsOptArr -split '~'
            foreach($appOpt in $appsOpts){
                if($appOpt -ne 'none'){
                    $appOptArr=$appOpt -split '@'
                    $chkOS=Chk-OSTypes $appOptArr[1]
                    $chkReg=Chk-Registry $appOptArr[2]
                    if($chkOS -and $chkReg){
                        $APPName=$appOptArr[0]
                        $APPFile=$appOptArr[3]
                        if($APPFile -match '#'){
                            $arr=$APPFile -split '#'
                            $appDst=$arr[0].Substring($arr[0].LastIndexOf('/')+1)
                            $dest=$DownloadLocation+$appDst
                            $isPresent=Test-Path $dest -PathType Leaf
                            if(!$isPresent){
                                Try{
                                    $preDwnldHash.add($APPName,$APPFile)
                                }Catch{}
                            }
                            $dest=$dest.Replace(".zip",$arr[1])
                        }else{
                            $appDst=$APPFile.Substring($APPFile.LastIndexOf('/')+1)
                            $dest=$DownloadLocation+$appDst
                            $isPresent=Test-Path $dest -PathType Leaf
                            if(!$isPresent){
                                Try{
                                    $preDwnldHash.add($APPName,$APPFile)
                                }Catch{}
                            }
                        } 
                        Try{
                            $installHash.Add($dest,$APPName) 
                        }Catch{}
                    }
                }
            }
        }

        $appNAm=$opt+'_PG'
        $APPsPGArr=Get-INIContent -subject $subject -appNam $appNAm
        $pgArr=$APPsPGArr -split '~'
        $i=0
        foreach($pg in $pgArr){
            Try{
                if($availModules -notmatch $pg){
                    $moduleHash.add($pg,$i)
                }
            }Catch{}
            $i++
        }
    }
}
else{
    Write-Host 'you clicked cancel or did not select options...'
    exit
}

#DOWNLOAD
$proceedInstal1=$False
if($preDwnldHash.Count -ne 0){
    $message = @("Download the below?")
    $message+=" "
    foreach($key in $preDwnldHash.Keys){
    $message+=' -> '+$key
    }
    $res=[system.windows.forms.messagebox]::show(($message -join "`n"),"Download",'YesNo')
    if($res -eq 'Yes'){
        foreach($key in $preDwnldHash.Keys){
            Proceed-Download -APPName $key -APPFile $preDwnldHash[$key]
        } 
        $proceedInstal1=$true    
    }else{
        Write-Host 'You cancelled the download...'
    }
}else{
    $msg = @("Downloads available in")
    $msg+=$DownloadLocation
    $msg+=" "
    $msg+="Proceed with installation?"
    $procdIns=[system.windows.forms.messagebox]::show(($msg -join "`n"),"Download",'YesNo')
    if($procdIns -eq 'Yes'){
        $proceedInstal1=$true
    }else{
        Write-Host 'You cancelled the installation ....'
    }
}

#INSTALLATION
if($proceedInstal1){
    if($installHash.Count -ne 0){
        $insMsg=@("Install the below?")
        $insMsg+=" "
        foreach($key in $installHash.Keys){
            $insMsg+=' -> '+$installHash[$key]
        }
        $insRes=[system.windows.forms.messagebox]::show(($insMsg -join "`n"),"Installation",'YesNo')
        if($insRes -eq 'Yes'){
            foreach($key in $installHash.Keys){
                Try{
                    Write-Host $installHash[$key]' Installation Started...' -ForegroundColor Yellow
                    O365-WriteLog -writString 'Installation started' -LogPath $logFile -ReportingName $installHash[$key]
                    Start-Process $key -Wait -ErrorAction Stop
                    Write-Host $installHash[$key]' Installation process completed!' -ForegroundColor Yellow
                    O365-WriteLog -writString 'Installation process completed' -LogPath $logFile -ReportingName $installHash[$key]
                }Catch{
                    Write-Host 'Installation failed!' -ForegroundColor Red
                    O365-WriteLog -writString 'Installation process not completed or failed' -LogPath $logFile -ReportingName $installHash[$key]
                }  
            } 
            
            foreach($key in $moduleHash.Keys){
                Try{
                    Install-Module $key -Scope AllUsers -AllowClobber -Force
                    Write-Host $key ' modules installed successfully!' -ForegroundColor Green
                    O365-WriteLog -writString $pg ' modules are installed Successfully' -LogPath $logFile -ReportingName $key
                }
                Catch{
                    Write-Host $key ' - Exception occured - '$_.Exception.Message -ForegroundColor Red
                    O365-WriteLog -writString 'Excepton occured in'$key $_.Exception.Message -LogPath $logFile -ReportingName $key
                }
            }          
        }else{
            Write-Host 'You cancelled installation process...'
        }
    }else{
       [system.windows.forms.messagebox]::show("All Prerequisites are in place","Installation",'Ok')
    }
}

if($isRunNetwrkAssmnt){
    $egurkhaPath=(Get-Item Env:EGURKHA_INSTALL_DIR).value.ToString()
    $ntwrkAssmntFile=$egurkhaPath+'\lib\SBONtwrkAssmnt.ps1'
    $nwAssesTool=Get-Childitem "C:\*\Microsoft Skype for Business Network Assessment Tool"
    if($nwAssesTool -ne $null -and $nwAssesTool -ne ''){
        & $ntwrkAssmntFile
        write-host 'Network Assessment Tool config updated!'
    }  
}

#TESTING
#-------
Write-Host 'Checking...'
O365-WriteLog -writString 'Testing started ' -LogPath $logFile -ReportingName 'Testing'
if($credential -ne $null -and $credential -ne ''){
    foreach($opt in $options.Values){
        $subject='APPs-'+$opt
        if($chkBxStr -match $opt){ 
            $appNAm=$opt+'_Name'
            $nam=Get-INIContent -subject $subject -appNam $appNAm

            if($nam -eq 'Office 365'){
             
                #MSOnline
                Write-host "Trying to connect to Microsoft Online..." -ForegroundColor Yellow
                O365-WriteLog -writString 'trying to connect Microsoft Online.....' -LogPath $logFile -ReportingName 'TESTING - MSOnline'
                try{
                    Connect-MsolService -Credential $Credential -ErrorAction Stop
                    $Tenant = Get-MsolAccountSku
                    $domainNam = $Tenant | select -First 1
                    Write-Host 'Microsoft Online connected successfully!' -ForegroundColor Green
                    O365-WriteLog -writString 'Microsoft Online connected successfully' -LogPath $logFile -ReportingName 'TESTING - MSOnline'
                }Catch{
                    Write-Host "Failed - unable to connect to Microsoft Online!" -ForegroundColor Red
                    O365-WriteLog -writString 'Failed - Cannot connect to Microsoft Online' -LogPath $logFile -ReportingName 'TESTING - MSOnline'
                }

                #Exchange Online
                Write-host "Trying to connect to Exchange Online..." -ForegroundColor Yellow
                O365-WriteLog -writString 'trying to connect Exchange Online...' -LogPath $logFile -ReportingName 'TESTING - Exchange Online'
                try {
                    $ExchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential  -Authentication Basic -AllowRedirection -SessionOption $sessionOption -ErrorAction Stop
                    Import-PSSession $ExchSession -DisableNameChecking -AllowClobber  -ErrorAction Stop | Out-Null
                    $domain = Get-AcceptedDomain | where {$_.Name -like "*.onmicrosoft.com" -and $_.Name -notlike "*.mail.onmicrosoft.com"} | select name
                    $domainFullNam=$domain.Name   
                    Write-Host 'Exchange Online connected successfully!' -ForegroundColor Green
                    O365-WriteLog -writString 'Exchange Online connected successfully' -LogPath $logFile -ReportingName 'TESTING - Exchange Online'
                    Get-PSSession | Remove-PSSession
                } Catch {
                    Write-Host "Failed - Unable to connect to Exchange Online" -ForegroundColor Red
                    O365-WriteLog -writString 'Failed - Cannot connect to Exchange Online' -LogPath $logFile -ReportingName 'TESTING - Exchange Online'
                }             
            }

            if($nam -eq 'SharePointOnline'){
                $domainNam =""
                try{
                    Connect-MsolService -Credential $Credential -ErrorAction Stop
                    $Tenant = Get-MsolAccountSku
                    $domainNam = $Tenant | select -First 1
                    $domainNam=($domainNam.AccountName).ToString().Trim()
                    O365-WriteLog -writString $domainNam -LogPath $logFile -ReportingName 'TESTING - SharePoint Online'
                }catch{}
                if($domainNam -ne $null -and $domainNam -ne ""){
                    Write-host "Trying to connect to SharePoint Online..." -ForegroundColor Yellow
                    O365-WriteLog -writString 'trying to connect SharePoint Online...' -LogPath $logFile -ReportingName 'TESTING - SharePoint Online'
                    try{     
                        $url='https://'+$domainNam+'-admin.sharepoint.com'
                        Connect-SPOService -Url $url -Credential $credential -ErrorAction Stop
                        Write-Host 'SharePoint Online connected successfully' -ForegroundColor Green
                        O365-WriteLog -writString 'SharePoint Online connected successfully' -LogPath $logFile -ReportingName 'TESTING - SharePoint Online'
                        Disconnect-SPOService
                    }Catch{
                        Write-Host "Failed - Cannot connect to SharePoint Online" -ForegroundColor Red
                        O365-WriteLog -writString 'Failed - Cannot connect to SharePoint Online' -LogPath $logFile -ReportingName 'TESTING - SharePoint Online'
                    }
                }else{
                    Write-Host "[$domainNam is null or empty] - SharePoint Online" -ForegroundColor Red
                }
            }

            if($nam -eq 'Skype for Business Online'){
                $domainFullNam=''
                try{
                    $ExchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential  -Authentication Basic -AllowRedirection -ErrorAction Stop
                    Import-PSSession $ExchSession -DisableNameChecking -AllowClobber  -ErrorAction Stop | Out-Null
                    $domain = Get-AcceptedDomain | where {$_.Name -like "*.onmicrosoft.com" -and $_.Name -notlike "*.mail.onmicrosoft.com"} | select name
                    $domainFullNam=$domain.Name
                    O365-WriteLog -writString $domainFullNam -LogPath $logFile -ReportingName 'TESTING - Skype for Business Online'
                }catch{}
                Get-PSSession | Remove-PSSession
                if($domainFullNam -ne $null -and $domainFullNam -ne ""){
                    Write-host "Trying to connect Skype for Business Online..." -ForegroundColor Yellow
                    O365-WriteLog -writString 'trying to connect Skype for Business Online.....' -LogPath $logFile -ReportingName 'TESTING - Skype for Business Online'
                    try {
                        $SfBSession = New-CsOnlineSession -Credential $Credential -OverrideAdminDomain $domainFullNam -SessionOption $sessionOption -ErrorAction Stop 
                        Import-PSSession $SfBSession -ErrorAction Stop -AllowClobber -DisableNameChecking | Out-Null
                        Write-Host "Skype for Business Online connected successfully!" -ForegroundColor Green
                        O365-WriteLog -writString 'Skype for Business Online connected successfully' -LogPath $logFile -ReportingName 'TESTING - Skype for Business Online'
                        Get-PSSession | Remove-PSSession
                    }catch{
                        Write-Host "Failed - Unable to connect to Skype for Business Online" -ForegroundColor Red
                        O365-WriteLog -writString 'Failed - Cannot connect to Skype for Business Online' -LogPath $logFile -ReportingName 'TESTING - Skype for Business Online'
                    } 
                }else{
                    Write-Host "[$domainFullNam is null or empty] - SharePoint Online" -ForegroundColor Red
                }
            }

            if($nam -eq 'Microsoft Teams'){
                try{
                    Connect-MsolService -Credential $Credential -ErrorAction Stop
                    $Tenant = Get-MsolAccountSku
                    $domainNam = $Tenant | select -First 1
                    Write-Host 'Microsoft Online connected successfully' -ForegroundColor Green
                    O365-WriteLog -writString 'Microsoft Online connected successfully' -LogPath $logFile -ReportingName 'TESTING - MSOnline'
                }Catch{
                    Write-Host "Failed - Unable to connect to Microsoft Online" -ForegroundColor Red
                    O365-WriteLog -writString 'Failed - Cannot connect to Microsoft Online' -LogPath $logFile -ReportingName 'TESTING - MSOnline'
                }

                $ConneTeams=Connect-MicrosoftTeams -Credential $Credential
                try{

                    $ConneTeams=Connect-MicrosoftTeams -Credential $Credential
                    if($ConneTeams.Account -ne $null){

                        Write-Host 'Microsoft Teams connected successfully' -ForegroundColor Green
                    }else{
                        Write-Host 'Failed to connect Microsoft Teams ' -ForegroundColor Red
                    }
                 }catch{
                    Write-Host 'Exception Occured in  Connect-MicrosoftTeams - ' $_.Exception.Message -ForegroundColor Red
                 }                
            }

        }
    }
 }

 O365-WriteLog -writString '**************************************************************************' -LogPath $logFile -ReportingName 'END'

# SIG # Begin signature block
# MIIcdAYJKoZIhvcNAQcCoIIcZTCCHGECAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUv1x6nYconhDgAnJJm1dPJoOI
# fP+ggherMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0B
# AQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk
# IElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg
# Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
# +NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ
# 1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0
# sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6s
# cKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4Tz
# rGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg
# 0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIB
# ADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUH
# AQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYI
# KwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz
# c3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0
# LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaG
# NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD
# QS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0
# dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYE
# FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en
# IZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06
# GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5j
# DhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgC
# PC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIy
# sjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4Gb
# T8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIFNDCC
# BBygAwIBAgIQAuEYSxAWnqD3sU8D3BMzUjANBgkqhkiG9w0BAQsFADByMQswCQYD
# VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln
# aWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29k
# ZSBTaWduaW5nIENBMB4XDTE4MDcxMDAwMDAwMFoXDTIxMDkxNTEyMDAwMFowcTEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxDzANBgNVBAcTBklzZWxp
# bjEdMBsGA1UEChMUZUcgSW5ub3ZhdGlvbnMsIEluYy4xHTAbBgNVBAMTFGVHIElu
# bm92YXRpb25zLCBJbmMuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
# oNt7XWB1y9xwtvCGO/XipXallOkZ3ScdXunWCONnBzryRdCj7C/WX9s1CU8KkjRP
# FjWW+BOXvvC4ZUqw0Ad2uJAXyBY2/lV9eaoTRFB6Kb2/tJzG3je7Vcu8MxGJlwzP
# QQrr6icEJeqAPFE7vmzThVbd9H1n5Zdmwx20WCFe2V9qyVYHt7/6GS7WB2CwwjT6
# iVmiKP8HZXgr3tHZeAEb7tdQqd5//9e+8Mp8anb8ZdNgC9PQjBmbrQ/wH3kV65gK
# L+5kbgRvIfsmYxXiU1IFkq4rSQ+tfsDtYqBhGfovef9Gt8ZTjx7S4fortxwR7tlz
# i+wLO5m8I9sm4I2ouyIOQQIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoK
# o6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYEFD3yRqdsw6UIddfMPwhUMv2AaGRAMA4G
# A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWg
# M6Axhi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx
# LmNybDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl
# ZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcC
# ARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsG
# AQUFBwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
# ME4GCCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
# cnRTSEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADAN
# BgkqhkiG9w0BAQsFAAOCAQEAP1QnJ6TEczaeGxVokMinsKam1mJB+zDk4B9rfm31
# iaZe9OeNvR/UJAs+5b0gKBZF9NmTVdayAYV74vZU5IElRo59q6hbg/20Wu87UyoE
# Yjwrv2DxHgl3z80piuLllmoe79vEu/bYvreBamzZmHlyxRP0us2KRfEsLBH23y1o
# zBATLc3yBu+mCfDg9E1RfhpKyD1iMHkbC90To6bpOlP9Pd6R4WEAFROILgm2bofQ
# ZhN4UNKbJ1uLCvV2NiUbU7+YSC3NP9SdphaDBiOnUWiK8MjTIPZbhh3QjI5f342q
# cUiR4LGx/Z/6pq4w6YHWd8c1czexD7xVCom7ZafCOKFWyzCCBmowggVSoAMCAQIC
# EAMBmgI6/1ixa9bV6uYX8GYwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCVVMx
# FTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNv
# bTEhMB8GA1UEAxMYRGlnaUNlcnQgQXNzdXJlZCBJRCBDQS0xMB4XDTE0MTAyMjAw
# MDAwMFoXDTI0MTAyMjAwMDAwMFowRzELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERp
# Z2lDZXJ0MSUwIwYDVQQDExxEaWdpQ2VydCBUaW1lc3RhbXAgUmVzcG9uZGVyMIIB
# IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo2Rd/Hyz4II14OD2xirmSXU7
# zG7gU6mfH2RZ5nxrf2uMnVX4kuOe1VpjWwJJUNmDzm9m7t3LhelfpfnUh3SIRDsZ
# yeX1kZ/GFDmsJOqoSyyRicxeKPRktlC39RKzc5YKZ6O+YZ+u8/0SeHUOplsU/UUj
# joZEVX0YhgWMVYd5SEb3yg6Np95OX+Koti1ZAmGIYXIYaLm4fO7m5zQvMXeBMB+7
# NgGN7yfj95rwTDFkjePr+hmHqH7P7IwMNlt6wXq4eMfJBi5GEMiN6ARg27xzdPpO
# 2P6qQPGyznBGg+naQKFZOtkVCVeZVjCT88lhzNAIzGvsYkKRrALA76TwiRGPdwID
# AQABo4IDNTCCAzEwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0l
# AQH/BAwwCgYIKwYBBQUHAwgwggG/BgNVHSAEggG2MIIBsjCCAaEGCWCGSAGG/WwH
# ATCCAZIwKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw
# ggFkBggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgA
# aQBzACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQA
# ZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcA
# aQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwA
# eQBpAG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkA
# YwBoACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEA
# cgBlACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIA
# eQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4wCwYJYIZIAYb9bAMVMB8GA1UdIwQYMBaA
# FBUAEisTmLKZB+0e36K+Vw0rZwLNMB0GA1UdDgQWBBRhWk0ktkkynUoqeRqDS/Qe
# icHKfTB9BgNVHR8EdjB0MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRBc3N1cmVkSURDQS0xLmNybDA4oDagNIYyaHR0cDovL2NybDQuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcmwwdwYIKwYBBQUHAQEE
# azBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYB
# BQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRENBLTEuY3J0MA0GCSqGSIb3DQEBBQUAA4IBAQCdJX4bM02yJoFcm4bOIyAP
# gIfliP//sdRqLDHtOhcZcRfNqRu8WhY5AJ3jbITkWkD73gYBjDf6m7GdJH7+IKRX
# rVu3mrBgJuppVyFdNC8fcbCDlBkFazWQEKB7l8f2P+fiEUGmvWLZ8Cc9OB0obzpS
# CfDscGLTYkuw4HOmksDTjjHYL+NtFxMG7uQDthSr849Dp3GdId0UyhVdkkHa+Q+B
# 0Zl0DSbEDn8btfWg8cZ3BigV6diT5VUW8LsKqxzbXEgnZsijiwoc5ZXarsQuWaBh
# 3drzbaJh6YoLbewSGL33VVRAA5Ira8JRwgpIr7DUbuD0FAo6G+OPPcqvao173NhE
# MIIGzTCCBbWgAwIBAgIQBv35A5YDreoACus/J7u6GzANBgkqhkiG9w0BAQUFADBl
# MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
# d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
# b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMjExMTEwMDAwMDAwWjBiMQswCQYDVQQG
# EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
# cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBBc3N1cmVkIElEIENBLTEwggEiMA0G
# CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDogi2Z+crCQpWlgHNAcNKeVlRcqcTS
# QQaPyTP8TUWRXIGf7Syc+BZZ3561JBXCmLm0d0ncicQK2q/LXmvtrbBxMevPOkAM
# Rk2T7It6NggDqww0/hhJgv7HxzFIgHweog+SDlDJxofrNj/YMMP/pvf7os1vcyP+
# rFYFkPAyIRaJxnCI+QWXfaPHQ90C6Ds97bFBo+0/vtuVSMTuHrPyvAwrmdDGXRJC
# geGDboJzPyZLFJCuWWYKxI2+0s4Grq2Eb0iEm09AufFM8q+Y+/bOQF1c9qjxL6/s
# iSLyaxhlscFzrdfx2M8eCnRcQrhofrfVdwonVnwPYqQ/MhRglf0HBKIJAgMBAAGj
# ggN6MIIDdjAOBgNVHQ8BAf8EBAMCAYYwOwYDVR0lBDQwMgYIKwYBBQUHAwEGCCsG
# AQUFBwMCBggrBgEFBQcDAwYIKwYBBQUHAwQGCCsGAQUFBwMIMIIB0gYDVR0gBIIB
# yTCCAcUwggG0BgpghkgBhv1sAAEEMIIBpDA6BggrBgEFBQcCARYuaHR0cDovL3d3
# dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUF
# BwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUA
# cgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMA
# YwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQA
# IABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAA
# UABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkA
# bQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4A
# YwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYA
# ZQByAGUAbgBjAGUALjALBglghkgBhv1sAxUwEgYDVR0TAQH/BAgwBgEB/wIBADB5
# BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0
# LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp
# Z2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNy
# bDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl
# ZElEUm9vdENBLmNybDAdBgNVHQ4EFgQUFQASKxOYspkH7R7for5XDStnAs0wHwYD
# VR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQEFBQADggEB
# AEZQPsm3KCSnOB22WymvUs9S6TFHq1Zce9UNC0Gz7+x1H3Q48rJcYaKclcNQ5IK5
# I9G6OoZyrTh4rHVdFxc0ckeFlFbR67s2hHfMJKXzBBlVqefj56tizfuLLZDCwNK1
# lL1eT7EF0g49GqkUW6aGMWKoqDPkmzmnxPXOHXh2lCVz5Cqrz5x2S+1fwksW5Etw
# TACJHvzFebxMElf+X+EevAJdqP77BzhPDcZdkbkPZ0XN1oPt55INjbFpjE/7WeAj
# D9KqrgB87pxCDs+R1ye3Fu4Pw718CqDuLAhVhSK46xgaTfwqIa1JMYNHlXdx3LEb
# S0scEJx3FMGdTy9alQgpECYxggQzMIIELwIBATCBhjByMQswCQYDVQQGEwJVUzEV
# MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t
# MTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5n
# IENBAhAC4RhLEBaeoPexTwPcEzNSMAkGBSsOAwIaBQCgcDAQBgorBgEEAYI3AgEM
# MQIwADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w
# DAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUA9uRFpq8EyCxwYV3HT7QRtzc
# WdgwDQYJKoZIhvcNAQEBBQAEggEAkKPA+bU442FIzHWi7d5v6/wYUpPC2Kz5T+Lu
# 3PUfz8v4dMcRC5UHodE7UGobhgFTIQb2FO8V5atdQLLDCS3B37UcS/jumjaRHmqZ
# 7Zo7h2NH/lSC19PnMf//1zWqIMqatjDyrP8JhsnYeFcF7WBcfYULFu8doU1hasT0
# RW5kK91e7PerF9Tbj5k+BSq4yn8zuwXPRRQTcqFplOso/YqI0/bLdxCaYR9MstdL
# 0q+5+1tJFV9HXB01F7cp9E+h97PfjMCAUEjrlF2GDFyR6A+6NwjZuf0uJC+lL/nI
# JjfnpWMVcdjo4pgJsXPcvC7BKMi1hIiBMfmmVPcrh8htYgZz7qGCAg8wggILBgkq
# hkiG9w0BCQYxggH8MIIB+AIBATB2MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE
# aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMT
# GERpZ2lDZXJ0IEFzc3VyZWQgSUQgQ0EtMQIQAwGaAjr/WLFr1tXq5hfwZjAJBgUr
# DgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUx
# DxcNMjAwNzIzMDIwNDE0WjAjBgkqhkiG9w0BCQQxFgQUKBCPuL4vWffRUS/6thG8
# GDSb520wDQYJKoZIhvcNAQEBBQAEggEAMTePe2yHZEhtGh5W4UO0ciWg/dKbZsOq
# Q5+NU84ayxfMjrIHpsjDWRMG5gkmkMcljj76t8dxjpa44/E8RveQQS580E/mdt3C
# 5oXsN5Oas/h5Q3sSCV9+Dbncma9+ep28I/0M4dPiuyRE7lY4PyOrlgGmYvESm8tP
# m8T5OVogfTyvy/I2D5flQJ3h8SQ/qQFoj/Pl4b1w9nRgEacDba8YrtusZwFLSWnl
# jwYdp8c1VUxkZeahH0JmcEby0XOTW68LBmnu0gik7G3quKeEFCY6dezDt6JgqOvJ
# OhjcBHGNP482m2fYI0d54IMhqlJIjDg1pcVUGxFRDpwBTS6ykWQY+w==
# SIG # End signature block
