<#
    .Synopsis
        Powershell installer for Cavisson Agents
    .Description
        This is a powershell installer that would install Cavisson agents on
        local and in remote servers.
    .Example
        .\install.ps1 -tier AppTier -instance Instance1 -controller controller.cavisson.com:443

        Above example installs agents to the local only
    .Example
        .\install.ps1 -tier AppTier -instance Instance1 -poolName "pool1,pool2"
            -remote user1:pass1:host1,user2:pass2:host2 -dest E:\POC

        Above example installs the agents to the remote hosts
        Password is optional and if not provided it will prompt for it but in  that case
        -remote should be in format user:host,user2:host ...

    .Example
        .\install.ps1 -appAgent 1 -machineAgent 1 -logAgent 1 -tier Apptier

	.Example
        .\install.ps1 -appAgent 1 -machineAgent 1 -logAgent 1 -silent 

	above silent option is used for installing in silent mode.


        Above examples installs machineAgent, appAgent and logAgent
	
	 .\partialuninstall.ps1 -partialuninstall 1 -machineAgent 0 -appAgent 0 -logAgent 1  
	Above example uninstall logagent partially
    .Notes
        1. When using remote option -dest is required as this script copies
           related files to the remote host. The dest path must exists and it is
           not created by the script
        2. Trusted hosts must be enabled in winrm client config
        3. Password authentication may be required for each action

#>
[CmdletBinding()]
param (
    # The tier name, a logical grouping of applications
    [string] $tier="Default",
    # Netdiagnostics collector host port
    [string] $controller = "www.cav-test.com:443",
    # Instance name
    [string] $instance = "",
    # Communication protocol to use (WSS/TCP)
    [string] $protocol = "WSS",
	# Provide the value for tags
	[string] $tags = "",
	# Provide the value for Port
	[string] $port = "",
	# Provide the value for enable_listen
	[string] $enable_listen = "",
	# Provide the value for attributes 
	[string] $attributes = "",
    # Name of the MSI to install, default it picks from the current directory
    [string] $msi = (Get-ChildItem . -Filter "Cavisson*.msi").Name,
	[string] $msi1 = "WindowsApplicationDriver_1.2.1.msi",
	[string] $msi2 = "winsdksetup.exe",
    # Install Applicaton Agent, use this if you want to install the app agent
    [int] $appAgent = 1,
    # Install Machine Agent, use this if you want to install the machine agent
    [int] $machineAgent = 1,
    # Install Netforest Log Agent, use this if you want to install the log agent
    [int] $logAgent = 1,
    # Install winlogBeat as NFLogBeat, use this if you want to install the 
    [int] $nfLogBeat = 0,
	# Copy ProfilerHelper.DLL of profilerhelper_udp_folder copy to gcc folder (BUG_ID-146187)
    [int] $udp = 0,
	#For install WindowsApplicationDriver_1.2.1.msi & winsdksetup.exe (bug_id -146518)
	[int] $winapp = 0,
    # List of pool names to monitor separated by comma
    [string] $poolName = "",
    # NF Index prefix, use only with nfagent enabled
    [string] $nfIndexPrefix,
    # NF server hostname/IP, use only with nfagent enabled
    [string] $nfServer,
    # NF env name, use only with nfagent enabled
    [string] $nfEnv = "Production",
    # NF Reload Port, use only with nfagent enabled
    [int] $nfReloadPort = 9600,
    # Visual studio runtime executable
    [string] $vcExe = "VC_redist.x64.exe",
    # Visual studio runtime executable x86
    [string] $vcExe86 = "VC_redist.x86.exe",	
    # Log file to log installer logs
    [string] $logFile = "agent-install.log",
    # List of remote endpoints separated by comma (user1:host1,user2:host2...)
    [string] $remote,
	#Entry for server
	[string] $server = "",
    # Destination directory to copy related installation files
    [string] $dest="C:\Users",
    # Username to run Machine Agent with
    [string] $username = "",
    # Password of username to run Machine Agent
    [string] $password = "",
    # Copy local files to remote, useful when files are already present
    # on remote host
    [int] $copy = 1,
    # Flag to install vc++
    [int] $installVCRuntime = 0,
	$hostfile="",
    #ISS reset post installation
    [int] $iisreset = 0,
    #Flag to upgrade installer on server
    [switch] $upgrade=$false,
    #flag to do silent installation
    [switch] $silent=$false,
	#help
	[switch] $help=$false,
    # do remote installation
	[int] $remoteinstall = 0 ,
    #that is for installation path
    [string] $installdir = "C:\opt\",
    [string] $installedPath = $installdir + "cavisson\",
    # keyword for partial uninstallation
    #[switch] $partialuninstall=$false,
    #keyword for NDproxy setting
    [String] $ndproxy = "",
    #flag to uninstall agents
    [switch] $uninstall=$false,
	#flag for saas feature
    [switch] $saas,
	#Keyword for projectkey
	[string] $projectkey,
	#keyword for url
    [string] $url,	
	#keyword for tierattributes
	[string] $tierattributes,
	#Keyword for appname
	[string] $appname,
	#Agent name
	[string] $productName = "Cavisson Agent",
	#Log File of Uninstallation
    [string] $uninstall_logFile="agent-uninstall.log",
	#Log File of upgrade
    [string] $upgrade_logFile="agent-upgrade.log",
	#For uninstall agent
	[int] $uninstall_ndAgent = 0 ,
	#Flag to IISRESET value
	[int]$iis = 0
	
	
)

# Check for Windows Script Host
$registryPath = "HKLM:\Software\Microsoft\Windows Script Host\Settings"
$valueName = "Enabled"

# Check if the registry path exists
if (Test-Path $registryPath) {
    try {
        # Check if the "Enabled" value exists in the registry
        if (Test-Path "$registryPath\$valueName") {
            # Get the current value of the "Enabled" key
            $enabledValue = Get-ItemProperty -Path $registryPath -Name $valueName | Select-Object -ExpandProperty $valueName

            # Check if the value is 0
            if ($enabledValue -eq 0) {
                Write-Host "$($logEntry) Error : Windows Script Host access is disabled on this machine. To run the installer, you need to Enable it."
                exit  # Exit the script immediately
            }
        } else {
        }
    } catch {
        exit
    }
} else {
    exit
}


# Check if the current user has administrative privileges
	$admin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
	if ($admin) {
		#Write-Host "$($logEntry) Script is running with administrator privileges."
	} else {
		Write-Host "$($errorEntry) Script is not running with administrator privileges."
		exit
	}

#function for getting Buildversion
function build_version{
	$fileContent = Get-Content -Path "version"
	$versionNumber = $null
	$buildNumber = $null
	$HOSTNAME = hostname
	foreach ($line in $fileContent) {
		if ($line -match '^VERSION\s+(\d+\.\d+\.\d+)$') {
			$versionNumber = $matches[1]
		}

		elseif ($line -match '^BUILD\s+(\d+)$') {
			$buildNumber = $matches[1]
		}

		if ($versionNumber -ne $null -and $buildNumber -ne $null) {
			break
			}
	}
	$global:Buildversion = "$versionNumber.$buildNumber"
	#For log message 
	$global:logMessage = "| INFO |"
	$global:errorMessage = "| ERROR |"
	$global:dateTime = Get-Date
	$global:logEntry = "$dateTime $logMessage"
	$global:errorEntry = "$dateTime $errorMessage"
	$global:servername = "$HOSTNAME"
	
}
build_version


