TerminalService.ps1

$ScriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent

. ($ScriptDir + "/Global.ps1")

$ServiceProductName = "TerminalService"
$ServicePackageName = "Logeto.UWP.Service"
$ServiceExeFile = "Logeto.UWP.Service.Host.exe"
$ServiceInstallDir = "$Env:ProgramFiles\Systemart\Logeto.UWP.Service"

$ServiceDownloadFolderPath = $LogetoFolder + $ServiceProductName + "\" + $DownloadFolder
$ServiceUpdateFolderPath = $LogetoFolder + $ServiceProductName + "\" + $UpdateFolder

<#
    Return Json file for Terminal Service, if there is no newer version null is returned.
#>

function Get-LogetoTerminalServiceUpdateInfo 
{
    $scope = Get-LogetoScope
    $serviceVersion = Get-LogetoExeVersion (Get-LogetoServicePath $ServicePackageName)
    Write-LogetoDebug "Getting Terminal Update Info $ServiceProductName $scope $serviceVersion." 
    return Get-LogetoUpdateInfo -Product $ServiceProductName -Scope $scope -Version $serviceVersion
}

<#
    Install Logeto Terminal Service
#>

function Install-LogetoTerminalService {

    Param(
        [parameter(Mandatory=$true)]
        $UpdateInfo
    )

    Write-LogetoDebug "Installing terminal service"

    Get-LogetoProduct $UpdateInfo $ServiceProductName

    Write-LogetoProgress "Installing terminal after download" "ModuleInstallLogetoProductTerminalService"

    Get-CurrentStateInfo
    $oldServiceVersion = Get-LogetoExeVersion (Get-LogetoServicePath $ServicePackageName)
    Install-Service
    Update-LogetoTerminalService $oldServiceVersion (Get-LogetoExeVersion (Get-LogetoServicePath $ServicePackageName))

    # Clear download folder
    Remove-Item -Path $ServiceDownloadFolderPath -Recurse -ErrorAction SilentlyContinue
}

<#
    Uninstall Logeto Terminal Service
#>

function Uninstall-LogetoTerminalService 
{
    if ((Get-WmiObject win32_service | ?{$_.Name -eq $ServicePackageName}) -ne $null)
    {
        try
        {
            Write-LogetoDebug "Stopping service" -Debug
            Stop-Service -Name $ServicePackageName
        }
        catch {}
    }

    $installutilexe = Get-PlatformInstallUtil

    & $installutilexe /u (Join-Path $ServiceInstallDir $ServiceExeFile)

    if (Test-Path $ServiceInstallDir)
    {
        $maxRepeat = 10

        do 
        {
            Write-LogetoDebug "Removing folder" -Debug
            Remove-Item $ServiceInstallDir -Force -Recurse -ErrorAction SilentlyContinue      
            $maxRepeat--
            sleep -Milliseconds 3000
        } until ($maxRepeat -eq 0 -or (-Not (Test-Path $ServiceInstallDir)))

        if (Get-IsFolderEmpty "$Env:ProgramFiles\Systemart")
        {
            Remove-Item -Path "$Env:ProgramFiles\Systemart" -Recurse -ErrorAction SilentlyContinue
        }
    }

    # Clear product folder
    $value = Join-Path $LogetoFolder $ServiceProductName
    Remove-Item -Path $value -Recurse -ErrorAction SilentlyContinue
}

<#
    Return Json file from the URL for set product and scope. If version parameter is set it returns Json file only if higher version was found, otherwise returns null.
#>

function Clear-LogetoTerminalServiceEnvironment
{
    Param(
        [parameter(Mandatory=$true)]
        [ValidateSet('UpdateTask')]
        $Components
    )

    if ($Components -eq 'UpdateTask')
    {
        if (!(Get-IsElevated))
        {
            throw Get-LogetoCustomException "Clearing Update Task for Terminal Service can be run only as an admin!" "" $ResultExceptionThrown 0
        }

        $name = "Logeto TerminalService Update"
        $taskExists = (Get-ScheduledTask | Where-Object {$_.TaskName -eq $name })
        if ($taskExists)
        {
            Write-LogetoDebug "Logeto TerminalService Update task revert" -Debug
            Write-LogetoProgress "Removing old service task" "ScriptUnRegisterServiceUpdateTaskRemovingTask"
            UnRegister-ScheduledTask -TaskName $name -Confirm:$false
        } else
        {
            Write-LogetoDebug "Logeto TerminalService Update task do not exists" -Debug
        }

        Remove-Item -Path $ServiceUpdateFolderPath -Recurse -ErrorAction SilentlyContinue
    }
}

