EasitManagementFramework.psm1

function Backup-EasitFolder {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string] $FolderToBackup,
        [Parameter(Mandatory)]
        [string] $DestinationFolder,
        [Parameter()]
        [string] $ArchiveName,
        [Parameter()]
        [boolean] $Cleanup
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        $today = Get-Date -Format "yyyyMMdd"
        $now = Get-Date -Format "yyyyMMdd_HHmmss"
        $todayDestinationFolder = Join-Path -Path "$DestinationFolder" -ChildPath "$today"
        if ([string]::IsNullOrWhiteSpace($ArchiveName)) {
            $leaf = Split-Path $FolderToBackup -Leaf
            $ArchiveName = "${leaf}_${now}"
        }
        Write-Verbose "Using $ArchiveName as ArchiveName"
        if (!(Test-Path -Path $todayDestinationFolder)) {
            try {
                $todayDestinationFolder = (New-Item -Path $DestinationFolder -Name "$today" -ItemType Directory).FullName
                Write-Verbose "Created $todayDestinationFolder"
            } catch {
                throw $_
            }
        }
        $tempDirectory = [System.IO.Path]::GetTempPath()
        [string] $tempDirectoryName = [System.Guid]::NewGuid()
        $tempWorkingDirectoryPath = Join-Path -Path $tempDirectory -ChildPath $tempDirectoryName
        $tempWorkingDirectory = New-Item -ItemType Directory -Path $tempWorkingDirectoryPath
        try {
            Write-Verbose "Copying folder to temp location"
            Copy-Item -Path $FolderToBackup -Destination $tempWorkingDirectory
            $tempFolderToBackup = Join-Path -Path $tempWorkingDirectory -ChildPath "$leaf"
        } catch {
            throw $_
        }
        Write-Verbose "Using $todayDestinationFolder as todayDestinationFolder"
        $zipFile = Join-Path -Path $todayDestinationFolder -ChildPath "$ArchiveName.zip"
        try {
            Add-Type -Assembly System.IO.Compression.FileSystem
            $compressionLevel = [IO.Compression.CompressionLevel]::Optimal
            if (Test-Path -Path $FolderToBackup -PathType Leaf) {
                Write-Verbose "PathType is Leaf"
                try {
                    $zip = [System.IO.Compression.ZipFile]::Open($zipFile, 'create')
                    $zip.Dispose()
                    $zip = [System.IO.Compression.ZipFile]::Open($zipFile, 'update')
                    [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $tempFolderToBackup, $leaf, $compressionLevel) | Out-Null
                    $zip.Dispose()
                } catch {
                    $zip.Dispose()
                    Remove-Item $zipFile -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue
                    Remove-Item $zip -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue
                    Remove-Item $tempWorkingDirectoryPath -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue
                    throw $_
                }
            }
            if (Test-Path -Path $FolderToBackup -PathType Container) {
                Write-Verbose "PathType is Container"
                try {
                    [IO.Compression.ZipFile]::CreateFromDirectory($tempFolderToBackup, $zipFile, $compressionLevel, $false)
                } catch {
                    Remove-Item $zipFile -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue
                    Remove-Item $tempWorkingDirectoryPath -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue
                    throw $_
                }
            }
            Remove-Item $tempWorkingDirectoryPath -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue -ErrorAction SilentlyContinue
            Write-Verbose "Created zip archive for $FolderToBackup"
        } catch {
            throw $_
        }
        if ($Cleanup) {
            try {
                Remove-Item $FolderToBackup -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue
                Write-Verbose "Removed $FolderToBackup"
            } catch {
                throw $_
            }
        } else {
            Write-Verbose "Cleanup has not been specified, leaving $FolderToBackup as is"
        }
    }
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Convert-EasitLogEntryToPsObject {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Convert-EasitLogEntryToPsObject.md")]
    param (
        [Parameter(ValueFromPipeline)]
        [string] $String,
        [Parameter()]
        [string] $Source
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    process {
        Write-Verbose "Selecting strings from entry"
        $stringDate = Select-String -InputObject $String -Pattern '\d{4}-\d{2}-\d{2}'
        $stringDate = "$($stringDate.Matches.Value)"
        Write-Debug "stringDate = $stringDate"

        $stringTime = Select-String -InputObject $String -Pattern '\d{2}:\d{2}:\d{2}\.\d{3}'
        $stringTime = "$($stringTime.Matches.Value)"
        Write-Debug "stringTime = $stringTime"

        $stringLevel = Select-String -InputObject $String -Pattern 'FATAL|ERROR|WARN|INFO|DEBUG|TRACE'
        $stringLevel = "$($stringLevel.Matches.Value)"
        Write-Debug "stringLevel = $stringLevel"

        $stringMessage = Select-String -InputObject $String -Pattern '- .+\['
        $stringMessage = "$($stringMessage.Matches.Value)"
        $stringMessage = $stringMessage.TrimStart('- ')
        $stringMessage = $stringMessage.TrimEnd('[')
        Write-Debug "stringMessage = $stringMessage"

        $stringClass = Select-String -InputObject $String -Pattern '\[[\w\.]+\]$'
        $stringClass = "$($stringClass.Matches.Value)"
        $stringClass = $stringClass.TrimStart('[')
        $stringClass = $stringClass.TrimEnd(']')
        Write-Debug "stringClass = $stringClass"

        if (Select-String -InputObject $String -Pattern '\]\s?(\r|\n)+' -Quiet) {
            $stringStack = Select-String -InputObject $String -Pattern '\- [\w|\W|\n\r]*'
            $stringStack = "$($stringStack.Matches.Value)"
            $stringStack = $stringStack.TrimStart("- $stringMessage [$stringClass]")
            $stringStack = $stringStack.TrimStart()
            Write-Debug "stringStack = $stringStack"
        } else {
            $stringStack = $null
        }

        Write-Verbose "Creating object from entry strings"
        $returnObject = [PSCustomObject]@{
            Date                = "$stringDate"
            Time                = "$stringTime"
            Level               = "$stringLevel"
            Class               = "$stringClass"
            Message             = "$stringMessage"
            FullStackMessage    = "$stringStack"
            Source              = "$Source"
        }
        Write-Verbose "Returning entry as object"
        return $returnObject
    }
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Convert-EmailRequestConfigfile {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$Path
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        try {
            $xmlObject = New-Object XML
        } catch {
            throw $_
        }
        if (Test-Path $Path) {
            try {
                $xmlObject.Load($Path)
            } catch {
                throw $_
            }
        } else {
            throw "Unable to find $Path"
        }
        foreach ($entry in $xmlObject.configuration.entries.GetEnumerator()) {
            try {
                $erMailConfigAsPSObject = New-Object PSObject
            } catch {
                throw $_
            }
            foreach ($mainProperty in $entry.properties.GetEnumerator()) {
                Write-Verbose "Adding property $($mainProperty.name) = $($mainProperty.value)"
                Add-Member -InputObject $erMailConfigAsPSObject -MemberType NoteProperty -Name "$($mainProperty.name)" -Value "$($mainProperty.value)"
            }
            foreach ($sourceProperty in $entry.source.properties.GetEnumerator()) {
                Write-Verbose "Adding property $($sourceProperty.name) = $($sourceProperty.value)"
                Add-Member -InputObject $erMailConfigAsPSObject -MemberType NoteProperty -Name "$($sourceProperty.name)" -Value "$($sourceProperty.value)"
            }
            foreach ($destinationProperty in $entry.destination.properties.GetEnumerator()) {
                Write-Verbose "Adding property $($destinationProperty.name) = $($destinationProperty.value)"
                Add-Member -InputObject $erMailConfigAsPSObject -MemberType NoteProperty -Name "$($destinationProperty.name)" -Value "$($destinationProperty.value)"
            }
            Write-Verbose "Adding property sourceType = $($entry.source.type)"
            Add-Member -InputObject $erMailConfigAsPSObject -MemberType NoteProperty -Name 'sourceType' -Value "$($entry.source.type)"
            Add-Member -InputObject $erMailConfigAsPSObject -MemberType NoteProperty -Name 'Path' -Value "$Path"
            $erMailConfigAsPSObject
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Convert-KeytoolResult {
    [CmdletBinding()]
    param (
        [Parameter()]
        [String[]] $InputString,
        [Parameter()]
        [String] $ListCerts
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        if ($InputString) {
            if (Select-String -Pattern 'java.lang.Exception:' -InputObject $InputString) {
                Write-Verbose "Input is an exception"
                $InputString
            } elseif (Select-String -Pattern '-rfc.*-alias.*-keystore.*-cacerts.*-storepass.*' -InputObject $InputString) {
                Write-Verbose "Input is help section"
                $InputString
            } elseif ($ListCerts -match 'true') {
                Write-Verbose "ListCerts = $ListCerts"
                $returnObject = New-Object -TypeName psobject
                $entryId = 1
                foreach ($string in $InputString) {
                    if ($string.Length -gt 1) {
                        $Matches = $null
                        Write-Verbose "String = $string"
                        if ($string -match 'Keystore|Nyckellager') {
                            Write-Verbose "String matches Keystore|Nyckellager"
                            $string -match '^(.+): (.+)' | Out-Null
                            $propName = $Matches[1]
                            $propName = $propName.TrimStart()
                            $propValue = $Matches[2]
                            $propValue = $propValue.TrimEnd()
                            $propValue = $propValue.TrimStart()
                            Write-Verbose "$propName = $propValue"
                            $returnObject | Add-Member -MemberType Noteproperty -Name "$propName" -Value "$propValue"
                        } elseif ($string -cmatch '(\d+) poster|post|entry|entries') {
                            Write-Verbose "String matches poster|post|entry|entries"
                            $string -match '(\d+) poster|post|entry|entries' | Out-Null
                            $propName = 'NumberOfEntriesInStore'
                            $propValue = $Matches[1]
                            Write-Verbose "$propName = $propValue"
                            $returnObject | Add-Member -MemberType Noteproperty -Name "$propName" -Value "$propValue"
                        } elseif ($string -match '.*, .*, .*,') {
                            Write-Verbose "Split details"
                            $string -match '((.*), (.*), (.*)),' | Out-Null
                            $tempPropValues = $Matches[1]
                            $tempPropValuesArray = $tempPropValues -split ','
                            $returnObject | Add-Member -MemberType Noteproperty -Name "CertificateAlias_$entryId" -Value "$($tempPropValuesArray[0])"
                            foreach ($tempPropValue in $tempPropValuesArray) {
                                Write-Verbose "$tempPropValue"
                            }
                        } elseif ($string -match '.*(\(.*\)): (.*)') {
                            $string -match '.*(\(.*\)): (.*)' | Out-Null
                            $propName = "CertificateFingerprint $($Matches[1])_$entryId"
                            $propValue = $Matches[2]
                            $returnObject | Add-Member -MemberType Noteproperty -Name "$propName" -Value "$propValue"
                            $entryId++
                        }
                    }
                }
                $returnObject
            } else {
                Write-Verbose "Input is valid"
                $returnObject = New-Object -TypeName psobject
                foreach ($string in $InputString) {
                    if ($string.Length -gt 1 -and $string -match '^\s*(.+):{1} (.+)') {
                        if ($string -match '^\d{2}(\d|[A-Z])\d' -or $string -match '^\s+\[' -or $string -match '^\#\d+' -or $string -match 'access' -or $string -match 'PathLen') {
                            Write-Verbose "Not a relevant string, $string"
                        } else {
                            Write-Verbose "String = $string"
                            $string -match '^\s*(.+):{1} (.+)' | Out-Null
                            $propName = $Matches[1]
                            $propName = $propName.TrimStart()
                            $propValue = $Matches[2]
                            $propValue = $propValue.TrimEnd()
                            $propValue = $propValue.TrimStart()
                            Write-Verbose "$propName = $propValue"
                            if ($propName -match '.*alias.*') {
                                Write-Verbose "alias"
                                $propName = 'CertificateAlias'
                                $propValue = $propValue
                            } elseif ($propName -match 'Skapat|Creation') {
                                Write-Verbose "skapat"
                                $propName = 'CreationDate'
                                $propValue = $propValue
                            } elseif ($propName -match 'post|entry') {
                                Write-Verbose "post"
                                $propName = 'EntryType'
                                $propValue = $propValue
                            } elseif ($propName -match '.gare|owner') {
                                Write-Verbose "owner"
                                $propName = 'Owner'
                                $propValue = $propValue
                            } elseif ($propName -match 'utf.{1}rdare|issuer') {
                                Write-Verbose "issuer"
                                $propName = 'Issuer'
                                $propValue = $propValue
                            } elseif ($propName -match 'Serienummer|Serial') {
                                Write-Verbose "Serienummer"
                                $propName = 'SerialNumber'
                                $propValue = $propValue
                            } elseif ($propName -match 'Giltigt|Valid') {
                                Write-Verbose "Giltigt"
                                $propName = 'ValidFrom'
                                $propName2 = 'ValidUntil'
                                $string -match '(?>Giltigt |Valid ).*: (.*),? (?>till|until): (.*)' | Out-Null
                                $propValue = $Matches[1]
                                $propValue = $propValue.TrimEnd(',')
                                $propValue2 = $Matches[2]
                                if (!(${returnObject}.${propName2})) {
                                    $returnObject | Add-Member -MemberType Noteproperty -Name "$propName2" -Value "$propValue2"
                                }
                            } elseif ($propName -match '\w{2,3}\d{1,3}') {
                                Write-Verbose "hashes"
                                $propName = "CertificateFingerprint ($propName)"
                            } elseif ($propName -match 'Signaturalgoritmnamn|Signature') {
                                Write-Verbose "SignatureAlgorithmName"
                                $propName = 'SignatureAlgorithmName'
                            } elseif ($propName -match '(?>Algoritm f|Signature)') {
                                Write-Verbose "Signature"
                                $propName = 'AlgorithmForOpenKey'
                            } else {
                                Write-Verbose "$propName matches nothing"
                            }
                            if (!(${returnObject}.${propName})) {
                                $returnObject | Add-Member -MemberType Noteproperty -Name "$propName" -Value "$propValue"
                            }
                        }
                    } else {
                        Write-Verbose "String ($string) is not relevant"
                    }
                    $Matches = $null
                }
                $returnObject
            }
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Convert-XmlToPSObject {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [xml] $XmlObject,
        [Parameter()]
        [switch] $SystemProperties
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        $returnObject = New-Object -TypeName PSObject
        if ($SystemProperties) {
            foreach ($entry in $XmlObject.properties.entry) {
                Write-Verbose "Adding $($entry.key) = $($entry.'#text')"
                try {
                    Add-Member -InputObject $returnObject -MemberType Noteproperty -Name "$($entry.key)" -Value "$($entry.'#text')"
                } catch {
                    throw $_
                }
            }
        }
        return $returnObject
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Get-DatabaseDetails {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$Uri
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        $returnObject = New-Object PSObject
        $multiConnDets = $false
        if ($Uri -match 'sqlserver') {
            Write-Verbose "ConnString is for MSSQL"
            $supportedProtocol = $true
            $dbConnectionDetails = $Uri -split ';'
            if ($dbConnectionDetails.Count -ne '1') {
                $multiConnDets = $true
            }
        }
        if ($Uri -match 'mysql') {
            Write-Verbose "ConnString is for MySQL"
            $supportedProtocol = $false
            $cleanDbUrl = $Uri -replace '.+\:.+\:\/\/',''
            Write-Verbose "cleanDbUrl = $cleanDbUrl"
            $dbName = Split-Path $cleanDbUrl -Leaf
            $dbServerUrl = Split-Path $cleanDbUrl -Parent
            $dbServerUrlDetails = $dbServerUrl -split ':'
            $dbServerName = $dbServerUrlDetails[0]
            if ($dbServerUrlDetails[1]) {
                $dbServerPort = $dbServerUrlDetails[1]
            } else {
                $dbServerPort = 3306
            }
        }
        
        if ($multiConnDets) {
            Write-Verbose "Multiple connections details"
            foreach ($dbConnectionDetail in $dbConnectionDetails) {
                Write-Verbose $dbConnectionDetail
                if ($dbConnectionDetail -match '.+\:.+\:\/\/.*') {
                    $dbServerDetails = $dbConnectionDetail -replace '.+\:.+\:\/\/',''
                    if ($dbServerDetails -match '\\\\') {
                        Write-Verbose "$dbServerDetails contains \\"
                        $dbInstanceDetails = $dbServerDetails -split '\\\\'
                        Write-Verbose "dbInstanceDetails = $dbInstanceDetails"
                        $dbInstance = $dbInstanceDetails[1]
                        $dbServerDetails = $dbInstanceDetails[0]
                    }
                    if ($dbServerDetails -match ':') {
                        Write-Verbose "$dbServerDetails contains :"
                        $dbServerUrlDetails = $dbServerDetails -split ':'
                        Write-Verbose "dbServerUrlDetails = $dbServerUrlDetails"
                        $dbServerName = $dbServerUrlDetails[0]
                        $dbServerPort = $dbServerUrlDetails[1]
                    } 
                    if (!($dbServerName)) {
                        $dbServerName = $dbServerDetails
                    }
                    if (!($dbServerPort)) {
                        $dbServerPort = 1433
                    }
                    if (!($dbInstance)) {
                        $dbInstance = $null
                    }
                }
                if ($dbConnectionDetail -match 'databaseName.*') {
                    $dbName = $dbConnectionDetail -replace 'databaseName=',''
                }
            }
        }
        try {
            Write-Verbose "dbServerName = $dbServerName"
            $returnObject | Add-Member -MemberType NoteProperty -Name 'dbServerName' -Value "$dbServerName"
            Write-Verbose "dbServerPort = $dbServerPort"
            $returnObject | Add-Member -MemberType NoteProperty -Name 'dbServerPort' -Value "$dbServerPort"
            Write-Verbose "dbName = $dbName"
            $returnObject | Add-Member -MemberType NoteProperty -Name 'dbName' -Value "$dbName"
            Write-Verbose "dbInstance = $dbInstance"
            $returnObject | Add-Member -MemberType NoteProperty -Name 'dbInstance' -Value "$dbInstance"
            Write-Verbose "supportedProtocol = $supportedProtocol"
            $returnObject | Add-Member -MemberType NoteProperty -Name 'supportedProtocol' -Value "$supportedProtocol"
            return $returnObject
        } catch {
            throw $_
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Get-EasitJavaKeytool {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Path
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        $javaPath = Join-Path -Path $Path -ChildPath 'Java'
        if (Test-Path $javaPath) {
            try {
                Get-ChildItem "$javaPath\*" -Include 'keytool.exe' -Recurse | Sort-Object {[version]$_.VersionInfo.FileVersion} | Select-Object -Last 1
            } catch {
                throw $_
            }
        } else {
            throw "$javaPath is not a valid path.."
        }
    }
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

function Get-EasitService {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string] $ServiceName
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        try {
            $service = Get-CimInstance -ClassName Win32_Service -Filter "Name Like '$ServiceName'"
            Write-Verbose "Found service $($service.Name)"
        } catch {
            throw "Unable to find a service with a name like $ServiceName"
        }
        return $service
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Get-EasitWarFile {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$Path,
        [Parameter(Mandatory)]
        [string]$Name
    )
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    process {
        if (!(Test-Path -Path $Path)) {
            throw "Unable to find $Path"
        }
        try {
            $folders = Get-ChildItem -Path $Path -Exclude 'files', 'solr*' -Directory
        } catch {
            throw $_
        }
        foreach ($folder in $folders) {
            try {
                Get-ChildItem -Path $folder -Include "$Name" -File -Recurse
            } catch {
                throw $_
            }
        }
    }
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Import-EMFXMLData {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string] $Path,
        [Parameter()]
        [switch] $ReturnAsPSObject,
        [Parameter()]
        [switch] $Validate
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        Write-Verbose "Process block start"
        if ($Validate) {
            try {
                Test-EMFXMLData -Path $Path
                Write-Verbose 'XML validated successfully'
            } catch {
                throw $_
            }
        } else {
            Write-Verbose "Skipping validation"
        }
        $xmlObject = New-Object System.Xml.XmlDocument
        try {
            $xmlObject.Load($Path)
            Write-Verbose 'Loaded XML-file to XML-object'
        } catch {
            throw $_
        }
        
        if ($ReturnAsPSObject) {
            try {
                $psObject = Convert-XmlToPSObject -XmlObject $xmlObject -SystemProperties
            } catch {
                throw $_
            }
            return $psObject
        } else {
            return $xmlObject
        }
        Write-Verbose "Process block end"
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

function Set-EasitService {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [CimInstance] $Service,
        [Parameter(Mandatory)]
        [ValidateSet('StartService','StopService')]
        [string] $Action
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        $waitingTime = 0
    }
    
    process {
        if ($Action -eq 'StartService') {
            $waitForServiceState = 'Running'
        }
        if ($Action -eq 'StopService') {
            $waitForServiceState = 'Stopped'
        }
        Write-Information "Invoking method $Action on $($Service.Name)"
        try {
            Invoke-CimMethod -InputObject $Service -MethodName "$Action" | Out-Null
        } catch {
            throw $_
        }
        try {
            do {
                Write-Verbose "Waiting for service to complete method invokation"
                Start-Sleep -Seconds 5
                $waitingTime += 5
                $serviceToCheck = Get-CimInstance -InputObject $Service
            } while ($serviceToCheck.State -ne "$waitForServiceState" -AND $waitingTime -le 240)
            if ($waitingTime -gt 240) {
                Write-Warning "Time to invoke method $Action exceeded 2 minutes"
            }
        } catch {
            throw $_
        }
        return $serviceToCheck
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Test-ConfigurationSetting {
    [CmdletBinding()]
    param (
        [Parameter()]
        [hashtable]$Hashtable,
        [Parameter()]
        [System.Xml.XmlDocument]$XmlObject
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        $validatePathSetting = 'SystemRoot','EmailRequestRoot','EasitRoot','BackupRoot','TomcatRoot','ImportClientRoot','UpdateResourceDirectory'
    }
    
    process {
        $allSettingsPassedTest = $true
        if ($Hashtable) {
            foreach ($configSetting in $configurationSettings.GetEnumerator()) {
                $configSettingName = "$($configSetting.Key)"
                $configSettingValue = "$($configSetting.Value)"
                Write-Verbose "Validating configuration setting $configSettingName"
                if ($configSettingName -in $validatePathSetting) {
                    if (Test-Path "$configSettingValue" -IsValid) {
                        $validationResult = Test-Path "$configSettingValue"
                    } else {
                        $validationResult = $false
                    }
                }
                if ($configSettingName -eq 'ServiceName') {
                    $validationResult = Get-Service -Name "$configSettingValue" -ErrorAction SilentlyContinue
                }
                if ($configSettingName -eq 'WarName') {
                    $systemRoot = $configurationSettings['SystemRoot']
                    $validationResult = Get-ChildItem -Path "$systemRoot" -Recurse -Include "${configSettingValue}.war" -ErrorAction SilentlyContinue
                }
                if ($configSettingName -eq 'StoredBackupProcedure') {
                    # Unable to validate this setting
                    $validationResult = $true
                }
                if (!($validationResult)) {
                    Write-Warning "Configuration setting $configSettingName ($configSettingValue) failed validation"
                    $allSettingsPassedTest = $false
                }
            }
            if ($allSettingsPassedTest) {
                Write-Information "Validation OK" -InformationAction Continue
            }
        }
        if ($XmlObject) {
            foreach ($system in $XmlObject.systems.ChildNodes) {
                Write-Information "Validating settings for configuration $($system.Name)" -InformationAction Continue
                foreach ($configSetting in $system.ChildNodes) {
                    $configSettingName = "$($configSetting.Name)"
                    $configSettingValue = "$($configSetting.InnerText)"
                    Write-Verbose "Validating configuration setting $configSettingName"
                    if ($configSettingName -in $validatePathSetting) {
                        if (Test-Path "$configSettingValue" -IsValid) {
                            $validationResult = Test-Path "$configSettingValue"
                        } else {
                            $validationResult = $false
                        }
                    }
                    if ($configSettingName -eq 'ServiceName') {
                        $validationResult = Get-Service -Name "$configSettingValue" -ErrorAction SilentlyContinue
                    }
                    if ($configSettingName -eq 'WarName') {
                        $systemRoot = $system.GetElementsByTagName('SystemRoot')
                        $systemRoot = $systemRoot.'#text'
                        $validationResult = Get-EasitWarFile -Path "$systemRoot" -Name "${configSettingValue}.war"
                    }
                    if (!($validationResult)) {
                        Write-Warning "Configuration setting $configSettingName ($configSettingValue) failed validation"
                        $allSettingsPassedTest = $false
                    }
                }
                if ($allSettingsPassedTest) {
                    Write-Information "Validation OK" -InformationAction Continue
                }
            }
        }
        return
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Test-ForFileLock {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Test-ForFileLock.md")]
    param (
        [Parameter(Mandatory)]
        [string]$FilePath
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        Write-Verbose "Checking if $FilePath is locked"
        $fileInfo = New-Object System.IO.FileInfo $FilePath
        try {
            $fileStream = $fileInfo.Open( [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
            Write-Verbose "$FilePath is not locked"
            $returnValue = $false
        } catch {
            Write-Verbose "$FilePath is locked"
            $returnValue = $true
        }
        $fileStream.Close()
        $fileStream.Dispose()
        return $returnValue
    }
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
function Add-CertificateToEasitTrustStore {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Add-CertificateToEasitTrustStore.md")]
    [Alias("ACTET", "AddCert")]
    param (
        [Parameter(ParameterSetName='LiteralPath',Mandatory=$true)]
        [string] $LiteralPath,
        [Parameter(ParameterSetName='Path')]
        [string] $Path,
        [Parameter(ParameterSetName='Path',Mandatory=$true)]
        [string] $TrustStoreName,
        [Parameter(Mandatory=$true)]
        [string] $Certificate,
        [Parameter()]
        [string] $Keytool,
        [Parameter(Mandatory=$true)]
        [Alias('keystorepass','truststorepass')]
        [string] $StorePass,
        [Parameter(Mandatory=$true)]
        [string] $CertificateAlias,
        [Parameter()]
        [switch] $TrustCaCerts,
        [Parameter()]
        [switch] $NoPrompt,
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter()]
        [Alias('system')]
        [string] $EmfConfigurationName = 'Prod'
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        $emfConfig = Get-EMFConfig -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
    }
    
    process {
        if (!($Keytool)) {
            try {
                $Keytool = Get-EasitJavaKeytool -Path $emfConfig.EasitRoot
                Write-Verbose "Keytool = $Keytool"
            } catch {
                throw $_
            }
        }
        if ($Path -and $TrustStoreName) {
            $trustStorePath = Join-Path -Path $Path -ChildPath $TrustStoreName
            if (Test-Path $trustStorePath) {
                Write-Verbose "Using truststore at $trustStorePath"
            } else {
                throw "Unable to find $TrustStoreName in $Path"
            }
        }
        if ($Path -and !($TrustStoreName)) {
            throw "You need to provide a TrustStoreName when specifying Path. Otherwise use LiteralPath."
        }
        if ($LiteralPath) {
            if (Test-Path $LiteralPath) {
                $trustStorePath = $LiteralPath
                Write-Verbose "Using truststore at $trustStorePath"
            } else {
                throw "Unable to find $LiteralPath"
            }
        }
        if (Test-Path -Path $Certificate) {
            Write-Verbose "Will try to import file: $Certificate"
        } else {
            throw "Unable to find certificate $Certificate"
        }
        if ($NoPrompt) {
            if ($TrustCaCerts) {
                Write-Verbose "Executing: $Keytool -importcert -trustcacerts -noprompt -alias $CertificateAlias -file $Certificate -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -importcert -trustcacerts -noprompt -alias "$CertificateAlias" -file "$Certificate" -keystore "$trustStorePath" -storepass "$StorePass"
            } else {
                Write-Verbose "Executing: $Keytool -importcert -noprompt -alias $CertificateAlias -file $Certificate -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -importcert -noprompt -alias "$CertificateAlias" -file "$Certificate" -keystore "$trustStorePath" -storepass "$StorePass"
            }
        } else {
            if ($TrustCaCerts) {
                Write-Verbose "Executing: $Keytool -importcert -trustcacerts -alias $CertificateAlias -file $Certificate -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -importcert -trustcacerts -noprompt -alias "$CertificateAlias" -file "$Certificate" -keystore "$trustStorePath" -storepass "$StorePass"
            } else {
                Write-Verbose "Executing: $Keytool -importcert -alias $CertificateAlias -file $Certificate -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -importcert -noprompt -alias "$CertificateAlias" -file "$Certificate" -keystore "$trustStorePath" -storepass "$StorePass"
            }
        }
        if (!($result)) {
            break
        } else {
            return $result
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Add-CertificateToEasitTrustStore
function Disable-EasitScheduledTask {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline, ParameterSetName = 'InputObject')]
        [Microsoft.Management.Infrastructure.CimInstance[]] $InputObject,

        [Parameter(ParameterSetName = 'TaskName')]
        [string[]] $TaskName,

        [Parameter()]
        [switch] $AsJob
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        if ($InputObject) {
            $paramArgs = @{
                TaskName = "$($InputObject.TaskName)"
            }
            Write-Verbose "TaskName set to $($InputObject.TaskName)"
        } 
        if ($TaskName) {
            $paramArgs = @{
                TaskName = "$TaskName"
            }
            Write-Verbose "TaskName set to $TaskName"
        }
        if ($AsJob) {
            $paramArgs = @{
                AsJob = $true
            }
            Write-Verbose "Parameter AsJob specified"
        }
        try {
            Disable-ScheduledTask @paramArgs
            Write-Verbose "Task with name $TaskName disabled"
        } catch {
            throw $_
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Disable-EasitScheduledTask
function Enable-EasitScheduledTask {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline, ParameterSetName = 'InputObject')]
        [Microsoft.Management.Infrastructure.CimInstance[]] $InputObject,

        [Parameter(ParameterSetName = 'TaskName')]
        [string[]] $TaskName,

        [Parameter()]
        [switch] $AsJob
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized.."
    }
    
    process {
        if ($InputObject) {
            $paramArgs = @{
                TaskName = "$($InputObject.TaskName)"
            }
            Write-Verbose "TaskName set to $($InputObject.TaskName)"
        } 
        if ($TaskName) {
            $paramArgs = @{
                TaskName = "$TaskName"
            }
            Write-Verbose "TaskName set to $TaskName"
        }
        if ($AsJob) {
            $paramArgs = @{
                AsJob = $true
            }
            Write-Verbose "Parameter AsJob specified"
        }
        try {
            Enable-ScheduledTask @paramArgs
            Write-Verbose "Task with name $TaskName enabled"
        } catch {
            throw $_
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Enable-EasitScheduledTask
function Get-EasitEmailRequestMailbox {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',

        [Parameter()]
        [string] $EmfConfigurationName = 'Prod',

        [Parameter()]
        [string[]] $EmailRequestConfigurationFilename = '*config*.xml',

        [Parameter()]
        [Alias('Mailbox')]
        [string[]] $MailboxName
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        try {
            $emfConfig = Get-EMFConfig -Home $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
            Write-Verbose "Found EMF Config"
        } catch {
            throw $_
        }
    }
    
    process {
        $erXmlConfigFiles = @()
        foreach ($xmlConfigFilenames in $EmailRequestConfigurationFilename) {
            try {
                $erXmlConfigFiles += Get-ChildItem -Path "$($emfConfig.EmailRequestRoot)" -Include "$xmlConfigFilenames" -Recurse -Force
            } catch {
                throw $_
            }
        }
        foreach ($erXmlConfigFile in $erXmlConfigFiles) {
            if ($MailboxName) {
                foreach ($Mailbox in $MailboxName) {
                    if ($Mailbox -match '\*') {
                        try {
                            Convert-EmailRequestConfigfile $erXmlConfigFile | Where-Object {$_.displayName -Like "$Mailbox"}
                        } catch {
                            throw $_
                        }
                    } else {
                        try {
                            Convert-EmailRequestConfigfile $erXmlConfigFile | Where-Object {$_.displayName -eq "$Mailbox"}
                        } catch {
                            throw $_
                        }
                    }
                }
            } else {
                try {
                    Convert-EmailRequestConfigfile $erXmlConfigFile
                } catch {
                    throw $_
                }
            }
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Get-EasitEmailRequestMailbox
function Get-EasitLog {
    [CmdletBinding(DefaultParameterSetName='Configuration',HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Get-EasitLog.md")]
    param (
        [Parameter(ParameterSetName='LiteralPath')]
        [string]$LiteralPath,
        [Parameter(ParameterSetName='Path')]
        [string]$Path,
        [Parameter(Mandatory,ParameterSetName='Path')]
        [string]$LogFilename,
        [Parameter(ParameterSetName = 'Configuration')]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter(ParameterSetName = 'Configuration')]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter(Mandatory,Position=0,ParameterSetName = 'Configuration')]
        [Alias('system')]
        [string] $EmfConfigurationName
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    process {
        if (!($LiteralPath) -and !($Path)) {
            Write-Verbose "LiteralPath and Path are not provided.."
            try {
                Write-Verbose "Looking for EMF-Config"
                $emfConfig = Get-EMFConfig -Home $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
            } catch {
                throw $_
            }
            try {
                Write-Verbose "Joining path $($emfConfig.SystemRoot) and 'logs'"
                $Path = Join-Path "$($emfConfig.SystemRoot)" -ChildPath 'logs' -ErrorAction Stop
            } catch {
                throw $_
            }
            if (Test-Path -Path $Path) {
                Write-Verbose "Path = $Path"
            } else {
                Write-Verbose "Path = $Path"
                throw "Unable to find $Path. A valid path to logfiles need to be provided. This can be done with the following parameters 'LiteralPath' or 'Path'. If you would like to use your EMF-configurationfile place it in ${env:ALLUSERSPROFILE}\EMF and specify a value for SystemRoot (ex. D:\Easit\Systems\Prod) or use 'EmfHome', 'EmfConfigurationFileName' and 'EmfConfigurationName' parameters to take advantage from it."
            }
            
        } elseif ($Path) {
            if (Test-Path -Path $Path) {
                Write-Verbose "Path = $Path"
            } else {
                throw "Unable to find $Path"
            }
        } elseif ($LiteralPath) {
            if (Test-Path -Path $LiteralPath) {
                $Path = $LiteralPath
            } else {
                throw "Unable to find $LiteralPath"
            }
        } else {
            throw "Unable to figure out what to do. Either provide a 'LiteralPath', 'Path' and 'LogFilename' or a valid EMF-configurationfile"
        }
        if (!($LiteralPath)) {
            # If-block need to be performed for Get-ChildItem to work.
            if (Test-Path $Path -PathType Container) {
                if (!($Path -match '\\$')) {
                    $Path = "${Path}\"
                }
            }
            if ($LogFilename) {
                $gciParams = @{
                    Include = "*${LogFilename}*.log"
                    Exclude = $null
                }
            } else {
                $LogFilename = 'easit'
                $gciParams = @{
                    Include = '*easit*.log'
                    Exclude = '*stderr*', '*stdout*'
                }
            }
            try {
                $files = Get-ChildItem "${Path}*" @gciParams -ErrorAction Stop
                Write-Verbose "Collected all files matching *${LogFilename}*.log in $Path"
            } catch {
                throw $_
            }
        }
        if ($LiteralPath) {
            try {
                $files = Get-ChildItem "$Path" -ErrorAction Stop
                Write-Verbose "Collected $Path"
            } catch {
                throw $_
            }
        }
        
        foreach ($file in $files) {
            $logData += "`n1##$($file.Fullname)##`n"
            Write-Verbose "Getting content of $file"
            try {
                $encoding = [System.Text.Encoding]::UTF8
                $fileStream = [System.IO.FileStream]::new($file, 'Open', 'Read', 'ReadWrite')
                $textReader = [System.IO.StreamReader]::new($fileStream,$encoding)
                $collectedData = $textReader.ReadToEnd()
                if ([string]::IsNullOrWhiteSpace($collectedData)) {
                    Write-Verbose "$file did not contain any entries, skipping"
                    continue
                }
                if (!([string]::IsNullOrWhiteSpace($collectedData))) {
                    $collectedDataContainsData = $true
                }
                $logData += $collectedData
                Write-Verbose "Content collected"
            } catch [System.IO.IOException] {
                Write-Warning "$file locked by other process, skipping"
                continue
            } catch {
                Write-Warning "$($_.Exception), skipping"
                continue
            }
        }
        $returnObject = @()
        if ($collectedDataContainsData) {
            Write-Verbose "Splitting entries in logfile"
            $logEvents = $logData -split "(?=[\r|\n]+\d)"
            Write-Verbose "Converting entries to objects"
            foreach ($logEvent in $logEvents) {
                $logEvent = $logEvent.TrimEnd()
                $logEvent = $logEvent.TrimStart()
                if (Select-String -InputObject $logEvent -Pattern '##.+##' -Quiet) {
                    $source = Select-String -InputObject $logEvent -Pattern '##.+##'
                    $source = "$($source.Matches.Value)"
                    $source = $source.TrimStart('##')
                    $source = $source.TrimEnd('##')
                    Write-Verbose "source = $source"
                } else {
                    if ($logEvent.length -gt 0) {
                        try {
                            $returnObject += $logEvent | Convert-EasitLogEntryToPsObject -Source "$source"
                        } catch {
                            throw $_
                        }
                    }
                }
            }
            Write-Verbose "Returning converted entries as objects"
            return $returnObject
        } else {
            Write-Verbose "Log collection did not produce any entries"
            return
        }
    }

    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

Export-ModuleMember -Function Get-EasitLog
function Get-EasitScheduledTask {
    [CmdletBinding()]
    param (
        [Parameter()]
        [switch] $EmailRequest,

        [Parameter()]
        [switch] $ImportClient
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        $easitTasks = @()
        if (!($EmailRequest) -and !($ImportClient)) {
            try {
                $easitTasks = Get-ScheduledTask -TaskName "*easit*"
            } catch {
                throw $_
            }
        }
        if ($EmailRequest) {
            try {
                $easitErTask = Get-ScheduledTask -TaskName "*easit*" | Where-Object -Property 'TaskName' -Match -Value 'mail'
                $easitTasks += $easitErTask
            } catch {
                throw $_
            }
        }
        if ($ImportClient) {
            try {
                $easitIcTask = Get-ScheduledTask -TaskName "*easit*" | Where-Object -Property 'TaskName' -Match -Value 'import'
                $easitTasks += $easitIcTask
            } catch {
                throw $_
            }
        }
        foreach ($task in $easitTasks) {
            $taskDetails = Get-ScheduledTaskInfo -InputObject $task
            $taskDetails | Add-Member -NotePropertyName Status -NotePropertyValue $task.State
            $taskDetails | Format-Table TaskName, LastRunTime, NextRunTime, Status -AutoSize
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Get-EasitScheduledTask
function Get-EasitTrustStoreCertificate {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Get-EasitTrustStoreCertificate")]
    param (
        [Parameter(ParameterSetName='LiteralPath',Mandatory=$true)]
        [string] $LiteralPath,
        [Parameter(ParameterSetName='Path')]
        [string] $Path,
        [Parameter(ParameterSetName='Path',Mandatory=$true)]
        [string] $TrustStoreName,
        [Parameter()]
        [string] $Keytool,
        [Parameter(Mandatory=$true)]
        [Alias('keystorepass','truststorepass')]
        [string] $StorePass,
        [Parameter()]
        [string] $CertificateAlias,
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter()]
        [Alias('system')]
        [string] $EmfConfigurationName = 'Prod'
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        $emfConfig = Get-EMFConfig -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
    }
    
    process {
        if (!($Keytool)) {
            try {
                $Keytool = Get-EasitJavaKeytool -Path $emfConfig.EasitRoot
                Write-Verbose "Keytool = $Keytool"
            } catch {
                throw $_
            }
        }
        if ($Path -and $TrustStoreName) {
            $trustStorePath = Join-Path -Path $Path -ChildPath $TrustStoreName
            if (Test-Path $trustStorePath) {
                Write-Verbose "Using truststore at $trustStorePath"
            } else {
                throw "Unable to find $TrustStoreName in $Path"
            }
        }
        if ($Path -and !($TrustStoreName)) {
            throw "You need to provide a TrustStoreName when specifying Path. Otherwise use LiteralPath."
        }
        if ($LiteralPath) {
            if (Test-Path $LiteralPath) {
                $trustStorePath = $LiteralPath
                Write-Verbose "Using truststore at $trustStorePath"
            } else {
                throw "Unable to find $LiteralPath"
            }
        }
        if ($StorePass) {
            if ($CertificateAlias) {
                Write-Verbose "Executing: $Keytool -list -v -alias $CertificateAlias -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -list -v -alias "$CertificateAlias" -keystore "$trustStorePath" -storepass "$StorePass"
                $listCerts = 'false'
            } else {
                Write-Verbose "Executing: $Keytool -list -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -list -keystore "$trustStorePath" -storepass "$StorePass"
                $listCerts = 'true'
            }
        } else {
            if ($CertificateAlias) {
                Write-Verbose "Executing: $Keytool -list -v -alias $CertificateAlias -keystore $trustStorePath"
                $result = & "$Keytool" -list -v -alias "$CertificateAlias" -keystore "$trustStorePath"
                $listCerts = 'false'
            } else {
                Write-Verbose "Executing: $Keytool -list -keystore $trustStorePath"
                $result = & "$Keytool" -list -keystore "$trustStorePath"
                $listCerts = 'true'
            }
        }
        if (!($result)) {
            break
        }
        Write-Verbose "$result"
        Convert-KeytoolResult -InputString $result -ListCerts "$listCerts"
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Get-EasitTrustStoreCertificate
function Get-EMFConfig {
    [CmdletBinding()]
    param (
        [Parameter()]
        [Alias('Home')]
        [string] $EMFHome = "${env:ALLUSERSPROFILE}\EMF",
        
        [Parameter()]
        [Alias('ConfigurationFileName','ConfigFile','ConfigFileName')]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',

        [Parameter(Mandatory, Position=0)]
        [Alias('ConfigurationName','ConfigName')]
        [string] $EmfConfigurationName
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        if (Test-Path "$EMFHome\$EmfConfigurationFileName") {
            Write-Verbose "Found $EMFHome\$EmfConfigurationFileName"
        } else {            
            throw [System.IO.FileNotFoundException] "$EMFHome\$EmfConfigurationFileName does not exist"
        }
        Write-Verbose "Retrieving configurations data"
        try {
            $configurationFileData = Import-EMFXMLData -Path "$EMFHome\$EmfConfigurationFileName"
            Write-Verbose "Configuration data retrieved"
        } catch {
            throw $_
        }
        if ($configurationFileData.systems.$EmfConfigurationName) {
            Write-Verbose "Found configuration named $EmfConfigurationName"
        } else {
            throw "No configuration found named $EmfConfigurationName"
        }
        $returnObject = New-Object -TypeName psobject
        $configProperties = $configurationFileData.systems.$EmfConfigurationName
        foreach ($property in $configProperties.ChildNodes) {
            $returnObject | Add-Member -MemberType NoteProperty -Name "$($property.Name)" -Value "$($property.InnerText)"
        }
        return $returnObject
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

Export-ModuleMember -Function Get-EMFConfig
function Initialize-EasitManagementFramework {
    [CmdletBinding()]
    param (
        [Parameter()]
        [Alias('Home')]
        [string] $EMFHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $ConfigURL = 'https://raw.githubusercontent.com/easitab/EasitManagementFramework/development/configurations/emfConfig.xml',
        [Parameter()]
        [string] $SchemaURL = 'https://raw.githubusercontent.com/easitab/EasitManagementFramework/development/schemas/emfConfig.xsd',
        [Parameter()]
        [string] $ConfigName = 'emfConfig.xml',
        [Parameter()]
        [string] $SchemaName = 'emfConfig.xsd'
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized!"
        $ProgressPreference = 'SilentlyContinue'
    }
    
    process {
        if (!(Test-Path -Path $EMFHome)) {
            try {
                $null = New-Item -Path "${env:ALLUSERSPROFILE}" -Name 'EMF' -ItemType Directory
                Write-Information "Created directory EMF in ${env:ALLUSERSPROFILE}" -InformationAction Continue
            } catch {
                throw $_
            }
        } else {
            Write-Verbose "Found $EMFHome"
        }
        try {
            $wc = New-Object System.Net.WebClient
            Write-Verbose "Created WebClient"
        } catch {
            throw $_
        }
        Write-Information "Downloading assets..." -InformationAction Continue
        try {
            $output1 = Join-Path -Path "$EMFHome" -ChildPath "$ConfigName"
            $wc.DownloadFile($ConfigURL, $output1)
            Write-Verbose "Download of $ConfigName complete"
        } catch {
            throw $_
        }
        try {
            $output2 = Join-Path -Path "$EMFHome" -ChildPath "$SchemaName"
            $wc.DownloadFile($SchemaURL, $output2)
            Write-Verbose "Download of $SchemaName complete"
        } catch {
            throw $_
        }
        Write-Information "Download of assets complete" -InformationAction Continue
    }
    
    end {
        $ProgressPreference = 'Continue'
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Initialize-EasitManagementFramework
function Invoke-EasitGOHealthCheck {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Invoke-EasitGOHealthCheck.md")]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter(Mandatory)]
        [Alias('system')]
        [string] $EmfConfigurationName
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        $emfConfig = Get-EMFConfig -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
    }
    
    process {
        $healthCheckResultObject = New-Object -TypeName PSObject
        if (Test-Path -Path "$($emfConfig.SystemRoot)") {
            Write-Verbose "Evalutating system drive.."
            try {
                $systemDriveLetter = Split-Path -Path "$($emfConfig.SystemRoot)" -Qualifier
            } catch {
                throw $_
            }
            if ($systemDriveLetter) {
                Write-Verbose "Using systemDriveLetter $systemDriveLetter to evaluate drive state"
                $systemDriveDetails = Get-CimInstance Win32_LogicalDisk -Filter DriveType=3 | Where-Object -Property DeviceID -EQ "$systemDriveLetter" | Select-Object DeviceID, @{'Name'='Size'; 'Expression'={[math]::truncate($_.size / 1GB)}}, @{'Name'='Freespace'; 'Expression'={[math]::truncate($_.freespace / 1GB)}}
                try {
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name EvaluatedDrive -Value "$systemDriveLetter"
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name DriveSize -Value "$($systemDriveDetails.Size)"
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name DriveFreespace -Value "$($systemDriveDetails.Freespace)"
                } catch {
                    Write-Warning "$($_.Exception)"
                }
            } else {
                Write-Warning "Unable to find systemDriveLetter, skipping evaluation of system drive"
            }
        } else {
            Write-Warning "Unable to find path for systemroot from emfConfig ($($emfConfig.SystemRoot)), skipping evalution of system drive"
        }
        Write-Verbose "Evalution of system drive complete"
        Write-Verbose "Evalutating system memory.."
        try {
            $memoryInfo = Get-CimInstance win32_physicalmemory
            $totalMemoryCapacity = ($memoryInfo | Measure-Object -Property capacity -Sum).sum /1gb
            $totalMemoryFree = [math]::round(((Get-CIMInstance Win32_OperatingSystem | Measure-Object -Property FreePhysicalMemory -Sum).sum /1024) /1024,2)
        } catch {
            throw $_
        }
        try {
            $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name TotalMemoryCapacity -Value "$totalMemoryCapacity"
            $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name TotalMemoryFree -Value "$totalMemoryFree"
        } catch {
            throw $_
        }
        Write-Verbose "Evalution of system memory complete"
        Write-Verbose "Evalutating system service.."
        if ($emfConfig.ServiceName) {
            try {
                $systemName = $emfConfig.serviceName
                $service = Get-CimInstance -ClassName Win32_Service -Filter "Name Like '$systemName'"
            } catch {
                throw $_
            }
            if ($service) {
                try {
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name ServiceState -Value "$($service.State)"
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name ServiceStatus -Value "$($service.Status)"
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name ServiceStartMode -Value "$($service.StartMode)"
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name ServiceProcessId -Value "$($service.ProcessId)"
                } catch {
                    throw $_
                }
                Write-Verbose "Evalution of system service complete"
            } else {
                Write-Warning "Unable to find system service with name $systemName"
            }
        } else {
            Write-Warning "ServiceName from emfConfig is invalid, skipping evalution of system service"
        }
        $systemPortFound = $false
        $systemPropertiesPathFound = $false
        if (Test-Path "$($emfConfig.SystemRoot)") {
            $systemPropertiesPath = Get-ChildItem -Path "$($emfConfig.SystemRoot)\*server.xml" -Recurse
            if ($systemPropertiesPath) {
                $systemPropertiesPathFound = $true
            }
        } 
        if (!($systemPropertiesPathFound)) {
            if (Test-Path "$($emfConfig.TomcatRoot)") {
                $systemPropertiesPath = Get-ChildItem -Path "$($emfConfig.TomcatRoot)\*server.xml" -Recurse
                if ($systemPropertiesPath) {
                    $systemPropertiesPathFound = $true
                }
            }
        }
        if ($systemPropertiesPathFound) {
            Write-Verbose "Evalutating ping and database response time.."
            try {
                $systemServerXML = Get-Content -Path "$systemPropertiesPath" -Raw
                $systemServerXML -imatch 'Connector port="(\d{4})" protocol="HTTP.*"' | Out-Null
                $systemPort = $Matches[1]
                $systemPortFound = $true
            } catch {
                Write-Warning "$($_.Exception)"
            }
            if ($systemPortFound) {
                $systemMonitorUrl = "http://localhost:${systemPort}/monitor/?bypassSSO=true"
                Write-Verbose "systemMonitorUrl = $systemMonitorUrl"
                try {
                    $systemStatus = Invoke-WebRequest -Uri "${systemMonitorUrl}&type=alive" -UseBasicParsing -ErrorAction Stop
                    Write-Verbose "Successfully connected to ${systemMonitorUrl}&type=alive"
                    $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name SystemStatusCode -Value "$($systemStatus.StatusCode)"
                } catch {
                    Write-Verbose "Unable to contact system monitor 'alive'"
                    Write-Verbose "$($_.Exception)"
                }
                Write-Verbose "Evalutating database response time.."
                try {
                    $dbLatency = Invoke-WebRequest -Uri "${systemMonitorUrl}&type=db" -UseBasicParsing -ErrorAction Stop
                    Write-Verbose "Successfully connected to ${systemMonitorUrl}&type=db"
                    if ($dbLatency.StatusCode -eq 200) {
                        $dbLatency.Content -match '1000 times:\s?(.*)\s?ms' | Out-Null
                        [int]$dbResponseTime = $Matches[1]
                        $healthCheckResultObject | Add-Member -MemberType NoteProperty -Name DatabaseResponseTime -Value "$dbResponseTime"
                    } else {
                        Write-Verbose "Unable to query for DB response time"
                    }
                } catch {
                    Write-Verbose "Unable to contact system monitor 'db'"
                    Write-Verbose "$($_.Exception)"
                }
            } else {
                Write-Warning "Unable to resolve system port"
            }
        } else {
            Write-Warning "Unable to find port for system. Skipping evaluation of ping and database response time"
        }
        return $healthCheckResultObject
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

Export-ModuleMember -Function Invoke-EasitGOHealthCheck
function Invoke-EasitGOUpdate {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Invoke-EasitGOUpdate.md")]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter()]
        [string] $EmfConfigurationName = 'Dev',
        [Parameter()]
        [string] $UpdateResourceDirectory = $null,
        [Parameter(Mandatory)]
        [string] $UpdateFilename,
        [Parameter()]
        [switch] $RunningElevated,
        [Parameter()]
        [switch] $SkipDbBackup,
        [Parameter()]
        [switch] $StoredProcedureName
    )

    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        if (!($RunningElevated)) {
            throw "Session is not running with elevated priviliges that is need to perfom this action, ensure you are running an elevated session and specify -RunningElevated"
        }
        $emfConfig = Get-EMFConfig -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
    }

    process {
        if ([string]::IsNullOrWhiteSpace($UpdateResourceDirectory)) {
            if ([string]::IsNullOrWhiteSpace($emfConfig.UpdateResourceDirectory)) {
                throw "No path provided as UpdateResourceDirectory. Use -UpdateResourceDirectory or UpdateResourceDirectory in $EmfHome\$EmfConfigurationFileName"
            } else {
                $UpdateResourceDirectory = "$($emfConfig.UpdateResourceDirectory)"
            }
        }
        if (Test-Path -Path "$UpdateResourceDirectory") {
            Write-Verbose "Using $UpdateResourceDirectory as UpdateResourceDirectory"
        } else {
            throw "Unable to find $UpdateResourceDirectory"
        }

        if ([string]::IsNullOrWhiteSpace($emfConfig.SystemRoot)) {
            throw "No path provided as SystemRoot. Please update SystemRoot in $EmfHome\$EmfConfigurationFileName for GO"
        } else {
            if (!(Test-Path -Path "$($emfConfig.SystemRoot)")) {
                throw "Unable to find $($emfConfig.SystemRoot)"
            } else {
                $systemRoot = "$($emfConfig.SystemRoot)"
                Write-Verbose "Using systemRoot: $systemRoot"
            }
        }

        if ([string]::IsNullOrWhiteSpace($emfConfig.BackupRoot)) {
            throw "No path provided as BackupRoot. Please update BackupRoot in $EmfHome\$EmfConfigurationFileName for GO"
        } else {
            if (!(Test-Path -Path "$($emfConfig.BackupRoot)")) {
                try {
                    $backupRootName = Split-Path -Path "$($emfConfig.BackupRoot)" -Leaf
                    $backupRootParent = Split-Path -Path "$($emfConfig.BackupRoot)" -Parent
                    $backupRoot = New-Item -Path $backupRootParent -Name $backupRootName -ItemType Directory
                } catch {
                    throw $_
                }
                Write-Verbose "Created directory named $backupRootName in $backupRootParent"
            } else {
                $backupRoot = "$($emfConfig.BackupRoot)"
            }
        }
        Write-Verbose "Using backupRoot: $backupRoot"
        $foldersToFind = @('config','logs','webapps')
        foreach ($folderToFind in $foldersToFind) {
            $varName = "${folderToFind}Root"
            if (!(Get-Variable -Name "$varName" -ErrorAction SilentlyContinue)) {
                New-Variable -Name "$varName"
            }
            Set-Variable -Name "$varName" -Value (Get-ChildItem -Path "$systemRoot" -Include "$folderToFind" -Directory -Recurse).Fullname
            if (!(Get-Variable -Name "$varName" -ValueOnly)) {
                Set-Variable -Name "$varName" -Value (Get-ChildItem -Path "$systemRoot" -Include "$folderToFind" -Directory -Recurse).Fullname
                if (!(Get-Variable -Name "$varName" -ValueOnly)) {
                    throw "Unable to find ${varName}"
                }
            }
            $varValue = Get-Variable -Name "$varName" -ValueOnly
            Write-Verbose "Using ${varName}: $varValue"
        }
        
        try {
            $systemConfigFile = (Get-ChildItem -Path "$configRoot" -Include 'properties.xml' -File -Recurse).Fullname
        } catch {
            throw $_
        }
        if (!($systemConfigFile)) {
            throw "Unable to find configRoot: $configRoot"
        }
        Write-Verbose "Found systemConfigFile: $systemConfigFile"
        try {
            $systemProperties = Import-EMFXMLData -Path $systemConfigFile -ReturnAsPSObject
        } catch {
            throw $_
        }
        Write-Verbose "Got system properties"

        try {
            $warFile = (Get-EasitWarFile -Path "$systemRoot" -Name "$($emfConfig.WarName).war").Fullname
        } catch {
            throw $_
        }
        if (!($warFile)) {
            try {
                $warFile = (Get-EasitWarFile -Path "$($emfConfig.TomcatRoot)" -Name "$($emfConfig.WarName).war").Fullname
            } catch {
                throw $_
            }
            if (!($warFile)) {
                throw "Unable to find warFile: $warFile"
            }
        }
        Write-Verbose "Using warFile: $warFile"
        $UpdateFile = Join-Path -Path $UpdateResourceDirectory -ChildPath $UpdateFilename
        Write-Information "Trying to find update file" -InformationAction Continue
        if (Test-Path -Path $UpdateFile) {
            Write-Information "Using UpdateFile: $UpdateFile" -InformationAction Continue
        } else {
            throw "Unable to find $UpdateFile"
        }
        try {
            $service = Get-EasitService -ServiceName "$($emfConfig.ServiceName)"
            Write-Information "Found service $($service.Name)" -InformationAction Continue
        } catch {
            throw "Unable to find service for Easit GO"
        }

        if (!($SkipDbBackup)) {
            $rawDbUrl = "$($systemProperties.'dataSource.url')"
            try {
                $dbConnectionDetails = Get-DatabaseDetails -Uri $rawDbUrl
                Write-Verbose $dbConnectionDetails
            } catch {
                Write-Verbose $dbConnectionDetails
                throw "Unable to resolve database connection details"
            }
            if ($dbConnectionDetails.supportedProtocol) {
                Write-Warning "EasitManagementFramework only supports MSSQL at the moment. Perform manual backup of database and specify -SkipDbBackup"
                break
            } else {
                $useLocalCommand = $false
                if (Get-Command -Module 'SqlServer') {
                    Write-Verbose "Found module SqlServer"
                    $useLocalCommand = $true
                } else {
                    Write-Verbose "Module SqlServer is not installed on this computer, will attempt to connect to sql server $($dbConnectionDetails.dbServerName)"
                    if (!(Test-NetConnection -ComputerName "$($dbConnectionDetails.dbServerName)" -Port $dbConnectionDetails.dbServerPort)) {
                        throw "Unable to connect to sql server $($dbConnectionDetails.dbServerName) on port $($dbConnectionDetails.dbServerPort), check connection or perform manual backup of database and specify -SkipDbBackup"
                    }
                    Write-Verbose "Successfully connected to sql server $($dbConnectionDetails.dbServerName)"
                }
            }
        }
        Write-Information "Starting update process for Easit GO" -InformationAction Continue
        Write-Information "Stopping service" -InformationAction Continue
        try {
            $service = Stop-EasitGOApplication -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName -RunningElevated:$RunningElevated
        } catch {
            throw $_
        }
        Write-Information "Service stopped" -InformationAction Continue
        if ($SkipDbBackup) {
            Write-Warning "-SkipDbBackup is specified, assuming manual backup of database have been done"
        }
        if (!($SkipDbBackup)) {
            $LASTEXITCODE = 0
            $ErrorActionPreference = 'Stop'
            Write-Information "Attempting to execute stored procedure on database server" -InformationAction Continue
            if ($useLocalCommand) {
                if ($dbConnectionDetails.dbInstance) {
                    $serverInstance = "$($dbConnectionDetails.dbServerName)\$($dbConnectionDetails.dbInstance)"
                } else {
                    $serverInstance = "$($dbConnectionDetails.dbServerName)"
                }
                try {
                    Invoke-Sqlcmd -ServerInstance "$serverInstance" -Database "$($dbConnectionDetails.dbName)" -Query "EXEC $StoredProcedureName" -OutputSqlErrors $true
                } catch {
                    throw $_
                }
                if ($LASTEXITCODE -ne 0) {
                    throw "Invoke-Sqlcmd returned $LASTEXITCODE"
                }
            }
            if (!($useLocalCommand)) {
                try {
                    $dbSession = New-PSSession -ComputerName "$dbServer"
                    Enter-PSSession -Session $dbSession
                } catch {
                    throw $_
                }
                Invoke-Sqlcmd -Database "$dbName" -Query "EXEC $StoredProcedureName" -OutputSqlErrors $true -ErrorAction Continue
                Exit-PSSession
                Remove-PSSession -Session $dbSession
                if ($LASTEXITCODE -ne 0) {
                    throw "Invoke-Sqlcmd returned $LASTEXITCODE"
                }
            }
            $ErrorActionPreference = $null
            $LASTEXITCODE = 0
            Write-Information "Backup of database complete" -InformationAction Continue
        }
        Write-Information "Perfoming backup action on files and folders" -InformationAction Continue
        $foldersToBackup = @("$configRoot","$logsRoot","$warFile")
        foreach ($folder in $foldersToBackup) {
            try {
                Backup-EasitFolder -FolderToBackup "$folder" -DestinationFolder $backupRoot
            } catch {
                throw $_
            }
        }
        try {
            Write-Verbose "Removing $logsRoot"
            Remove-Item "$logsRoot" -Include '*.*' -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue
            Write-Verbose "$logsRoot removed"
        } catch {
            Write-Warning "$($_.Exception)"
        }
        try {
            Write-Verbose "Removing $warFile"
            Remove-Item "$warFile" -Confirm:$false -InformationAction SilentlyContinue
            Write-Verbose "$warFile removed"
        } catch {
            Write-Warning "$($_.Exception)"
        }
        $expandedWarFolder = Join-Path -Path "$webappsRoot" -ChildPath "$($emfConfig.WarName)"
        try {
            Write-Verbose "Removing $expandedWarFolder"
            Remove-Item "$expandedWarFolder" -Recurse -Force -Confirm:$false -InformationAction SilentlyContinue
            Write-Verbose "$expandedWarFolder removed"
        } catch {
            Write-Warning "$($_.Exception)"
        }
        Write-Information "Backup of files and folders have been completed" -InformationAction Continue

        Write-Information "Updating war file" -InformationAction Continue
        $newWarToCopy = Join-Path -Path "$($emfConfig.UpdateResourceDirectory)" -ChildPath "$UpdateFilename"
        Write-Verbose "Looking for $UpdateFilename in $($emfConfig.UpdateResourceDirectory)"
        if (!(Test-Path -Path $newWarToCopy)) {
            throw "Unable to find $newWarToCopy. Update can be completed by copying new war ($UpdateFilename) file to $webappsRoot and running Start-EasitGOApplication"
        }
        try {
            Copy-Item -Path "$newWarToCopy" -Destination "$webappsRoot"
            Get-ChildItem -Path "$webappsRoot\${UpdateFilename}" | Rename-Item -NewName "$($emfConfig.WarName).war"
        } catch {
            throw $_
        }
        Write-Information "Starting service" -InformationAction Continue
        try {
            $service = Start-EasitGOApplication -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName -Verify -RunningElevated:$RunningElevated
        } catch {
            throw $_
        }
        Write-Information "Update of Easit GO have been completed" -InformationAction Continue
    }

    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Invoke-EasitGOUpdate
function Invoke-Email2GOUpdate {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Invoke-Email2GOUpdate.md")]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter()]
        [string] $EmfConfigurationName = 'Email2GO',
        [Parameter()]
        [string] $UpdateResourceDirectory = $null,
        [Parameter(Mandatory)]
        [string] $UpdateFilename,
        [Parameter()]
        [switch] $RunningElevated,
        [Parameter()]
        [switch] $Cleanup
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        if (!($RunningElevated)) {
            throw "Session is not running with elevated priviliges that is need to perfom this action, ensure you are running an elevated session and specify -RunningElevated"
        }
        $emfConfig = Get-EMFConfig -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
    }
    
    process {
        if ([string]::IsNullOrWhiteSpace($UpdateResourceDirectory)) {
            if ([string]::IsNullOrWhiteSpace($emfConfig.UpdateResourceDirectory)) {
                throw "No path provided as UpdateResourceDirectory. Use -UpdateResourceDirectory or UpdateResourceDirectory in $EmfHome\$EmfConfigurationFileName"
            } else {
                $UpdateResourceDirectory = "$($emfConfig.UpdateResourceDirectory)"
            }
        }
        if (Test-Path -Path "$UpdateResourceDirectory") {
            Write-Verbose "Using $UpdateResourceDirectory as UpdateResourceDirectory"
        } else {
            throw "Unable to find $UpdateResourceDirectory"
        }

        if ([string]::IsNullOrWhiteSpace($emfConfig.SystemRoot)) {
            throw "No path provided as SystemRoot. Please update SystemRoot in $EmfHome\$EmfConfigurationFileName for Email2GO"
        } else {
            if (!(Test-Path -Path "$($emfConfig.SystemRoot)")) {
                throw "Unable to find $($emfConfig.SystemRoot)"
            } else {
                $systemRoot = "$($emfConfig.SystemRoot)"
                Write-Verbose "Using systemRoot: $systemRoot"
            }
        }
        
        if ([string]::IsNullOrWhiteSpace($emfConfig.BackupRoot)) {
            throw "No path provided as BackupRoot. Please update BackupRoot in $EmfHome\$EmfConfigurationFileName for Email2GO"
        } else {
            if (!(Test-Path -Path "$($emfConfig.BackupRoot)")) {
                $backupRootName = Split-Path -Path "$($emfConfig.BackupRoot)" -Leaf
                $backupRootParent = Split-Path -Path "$($emfConfig.BackupRoot)" -Parent
                $backupRoot = New-Item -Path $backupRootParent -Name $backupRootName -ItemType Directory
                Write-Verbose "Created directory named $backupRootName in $backupRootParent"
            } else {
                $backupRoot = "$($emfConfig.BackupRoot)"
            }
        }
        Write-Verbose "Using backupRoot: $backupRoot"

        $configRoot = Join-Path -Path $systemRoot -ChildPath 'config'
        if (!(Test-Path $configRoot)) {
            throw "Unable to find configRoot: $configRoot"
        } else {
            Write-Verbose "Using configRoot: $configRoot"
        }

        $UpdateFile = Join-Path -Path $UpdateResourceDirectory -ChildPath $UpdateFilename
        $todayMinute = Get-Date -Format "yyyyMMdd_HHmm"
        Write-Information "Trying to find update file" -InformationAction Continue
        if (Test-Path -Path $UpdateFile) {
            if ($UpdateFile -match '\.zip$') {
                $expandedArchiveFolder = Join-Path -Path $UpdateResourceDirectory -ChildPath "$todayMinute"
                if (!(Test-Path -Path $expandedArchiveFolder)) {
                    try {
                        Write-Verbose "Creating $expandedArchiveFolder"
                        $expandedArchiveFolder = New-Item -Path $UpdateResourceDirectory -Name $todayMinute -ItemType Directory
                    } catch {
                        throw $_
                    }
                } else {
                    try {
                        Write-Verbose "$expandedArchiveFolder already exist, removing files in folder"
                        Get-ChildItem $expandedArchiveFolder | Remove-Item
                        Write-Verbose "Files removed"
                    } catch {
                        throw $_
                    }
                }
                try {
                    Expand-Archive -Path $UpdateFile -DestinationPath $expandedArchiveFolder -InformationAction SilentlyContinue
                    $UpdateFile = (Get-ChildItem -Path $expandedArchiveFolder | Where-Object -Property Name -Like '*.msp').Fullname
                } catch {
                    throw $_
                }
            }
            Write-Information "Using UpdateFile: $UpdateFile" -InformationAction Continue
        } else {
            throw "Unable to find $UpdateFile"
        }
        try {
            $service = Get-EasitService -ServiceName '%mail2go%'
            Write-Information "Found service $($service.Name)" -InformationAction Continue
        } catch {
            throw "Unable to find service for Email2GO"
        }
        Write-Information "Starting update process for Email2GO" -InformationAction Continue
        Write-Information "Stopping service" -InformationAction Continue
        try {
            $service = Set-EasitService -Service $service -Action 'StopService'
        } catch {
            throw $_
        }
        Write-Information "Service stopped" -InformationAction Continue
        $logs = Join-Path -Path $systemRoot -ChildPath 'logs'
        $email2GOFoldersToBackup = @("$configRoot","$logs")
        foreach ($folder in $email2GOFoldersToBackup) {
            try {
                Backup-EasitFolder -FolderToBackup "$folder" -DestinationFolder $backupRoot -Cleanup $Cleanup
            } catch {
                throw $_
            }
        }
        try {
            $updateProcess = Start-Process -FilePath $UpdateFile -Wait -PassThru
        } catch {
            throw $_
        }
        if ($updateProcess.ExitCode -ne '0') {
            if ($updateProcess.ExitCode -eq '1602') {
                Write-Information "Update process terminated" -InformationAction Continue
            } else {
                Write-Warning "The update process did not exit (ExitCode: $($updateProcess.ExitCode)) successfully, therefor $($MyInvocation.MyCommand) have been terminated and manual update of Email2GO is needed"
            }
            return
        }
        try {
            Get-ChildItem -Path $expandedArchiveFolder | Remove-Item
            Remove-Item -Path $expandedArchiveFolder
            Write-Verbose "Removed $expandedArchiveFolder and its contents"
        } catch {
            throw $_
        }
        try {
            $service = Get-EasitService -ServiceName "$($service.Name)"
            Write-Verbose "Found service $($service.Name)"
            if ("$($service.State)" -ne 'Running') {
                Write-Information "Trying to start service $($service.Name)" -InformationAction Continue
                $service = Set-EasitService -Service $service -Action 'StartService'
            } else {
                Write-Verbose "Service $($service.Name) is running"
            }
        } catch {
            throw $_
        }        
        Write-Information "Email2GO successfully updated" -InformationAction Continue
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Invoke-Email2GOUpdate
function New-EMFConfig {
    [CmdletBinding()]
    param (
        [Parameter()]
        [Alias('Home')]
        [string] $EMFHome = "${env:ALLUSERSPROFILE}\EMF",
        
        [Parameter()]
        [Alias('ConfigurationFileName','ConfigFile','ConfigFileName')]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        
        [Parameter(Mandatory)]
        [ValidateSet("Prod","Test","Dev","IntegrationProd","IntegrationTest","IntegrationDev")]
        [Alias('ConfigurationName','ConfigName')]
        [string] $EmfConfigurationName,

        [Parameter(Mandatory)]
        [Alias('ConfigurationSettings','ConfigSettings')]
        [hashtable] $EmfConfigurationSettings,

        [Parameter()]
        [switch ] $Validate,

        [Parameter()]
        [string] $SchemaFile = "$EMFHome\emfConfig.xsd"
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        $emfConfigFilePath = "$EMFHome\$EmfConfigurationFileName"
        if (Test-Path "$emfConfigFilePath") {
            Write-Verbose -Message "$emfConfigFilePath already exists."
            try {
                Get-EMFConfig -EMFHome $EMFHome -EmfConfigurationFileName $EmfConfigurationFileName -EmfConfigurationName $EmfConfigurationName
                Write-Warning "A configuration with the name $EmfConfigurationName does already exist in $emfConfigFilePath. Use Set-EMFConfig to update configuration!"
                break
            } catch {
                Write-Verbose "No configuration with name $EmfConfigurationName found"
            }
        } else {
            Write-Verbose "$emfConfigFilePath does not exist."
            if (!(Test-Path -Path $EMFHome)) {
                New-Item -Path "${env:ALLUSERSPROFILE}" -Name 'EMF' -ItemType Directory
                Write-Verbose -Message "Created directory EMF in ${env:ALLUSERSPROFILE}"
            } else {
                Write-Verbose "Found $EMFHome"
            }
        }
        try {
            Write-Verbose "Creating xml object for config"
            $configObject = New-Object System.Xml.XmlDocument
            [System.Xml.XmlDeclaration] $xmlDeclaration = $configObject.CreateXmlDeclaration("1.0", "UTF-8", $null)
            $configObject.AppendChild($xmlDeclaration) | Out-Null
        } catch {
            Write-Verbose "Failed to create xml object for payload"
            throw "$_"
        }
        try {
            Write-Verbose "Creating xml element for systems"
            $configObjectItems = $configObject.CreateElement('systems')
            $configObject.AppendChild($configObjectItems) | Out-Null
        } catch {
            Write-Verbose "Failed to create xml element for systems"
            throw $_
        }
        try {
            Write-Verbose "Creating xml element for $EmfConfigurationName"
            $configObjectItem = $configObject.CreateElement("$EmfConfigurationName")
            $configObjectItems.AppendChild($configObjectItem) | Out-Null
        } catch {
            Write-Verbose "Failed to create xml element for $EmfConfigurationName"
            throw $_
        }
        foreach ($setting in $ConfigurationSettings.GetEnumerator()) {
            $settingName = $setting.Name
            $settingValue = $setting.Value
            if (!($settingName -eq 'EmfConfigurationName')) {
                try {
                    Write-Verbose "Creating xml element for setting $settingName"
                    $configObjectItemSetting = $configObject.CreateElement("$settingName")
                    $configObjectItemSetting.InnerText = $settingValue
                    $configObjectItem.AppendChild($configObjectItemSetting) | Out-Null
                } catch {
                    Write-Verbose "Failed to create xml element for $settingName"
                    throw $_
                }
            } else {
                Write-Verbose "SettingName = EmfConfigurationName"
            }
        }

        if ($Validate) {
            $emfConfigFilePathTemp = "$EMFHome\temp.xml"
            $configObject.Save("$emfConfigFilePathTemp")
            try {
                Test-EMFXMLData -Path $emfConfigFilePathTemp -SchemaFile $SchemaFile
                Test-ConfigurationSetting -XmlObject $configObject
                Remove-Item $emfConfigFilePathTemp -Force | Out-Null
            } catch {
                Remove-Item $emfConfigFilePathTemp -Force | Out-Null
                throw $_
            }
        }

        try {
            $configObject.Save("$emfConfigFilePath")
            Write-Verbose -Message "Saved config to $emfConfigFilePath"
        } catch {
            throw "Unable to save config to $emfConfigFilePath"
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

Export-ModuleMember -Function New-EMFConfig
function Remove-CertificateFromEasitTrustStore {
    [CmdletBinding(HelpURI="https://github.com/easitab/EasitManagementFramework/blob/main/docs/v1/Remove-CertificateFromEasitTrustStore.md")]
    param (
        [Parameter(ParameterSetName='LiteralPath',Mandatory=$true)]
        [string] $LiteralPath,
        [Parameter(ParameterSetName='Path')]
        [string] $Path,
        [Parameter(ParameterSetName='Path',Mandatory=$true)]
        [string] $TrustStoreName,
        [Parameter()]
        [string] $Keytool,
        [Parameter(Mandatory=$true)]
        [Alias('keystorepass','truststorepass')]
        [string] $StorePass,
        [Parameter(Mandatory=$true)]
        [string] $CertificateAlias,
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',
        [Parameter()]
        [Alias('system')]
        [string] $EmfConfigurationName = 'Prod'
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        $emfConfig = Get-EMFConfig -EMFHome $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
    }
    
    process {
        if (!($Keytool)) {
            try {
                $Keytool = Get-EasitJavaKeytool -Path $emfConfig.EasitRoot
                Write-Verbose "Keytool = $Keytool"
            } catch {
                throw $_
            }
        }
        if ($Path -and $TrustStoreName) {
            $trustStorePath = Join-Path -Path $Path -ChildPath $TrustStoreName
            if (Test-Path $trustStorePath) {
                Write-Verbose "Using truststore at $trustStorePath"
            } else {
                throw "Unable to find $TrustStoreName in $Path"
            }
        }
        if ($Path -and !($TrustStoreName)) {
            throw "You need to provide a TrustStoreName when specifying Path. Otherwise use LiteralPath."
        }
        if ($LiteralPath) {
            if (Test-Path $LiteralPath) {
                $trustStorePath = $LiteralPath
                Write-Verbose "Using truststore at $trustStorePath"
            } else {
                throw "Unable to find $LiteralPath"
            }
        }
        if ($StorePass) {
            if ($CertificateAlias) {
                Write-Verbose "Executing: $Keytool -delete -alias $CertificateAlias -keystore $trustStorePath -storepass $StorePass"
                $result = & "$Keytool" -delete -alias "$CertificateAlias" -keystore "$trustStorePath" -storepass "$StorePass"
            } else {
                throw "No certificate alias provided"
            }
        } else {
            throw "No storepass provided"
        }
        if (!($result)) {
            break
        } else {
            return $result
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Remove-CertificateFromEasitTrustStore
function Set-EasitEmailRequestMailboxSetting {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",
        
        [Parameter()]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',

        [Parameter()]
        [string] $EmfConfigurationName = 'Prod',

        [Parameter()]
        [string] $EmailRequestConfigurationFilename = 'config.xml',

        [Parameter(Mandatory)]
        [Alias('Mailbox')]
        [string] $MailboxName,

        [Parameter(Mandatory)]
        [Alias('Name')]
        [string] $SettingName,

        [Parameter(Mandatory)]
        [Alias('Value')]
        [string] $SettingValue
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        try {
            $emfConfig = Get-EMFConfig -Home $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
            Write-Verbose "Found EMF Config"
        } catch {
            throw $_
        }
    }
    
    process {
        try {
            $erXmlConfigFile = Get-ChildItem -Path "$($emfConfig.EmailRequestRoot)" -Include "$EmailRequestConfigurationFilename" -Recurse -Force
            Write-Verbose "Found ER config."
        } catch {
            throw $_
        }
        try {
            $erConfig = Import-EMFXMLData -Path "$($erXmlConfigFile.FullName)"
            Write-Verbose "Imported configuration"
        } catch {
            throw $_
        }
        try {
            $node = $erConfig.SelectNodes("//properties/property") | Where-Object {$_.name -eq "displayName"} | Where-Object {$_.value -eq "$MailboxName"}
        } catch {
            throw $_
        }
        try {
            $mailBoxNode = $node.ParentNode.ParentNode
            Write-Verbose "Found mailbox in configuration"
        } catch {
            throw $_
        }
        try {
            $settingNode = $mailBoxNode.properties.property | Where-Object {$_.name -eq "$SettingName"}
        } catch {
            throw $_
        }
        try {
            $settingNode.Value = "$SettingValue"
            Write-Verbose "Updated value for $SettingName"
        } catch {
            throw $_
        }
        try {
            $erConfig.Save("$($emfConfig.EmailRequestRoot)\${EmfConfigurationFileName}")
            Write-Verbose "Saved EmailRequest configuration"
        } catch {
            throw $_
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Set-EasitEmailRequestMailboxSetting
function Set-EMFConfig {
    [CmdletBinding()]
    param (
        [Parameter()]
        [Alias('Home')]
        [string] $EMFHome = "${env:ALLUSERSPROFILE}\EMF",

        [Parameter()]
        [Alias('ConfigurationFileName','ConfigFile','ConfigFileName')]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',

        [Parameter(Mandatory,Position=0)]
        [Alias('ConfigurationName','ConfigName')]
        [string] $EmfConfigurationName,

        [Parameter(Mandatory,ParameterSetName='Manual')]
        [string] $EasitRoot,

        [Parameter(ParameterSetName='Manual')]
        [string] $SystemRoot = "$EasitRoot\Systems\$EmfConfigurationName",

        [Parameter(ParameterSetName='Manual')]
        [string] $ServiceName = "Easit$EmfConfigurationName",

        [Parameter(ParameterSetName='Manual')]
        [string] $WarName = "ROOT",

        [Parameter(ParameterSetName='Manual')]
        [string] $TomcatRoot = "$EasitRoot\Systems\$EmfConfigurationName",

        [Parameter(ParameterSetName='Manual')]
        [string] $BackupRoot = "$EasitRoot\_Backup\$EmfConfigurationName",

        [Parameter(ParameterSetName='Manual')]
        [Alias('ER','EmailRequest','erRoot')]
        [string] $EmailRequestRoot = "$EasitRoot\EmailRequest",

        [Parameter(ParameterSetName='Manual')]
        [Alias('IC','ImportClient','icRoot')]
        [string] $ImportClientRoot = "$EasitRoot\ImportClient",

        [Parameter(ParameterSetName='Manual')]
        [Alias('urd')]
        [string] $UpdateResourceDirectory = "$EasitRoot\Update",

        [Parameter(ParameterSetName='Manual')]
        [Alias('sbp')]
        [string] $StoredBackupProcedure = 'StoredBackupProcedureName',

        [Parameter(Mandatory,ParameterSetName='Array')]
        [string[]] $PropertySetting,
        [Parameter()]
        [switch]$ValidateSettings
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        if (Test-Path "$EMFHome\$EmfConfigurationFileName") {
            Write-Verbose "Located $EMFHome\$EmfConfigurationFileName"
            try {
                $currentConfigSettings = Get-EMFConfig -EMFHome $EMFHome -EmfConfigurationFileName $EmfConfigurationFileName -EmfConfigurationName $EmfConfigurationName
                Write-Verbose "Successfully retrieved configuration"
            } catch {
                throw $_
            }
        } else {
            throw "Cannot find $EMFHome\$EmfConfigurationFileName"
        }
        $paramName = $PSCmdlet.ParameterSetName
        if ($paramName -eq 'Manual') {
            Write-Verbose "ParameterSetName = $paramName"
            $configurationSettings = [ordered]@{
                EasitRoot = "$EasitRoot"
                WarName = "$WarName"
                SystemRoot = "$SystemRoot"
                ServiceName = "$ServiceName"
                TomcatRoot = "$TomcatRoot"
                BackupRoot = "$BackupRoot"
                EmailRequestRoot = "$EmailRequestRoot"
                ImportClientRoot = "$ImportClientRoot"
                UpdateResourceDirectory = "$UpdateResourceDirectory"
                StoredBackupProcedure = "$StoredBackupProcedure"
            }
            Write-Verbose "Created hashtable with settings"
        } 
        if ($paramName -eq 'Array') {
            Write-Verbose "ParameterSetName = $paramName"
            try {
                foreach ($prop in $PropertySetting) {
                    $tempArray = $prop -split ','
                    $propName = ($tempArray[0]) -replace ' ', ''
                    $propValue = ($tempArray[1]) -replace ' ', ''
                    $currentConfigSettings | Add-Member -MemberType NoteProperty -Name "$propName" -Value "$propValue" -Force
                }
                Write-Verbose "Added new settings to CustomObject"
            } catch {
                throw $_
            }
            try {
                $configurationSettings = [ordered]@{}
                $currentConfigSettings | Get-Member -Type NoteProperty -ErrorAction Stop | ForEach-Object {
                    $value = $currentConfigSettings."$($_.Name)"
                    $configurationSettings.Add("$($_.Name)", "$value")
                }
            } catch {
                throw $_
            }
        }
        try {
            $currentConfigurationFile = New-Object System.Xml.XmlDocument
            $currentConfigurationFile.Load("$EMFHome\$EmfConfigurationFileName")
        } catch {
            Write-Verbose "Something went wrong while loading currentConfigurationFile"
            throw "$($_.Exception.Message)"
        }
        if (!($currentConfigurationFile.systems.${EmfConfigurationName})) {
            Write-Warning "Unable to find configuration block for $EmfConfigurationName"
            return
        }
        if ($ValidateSettings) {
            Test-ConfigurationSetting -Hashtable $configurationSettings
        }
        try {
            $configurationSettings.GetEnumerator() | ForEach-Object {
                $settingName = "$($_.Key)"
                $settingValue = "$($_.Value)"
                $currentConfigurationFile.systems.${EmfConfigurationName}.${settingName} = $settingValue
            }
        } catch {
            Write-Warning "$($_.Exception.Message)"
        }
        
        try {
            $currentConfigurationFile.Save("$EMFHome\$EmfConfigurationFileName")
        } catch {
            Write-Verbose "Something went wrong while updating configuration file ($EmfConfigurationFileName), block $EmfConfigurationName"
            throw $_
        }
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

Export-ModuleMember -Function Set-EMFConfig
function Start-EasitGOApplication {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",

        [Parameter()]
        [Alias('ConfigurationFileName','ConfigFile','ConfigFileName')]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',

        [Parameter()]
        [Alias('ConfigurationName','ConfigName')]
        [string] $EmfConfigurationName = 'Dev',

        [Parameter()]
        [switch] $Verify,
        
        [Parameter()]
        [switch] $RunningElevated
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        if (!($RunningElevated)) {
            throw "Session is not running with elevated priviliges that is need to perfom this action"
        }
        try {
            $emfConfig = Get-EMFConfig -Home $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
            Write-Verbose "Found EMF Config"
            $easitGoServiceName = "$($emfConfig.ServiceName)"
            Write-Verbose "ServiceName is $($emfConfig.ServiceName)"
        } catch {
            throw $_
        }
    }
    
    process {
        try {
            $easitGoService = Get-EasitService -ServiceName "$easitGoServiceName"
        } catch {
            throw $_
        }
        if ($null -eq $easitGoService) {
            throw "Unable to find service with name like $easitGoServiceName"
        } else {
            Write-Verbose "Successfully got CimInstance for $easitGoServiceName"
        }
        Write-Verbose "Starting service $easitGoServiceName"
        try {
            $easitGoService = Set-EasitService -Service $easitGoService -Action 'StartService'
        } catch {
            throw $_
        }
        Write-Information -Message "Service $easitGoServiceName have been started and is running" -InformationAction Continue
        if ($Verify) {
            $verificationFailed = $false
            Write-Verbose "Trying to verify connectivity"
            $tomcatConf = (Get-ChildItem -Path "$($emfConfig.SystemRoot)" -Include 'conf' -Directory -Recurse).Fullname
            if (!($tomcatConf)) {
                try {
                    $tomcatConf = (Get-ChildItem -Path "$($emfConfig.TomcatRoot)" -Include 'conf' -Directory -Recurse).Fullname
                } catch {
                    Write-Warning "Unable to find folder conf in $($emfConfig.TomcatRoot)"
                    $verificationFailed = $true
                }
                if (!($tomcatConf)) {
                    Write-Warning "Unable to find tomcatConf: $tomcatConf"
                    $verificationFailed = $true
                }
            }
            if (!($verificationFailed)) {
                if (Test-Path -Path "$tomcatConf") {
                    $tomcatServerXMLPath = (Get-ChildItem -Path "$tomcatConf" -Recurse -Include 'server.xml').FullName
                    if ($tomcatServerXMLPath) {
                        try {
                            $tomcatServerXML = Import-EMFXMLData -Path "$tomcatServerXMLPath"
                        } catch {
                            Write-Warning "Unable to import server.xml, system connectivity not verified"
                            $verificationFailed = $true
                        }
                        $tomcatServerPort = "$($tomcatServerXML.Server.Port)"
                    } else {
                        Write-Warning "Unable to get server.xml from $tomcatConf"
                        $verificationFailed = $true
                    }
                } else {
                    $verificationFailed = $true
                }
            }
            if (!($verificationFailed)) {
                Write-Information "Giving the Easit application some time to startup" -InformationAction Continue
                try {
                    Start-Sleep -Seconds 15
                    Write-Information "Trying to ping Easit application" -InformationAction Continue
                    $url = "http://localhost:${tomcatServerPort}/monitor/?type=alive"
                    $systemStatus = Invoke-WebRequest -Uri "$url" -UseBasicParsing -ErrorAction Stop
                } catch {
                    Write-Verbose "$($_.Exception)"
                }
                if (!($systemStatus.StatusCode -eq 200)) {
                    Write-Verbose "Web request did not return 200, but $($systemStatus.StatusCode)"
                    $verificationFailed = $true
                }
                if ($systemStatus.StatusCode -eq 200) {
                    Write-Information "Connectivity to the Easit application have been verified" -InformationAction Continue
                    $verificationFailed = $false
                }
            }
            if ($verificationFailed) {
                Write-Information "Unable to verify connectivity to the Easit application" -InformationAction Continue
            }
        }
        return $easitGoService
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Start-EasitGOApplication
function Stop-EasitGOApplication {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $EmfHome = "${env:ALLUSERSPROFILE}\EMF",

        [Parameter()]
        [Alias('ConfigurationFileName','ConfigFile','ConfigFileName')]
        [string] $EmfConfigurationFileName = 'emfConfig.xml',

        [Parameter()]
        [Alias('ConfigurationName','ConfigName')]
        [string] $EmfConfigurationName = 'Dev',
        
        [Parameter()]
        [switch] $RunningElevated
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
        if (!($RunningElevated)) {
            throw "Session is not running with elevated priviliges that is need to perfom this action"
        }
        try {
            $emfConfig = Get-EMFConfig -Home $EmfHome -ConfigurationFileName $EmfConfigurationFileName -ConfigurationName $EmfConfigurationName
            Write-Verbose "Found EMF Config"
            $easitGoServiceName = "$($emfConfig.ServiceName)"
            Write-Verbose "ServiceName is $($emfConfig.ServiceName)"
        } catch {
            throw $_
        }
    }
    
    process {
        try {
            $easitGoService = Get-EasitService -ServiceName "$easitGoServiceName"
        } catch {
            throw $_
        }
        if ($null -eq $easitGoService) {
            throw "Unable to find service with name like $easitGoServiceName"
        } else {
            Write-Verbose "Successfully got CimInstance for $easitGoServiceName"
        }
        Write-Verbose "Stopping service $easitGoServiceName"
        try {
            $easitGoService = Set-EasitService -Service $easitGoService -Action 'StopService'
        } catch {
            throw $_
        }
        Write-Verbose "Service $easitGoServiceName have been stopped"
    }
    
    end {
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}
Export-ModuleMember -Function Stop-EasitGOApplication
function Test-EMFXMLData {
    [CmdletBinding()]
    param (
        [Parameter()]
        [Alias('Home')]
        [string] $EMFHome = "${env:ALLUSERSPROFILE}\EMF",

        [Parameter()]
        [string] $Path = "$EMFHome\emfConfig.xml",

        [Parameter()]
        [string] $SchemaFile = "$EMFHome\emfConfig.xsd",

        [Parameter()]
        [switch]$ValidateSettings
    )
    
    begin {
        Write-Verbose "$($MyInvocation.MyCommand) initialized"
    }
    
    process {
        if (Test-Path $Path) {
            Write-Verbose "Found $Path"
        } else {
            Write-Verbose "Unable to find $Path"
        }
        if (Test-Path $SchemaFile) {
            Write-Verbose "Found $SchemaFile"
        } else {
            throw $_
        }
        [scriptblock] $ValidationEventHandler = { Write-Error $args[1].Exception.InnerExceptionMessage }
        $schemaReader = New-Object System.Xml.XmlTextReader $SchemaFile
        $schema = [System.Xml.Schema.XmlSchema]::Read($schemaReader, $ValidationEventHandler)

        $xml = New-Object System.Xml.XmlDocument
        Write-Verbose 'Created XML-object'
        try {
            $xml.Schemas.Add($schema) | Out-Null
            Write-Verbose 'Added schema to XML-object'
        } catch {
            $schemaReader.Close()
            throw $_
        }
        try {
            $xml.Load($Path)
            Write-Verbose 'Loaded XML-file to XML-object'
        } catch {
            $schemaReader.Close()
            throw $_
        }
        try {
            Write-Verbose "Validating $Path against $SchemaFile"
            $xml.Validate({
                throw ($Exception = $args[1].Exception)
            })
            Write-Verbose "XML validate without errors"
        } catch {
            $schemaReader.Close()
            throw $_
        }
        if ($ValidateSettings) {
            Test-ConfigurationSetting -XmlObject $xml
        }
        Write-Information "Configuration file ($Path) validation OK against $SchemaFile" -InformationAction Continue
        return
    }
    
    end {
        $schemaReader.Close()
        Write-Verbose "$($MyInvocation.MyCommand) completed"
    }
}

Export-ModuleMember -Function Test-EMFXMLData