if ($upgrade -and $uninstall ) {
    Write-Host "$($errorEntry) Upgradation and uninstallation can't be done simultaneously."
    Write-Host "$($errorEntry) Please select right option."
    exit
} 

#For checking msi is persent 
if ($msi -eq "") {
	Write-Host "$($errorEntry) Cavisson-Agent-Installer.msi is not present or may be file name is different "
	exit
}

#For enabling the saas feature
	if ($saas){
	$MSIArgs += " SAAS_PRO=1"
	}
	if ($silent) {
		$uiState = "/qn"
	} else {
		$uiState = ""
	}
#For Help 
if ($help){
Write-Host	"----------------------------------------------------HELP----------------------------------------------"
Write-Host ""
Write-Host ""
Write-Host "[-tier tier] -- To pass tier value.The tier name a logical grouping of applications"
Write-Host "[-controller controller] -- To pass controller value"
Write-Host "[-instance instance] -- To pass instance value"
Write-Host "[-protocol protocol] -- Communication protocol to use (WSS/TCP)"
Write-Host "[-tags tag]-- Provide the value for tags"
Write-Host "[-port port] -- Provide the value for Port"
Write-Host "[-enable_listen 0] -- Provide the value for enable_listen"
Write-Host "[-attributes attribute] -- Provide the value for attributes"
Write-Host "[-appAgent 1] -- Install Applicaton Agent, use this if you want to install the app agent"
Write-Host "[-machineAgent 1] -- Install Machine Agent, use this if you want to install the machine agent"
Write-Host "[-logAgent 1] -- Install Netforest Log Agent, use this if you want to install the log agent"
Write-Host "[-nfLogBeat 1] -- Install winlogBeat as NFLogBeat, use this if you want to install"
Write-Host "[-udp 1] -- To enable udp option "
Write-Host "[-poolName poolName] -- List of pool names to monitor separated by comma"
Write-Host "[-winapp 1] -- To install WindowsApplicationDriver_1.2.1.msi & winsdksetup.exe"
Write-Host "[-nfIndexPrefix ] -- NF Index prefix, use only with nfagent enabled"
Write-Host "[-nfServer nfserver] -- NF server hostname/IP, use only with nfagent enabled"
Write-Host "[-nfEnv nfEnv] -- NF env name, use only with nfagent enabled"
Write-Host "[-nfReloadPort nfReloadPort] -- NF Reload Port, use only with nfagent enabled"
Write-Host "[-upgrade ] -- To upgrade installer on server "
Write-Host "[-uninstall ] -- To uninstall installer on server "
Write-Host "[-silent ] -- To do silent installation "
Write-Host "[-remoteinstall 1] -- To remote installtion"
Write-Host "[-ndproxy proxyip:port] -- keyword for NDproxy setting"
Write-Host "[-saas 1] -- To enable saas feature"
Write-Host "[-hostfile hostfile.txt] -- For remoteinstall "
Write-Host "[Hostfile format] - <username>:<password>:<ip> "
Write-Host ""
Write-Host ""

Write-Host "Example

.\install.ps1 -appAgent 1 -machineAgent 1 -logAgent 0  -tier tier -nfServer 10.20.0.74:7676 -controller 10.20.0.74:7892 -instance Instance1  -poolName "pool1,pool2" -port 80 -enable_listen 1 -udp 1 -winapp 1  -upgrade  -remoteinstall 1 -hostfile hostfile.txt -silent
"
Write-Host ""
Write-Host ""


exit


}

#function for check install MSI 
function check_install_msi {
	
	#Define additional registry paths
	$additionalRegistryPaths = @(
    "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
	)

	# Find Cavisson Agent
	$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Cavisson Agent*" }

	if ($cavissonKey) {
		# Extract GUID and version from uninstall string
		$global:guid = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
		$global:productVersion = $cavissonKey.DisplayVersion
		Write-Host "$($logEntry) Cavisson-Agent $productVersion is installed."
	} 
	else {
		Write-Host "$($errorEntry) Cavisson Agent is not installed."
		exit 
	}
}

#function for pass remoteinstall credential and check file for remoteinstall
function remote_file {
	if ($dest -eq "") {
		Write-Host "$($errorEntry) Usage: -dest is needed for remote installation"
		$dest = Read-Host -Prompt "Enter destination directory to copy files"
		if ($dest.Trim() -eq "") { return }
	}
	# Check if the file exists
	if (Test-Path -Path "hostfile.txt") {
		# Check if the file is not empty
		$content = Get-Content -Path "hostfile.txt"
		if ($content -ne $null -and $content.Length -gt 0) {
			#Write-Host "$($logEntry) Hostfile is present and not empty."
		}
		else {
			Write-Host "$($errorEntry) Hostfile is present but empty.Please provide the entries in hostfile like this <Username>:<Password>:<MachineIP>"
			exit
		}
	} 
	else {
		Write-Host "$($errorEntry) Hostfile does not exist.Please create a hostfile and provide the entries in hostfile like this <Username>:<Password>:<MachineIP>"
		exit
	}

	#$hostfile = Get-Content "hostfile.txt "
				

	foreach ($remote in $hostfile){
		foreach ($userHost in $remote) {
		# Extract user:host from remote delimited by ':'
		$params = $userHost.Split(":")
		# Password has been set by user
		if ($params.Length -eq 3) {
			$remoteUser = $params[0]
			$remotePlainPass = $params[1]
			$global:remoteHost = $params[2]
			$usingPassword = $true
		}
		else {
			$remoteUser = $params[0]
			$global:remoteHost = $params[1]
		}

		#Write-Host "Installing on $remoteUser@$remoteHost"
		# Default auth mechanism
		$global:credential = $remoteUser
		if ($usingPassword) {
			$remotePassword = ConvertTo-SecureString -AsPlainText $remotePlainPass -Force
			$global:credential = New-Object System.Management.Automation.PSCredential -ArgumentList $remoteUser, $remotePassword
		}
	
}
}
}
if ($remoteinstall -eq 1){
	remote_file
}

#function for check VC_redist
function check_vc_redist {
    
	#Define additional registry paths
	$additionalRegistryPaths = @(
    "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
	)
	
	# Checking vcExe64 is installed
	write-host "$($logEntry) Checking if Microsoft Visual C++ x64 2015-2019 is installed..."
	$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Microsoft Visual C++ 2022 X64 Additional Runtime - 14.32.31332*" }

	if ($cavissonKey) {
		# Extract GUID and version from uninstall string
		$global:guid_vc64 = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
		$global:productVersion_vc64 = $cavissonKey.DisplayVersion
		#Write-Host "$($logEntry) Microsoft Visual C++ X64 $productVersion_vc64 is already installed"
		Write-Host "$($logEntry) Microsoft Visual C++ X64 2015-2019 is already installed"
	} 
	else {
		Write-Host "$($logEntry) Microsoft Visual C++ X64 2015-2019 is not installed. Installing..."
        Start-Process -FilePath "$vcExe" -Wait -ArgumentList "/install /passive /norestart /log $logFile"   
	
	}
	# Checking vcExe86 is installed 
	write-host "$($logEntry) Checking if Microsoft Visual C++ x86 2015-2019 is installed..."
	$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Microsoft Visual C++ 2022 X86 Additional Runtime - 14.32.31332*" }

	if ($cavissonKey) {
		# Extract GUID and version from uninstall string
		$global:guid_vc86 = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
		$global:productVersion_vc86 = $cavissonKey.DisplayVersion
		#Write-Host "$($logEntry) Microsoft Visual C++ X86 $productVersion_vc86 is installed"
		Write-Host "$($logEntry) Microsoft Visual C++ X86 2015-2019 is already installed"
	} 
	else {
		Write-Host "$($logEntry) Microsoft Visual C++ X86 2015-2019 is not installed. Installing..."
		Start-Process -FilePath "$vcExe86" -Wait -ArgumentList "/install /passive /norestart /log $logFile"
           
	
	}
	
}