function Set-LogetoTerminalServiceEnvironment
{
        Param(
        [parameter(Mandatory=$true)]
        [ValidateSet('UpdateTask')]
        $Components
    )
    
    if ($Components -eq 'UpdateTask')
    {
        if (!(Get-IsElevated))
        {
            throw Get-LogetoCustomException "Creating Update Task for Terminal Service can be run only as an admin!" "" $ResultExceptionThrown 0
        }

        Write-LogetoDebug "Creating Scheduler Update Task"

        Write-LogetoDebug "Path to file: $PSScriptRoot\TerminalServiceUpdate.vbs"
        Write-LogetoDebug "Destination path: $ServiceUpdateFolderPath"
        New-Item -ItemType Directory $ServiceUpdateFolderPath -Force
        Copy-Item -Path "$PSScriptRoot\TerminalServiceUpdate.vbs" -Destination $ServiceUpdateFolderPath -Force
        Copy-Item -Path "$PSScriptRoot\TerminalServiceUpdate.ps1" -Destination $ServiceUpdateFolderPath -Force
        Copy-Item -Path "$PSScriptRoot\InstallLogetoModule.ps1" -Destination $ServiceUpdateFolderPath -Force

        $A = New-ScheduledTaskAction �Execute $ServiceUpdateFolderPath\TerminalServiceUpdate.vbs `"$ServiceUpdateFolderPath\TerminalServiceUpdate.ps1`"
        $T = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 60)
        $S = New-ScheduledTaskSettingsSet
        $P = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType S4U -RunLevel Highest
        $name = "Logeto TerminalService Update"
        $taskExists = (Get-ScheduledTask | Where-Object {$_.TaskName -eq $name })
        if ($taskExists)
        {
            Write-LogetoDebug "Logeto TerminalService Update task exists" -Debug
            Write-LogetoProgress "Removing old service task" "ScriptRegisterServiceUpdateTaskRemovingTask"
            UnRegister-ScheduledTask -TaskName $name -Confirm:$false
        } else
        {
            Write-LogetoDebug "Logeto TerminalService Update task do not exists" -Debug
        }
        Write-LogetoProgress "Registering new service task" "ScriptRegisterServiceUpdateTaskRegisteringTask"
        Register-ScheduledTask -TaskName $name -Action $A -Trigger $T -Settings $S -Principal $P -Force
    }
}


Function Get-CurrentStateInfo
{
    if ((Get-WmiObject win32_service | ?{$_.Name -eq $ServicePackageName}) -ne $null)
    {
        $global:OldServiceExeFile = Get-ServicePath $ServicePackageName
        $global:OldServiceInstallDir = Split-Path $OldServiceExeFile -Parent
    }
}

