EnhancedPSADTAO.psm1
#Region '.\Public\Create-LocalAdminAccount.ps1' -1 function Create-LocalAdminAccount { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Username, [Parameter(Mandatory = $true)] [string]$Password ) begin { Write-EnhancedLog -Message 'Starting Create-LocalAdminAccount function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { # Check if the user already exists $userExists = Get-LocalUser -Name $Username -ErrorAction SilentlyContinue if (-not $userExists) { # Create the user account $securePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force $userParams = @{ Name = $Username Password = $securePassword FullName = "FC Remove Account" Description = "Account used for FC removal process" PasswordNeverExpires = $true AccountNeverExpires = $true } New-LocalUser @userParams Write-EnhancedLog -Message "Local administrator account '$Username' created." -Level 'INFO' } else { Write-EnhancedLog -Message "Local administrator account '$Username' already exists." -Level 'WARNING' } # Check if the user is already a member of the local Administrators group $group = Get-LocalGroup -Name "Administrators" $memberExists = $null try { $memberExists = $group | Get-LocalGroupMember | Where-Object { $_.Name -eq $Username } } catch { Write-EnhancedLog -Message "Failed to retrieve group members: $_" -Level 'ERROR' } if (-not $memberExists) { # Add the user to the local Administrators group $groupParams = @{ Group = "Administrators" Member = $Username } try { Add-LocalGroupMember @groupParams Write-EnhancedLog -Message "User '$Username' added to the Administrators group." -Level 'INFO' } catch [Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand+MemberExistsException] { Write-EnhancedLog -Message "User '$Username' is already a member of the Administrators group." -Level 'WARNING' } } else { Write-EnhancedLog -Message "User '$Username' is already a member of the Administrators group." -Level 'WARNING' } } catch { Write-EnhancedLog -Message "An error occurred while creating the local admin account or adding to Administrators group: $_" -Level 'ERROR' Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Create-LocalAdminAccount function completed' -Level 'INFO' } } # # Define parameters for creating the local admin account # $localAdminParams = @{ # Username = "fcremove" # Password = "fcremove" # } # # Create the local admin account # Create-LocalAdminAccount @localAdminParams #EndRegion '.\Public\Create-LocalAdminAccount.ps1' 82 #Region '.\Public\Detect-BitLockerStatus.ps1' -1 function Detect-BitLockerStatus { [CmdletBinding()] param ( [string[]]$DriveLetters = @("C:") ) begin { Write-EnhancedLog -Message 'Starting Detect-BitLockerStatus function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { foreach ($drive in $DriveLetters) { try { $bitLockerStatus = Get-BitLockerVolume -MountPoint $drive if ($bitLockerStatus) { $protectionStatus = $bitLockerStatus.ProtectionStatus Write-EnhancedLog -Message "BitLocker status for drive $drive $protectionStatus" -Level 'INFO' Write-Output "BitLocker status for drive $drive $protectionStatus" } else { Write-EnhancedLog -Message "BitLocker status not found for drive $drive" -Level 'WARNING' Write-Output "BitLocker status not found for drive $drive" } } catch { Handle-Error -ErrorRecord $_ } } } end { Write-EnhancedLog -Message 'Detect-BitLockerStatus function completed' -Level 'INFO' } } # # Example usage of Detect-BitLockerStatus function with splatting # $params = @{ # DriveLetters = @("C:", "D:") # } # # Call the Detect-BitLockerStatus function using splatting # Detect-BitLockerStatus @params #EndRegion '.\Public\Detect-BitLockerStatus.ps1' 43 #Region '.\Public\Detect-FortiClientEMSInstallation.ps1' -1 function Detect-FortiClientEMSInstallation { <# .SYNOPSIS Checks for FortiClientEMS installation and version. .PARAMETER RegistryPaths An array of registry paths to check. .PARAMETER SoftwareName The name of the software to search for. .PARAMETER ExcludedVersion The version of the software to exclude. .OUTPUTS A hashtable indicating whether the software is installed and its version. #> [CmdletBinding()] param ( [string[]]$RegistryPaths, [string]$SoftwareName, [version]$ExcludedVersion ) foreach ($path in $RegistryPaths) { $items = Get-ChildItem -Path $path -ErrorAction SilentlyContinue foreach ($item in $items) { $app = Get-ItemProperty -Path $item.PsPath -ErrorAction SilentlyContinue if ($app.DisplayName -like "*$SoftwareName*") { $installedVersion = New-Object Version $app.DisplayVersion if ($installedVersion -lt $ExcludedVersion) { return @{ IsInstalled = $true Version = $app.DisplayVersion ProductCode = $app.PSChildName } } } } } return @{IsInstalled = $false} } #EndRegion '.\Public\Detect-FortiClientEMSInstallation.ps1' 41 #Region '.\Public\Detect-SystemMode.ps1' -1 function Detect-SystemMode { [CmdletBinding()] param ( [string]$RegistryPath ) begin { Write-EnhancedLog -Message 'Starting Detect-SystemMode function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { $safeMode = Get-ItemProperty -Path $RegistryPath -ErrorAction Stop if ($safeMode.Option -eq 1) { Write-EnhancedLog -Message "System is in Safe Mode" -Level 'INFO' $Global:SystemMode = "Safe Mode" } else { Write-EnhancedLog -Message "System is in Normal Mode" -Level 'INFO' $Global:SystemMode = "Normal Mode" } } catch { Write-EnhancedLog -Message "System is in Normal Mode (SafeBoot key not found)" -Level 'INFO' $Global:SystemMode = "Normal Mode" } } end { Write-EnhancedLog -Message 'Detect-SystemMode function completed' -Level 'INFO' } } # # Example usage of Detect-SystemMode function with splatting # $params = @{ # RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option' # } # # Call the Detect-SystemMode function using splatting # Detect-SystemMode @params # Access the result # $SystemMode #EndRegion '.\Public\Detect-SystemMode.ps1' 44 #Region '.\Public\Disable-BitLocker.ps1' -1 function Disable-BitLocker { [CmdletBinding()] param ( [string[]]$DriveLetters = @("C:") ) begin { Write-EnhancedLog -Message 'Starting Disable-BitLocker function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { # Detect BitLocker status for the provided drives $bitLockerStatusResults = Detect-BitLockerStatus -DriveLetters $DriveLetters foreach ($status in $bitLockerStatusResults) { $drive = $status.MountPoint $protectionStatus = $status.ProtectionStatus if ($protectionStatus -eq "On") { try { Write-EnhancedLog -Message "Disabling BitLocker on drive $drive" -Level 'INFO' Disable-BitLocker -MountPoint $drive -RebootCount 0 -Wait Write-EnhancedLog -Message "BitLocker disabled on drive $drive" -Level 'INFO' Write-Output "BitLocker disabled on drive $drive" } catch { Handle-Error -ErrorRecord $_ } } else { Write-EnhancedLog -Message "BitLocker is not enabled on drive $drive" -Level 'INFO' Write-Output "BitLocker is not enabled on drive $drive" } } } end { Write-EnhancedLog -Message 'Disable-BitLocker function completed' -Level 'INFO' } } # # Example usage of Disable-BitLocker function with splatting # $params = @{ # DriveLetters = @("C:", "D:") # } # # Call the Disable-BitLocker function using splatting # Disable-BitLocker @params #EndRegion '.\Public\Disable-BitLocker.ps1' 49 #Region '.\Public\Enter-SafeModeBasedOnDetection.ps1' -1 function Enter-SafeModeBasedOnDetection { [CmdletBinding()] param ( [string]$RegistryPath, [string]$BCDeditPath, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message 'Starting Enter-SafeModeBasedOnDetection function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { # Detect system mode $params = @{ RegistryPath = $RegistryPath } Detect-SystemMode @params if ($Global:SystemMode -eq "Normal Mode") { # Construct the arguments $arguments = $ArgumentTemplate # Execute the bcdedit command to enable Safe Mode Write-EnhancedLog -Message "Executing bcdedit with arguments: $arguments" -Level 'INFO' Start-Process -FilePath $BCDeditPath -ArgumentList $arguments -Wait Write-EnhancedLog -Message 'Successfully set the system to boot into Safe Mode on next restart' -Level 'INFO' } else { Write-EnhancedLog -Message 'System is already in Safe Mode' -Level 'INFO' } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Enter-SafeModeBasedOnDetection function completed' -Level 'INFO' } } # # Example usage of Enter-SafeModeBasedOnDetection function with splatting # $params = @{ # RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option' # BCDeditPath = 'bcdedit.exe' # ArgumentTemplate = '/set {current} safeboot minimal' # } # # Call the Enter-SafeModeBasedOnDetection function using splatting # Enter-SafeModeBasedOnDetection @params #EndRegion '.\Public\Enter-SafeModeBasedOnDetection.ps1' 53 #Region '.\Public\Exit-SafeModeBasedOnDetection.ps1' -1 function Exit-SafeModeBasedOnDetection { [CmdletBinding()] param ( [string]$RegistryPath, [string]$BCDeditPath, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message 'Starting Exit-SafeModeBasedOnDetection function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { # Detect system mode $params = @{ RegistryPath = $RegistryPath } Detect-SystemMode @params if ($Global:SystemMode -eq "Safe Mode") { # Construct the arguments $arguments = $ArgumentTemplate # Execute the bcdedit command to disable Safe Mode Write-EnhancedLog -Message "Executing bcdedit with arguments: $arguments" -Level 'INFO' Start-Process -FilePath $BCDeditPath -ArgumentList $arguments -Wait Write-EnhancedLog -Message 'Successfully set the system to boot into Normal Mode on next restart' -Level 'INFO' } else { Write-EnhancedLog -Message 'System is already in Normal Mode' -Level 'INFO' } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Exit-SafeModeBasedOnDetection function completed' -Level 'INFO' } } # # Example usage of Exit-SafeModeBasedOnDetection function with splatting # $params = @{ # RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot\Option' # BCDeditPath = 'bcdedit.exe' # ArgumentTemplate = '/deletevalue {current} safeboot' # } # # Call the Exit-SafeModeBasedOnDetection function using splatting # Exit-SafeModeBasedOnDetection @params #EndRegion '.\Public\Exit-SafeModeBasedOnDetection.ps1' 53 #Region '.\Public\Export-RegistryKeys.ps1' -1 function Export-RegistryKeys { [CmdletBinding()] param ( [string]$ScriptDirectory, [string]$RegistryKeyPath ) begin { Write-EnhancedLog -Message 'Starting Export-RegistryKeys function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { if (-not (Test-Path $ScriptDirectory)) { Write-EnhancedLog -Message "Script directory not found: $ScriptDirectory" -Level 'ERROR' return } $timestamp = (Get-Date).ToString("yyyyMMddHHmmss") $exportFilePath = Join-Path -Path $ScriptDirectory -ChildPath "RegistryExport_$timestamp.reg" $arguments = "export `"$RegistryKeyPath`" `"$exportFilePath`" /y" $startProcessParams = @{ FilePath = "reg.exe" ArgumentList = $arguments Wait = $true } Write-EnhancedLog -Message "Exporting registry key: $RegistryKeyPath to file: $exportFilePath" -Level 'INFO' Start-Process @startProcessParams if (Test-Path $exportFilePath) { Write-EnhancedLog -Message "Registry key export completed successfully: $exportFilePath" -Level 'INFO' # Validate the exported registry keys $validateParams = @{ RegistryFilePath = $exportFilePath } Validate-RegistryKeys @validateParams } else { Write-EnhancedLog -Message "Failed to export registry key: $RegistryKeyPath" -Level 'ERROR' } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Export-RegistryKeys function completed' -Level 'INFO' } } # # Usage Example with Splatting # $scriptDirectory = "C:\Path\To\Your\Export\Directory" # $params = @{ # ScriptDirectory = $scriptDirectory # RegistryKeyPath = 'HKEY_LOCAL_MACHINE\SOFTWARE\Fortinet\FortiClient\Sslvpn\Tunnels' # } # Export-RegistryKeys @params #EndRegion '.\Public\Export-RegistryKeys.ps1' 63 #Region '.\Public\Find-UninstallString.ps1' -1 # Function to find the uninstall string from the registry function Find-UninstallString { param ( [string[]]$UninstallKeys, [string]$ApplicationName ) try { foreach ($key in $UninstallKeys) { $items = Get-ChildItem -Path $key -ErrorAction SilentlyContinue foreach ($item in $items) { $app = Get-ItemProperty -Path $item.PsPath if ($app.DisplayName -like $ApplicationName) { Write-EnhancedLog -Message "Found application: $($app.DisplayName) with product ID: $($app.PSChildName)" -Level 'INFO' return $app.PSChildName.Trim('{}') } } } Write-EnhancedLog -Message "No matching application found for: $ApplicationName" -Level 'WARNING' } catch { Handle-Error -ErrorRecord $_ } return $null } #EndRegion '.\Public\Find-UninstallString.ps1' 25 #Region '.\Public\Import-FortiClientConfig.ps1' -1 function Import-FortiClientConfig { [CmdletBinding()] param ( [string]$ScriptRoot, [string]$FortiClientPath, [string]$ConfigFileExtension, [string]$FCConfigExecutable, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message 'Starting Import-FortiClientConfig function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { # Find the configuration file in the root of the script directory $xmlConfigFile = Get-ChildItem -Path $ScriptRoot -Filter $ConfigFileExtension | Select-Object -First 1 if (-not $xmlConfigFile) { Write-EnhancedLog -Message "No configuration file found in the script directory: $ScriptRoot" -Level 'ERROR' Write-Output "No configuration file found in the script directory: $ScriptRoot" return } # Check if the FortiClient directory exists if (-not (Test-Path -Path $FortiClientPath)) { Write-EnhancedLog -Message "FortiClient directory not found at path: $FortiClientPath" -Level 'ERROR' Write-Output "FortiClient directory not found at path: $FortiClientPath" return } # Set location to FortiClient directory Set-Location -Path $FortiClientPath # Execute the FCConfig.exe with the specified arguments $fcConfigPath = Join-Path -Path $FortiClientPath -ChildPath $FCConfigExecutable $arguments = $ArgumentTemplate -replace '{ConfigFilePath}', $xmlConfigFile.FullName Start-Process -FilePath $fcConfigPath -ArgumentList $arguments -Wait Write-EnhancedLog -Message 'FCConfig process completed' -Level 'INFO' Write-Output "FCConfig process completed" } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Import-FortiClientConfig function completed' -Level 'INFO' } } # # Example usage of Import-FortiClientConfig function with splatting # $importParams = @{ # ScriptRoot = $PSScriptRoot # FortiClientPath = "C:\Program Files\Fortinet\FortiClient" # ConfigFileExtension = "*.xml" # FCConfigExecutable = "FCConfig.exe" # ArgumentTemplate = "-m all -f `{ConfigFilePath}` -o import -i 1" # } # # Call the Import-FortiClientConfig function using splatting # Import-FortiClientConfig @importParams #EndRegion '.\Public\Import-FortiClientConfig.ps1' 66 #Region '.\Public\Import-RegistryFilesInScriptRoot.ps1' -1 function Import-RegistryFilesInScriptRoot { [CmdletBinding()] param ( [string]$Filter, [string]$FilePath, [string]$Arguments, $scriptDirectory ) begin { Write-EnhancedLog -Message 'Starting Import-RegistryFilesInScriptRoot function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { $registryFiles = Get-ChildItem -Path $scriptDirectory -Filter $Filter if ($registryFiles.Count -eq 0) { Write-EnhancedLog -Message "No registry files found in the directory: $scriptDirectory" -Level 'WARNING' return } foreach ($registryFile in $registryFiles) { $registryFilePath = $registryFile.FullName if (Test-Path $registryFilePath) { Write-EnhancedLog -Message "Found registry file: $registryFilePath" -Level 'INFO' $startProcessParams = @{ FilePath = $FilePath ArgumentList = $Arguments Wait = $true } Start-Process @startProcessParams Write-EnhancedLog -Message "Registry file import process completed for: $registryFilePath" -Level 'INFO' # Validate the registry keys Validate-RegistryKeys -RegistryFilePath $registryFilePath } else { Write-EnhancedLog -Message "Registry file not found at path: $registryFilePath" -Level 'ERROR' } } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Import-RegistryFilesInScriptRoot function completed' -Level 'INFO' } } # # Define parameters for splatting # $params = @{ # Filter = "*.reg" # FilePath = "reg.exe" # Args = "import `"$registryFilePath`"" # } # # Call the Import-RegistryFilesInScriptRoot function using splatting # Import-RegistryFilesInScriptRoot @params #EndRegion '.\Public\Import-RegistryFilesInScriptRoot.ps1' 65 #Region '.\Public\Install-MSIPackage.ps1' -1 function Install-MsiPackage { [CmdletBinding()] param ( [string]$ScriptRoot, [string]$MsiFileName, [string]$FilePath, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message "Starting Install-MsiPackage function for: $MsiFileName" -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { $installerPath = Join-Path -Path $ScriptRoot -ChildPath $MsiFileName if (Test-Path $installerPath) { Write-EnhancedLog -Message "Found installer file: $installerPath" -Level 'INFO' $arguments = $ArgumentTemplate -replace '{InstallerPath}', $installerPath Start-Process -FilePath $FilePath -ArgumentList $arguments -Wait Write-EnhancedLog -Message "Installation process completed for: $installerPath" -Level 'INFO' Write-EnhancedLog -Message "Installation process completed for: $installerPath" -Level 'INFO' } else { Write-EnhancedLog -Message "Installer file not found at path: $installerPath.. proceeding to extract ZIP files" -Level 'WARNING' Write-EnhancedLog -Message "Extracting all ZIP files recursively..." $zipFiles = Get-ChildItem -Path $ScriptRoot -Recurse -Include '*.zip.001' foreach ($zipFile in $zipFiles) { $destinationFolder = [System.IO.Path]::GetDirectoryName($zipFile.FullName) Write-EnhancedLog -Message "Combining and extracting segmented ZIP files for $($zipFile.BaseName) using 7-Zip..." $sevenZipCommand = "& `"$env:ProgramFiles\7-Zip\7z.exe`" x `"$zipFile`" -o`"$destinationFolder`"" Write-EnhancedLog -Message "Executing: $sevenZipCommand" Invoke-Expression $sevenZipCommand } Write-EnhancedLog -Message "All ZIP files extracted." $arguments = $ArgumentTemplate -replace '{InstallerPath}', $installerPath Start-Process -FilePath $FilePath -ArgumentList $arguments -Wait # Write-Output "Installer file not found at path: $installerPath" } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Install-MsiPackage function completed' -Level 'INFO' } } # # Example usage of Install-MsiPackage function with splatting # $params = @{ # ScriptRoot = $PSScriptRoot # MsiFileName = 'FortiClient.msi' # FilePath = 'MsiExec.exe' # ArgumentTemplate = "/i `{InstallerPath}` /quiet /norestart" # } # Install-MsiPackage @params #EndRegion '.\Public\Install-MSIPackage.ps1' 63 #Region '.\Public\Invoke-Uninstall.ps1' -1 function Invoke-Uninstall { [CmdletBinding()] param ( [string]$ProductId, [string]$FilePath, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message 'Starting Invoke-Uninstall function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { Write-EnhancedLog -Message 'Starting uninstallation process.' -Level 'INFO' # Ensure the ProductId is wrapped in curly braces $wrappedProductId = "{$ProductId}" # Construct the argument list using the template $arguments = $ArgumentTemplate -replace '{ProductId}', $wrappedProductId Write-EnhancedLog -Message "FilePath: $FilePath" -Level 'INFO' Write-EnhancedLog -Message "Arguments: $arguments" -Level 'INFO' Start-Process -FilePath $FilePath -ArgumentList $arguments -Wait -WindowStyle Hidden Write-EnhancedLog -Message "Executed uninstallation with arguments: $arguments" -Level 'INFO' } catch { Write-EnhancedLog -Message "An error occurred during the uninstallation process: $($_.Exception.Message)" -Level 'ERROR' Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Invoke-Uninstall function completed' -Level 'INFO' } } # # Example usage of Invoke-Uninstall function with splatting # $params = @{ # ProductId = '0DC51760-4FB7-41F3-8967-D3DEC9D320EB' # FilePath = 'MsiExec.exe' # ArgumentTemplate = "/X{ProductId} /quiet /norestart" # } # Invoke-Uninstall @params #EndRegion '.\Public\Invoke-Uninstall.ps1' 47 #Region '.\Public\Remove-Autologin.ps1' -1 function Remove-AutoLogin { [CmdletBinding()] param () begin { Write-EnhancedLog -Message 'Starting Remove-AutoLogin function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { # Check and remove the auto-login registry keys if they exist $keysToRemove = @("AutoAdminLogon", "DefaultUserName", "DefaultPassword", "DefaultDomainName") foreach ($key in $keysToRemove) { $keyPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\$key" if (Test-Path -Path $keyPath) { Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name $key -Force Write-EnhancedLog -Message "Removed auto-login key '$key'." -Level 'INFO' } else { Write-EnhancedLog -Message "Auto-login key '$key' does not exist." -Level 'INFO' } } Write-EnhancedLog -Message "Auto-login settings removed." -Level 'INFO' } catch { Write-EnhancedLog -Message "An error occurred while removing auto-login settings: $_" -Level 'ERROR' Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Remove-AutoLogin function completed' -Level 'INFO' } } # Example usage: # Remove-AutoLogin #EndRegion '.\Public\Remove-Autologin.ps1' 39 #Region '.\Public\Remove-FortiSoftware.ps1' -1 function Remove-FortiSoftware { [CmdletBinding()] param ( [string]$ScriptRoot, [string]$SoftwareName, [string]$MsiZapFileName, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message 'Starting Remove-FortiSoftware function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { $msiZapPath = Join-Path -Path $ScriptRoot -ChildPath $MsiZapFileName if (Test-Path $msiZapPath) { $identifyingNumber = Get-CimInstance -ClassName Win32_Product | Where-Object { $_.Name -like $SoftwareName } | Select-Object -ExpandProperty IdentifyingNumber if ($identifyingNumber) { Write-EnhancedLog -Message "Found software with IdentifyingNumber: $identifyingNumber" -Level 'INFO' Write-EnhancedLog -Message "Executing MsiZap with IdentifyingNumber: $identifyingNumber" -Level 'INFO' $argumentList = $ArgumentTemplate -replace '{IdentifyingNumber}', $identifyingNumber Start-Process -FilePath $msiZapPath -ArgumentList $argumentList -Verb RunAs -Wait Write-EnhancedLog -Message 'MsiZap process completed' -Level 'INFO' } else { Write-EnhancedLog -Message 'No matching software found' -Level 'WARNING' } } else { Write-EnhancedLog -Message "MsiZap.exe not found at path: $msiZapPath" -Level 'ERROR' } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Remove-FortiSoftware function completed' -Level 'INFO' } } # # Example usage of Remove-FortiSoftware function with splatting # $params = @{ # ScriptRoot = $PSScriptRoot # SoftwareName = '*forti*' # MsiZapFileName = 'MsiZap.Exe' # ArgumentTemplate= 'TW! {IdentifyingNumber}' # } # Remove-FortiSoftware @params #EndRegion '.\Public\Remove-FortiSoftware.ps1' 54 #Region '.\Public\Remove-RegistryPath.ps1' -1 function Remove-RegistryPath { param ( [string]$RegistryPath ) Write-EnhancedLog -Message "Starting Remove-RegistryPath function for: $RegistryPath" -Level 'INFO' try { if (Test-Path -Path "Registry::$RegistryPath") { Remove-Item -Path "Registry::$RegistryPath" -Recurse -Force Write-EnhancedLog -Message "Successfully removed registry path: $RegistryPath" -Level 'INFO' Write-Output "Successfully removed registry path: $RegistryPath" } else { Write-EnhancedLog -Message "Registry path not found: $RegistryPath" -Level 'WARNING' Write-Output "Registry path not found: $RegistryPath" } } catch { Handle-Error -ErrorRecord $_ } finally { Write-EnhancedLog -Message 'Remove-RegistryPath function completed' -Level 'INFO' } } #EndRegion '.\Public\Remove-RegistryPath.ps1' 23 #Region '.\Public\Suspend-BitLockerForDrives.ps1' -1 function Suspend-BitLockerForDrives { [CmdletBinding()] param ( [string[]]$DriveLetters ) begin { Write-EnhancedLog -Message 'Starting Suspend-BitLockerForDrives function' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { # Detect BitLocker status for the provided drives $bitLockerStatusResults = Detect-BitLockerStatus -DriveLetters $DriveLetters foreach ($status in $bitLockerStatusResults) { $drive = $status.MountPoint $protectionStatus = $status.ProtectionStatus if ($protectionStatus -eq "On") { try { Write-EnhancedLog -Message "Suspending BitLocker on drive $drive" -Level 'INFO' Suspend-BitLocker -MountPoint $drive -RebootCount 0 Write-EnhancedLog -Message "BitLocker suspended on drive $drive" -Level 'INFO' } catch { Handle-Error -ErrorRecord $_ } } else { Write-EnhancedLog -Message "BitLocker is not enabled on drive $drive" -Level 'INFO' } } } end { Write-EnhancedLog -Message 'Suspend-BitLockerForDrives function completed' -Level 'INFO' } } # # Example usage of Suspend-BitLockerForDrives function with splatting # $params = @{ # DriveLetters = @("C:", "D:") # } # # Call the Suspend-BitLockerForDrives function using splatting # Suspend-BitLockerForDrives @params #EndRegion '.\Public\Suspend-BitLockerForDrives.ps1' 47 #Region '.\Public\Uninstall-FortiClientEMSAgentApplication.ps1' -1 function Uninstall-FortiClientEMSAgentApplication { [CmdletBinding()] param ( [string[]]$UninstallKeys, [string]$ApplicationName, [string]$FilePath, [string]$ArgumentTemplate ) begin { Write-EnhancedLog -Message 'Starting the Uninstall-FortiClientEMSAgentApplication function...' -Level 'INFO' Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } process { try { $findParams = @{ UninstallKeys = $UninstallKeys ApplicationName = $ApplicationName } $productId = Find-UninstallString @findParams if ($null -ne $productId) { Write-EnhancedLog -Message "Found product ID: $productId" -Level 'INFO' # Prepare parameters for Invoke-Uninstall $invokeParams = @{ ProductId = $productId FilePath = $FilePath ArgumentTemplate = $ArgumentTemplate } Invoke-Uninstall @invokeParams #wait a bit before going into detection/validation Start-Sleep -Seconds 30 } else { Write-EnhancedLog -Message 'Product ID not found for FortiClientEMSAgent application.' -Level 'WARNING' } } catch { Handle-Error -ErrorRecord $_ } } end { Write-EnhancedLog -Message 'Uninstall process completed.' -Level 'INFO' } } # # Example usage of Uninstall-FortiClientEMSAgentApplication function with splatting # $params = @{ # UninstallKeys = @( # 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', # 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' # ) # ApplicationName = '*Forti*' # FilePath = 'MsiExec.exe' # ArgumentTemplate = "/X{ProductId} /quiet /norestart" # } # Uninstall-FortiClientEMSAgentApplication @params #EndRegion '.\Public\Uninstall-FortiClientEMSAgentApplication.ps1' 59 #Region '.\Public\Validate-RegistryKeys.ps1' -1 function Validate-RegistryKeys { param ( [string]$RegistryFilePath ) Write-EnhancedLog -Message "Starting Validate-RegistryKeys function for: $RegistryFilePath" -Level 'INFO' try { $importedKeys = Get-Content -Path $RegistryFilePath | Where-Object { $_ -match '^\[.*\]$' } | ForEach-Object { $_ -replace '^\[|\]$', '' } $importSuccess = $true foreach ($key in $importedKeys) { if (Test-Path -Path "Registry::$key") { Write-EnhancedLog -Message "Validated registry key: $key" -Level 'INFO' Write-EnhancedLog "Validated registry key: $key" -Level 'INFO' } else { Write-EnhancedLog -Message "Failed to validate registry key: $key" -Level 'ERROR' Write-EnhancedLog "Failed to validate registry key: $key" -Level 'ERROR' $importSuccess = $false } } if ($importSuccess) { Write-EnhancedLog -Message "Successfully validated all registry keys for: $RegistryFilePath" -Level 'INFO' } else { Write-EnhancedLog -Message "Some registry keys failed to validate for: $RegistryFilePath" -Level 'ERROR' } } catch { Handle-Error -ErrorRecord $_ } finally { Write-EnhancedLog -Message 'Validate-RegistryKeys function completed' -Level 'INFO' } } #EndRegion '.\Public\Validate-RegistryKeys.ps1' 38 #Region '.\Public\Validate-RegistryRemoval.ps1' -1 function Validate-RegistryRemoval { param ( [string]$RegistryPath ) Write-EnhancedLog -Message "Starting Validate-RegistryRemoval function for: $RegistryPath" -Level 'INFO' try { if (Test-Path -Path "Registry::$RegistryPath") { Write-EnhancedLog -Message "Registry path still exists: $RegistryPath" -Level 'ERROR' Write-Output "Registry path still exists: $RegistryPath" } else { Write-EnhancedLog -Message "Registry path successfully removed: $RegistryPath" -Level 'INFO' Write-Output "Registry path successfully removed: $RegistryPath" } } catch { Handle-Error -ErrorRecord $_ } finally { Write-EnhancedLog -Message 'Validate-RegistryRemoval function completed' -Level 'INFO' } } #EndRegion '.\Public\Validate-RegistryRemoval.ps1' 22 #Region '.\Public\WaitForRegistryKey.ps1' -1 function WaitForRegistryKey { param ( [string[]]$RegistryPaths, [string]$SoftwareName, [version]$MinimumVersion, [int]$TimeoutSeconds = 120 ) Write-EnhancedLog -Message "Starting WaitForRegistryKey function" -Level "INFO" Write-EnhancedLog -Message "Checking for $SoftwareName version $MinimumVersion or later" -Level "INFO" $elapsedSeconds = 0 try { while ($elapsedSeconds -lt $TimeoutSeconds) { foreach ($path in $RegistryPaths) { $items = Get-ChildItem -Path $path -ErrorAction SilentlyContinue foreach ($item in $items) { $app = Get-ItemProperty -Path $item.PsPath -ErrorAction SilentlyContinue if ($app.DisplayName -like "*$SoftwareName*") { $installedVersion = New-Object Version $app.DisplayVersion if ($installedVersion -ge $MinimumVersion) { Write-EnhancedLog -Message "Found $SoftwareName version $installedVersion at $item.PsPath" -Level "INFO" return @{ IsInstalled = $true Version = $app.DisplayVersion ProductCode = $app.PSChildName } } } } } Start-Sleep -Seconds 1 $elapsedSeconds++ } Write-EnhancedLog -Message "Timeout reached. $SoftwareName version $MinimumVersion or later not found." -Level "WARNING" return @{ IsInstalled = $false } } catch { Handle-Error -ErrorRecord $_ } finally { Write-EnhancedLog -Message "WaitForRegistryKey function completed" -Level "INFO" } } #EndRegion '.\Public\WaitForRegistryKey.ps1' 50 |