# For uninstall agent
	if ($uninstall -eq $true ) {
		#For uninstall agent on local 
		if  ($remoteinstall -eq 0 ){
			check_install_msi	
			# Retrieve all system environment variables
			$systemEnvVars = [System.Environment]::GetEnvironmentVariables('Machine')
			if ($systemEnvVars.ContainsKey('COR_PROFILER_PATH_64')){
				
				if ($iis -eq 1) {
					Write-Output "$($logEntry) Stopping IIS as IIS=1 is passed"
					$uninstall_ndAgent = 1
					& iisreset /stop > $null 2>&1
					if ($?) {
						Write-Host "$($logEntry) IIS stopped successfully"
					}
					else {
						Write-Host "$($errorEntry) Failed to stop IIS"
						exit
					}
				} else {
				# Check the status of iisreset service (W3SVC)
					$service = Get-Service -Name W3SVC -ErrorAction SilentlyContinue
					if ($service.Status -eq 'Running') {
						$attemptCount = 0
						$maxAttempts = 3
						
						while ($attemptCount -lt $maxAttempts) {
							# Prompt the user for input if iisreset is running
							$userInput = Read-Host "$($logEntry) IIS is running and needs to be stop for uninstalling Cavisson-Agent. Do you want to stop IIS? Type 'yes' to proceed, otherwise type 'no'"
							
							# Check the user input
							if ($userInput -eq "yes") {
								Write-Output "$($logEntry) Stopping IIS"
								$uninstall_ndAgent = 1
								& iisreset /stop > $null 2>&1
								if ($?) {
									Write-Host "$($logEntry) IIS stopped successfully"
								}
								else {
									Write-Host "$($errorEntry) Failed to stop IIS"
									exit
								}
								break
							}
							elseif ($userInput -eq "no") {
								Write-Output "$($logEntry) As you selected 'no'. Exiting without Stopping IIS"
								exit
							}
							else {
								$attemptCount++
								if ($attemptCount -lt $maxAttempts) {
									Write-Output "$($errorEntry) Invalid input. Please provide a correct input."
								}
								else {
									Write-Output "$($errorEntry) Invalid input. Exiting without Stopping IIS"
									exit
								}
							}
						}
					}
				}
			}
			Write-Host "$($logEntry) Now uninstalling Cavisson Agent $($productVersion) " 
			
			$services = @("CavNDProxy", "CavWMON", "NFAgent")

				# Loop through each service and check its status
				foreach ($service in $services) {
					# Check if the service exists
					$serviceObject = Get-Service -Name $service -ErrorAction SilentlyContinue
					if ($serviceObject) {
						# Check the service status
						if ($serviceObject.Status -eq "Running") {
							#Write-Output "Stopping service: $service"
							# Stop the service
							Stop-Service -Name $service > $null 3>&1
							#Write-Output "Service $service stopped."
						} else {
							#Write-Output "Service $service is not running."
						}
					} 
				}
			
			#Uninstall Cavisson Agent silently
			$uninstallResult = Start-Process -FilePath "msiexec"  -Wait -PassThru -ArgumentList "/x {$guid} /log $uninstall_logFile $uiState /norestart $MSIArgs"
			$exitCode = $uninstallResult.ExitCode
			
			if ($exitCode -eq 0) {
				Write-Host "$($logEntry) Cavisson-Agent ($productVersion) uninstalled successfully"
				#For restart ISS....
				if ($uninstall_ndAgent -eq 1) {
					$service = Get-Service -Name W3SVC
					if ($service.Status -eq 'Stopped') {
						Write-Output "$($logEntry) Restarting IIS"
						& iisreset /start > $null 2>&1
						if ($?) {
							Write-Host "$($logEntry) IIS restarted successfully"
						}
						else {
							Write-Host "$($errorEntry) Failed to restart IIS"
							exit
						}
					}		
				}
			}
			else {
				Write-Host "$($errorEntry) Failed to uninstall Cavisson-Agent $($productVersion). Exit code: $($exitCode)"
				 # Get the error message associated with the exit code
				$errorMessage = [System.ComponentModel.Win32Exception]::new($exitCode).Message
				Write-Host "$($errorEntry) Error message: $errorMessage"
				exit
			}
		}
		#For uninstall agent on remote server
		elseif ($remoteinstall -eq 1){
			$hostfile = get-content "$hostfile"
				foreach ($line in $hostfile){
					$remote = $line
						# For each user:host pair extract user and host
						foreach ($userHost in $remote) {
							# Extract user:host from remote delimited by ','
							$params = $userHost.Split(":")
							$usingPassword = $true
							# Password has been set by user
							if ($params.Length -eq 3) {
								$remoteUser = $params[0]
								$remotePlainPass = $params[1]
								$global:remoteHost = $params[2]
							
								$usingPassword = $true
							}
							else {
								$remoteUser = $params[0]
								$global:remoteHost = $params[1]
							}

							#Write-Host "Installing on $remoteUser@$remoteHost"
							# Default auth mechanism
							$credential = $remoteUser

							if ($usingPassword) {
								$remotePassword = ConvertTo-SecureString -AsPlainText $remotePlainPass -Force
								$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $remoteUser, $remotePassword

							}
			Invoke-Command -ComputerName $remoteHost -Credential $credential -ScriptBlock {
				param($destDir,$guid, $vsRuntime, $uninstall_logFile, $msi, $iisreset, $msiArgs, $app,$hostfile, $installVCRuntime, $isVSRuntimeInstalledFunc,$uninstall_ndAgent, $remoteHost)
						
					#For log message 
					$global:logMessage = "| INFO |"
					$global:errorMessage = "| ERROR |"
					$global:dateTime = Get-Date
					$global:logEntry = "$dateTime $logMessage"
					$global:errorEntry = "$dateTime $errorMessage"
					$global:servername = "$HOSTNAME"
						
					#function for check install MSI 
					function check_install_msi {
					#Define additional registry paths
					$additionalRegistryPaths = @(
						"HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
						"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
					)
					# Find Cavisson Agent
					$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Cavisson Agent*" }
						if ($cavissonKey) {
							# Extract GUID and version from uninstall string
							$global:guid = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
							$global:productVersion = $cavissonKey.DisplayVersion
							Write-Host "$($logEntry) Cavisson-Agent $productVersion is installed on server $remoteHost."
						} 
						else {
							Write-Host "$($errorEntry) Cavisson-Agent is not installed on server $remoteHost . "
							Exit
									
						}
					}	
					check_install_msi	
					
					$systemEnvVars = [System.Environment]::GetEnvironmentVariables('Machine')
					if ($systemEnvVars.ContainsKey('COR_PROFILER_PATH_64')){
						
						if ($iis -eq 1) {
							Write-Output "$($logEntry) Stopping IIS as IIS=1 is passed"
							$uninstall_ndAgent = 1
							& iisreset /stop > $null 2>&1
							if ($?) {
								Write-Host "$($logEntry) IIS stopped successfully"
							}
							else {
								Write-Host "$($errorEntry) Failed to stop IIS"
								exit
							}
						} else {
							# Check the status of iisreset service (W3SVC)
							$service = Get-Service -Name W3SVC -ErrorAction SilentlyContinue

							if ($service.Status -eq 'Running') {
								$attemptCount = 0
								$maxAttempts = 3
								
								while ($attemptCount -lt $maxAttempts) {
									# Prompt the user for input if iisreset is running
									$userInput = Read-Host "$($logEntry) iisreset is running and needs to be stopped for uninstalling Cavisson-Agent. Do you want to stop iisreset? Type 'yes' to proceed, otherwise type 'no'"
									
									# Check the user input
									if ($userInput -eq "yes") {
										Write-Output "$($logEntry) Stopping IIS"
										$uninstall_ndAgent = 1
										& iisreset /stop > $null 2>&1
										if ($?) {
											Write-Host "$($logEntry) IIS Stopped successfully"
										}
										else {
											Write-Host "$($errorEntry) Failed to Stop IIS"
											exit
										}
										break
									}
									elseif ($userInput -eq "no") {
										Write-Output "$($logEntry) As you selected 'no'. Exiting without Stopping IIS"
										exit
									}
									else {
										$attemptCount++
										if ($attemptCount -lt $maxAttempts) {
											Write-Output "$($errorEntry) Invalid input. Please provide a correct input."
										}
										else {
											Write-Output "$($errorEntry) Invalid input. Exiting without Stopping IIS"
											exit
										}
									}
								}
							} 
						}
					}
					
					Write-Host "$($logEntry) Now uninstalling Cavisson Agent $($productVersion) on server $($remoteHost) "
					
					$services = @("CavNDProxy", "CavWMON", "NFAgent")

					# Loop through each service and check its status
					foreach ($service in $services) {
						# Check if the service exists
						$serviceObject = Get-Service -Name $service -ErrorAction SilentlyContinue
						if ($serviceObject) {
							# Check the service status
							if ($serviceObject.Status -eq "Running") {
								#Write-Output "Stopping service: $service"
								# Stop the service
								Stop-Service -Name $service > $null 3>&1
								#Write-Output "Service $service stopped."
							} else {
								#Write-Output "Service $service is not running."
							}
						} 
					}
					$uninstall=Start-Process -FilePath "msiexec" -Wait -PassThru -ArgumentList "/x {$guid} /log $destDir\$uninstall_logFile /qn /norestart "					
					if ($uninstall.ExitCode -eq 0) {
						Write-Host "$($logEntry) Cavisson-Agent ($productVersion) uninstalled successfully on server $remoteHost"
						#For restart ISS....
						if ($uninstall_ndAgent -eq 1) {
							$service = Get-Service -Name W3SVC
							if ($service.Status -eq 'Stopped') {
								Write-Output "$($logEntry) Restarting IIS"
								& iisreset /start > $null 2>&1
								if ($?) {
									Write-Host "$($logEntry) IIS restarted successfully"
								}
								else {
									Write-Host "$($errorEntry) Failed to restart IIS"
									exit
								}
							}		
						}
					}
					else {
						Write-Host "$($errorEntry) Failed to uninstall Cavisson-Agent $($productVersion) on $remoteHost. Exit code: $($uninstallResult.ExitCode)"
					exit
					}	
		} -ArgumentList $dest,$guid, $productVersion, $uninstall_logFile,$iisreset, $errorEntry, $uninstall_logFile, $MSIArgs, $destDir, $hostfile, $dest,$uninstall_ndAgent, $remoteHost
	}
	}
	}
			
}		
		
	  
#For upgrade agent 
	elseif($upgrade -eq $true)  {
		#For upgrade agent on local
		if  ($remoteinstall -eq 0 ){
			check_install_msi
			Write-Host "$($logEntry) Upgrading Cavisson Agent from $($productVersion) to $($Buildversion)"
			# Define the list of services to check
			                         
			$MSIArgs += $addLocal
			$MSIArgs += " OPERATION=upgrade"
			
			$systemEnvVars = [System.Environment]::GetEnvironmentVariables('Machine')
			if ($systemEnvVars.ContainsKey('COR_PROFILER_PATH_64')){
				$appAgent = 1
				if ($iis -eq 1) {
						Write-Output "$($logEntry) Stopping IIS as IIS=1 is passed"
						$uninstall_ndAgent = 1
						& iisreset /stop > $null 2>&1
						if ($?) {
							Write-Host "$($logEntry) IIS stopped successfully"
						}
						else {
							Write-Host "$($errorEntry) Failed to Stop IIS"
							exit
						}
				} else {
					
					# Check the status of iisreset service (W3SVC)
					$service = Get-Service -Name W3SVC -ErrorAction SilentlyContinue

					if ($service.Status -eq 'Running') {
						$attemptCount = 0
						$maxAttempts = 3
						
						while ($attemptCount -lt $maxAttempts) {
							# Prompt the user for input if iisreset is running
							$userInput = Read-Host "$($logEntry) IIS is running and needs to be stopped and restarted for the upgrade of Cavisson-Agent. Do you want to stop and restart iisreset? Type 'yes' to proceed, otherwise type 'no'"
							
							# Check the user input
							if ($userInput -eq "yes") {
								Write-Output "$($logEntry) Stopping IIS"
								$uninstall_ndAgent = 1
								& iisreset /stop > $null 2>&1
								if ($?) {
									Write-Host "$($logEntry) IIS Stopped successfully"
								}
								else {
									Write-Host "$($errorEntry) Failed to Stop IIS"
									exit
								}
								break
							}
							elseif ($userInput -eq "no") {
								Write-Output "$($logEntry) As you selected 'no'. Exiting without Stopping IIS"
								exit
							}
							else {
								$attemptCount++
								if ($attemptCount -lt $maxAttempts) {
									Write-Output "$($errorEntry) Invalid input. Please provide a correct input."
								}
								else {
									Write-Output "$($errorEntry) Invalid input. Exiting without Stopping IIS"
									exit
								}
							}
						}
					} else {
						Write-Output "$($logEntry) IIS is not running."
					}
				}	
					
			}
				
				$services = @("CavNDProxy", "CavWMON", "NFAgent")

				# Loop through each service and check its status
				foreach ($service in $services) {
					# Check if the service exists
					$serviceObject = Get-Service -Name $service -ErrorAction SilentlyContinue
					if ($serviceObject) {
						# Check the service status
						if ($serviceObject.Status -eq "Running") {
							#Write-Output "Stopping service: $service"
							# Stop the service
							Stop-Service -Name $service > $null 3>&1
							#Write-Output "Service $service stopped."
						} else {
							#Write-Output "Service $service is not running."
						}
					} 
				}
			
				# Define the paths to check and remove
				$paths = @(
					"$installedPath\netdiagnostics\dotnet\dll\ProfilerHelper.dll",
					"$installedPath\netdiagnostics\dotnet\profilerhelper_folder",
					"$installedPath\netdiagnostics\dotnet\profilerhelper_folder_32",
					"C:\Windows\Microsoft.NET\assembly\GAC_64\ProfilerHelper",
					"C:\Windows\Microsoft.NET\assembly\GAC_32\ProfilerHelper",
					"$installedPath\wmonitors\bin\CavWMON.exe"
				)

				# Loop through each path and check if it exists, then remove it if it does
				foreach ($path in $paths) {
					if (Test-Path -Path $path) {
						#Write-Output "Removing: $path"
						Remove-Item -Path $path -Recurse -Force
						#Write-Output "Removed: $path"
					} 
				}
				$p=Start-Process -FilePath "msiexec" -Wait -PassThru -ArgumentList "/i $msi /log $upgrade_logFile /norestart REINSTALL=ALL  REINSTALLMODE=vomus $uiState $MSIArgs "	
				$exitCode = $p.ExitCode	
				if ($exitCode -eq 0) {
					Write-Host "$($logEntry) Cavisson Agent $($Buildversion) upgrade completed successfully on server $servername"
				}
				else {
					Write-Host "$($errorEntry) Failed to upgrade Cavisson Agent $($Buildversion) on server $remoteHost. Exit code: $($exitCode)"
					# Get the error message associated with the exit code
					$errorMessage = [System.ComponentModel.Win32Exception]::new($exitCode).Message
					Write-Host "$($errorEntry) Error message: $errorMessage"
					exit
				}
				#For restart iisreset....
				if ($uninstall_ndAgent -eq 1) {
					$service = Get-Service -Name W3SVC
					if ($service.Status -eq 'Stopped') {
						Write-Output "$($logEntry) Restarting IIS"
						& iisreset /start > $null 2>&1
						if ($?) {
							Write-Host "$($logEntry) IIS restarted successfully"
						}
						else {
							Write-Host "$($errorEntry) Failed to restart IIS"
							exit
						}
					}		
				}
				if ($appAgent -eq 1) {
					if ($poolName -eq "") {
						Write-Host "$($logEntry) App agent will monitor all pools "
					}
					try {
						setx ND_ENABLE_ALL_POOL "1" -m > $null 2>&1
					}
					catch {
						Write-Error "$($errorEntry) Unable to set flag for monitoring all pools"
					}
				}
				if (($app -eq "CMON,ND") -or ($app -eq "CMON") -or ($app -eq "ND"))
				{
					[Environment]::SetEnvironmentVariable("NFHOME",$null,"Machine")
				}	
			}
		
		#For upgrade agent on remote server
		elseif ($remoteinstall -eq 1){	
			$hostfile = get-content "$hostfile"
				foreach ($line in $hostfile){
					$remote = $line
						# For each user:host pair extract user and host
						foreach ($userHost in $remote) {
							# Extract user:host from remote delimited by ','
							$params = $userHost.Split(":")
							$usingPassword = $true
							# Password has been set by user
							if ($params.Length -eq 3) {
								$remoteUser = $params[0]
								$remotePlainPass = $params[1]
								$global:remoteHost = $params[2]
							
								$usingPassword = $true
							}
							else {
								$remoteUser = $params[0]
								$global:remoteHost = $params[1]
							}

							#Write-Host "Installing on $remoteUser@$remoteHost"
							# Default auth mechanism
							$credential = $remoteUser

							if ($usingPassword) {
								$remotePassword = ConvertTo-SecureString -AsPlainText $remotePlainPass -Force
								$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $remoteUser, $remotePassword

							}
			if ($copy -eq 1) {
				#Initiate a new PSSession to copy files to remote	
				$session = New-PSSession -ComputerName $remoteHost -Credential $credential
				Write-Host "$($logEntry) Copying the $msi on server $remoteHost"
				Copy-Item $msi -Destination $dest -ToSession $session 2>&1 > "copy.log"
				if ( -not $? ) {
				Write-Host "$($errorEntry) Unable to copy  the $msi on server $remoteHost.Please check the copy.log file"
				}
				else {
					Write-Host "$($logEntry) Copied  the $msi on server $remoteHost"
				} 
				
					
			}
			 Invoke-Command -ComputerName $remoteHost -Credential $credential -ScriptBlock {
				param($destDir, $vsRuntime, $upgrade_logFile, $msi, $pool, $iisreset, $msiArgs, $app,$hostfile, $installVCRuntime, $isVSRuntimeInstalledFunc,$Buildversion,$appAgent,$machineAgent,$logAgent,$remoteHost)			
					
					#For log message 
					$global:logMessage = "| INFO |"
					$global:errorMessage = "| ERROR |"
					$global:dateTime = Get-Date
					$global:logEntry = "$dateTime $logMessage"
					$global:errorEntry = "$dateTime $errorMessage"
					$HOSTNAME = hostname
					$global:servername = "$HOSTNAME"
					
					#function for check install MSI 
					function check_install_msi {			
					#Define additional registry paths
					$additionalRegistryPaths = @(
						"HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
						"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
					)

					#Find Cavisson Agent
					$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Cavisson Agent*" }
					if ($cavissonKey) {
						# Extract GUID and version from uninstall string
						$global:guid = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
						$global:productVersion = $cavissonKey.DisplayVersion
						Write-Host "$($logEntry) Cavisson-Agent $productVersion is installed."
					} 
					else {
						Write-Host "$($logEntry) Cavisson-Agent is not installed. "
						Exit		
						}
					}	
					check_install_msi
					
					#For stop iisreset
					$systemEnvVars = [System.Environment]::GetEnvironmentVariables('Machine')
					if ($systemEnvVars.ContainsKey('COR_PROFILER_PATH_64')){
						# Check the status of iisreset service (W3SVC)
						$appAgent = 1
						if ($iis -eq 1) {
								Write-Output "$($logEntry) Stopping IIS as IIS=1 is passed"
								$uninstall_ndAgent = 1
								& iisreset /stop > $null 2>&1
								if ($?) {
									Write-Host "$($logEntry) IIS stopped successfully"
								}
								else {
									Write-Host "$($errorEntry) Failed to Stop IIS"
									exit
								}
						} else {
							$service = Get-Service -Name W3SVC -ErrorAction SilentlyContinue
								if ($service.Status -eq 'Running') {
									$attemptCount = 0
									$maxAttempts = 3
									
									while ($attemptCount -lt $maxAttempts) {
										# Prompt the user for input if iisreset is running
										$userInput = Read-Host "$($logEntry) iisreset is running and needs to be stopped and restarted for the upgrade of Cavisson-Agent. Do you want to stop and restart iisreset? Type 'yes' to proceed, otherwise type 'no'"
										
										# Check the user input
										if ($userInput -eq "yes") {
											Write-Output "$($logEntry) Stopping IIS"
											$uninstall_ndAgent = 1
											& iisreset /start > $null 2>&1
											if ($?) {
												Write-Host "$($logEntry) IIS Stopped successfully"
											}
											else {
												Write-Host "$($errorEntry) Failed to Stop IIS"
												exit
											}
											break
										}
										elseif ($userInput -eq "no") {
											Write-Output "$($logEntry) As you selected 'no'. Exiting without Stopping IIS"
											exit
										}
										else {
											$attemptCount++
											if ($attemptCount -lt $maxAttempts) {
												Write-Output "$($errorEntry) Invalid input. Please provide a correct input."
											}
											else {
												Write-Output "$($errorEntry) Invalid input. Exiting without Stopping IIS"
												exit
											}
										}
									}
								} 
								else {
									Write-Output "$($logEntry) IIS is not running."
								}
							}	
						
					}
					#Write-Host "$($logEntry) Now upgrading Cavisson Agent from $($productVersion) to $($Buildversion)"
					
					$services = @("CavNDProxy", "CavWMON", "NFAgent")
					# Loop through each service and check its status
					foreach ($service in $services) {
						# Check if the service exists
						$serviceObject = Get-Service -Name $service -ErrorAction SilentlyContinue
						if ($serviceObject) {
							# Check the service status
							if ($serviceObject.Status -eq "Running") {
								#Write-Output "Stopping service: $service"
								# Stop the service
								Stop-Service -Name $service > $null 3>&1
								#Write-Output "Service $service stopped."
							} else {
								#Write-Output "Service $service is not running."
							}
						} 
					} 
					$MSIArgs += $addLocal
					$MSIArgs += " OPERATION=upgrade"
					# Define the paths to check and remove
					$paths = @(
						"$installedPath\netdiagnostics\dotnet\dll\ProfilerHelper.dll",
						"$installedPath\netdiagnostics\dotnet\profilerhelper_folder",
						"$installedPath\netdiagnostics\dotnet\profilerhelper_folder_32",
						"C:\Windows\Microsoft.NET\assembly\GAC_64\ProfilerHelper",
						"C:\Windows\Microsoft.NET\assembly\GAC_32\ProfilerHelper",
						"$installedPath\wmonitors\bin\CavWMON.exe"
					)

					# Loop through each path and check if it exists, then remove it if it does
					foreach ($path in $paths) {
						if (Test-Path -Path $path) {
							#Write-Output "Removing: $path"
							Remove-Item -Path $path -Recurse -Force
							#Write-Output "Removed: $path"
						} 
					}		
					$upgrade=Start-Process -FilePath "msiexec" -Wait -PassThru -ArgumentList "/i $destDir\$msi /log $destDir\$upgrade_logFile /norestart /qn REINSTALL=ALL  REINSTALLMODE=vomus  $MSIArgs  "				
					if ($upgrade.ExitCode -eq 0) {
						Write-Host "$($logEntry) Cavisson Agent $($Buildversion) upgrade completed successfully on server $remoteHost"
					}
					else {
						Write-Host "$($errorEntry) Failed to upgrade Cavisson Agent $($Buildversion) on server $remoteHost. Exit code: $($p.ExitCode)"
						exit
					}								
					#For restart ISS....
					if ($uninstall_ndAgent -eq 1) {
						$service = Get-Service -Name W3SVC
						if ($service.Status -eq 'Stopped') {
							Write-Output "$($logEntry) Restarting IIS"
							& iisreset /start > $null 2>&1
							if ($?) {
								Write-Host "$($logEntry) IIS restarted successfully"
							}
							else {
								Write-Host "$($errorEntry) Failed to restart IIS"
								exit
							}
						}		
					}
					if ($appAgent -eq 1) {
						if ($poolName -eq "") {
							Write-Host "$($logEntry) App agent will monitor all pools "
						}
						try {
							setx ND_ENABLE_ALL_POOL "1" -m > $null 2>&1
						}
						catch {
							Write-Error "$($errorEntry) Unable to set flag for monitoring all pools"
						}
					}
					if (($app -eq "CMON,ND") -or ($app -eq "CMON") -or ($app -eq "ND"))
						{
							[Environment]::SetEnvironmentVariable("NFHOME",$null,"Machine")
						}
		}-ArgumentList $dest, $vcExe, $upgrade_logFile, $msi, $poolName, $iisreset, $MSIArgs, $app,$hostfile,$installVCRuntime, ${function:IsVSRuntimeInstalled},$Buildversion,$appAgent,$machineAgent,$logAgent,$remoteHost
	}
	}
	}
			
}	
		