Function Install-Service
{
    Write-Host "Updating service" -ForegroundColor Yellow

    $packageDataPath = Get-PlatformDataFolder
    $installutilexe = Get-PlatformInstallUtil

    Write-Host "Package data: $packageDataPath"
    Write-Host "Service install directory: $ServiceInstallDir"

    if ((Get-WmiObject win32_service | ?{$_.Name -eq $ServicePackageName}) -ne $null)
    {
        try
        {
            Write-Host "Trying to stop running service..." -ForegroundColor Cyan
            Stop-Service -Name $ServicePackageName
            
            if ($OldServiceExeFile)
            {
                Write-Host "Uninstalling service..." -ForegroundColor Cyan
                & $installutilexe /u $OldServiceExeFile
            }
        }
        catch {}
    }

    if (-not (Test-Path $ServiceInstallDir))
    {
        New-Item -ItemType Directory -Path $ServiceInstallDir -Force

        Write-Host "Creating new service files in" $ServiceInstallDir -ForegroundColor Cyan
        Copy-Item $packageDataPath/*.* -Destination $ServiceInstallDir
    }
    else
    {
        if ($OldServiceInstallDir)
        {
            Clear-ServiceFolder
        }

        Write-Host "Updating existing service files in" $ServiceInstallDir -ForegroundColor Cyan
        Copy-Item $packageDataPath/*.* -Destination $ServiceInstallDir
    }

    $Acl = Get-Acl $ServiceInstallDir
    $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule("Local Service", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
    $Acl.SetAccessRule($Ar)
    Set-Acl $ServiceInstallDir $Acl

    Write-Host "Installing service..." -ForegroundColor Cyan
    & $installutilexe /i (Join-Path $ServiceInstallDir $ServiceExeFile)

    Write-Host "Trying to start service..." -ForegroundColor Cyan
    Start-Service -Name $ServicePackageName

    $service = Get-Service -Name $ServicePackageName
    if ($service.Status -eq 'running')
    { 
        Write-Host "Service `"$ServicePackageName`" started succesfully" -ForegroundColor Cyan
    }
    else
    {
        Write-Host "Unable to start service `"$ServicePackageName`"" -ForegroundColor Red -BackgroundColor Black
    }
}

Function Get-PlatformDataFolder
{
    if (($Env:Processor_Architecture -eq 'amd64') -and (Test-Path (Join-Path $ServiceDownloadFolderPath 'x64')))
    {
        return Join-Path $ServiceDownloadFolderPath 'x64'
    }
    elseif (($Env:Processor_Architecture -eq 'x86') -and (Test-Path (Join-Path $ServiceDownloadFolderPath 'x86')))
    {
        return Join-Path $ServiceDownloadFolderPath 'x86'
    }
    throw [System.PlatformNotSupportedException] "Data files for architecture `"$Env:Processor_Architecture`" not found"
}

function Get-PlatformInstallUtil
{
    if ($Env:Processor_Architecture -eq 'amd64')
    {
        return $Env:WinDir + "\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe"
    }
    else
    {
        return $Env:WinDir + "\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe"
    }
}

Function Clear-ServiceFolder
{
    Write-Host "Cleaning service folder" -ForegroundColor Cyan

    while ($true)
    {
        Start-Sleep -s 2
        Write-Host -NoNewline "."
        Get-ChildItem -Path $OldServiceInstallDir/* -Recurse | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue

        if(-not (Test-Path $OldServiceInstallDir\*.dll))
        {
            Write-Host "."
            return;
        }
    }
}

Function Update-LogetoTerminalServiceSystemEnvironment
{
    Param(
        [parameter(Mandatory=$true)]
        [ValidateSet('All', 'UpdateTask')]
        $Components
    )

    if (($Components -eq 'UpdateTask') -or ($Components -eq 'All'))
    {
        if (!(Get-IsElevated))
        {
            throw Get-LogetoCustomException "Creating Update Task for Terminal Service can be run only as an admin!" "" $ResultExceptionThrown 0
        }

        $A = New-ScheduledTaskAction �Execute $ServiceUpdateFolderPath\TerminalServiceUpdate.vbs `"$ServiceUpdateFolderPath\TerminalServiceUpdate.ps1`"
        $T = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 60)
        $S = New-ScheduledTaskSettingsSet
        $P = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType S4U -RunLevel Highest
        $name = "Logeto TerminalService Update"
        $taskExists = (Get-ScheduledTask | Where-Object {$_.TaskName -eq $name })
        if (-Not($taskExists))
        {
            Register-ScheduledTask -TaskName $name -Action $A -Trigger $T -Settings $S -Principal $P -Force
        }
        New-Item -ItemType Directory $ServiceUpdateFolderPath -Force
        Copy-Item -Path "$PSScriptRoot\TerminalServiceUpdate.vbs" -Destination $ServiceUpdateFolderPath -Force
        Copy-Item -Path "$PSScriptRoot\TerminalServiceUpdate.ps1" -Destination $ServiceUpdateFolderPath -Force
        Copy-Item -Path "$PSScriptRoot\InstallLogetoModule.ps1" -Destination $ServiceUpdateFolderPath -Force
    }
}

Function Get-ServicePath
{
    return (Get-WmiObject win32_service | ?{$_.Name -eq $ServicePackageName}).PathName.Replace("`"","")
}

Function Update-LogetoTerminalService($oldVersion, $newVersion)
{
    if ($DefaultVersion -eq $oldVersion)
    {
        return
    }

    Write-LogetoDebug "Update-LogetoTerminalService (Service) $oldVersion $newVersion" -Debug

    $patchVersion = "7.7.0"
    if (([System.Version]$patchVersion -gt [System.Version]$oldVersion) -And ([System.Version]$patchVersion -le [System.Version]$newVersion))
    {
        $name = "Logeto Terminal Service Update"
        $taskExists = (Get-ScheduledTask | Where-Object {$_.TaskName -eq $name })
        if ($taskExists)
        {
            UnRegister-ScheduledTask -TaskName $name -Confirm:$false
        }
    }
}