#For Install Agent	  
	else{
		#install VC runtime only if ND APM agent is to be installed;
		$installVCRuntime = $appAgent
		$MSIArgs += " OPERATION=install"  
		$addLocal = " ADDLOCAL=CONFIGFILES,"
		# Determine which agents to install and update $addLocal
		if ($machineAgent -eq 1) {
			$addLocal += "CMON"
			$app = "CMON"
			if ($appAgent -eq 1) {
				$addLocal += ",ND"
				$app += ",ND"
			}
			if ($logAgent -eq 1) {
				$addLocal += ",NF"
				$app += ",NF"
			}
		}
		elseif ($appAgent -eq 1) {
			$addLocal += "ND"
			$app = "ND"
			if ($logAgent -eq 1) {
				$addLocal += ",NF"
				$app += ",NF"
			}
		}
		elseif ($logAgent -eq 1) {
			$addLocal += "NF"
			$app = "NF"
		}
		#pass agent modules to be installed in argument list to msi for
		$MSIArgs += $addLocal	  
		if ($saas ){
			if($projectkey -eq ""){
				$projectkey=Read-Host -Prompt "Project key"
			}
			$MSIArgs += " PROJECTKEY=`"$projectkey`" URL=`"$url`" TIERATTRIBUTES=`"$tierattributes`" APPNAME=`"$appname`" ENDPOINT=`"$endpoint`""
		}	
		else{
			if ($logAgent -eq 1) {
				$MSIArgs += " INDEX_PREFIX=`"$nfIndexPrefix`" NFSERVER=`"$nfServer`" ENV=`"$nfEnv`" RELOADPORT=`"$nfReloadPort`"" 
			}
		}
		if ($remoteinstall -eq 0){
			#Bug - 146613
			if ($ndproxy -eq "") {
			$ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias (Get-NetAdapter | Where-Object { $_.Status -eq 'Up' } | Select-Object -First 1).InterfaceAlias).IPAddress
			$nd_port = "1111"
			$ndproxy = $ip + ":" + $nd_port
			}
		}
			
		$MSIArgs += " NDSERVER=`"$controller`" Port=`"$port`" ENABLE_LISTEN=`"$enable_listen`" TIER=`"$tier`" INSTANCE=`"$instance`" NDCPROTOCOL=`"$protocol`" TAGS=`"$tags`" ATTRIBUTES=`"$attributes`" USERNAME=`"$username`" PASSWORD=`"$password`" SERVER=`"$server`" NDPROXY=`"$ndproxy`" INSTALLDIR=`"$installdir`" CAVWMON=`"$machineAgent`" NFAGENT=`"$logAgent`" NDAGENT=`"$appAgent`" NFLOGBEAT=`"$nfLogBeat`""

		if ($poolName) { $MSIArgs += " APP=`"$poolName`"" }
			
		if ($remoteinstall -eq 0) {
				if ($installVCRuntime -eq 1) {
					check_vc_redist
				}
				Write-Host "$($logEntry) Now Installing Cavisson Agent Modules $($Buildversion)"
				$p=Start-Process -FilePath "msiexec" -PassThru -Wait -ArgumentList "/i $msi /norestart /log $logFile $uiState $MSIArgs"
				$exitcode = $p.ExitCode         
				if ($exitcode -eq 0) {
					Write-Host "$($logEntry) Cavisson agent $($Buildversion) is deployed successfully on $servername."
				}
				else {
					Write-Host "$($errorEntry) Cavisson agent $($Buildversion) is failed to deployed on $servername with Exit code: $($exitCode)"
					# Get the error message associated with the exit code
					$errorMessage = [System.ComponentModel.Win32Exception]::new($exitCode).Message
					Write-Host "$($errorEntry) Error message: $errorMessage"
					exit
				}
				if ($udp -eq 1) {
					#Write-Host "udp"
					Copy-Item -Path "$installedPath\netdiagnostics\dotnet\profilerhelper_udp_folder\profilerhelper_udp_folder\v4.0_1.0.0.0__fcb740f63446e2f2\ProfilerHelper.dll" -Destination "C:\Windows\Microsoft.NET\assembly\GAC_64\ProfilerHelper\v4.0_1.0.0.0__fcb740f63446e2f2" -Force
					Copy-Item -Path "$installedPath\netdiagnostics\dotnet\profilerhelper_udp_folder_32\profilerhelper_udp_folder_32\v4.0_1.0.0.0__fcb740f63446e2f3\ProfilerHelper.dll" -Destination "C:\Windows\Microsoft.NET\assembly\GAC_32\ProfilerHelper\v4.0_1.0.0.0__fcb740f63446e2f2" -Force
				}
				if ($winapp -eq 1){
					Start-Process $msi1 /qn  2>&1 > "error.log"
					Write-Host "$($logEntry) Installing winsdksetup it will take 4-5 min..."
					Start-Process $msi2 /S  2>&1 > "error.log"
					Start-Sleep -Seconds 201
				}
				if ($appAgent -eq 1){
					
					$service = Get-Service -Name W3SVC -ErrorAction SilentlyContinue

					if ($service) {
					
						if ($iis -eq 1) {
							Write-Output "$($logEntry) Restarting IIS as IIS=1 is passed"
							$uninstall_ndAgent = 1
							& iisreset /start > $null 2>&1
							if ($?) {
								Write-Host "$($logEntry) IIS Restarted successfully"
							}
							else {
								Write-Host "$($errorEntry) Failed to restart IIS"
								exit
							}
						} else {
							# Set a counter for invalid attempts
							$attemptCount = 0
							$maxAttempts = 3
							
							while ($attemptCount -lt $maxAttempts) {
								# Prompt the user for input if iisreset is running
								$userInput = Read-Host "$($logEntry) To reflect the changes made to the Cavisson-Agent, we need to restart IIS. Do you want to restart IIS? Type 'yes' to proceed, otherwise type 'no'"
								
								# Check the user input
								if ($userInput -eq "yes") {
									Write-Output "$($logEntry) Restarting IIS"
									& iisreset /start > $null 2>&1
									if ($?) {
										Write-Host "$($logEntry) IIS restarted successfully"
									}
									else {
										Write-Host "$($errorEntry) Failed to restart IIS"
										exit
									}
									break
								}
								elseif ($userInput -eq "no") {
									Write-Output "$($logEntry) As you selected 'no'. Exiting without restarting IIS"
									exit
								}
								else {
									$attemptCount++
									if ($attemptCount -lt $maxAttempts) {
										Write-Output "$($errorEntry) Invalid input. Please provide a correct input."
									}
									else {
										Write-Output "$($errorEntry) Invalid input. Exiting without restarting IIS"
										exit
									}
								}
							}
						}
					}					
				}			

				if ($appAgent -eq 1) {
					if ($poolName -eq "") {
						Write-Host "$($logEntry) App agent will monitor all pools  "
					}
						
					try {
						setx ND_ENABLE_ALL_POOL "1" -m > $null 2>&1
					}
					catch {
						Write-Error "$($errorEntry) Unable to set flag for monitoring all pools"
					}
						
					if (($app -eq "CMON,ND") -or ($app -eq "CMON") -or ($app -eq "ND")){
						[Environment]::SetEnvironmentVariable("NFHOME",$null,"Machine") 
					}
				}
				if ($iisreset -eq 1) {
					Write-Host "$($logEntry) Post install - resetting IIS"
					iisreset /noforce /RESTART
				}
			}
			#For Install agent on remote server
			elseif($remoteinstall -eq 1) {
				$hostfile = get-content "$hostfile"
				foreach ($line in $hostfile){
					$remote = $line
						# For each user:host pair extract user and host
						foreach ($userHost in $remote) {
							# Extract user:host from remote delimited by ','
							$params = $userHost.Split(":")
							$usingPassword = $true
							# Password has been set by user
							if ($params.Length -eq 3) {
								$remoteUser = $params[0]
								$remotePlainPass = $params[1]
								$global:remoteHost = $params[2]
							
								$usingPassword = $true
							}
							else {
								$remoteUser = $params[0]
								$remoteHost = $params[1]
							}

							#Write-Host "Installing on $remoteUser@$remoteHost"
							# Default auth mechanism
							$credential = $remoteUser

							if ($usingPassword) {
								$remotePassword = ConvertTo-SecureString -AsPlainText $remotePlainPass -Force
								$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $remoteUser, $remotePassword

							}

					if ($copy -eq 1) {
						# Initiate a new PSSession to copy files to remote
						$session = New-PSSession -ComputerName $remoteHost -Credential $credential
						
						Write-Host "$($logEntry) Copying the $msi on server $remoteHost"
						Copy-Item $msi -Destination $dest -ToSession $session 2>&1 > "copy.log"
						if ( -not $? ) {
							Write-Host "$($errorEntry) Unable to copy  the $msi on server $remoteHost.Please check the copy.log file"
						}
						else {
							Write-Host "$($logEntry) Copied  the $msi on server $remoteHost"
						} 
						
						Write-Host "$($logEntry) Copying the $vcExe on server $remoteHost"
						Copy-Item $vcExe -Destination $dest -ToSession $session 2>&1 > "copy.log"
						if ( -not $? ) {
							Write-Host "$($errorEntry) Unable to copy  the $vcExe on server $remoteHost.Please check the copy.log file"
						}
						else {
							Write-Host "$($logEntry) Copied  the $vcExe on server $remoteHost"
						} 
						
						Write-Host "$($logEntry) Copying the $vcExe86 on server $remoteHost"
						Copy-Item $vcExe86 -Destination $dest -ToSession $session 2>&1 > "copy.log"
						if ( -not $? ) {
							Write-Host "$($errorEntry) Unable to copy the $vcExe86 on server $remoteHost.Please check the copy.log file"
						}
						else {
							Write-Host "$($logEntry) Copied  the $vcExe86 on server $remoteHost"
						} 
					Invoke-Command -ComputerName $remoteHost -Credential $credential -ScriptBlock {
						param($destDir, $vsRuntime, $logFile, $msi, $pool, $iisreset, $msiArgs, $app,$hostfile, $installVCRuntime, $isVSRuntimeInstalledFunc,$Buildversion,$poolName,$appAgent,$machineAgent,$logAgent,$installedPath,$remoteHost,$ndproxy)
					
						#For log message 
						$global:logMessage = "| INFO |"
						$global:errorMessage = "| ERROR |"
						$global:dateTime = Get-Date
						$global:logEntry = "$dateTime $logMessage"
						$global:errorEntry = "$dateTime $errorMessage"
						$HOSTNAME = hostname
						$global:servername = "$HOSTNAME"
										
						#function for check VC_redist
						function check_vc_redist {		
						#Define additional registry paths
						$additionalRegistryPaths = @(
							"HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
							"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
						)
								
						# Checking vcExe64 is installed
						write-host "$($logEntry) Checking if Microsoft Visual C++ x64 2015-2019 is installed..."
						$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Microsoft Visual C++ 2022 X64 Additional Runtime - 14.32.31332*" }
						if ($cavissonKey) {
							# Extract GUID and version from uninstall string
							$global:guid_vc64 = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
							$global:productVersion_vc64 = $cavissonKey.DisplayVersion
							#Write-Host "$($logEntry) Microsoft Visual C++ X64 $productVersion_vc64 is already installed"
							Write-Host "$($logEntry) Microsoft Visual C++ X64 2015-2019 is already installed"
						} 
						else {
							Write-Host "$($logEntry) Microsoft Visual C++ X64 2015-2019 is not installed. Installing..."
							$global:runtimePath = Join-Path -Path $destDir -ChildPath $vsRuntime
							Start-Process -FilePath "$runtimePath" -Wait -ArgumentList "/install /passive /norestart /log $destDir\$logFile" 2>&1 > "error.log"
							if ( -not $?){
								Write-Host "$($errorEntry) Unable to install  the $vcExe on server $remoteHost.Please check the error.log file" 
							}	 
							else{
								Write-Host "$($logEntry) Successfully installed the $vcExe on server $remoteHost"
								}
							}
								# Checking vcExe86 is installed 
								write-host "$($logEntry) Checking if Microsoft Visual C++ x86 2015-2019 is installed..."
								$cavissonKey = Get-ItemProperty -Path $additionalRegistryPaths | Where-Object { $_.DisplayName -like "*Microsoft Visual C++ 2022 X86 Additional Runtime - 14.32.31332*" }

								if ($cavissonKey) {
									# Extract GUID and version from uninstall string
									$global:guid_vc86 = $cavissonKey.UninstallString -replace ".*{(.*)}.*",'$1'
									$global:productVersion_vc86 = $cavissonKey.DisplayVersion
									#Write-Host "$($logEntry) Microsoft Visual C++ X86 $productVersion_vc86 is installed"
									Write-Host "$($logEntry) Microsoft Visual C++ X86 2015-2019 is already installed"
								} 
								else {
									Write-Host "$($logEntry) Microsoft Visual C++ X86 2015-2019 is not installed. Installing..."
									Start-Process -FilePath "$destDir\VC_redist.x86.exe" -Wait -ArgumentList "/install /passive /norestart /log $destDir\$logFile" 2>&1 > "error.log"
									if ( -not $?){
										Write-Host "$($errorEntry) Unable to install  the $vcExe on server $remoteHost.Please check the error.log file" 
									}	 
									else{
										Write-Host "$($logEntry) Successfully installed the $vcExe on server $remoteHost"
									}
									   
								
								}
								
							}
								
								if ($installVCRuntime -eq 1) {
									check_vc_redist
								}
								#Bug - 146613
								if ($ndproxy -eq "") {
								$ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias (Get-NetAdapter | Where-Object { $_.Status -eq 'Up' } | Select-Object -First 1).InterfaceAlias).IPAddress
								$nd_port = "1111"
								$ndproxy = $ip + ":" + $nd_port 
								}
								#$MSIArgs += "NDPROXY=`"$ndproxy`""
								$MSIArgs += " NDPROXY=`"$ndproxy`""

								
								Write-Host "$($logEntry) Now Installing Cavisson Agent Modules $($Buildversion) on $remoteHost"
								$install=Start-Process -FilePath "msiexec" -Wait -PassThru -ArgumentList "/i $destDir\$msi /norestart /log $destDir\$logFile $uiState $MSIArgs" 					
								if ($install.ExitCode -eq 0) {
									Write-Host "$($logEntry) Cavisson agent $($Buildversion) is deployed successfully on $servername."
								}
								else {
									Write-Host "$($errorEntry) Cavisson agent $($Buildversion) is failed to deployed on $servername with 	exitcode:$exit_code"
									exit
								}	
								if ($udp -eq 1) {
									#Write-Host "udp"
									Copy-Item -Path "$installedPath\netdiagnostics\dotnet\profilerhelper_udp_folder\profilerhelper_udp_folder\v4.0_1.0.0.0__fcb740f63446e2f2\ProfilerHelper.dll" -Destination "C:\Windows\Microsoft.NET\assembly\GAC_64\ProfilerHelper\v4.0_1.0.0.0__fcb740f63446e2f2" -Force
									Copy-Item -Path "$installedPath\netdiagnostics\dotnet\profilerhelper_udp_folder_32\profilerhelper_udp_folder_32\v4.0_1.0.0.0__fcb740f63446e2f3\ProfilerHelper.dll" -Destination "C:\Windows\Microsoft.NET\assembly\GAC_32\ProfilerHelper\v4.0_1.0.0.0__fcb740f63446e2f2" -Force
								}
								if ($winapp -eq 1){
									Start-Process $msi1 /qn  2>&1 > "error.log"
									Write-Host "$($logEntry) Installing winsdksetup it will take 4-5 min..."
									Start-Process $msi2 /S  2>&1 > "error.log"
									Start-Sleep -Seconds 201
								}
								#For restart ISS
								if ($appAgent -eq 1){
									
									$service = Get-Service -Name W3SVC -ErrorAction SilentlyContinue

									if ($service) {
									
										if ($iis -eq 1) {
											Write-Output "$($logEntry) Restarting IIS as IIS=1 is passed"
											$uninstall_ndAgent = 1
											& iisreset /start > $null 2>&1
											if ($?) {
												Write-Host "$($logEntry) IIS Restarted successfully"
											}
											else {
												Write-Host "$($errorEntry) Failed to restart IIS"
												exit
											}
										} else {
											# Set a counter for invalid attempts
											$attemptCount = 0
											$maxAttempts = 3
											
											while ($attemptCount -lt $maxAttempts) {
												# Prompt the user for input if iisreset is running
												$userInput = Read-Host "$($logEntry) To reflect the changes made to the Cavisson-Agent, we need to restart IIS. Do you want to restart IIS? Type 'yes' to proceed, otherwise type 'no'"
												
												# Check the user input
												if ($userInput -eq "yes") {
													Write-Output "$($logEntry) Restarting IIS"
													& iisreset /start > $null 2>&1
													if ($?) {
														Write-Host "$($logEntry) IIS restarted successfully"
													}
													else {
														Write-Host "$($errorEntry) Failed to restart IIS"
														exit
													}
													break
												}
												elseif ($userInput -eq "no") {
													Write-Output "$($logEntry) As you selected 'no'. Exiting without restarting IIS"
													exit
												}
												else {
													$attemptCount++
													if ($attemptCount -lt $maxAttempts) {
														Write-Output "$($errorEntry) Invalid input. Please provide a correct input."
													}
													else {
														Write-Output "$($errorEntry) Invalid input. Exiting without restarting IIS"
														exit
													}
												}
											}
										}
									}
								}
								if ($installVCRuntime -eq 1) {
									if ($poolName -eq "") {
										Write-Host "$($logEntry) App agent will monitor all pools  "
									}
										
									try {
										setx ND_ENABLE_ALL_POOL "1" -m > $null 2>&1
									}
									catch {
										Write-Error "$($errorEntry) Unable to set flag for monitoring all pools"
									}
										
									if (($app -eq "CMON,ND") -or ($app -eq "CMON") -or ($app -eq "ND")){
										[Environment]::SetEnvironmentVariable("NFHOME",$null,"Machine")
									}
								}
								if ($iisreset -eq 1) {
									Write-Host "$($logEntry) Post install - resetting IIS"
									iisreset /noforce /RESTART
								}
							
									} -ArgumentList $dest, $vcExe, $logFile, $msi, $poolName, $iisreset, $MSIArgs, $app,$hostfile,$installVCRuntime, ${function:IsVSRuntimeInstalled},$Buildversion,$poolName,$appAgent,$machineAgent,$logAgent,$installedPath,$remoteHost,$ndproxy
								}
								}
				}
			}
	
}
