TisaneOnprem.psm1
#Region '.\Public\Check-ServiceCpu.ps1' 0 function Check-ServiceCpu { <# .SYNOPSIS Retrieves the CPU usage of a specified service. .DESCRIPTION The Check-ServiceCpu function retrieves the CPU usage of a specified service. It calculates the average CPU usage for the process associated with the service and returns the result. .PARAMETER service Specifies the name of the service for which to retrieve the CPU usage. .EXAMPLE PS C:\> Check-ServiceCpu -service "MyService" Description ----------- Retrieves the CPU usage of the "MyService" service. .INPUTS None. You cannot pipe objects to this function. .OUTPUTS System.Int32 The function returns an integer representing the CPU usage of the specified service. #> param ( [Parameter(Mandatory=$true)][string]$service ) $NUMBER_OF_CORES = 1 $procId = (Get-CimInstance Win32_Service | ?{$_.Name -like $service} | SELECT ProcessId).ProcessId $procPath = (Get-Counter "\Process(*)\ID Process" -ErrorAction SilentlyContinue).CounterSamples | Where-Object {$_.CookedValue -eq $procId} | Select-Object -ExpandProperty Path $procCpuUsage = [Math]::Round(((Get-Counter ($procPath -replace "\\id process$","\% Processor Time")).CounterSamples.CookedValue) / $NUMBER_OF_CORES) return $procCpuUsage } #EndRegion '.\Public\Check-ServiceCpu.ps1' 36 #Region '.\Public\Check-ServiceStatus.ps1' 0 function Check-ServiceStatus { <# .SYNOPSIS Checks the status of a service on a specified host. .DESCRIPTION The Check-ServiceStatus function sends a POST request to the specified host to check the status of a service. It returns $true if the service is available (HTTP status code 200), and $false otherwise. .PARAMETER hostIp The IP address or URL of the host where the service is running. This parameter is mandatory. .PARAMETER timeout The timeout value (in seconds) for the request. This parameter is mandatory. .EXAMPLE Check-ServiceStatus -hostIp "http://localhost:80/" -timeout 30 Checks the status of a service running on "http://localhost:80/" with a timeout of 30 seconds. #> param ( [Parameter(Mandatory=$true)][string]$hostIp, [Parameter(Mandatory=$true)][int]$timeout ) try { $uri = $hostIp + "parse" $response = Invoke-WebRequest -Uri $uri -Method POST -Headers $headers -ContentType 'application/json' -Body '{"language": "en", "content": "this is a test sentence to test the testing of tisane", "settings": {"parses":true,"debug":true}}' -TimeoutSec $timeout if ($response.StatusCode -eq 200) { return $true } else { return $false } } catch { # $date = Get-Date # Write-Output "[ $date ]WebRequest failed for $hostIp" return $false } } #EndRegion '.\Public\Check-ServiceStatus.ps1' 40 #Region '.\Public\Download-TisaneFromFTP.ps1' 0 function Download-TisaneFromFTP{ <# .SYNOPSIS Downloads Tisane data and web service from an FTP server. .DESCRIPTION The Download-TisaneFromFTP function allows you to download Tisane data and web service from an FTP server and save them to the specified local folders. It uses the System.Net.WebClient class to perform the FTP file transfer. .PARAMETER user Specifies the FTP user name for authentication. This parameter is mandatory. .PARAMETER password Specifies the FTP password for authentication. This parameter is mandatory. .PARAMETER ftp Specifies the FTP host name. This parameter is mandatory. .EXAMPLE Download-TisaneFromFTP -user "ftpuser" -password "ftppassword" -ftp "example.com" Downloads Tisane data and web service files from the FTP server "example.com" using the FTP user "ftpuser" and password "ftppassword". .EXAMPLE Download-TisaneFromFTP -user "ftpuser" -password "ftppassword" -ftp "example.com" | Do-Something Downloads Tisane data and web service files from the FTP server "example.com" using the FTP user "ftpuser" and password "ftppassword" and pipes the output to the Do-Something cmdlet. #> [CmdletBinding()] Param( [Parameter(Mandatory = $true, valueFromPipeline=$true, HelpMessage="FTP user: ")][String] $user, [Parameter(Mandatory = $true, HelpMessage="FTP password: ")][String] $password, [Parameter(Mandatory = $true, HelpMessage="FTP host: ")][String] $ftp ) $DOWNLOAD_FOLDER = "C:/Users/Administrator/Downloads/Tisane" $TISANE_ROOT = "C:/Tisane" $webclient = New-Object System.Net.WebClient if(-not(Test-Path($DOWNLOAD_FOLDER))) { # file with path $path doesn't exist mkdir $DOWNLOAD_FOLDER } $webclient.Credentials = New-Object System.Net.NetworkCredential("$user@$ftp", $password) $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_db.zip") Write-Host "Downloading Tisane data to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/tisane_db.zip") Write-Host "Downloading Tisane Web Service to $DOWNLOAD_FOLDER..." -ForegroundColor Green $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_ws.zip") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/tisane_ws.zip") if(Test-Path($TISANE_ROOT)) { #mkdir $TISANE_ROOT #Remove-Item -Path "$TISANE_ROOT/" -Recurse # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\.+[.]sst' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -Assembly "System.IO.Compression.Filesystem" Add-Type -Assembly "System.Io.Compression.FileSystem" [System.IO.Compression.ZipFile]::ExtractToDirectory("$DOWNLOAD_FOLDER/tisane_db.zip", "$DOWNLOAD_FOLDER/db") } #EndRegion '.\Public\Download-TisaneFromFTP.ps1' 68 #Region '.\Public\Install-TisaneFromFTP.ps1' 0 function Install-TisaneFromFTP{ [CmdletBinding()] <# .SYNOPSIS Installs Tisane from an FTP server. .DESCRIPTION The Install-TisaneFromFTP function downloads and installs Tisane from an FTP server. It retrieves the necessary files, including the Tisane database, Tisane Web Service, and Tisane Runtime Service, and extracts them to the specified location. It can also install .NET if specified. .PARAMETER user Specifies the FTP username used to connect to the FTP server. .PARAMETER password Specifies the FTP password used to authenticate the FTP user. .PARAMETER ftp Specifies the FTP host to connect to. .PARAMETER dotnet Specifies whether to install .NET. If set to $true, the function downloads and installs the .NET installer. .PARAMETER instances Specifies the number of Tisane instances to create. .PARAMETER winuser Specifies the Windows user account to use. If not specified, the default value is 'Administrator'. .EXAMPLE Install-TisaneFromFTP -user "ftpuser" -password "ftppassword" -ftp "ftp.example.com" -dotnet $true -instances 2 -winuser "User1" Downloads and installs Tisane from the FTP server 'ftp.example.com' using the FTP user credentials 'ftpuser' and 'ftppassword'. It installs .NET, creates 2 Tisane instances, and uses the Windows user account 'User1'. #> Param( [Parameter(Mandatory = $true, valueFromPipeline=$true, HelpMessage="FTP user: ")][String] $user, [Parameter(Mandatory = $true, HelpMessage="FTP password: ")][String] $password, [Parameter(Mandatory = $true, HelpMessage="FTP host: ")][String] $ftp, [Parameter(Mandatory = $false, HelpMessage="Install .NET? ")][boolean] $dotnet, [Parameter(Mandatory = $true, HelpMessage="Instance count: ")][int] $instances, [Parameter(Mandatory = $false, HelpMessage="Windows user: ")][String] $winuser ) if (-not($winuser)) { $winuser = 'Administrator' } $DOWNLOAD_FOLDER = "C:/Users/$winuser/Downloads/Tisane" $dotNETInstallerUrl = "https://go.microsoft.com/fwlink/?linkid=2088631" $TISANE_ROOT = "C:/Tisane" $webclient = New-Object System.Net.WebClient if(-not(Test-Path($DOWNLOAD_FOLDER))) { # file with path $path doesn't exist mkdir $DOWNLOAD_FOLDER } if ($dotnet) { Write-Host "Downloading .NET installer to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($dotNETInstallerUrl, "$DOWNLOAD_FOLDER/dotnetinstaller.exe") Write-Host "Installing .NET..." -ForegroundColor Green Start-Process -FilePath $DOWNLOAD_FOLDER/dotnetinstaller.exe -ArgumentList "/q","/norestart" -Wait } $webclient.Credentials = New-Object System.Net.NetworkCredential("$user@tisane.ai", $password) $uri = New-Object System.Uri("ftp://$ftp/tisane_db.zip") Write-Host "Downloading Tisane data to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/tisane_db.zip") Write-Host "Downloading Tisane Web Service to $DOWNLOAD_FOLDER..." -ForegroundColor Green $uri = New-Object System.Uri("ftp://$ftp/tisane_ws.zip") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/tisane_ws.zip") $uri = New-Object System.Uri("ftp://$ftp/Tisane.Runtime.Service.exe.config") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/Tisane.Runtime.Service.exe.config") if(Test-Path($TISANE_ROOT)) { #mkdir $TISANE_ROOT #Remove-Item -Path $TISANE_ROOT -Recurse } #Add-Type -AssemblyName System.IO.Compression.FileSystem #[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) Write-Host "Extracting Tisane data to $TISANE_ROOT..." -ForegroundColor Green # WE HAVE TO USE Ionic Zip because the standard compression libraries crash with very large archives [System.Reflection.Assembly]::LoadFrom("$DOWNLOAD_FOLDER/Ionic.Zip.dll") $zipFile = New-Object Ionic.Zip.ZipFile("$DOWNLOAD_FOLDER/tisane_db.zip") #Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER/tisane_db.zip" -DestinationPath $TISANE_ROOT $zipFile.ExtractAll($TISANE_ROOT, 1) $portNumber = 81 For ($i=1; $i -le $instances; $i++) { $formattedI = $i | % tostring 00 $portNumber = 79 + $i Write-Host "Creating instance under $TISANE_ROOT/instance$formattedI" -ForegroundColor Green Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER/tisane_ws.zip" -DestinationPath "$TISANE_ROOT/instance$formattedI" -Force $webclient.DownloadFile($uri, "$TISANE_ROOT/instance$formattedI/Tisane.Runtime.Service.exe.config") ((Get-Content -path "$TISANE_ROOT/instance$formattedI/Tisane.Runtime.Service.exe.config" -Raw) -replace 'localhost:80',"localhost:$portNumber") | Set-Content -Path "$TISANE_ROOT/instance$formattedI/Tisane.Runtime.Service.exe.config" Start-Process -FilePath "$TISANE_ROOT/instance$formattedI/Tisane.Runtime.Service.exe" -ArgumentList "-i" -Wait } # now open firewall ports netsh advfirewall firewall add rule name='Tisane ports' dir=in protocol=tcp localport="80-$portNumber" action=allow profile=any # create a quarterly update task SchTasks /Create /sc monthly /mo 3 /TN "Tisane update" /TR "$DOWNLOAD_FOLDER/UpdateTisaneFromFTP.ps1 -user $user -password $password -ftp $ftp" /ST 23:00 # start the services Start-Service "Tisane Runtime *" } #EndRegion '.\Public\Install-TisaneFromFTP.ps1' 113 #Region '.\Public\Monitor-Tisane.ps1' 0 function Monitor-Tisane { [CmdletBinding()] <# .SYNOPSIS Monitors specified services for health and restarts them if necessary. .DESCRIPTION The Monitor-Tisane function allows you to monitor the health of specified services and automatically restart them if they fail consecutive health checks. It checks the status of the services, their CPU consumption, and the availability of their endpoints. If a service fails the health check, it will be restarted and an email notification will be sent. .PARAMETER services Specifies the names of the services to monitor. Multiple service names can be provided separated by commas. .PARAMETER interval Specifies the timeout interval in seconds for the monitoring process. The default value is 120 seconds. .PARAMETER thresholdCpu Specifies the threshold for CPU consumption in percentage. If the CPU consumption of a service exceeds this threshold, it will be considered unhealthy. The default value is 100. .PARAMETER timeout Specifies the timeout value in seconds for each health check. If a health check takes longer than this timeout, the service will be considered unhealthy. The default value is 2 seconds. .PARAMETER failureBeforeRestart Specifies the number of consecutive health checks that must fail before a service is restarted. The default value is 1. .EXAMPLE Monitor-Tisane -services "Tisane Runtime [Tisane]","Tisane Runtime [Tisane1]" -interval 180 -thresholdCpu 90 -failureBeforeRestart 3 Monitors Tisane Runtime [Tisane] and Tisane Runtime [Tisane1] with an interval of 180 seconds, a CPU threshold of 90%, and restarts the service if it fails 3 consecutive health checks. #> param ( [Parameter(Mandatory=$true, HelpMessage="Service names to monitor: ")][String[]]$services, [Parameter(Mandatory=$false, HelpMessage="Timeout for monitor (Default 120s)")][int]$interval = 120, [Parameter(Mandatory=$false, HelpMessage="Threshold for CPU consuption (Default 100)")][int]$thresholdCpu = 100, [Parameter(Mandatory=$false, HelpMessage="Timeout for the healthcheck: (Default 2s)")][int]$timeout = 2, [Parameter(Mandatory=$false, HelpMessage="Number of health checks to fail consecutively before restart : (Default 1)")][int]$failureBeforeRestart = 1, [Parameter(Mandatory=$false, HelpMessage="Name for the server (Default public ip of machine: )")][string]$machine, [Parameter(Mandatory=$false, HelpMessage="base url for the port (Default http://localhost:) ")][string]$baseUrl = "http://localhost:" ) Write-Host "The script allows you to get email notification, Please run Setup-Email to configure the credentials" # [string[]]$services = $services.Split(",") if ([string]::IsNullOrEmpty($machine)){ $machine = (Invoke-WebRequest -uri "http://ifconfig.me/ip").Content } $hostName = [System.Net.Dns]::GetHostName() $Results = @{} $originalServiceNames = @{} $servicesOriginal = $services Write-Host $services $services = $servicesOriginal -replace '\[','?' -replace '\]','?' foreach ($service in $services) { $oneService = Get-CimInstance Win32_Service | ?{$_.Name -like $service} | SELECT Name , PathName if ([string]::IsNullOrEmpty($oneService)){ Write-Error "$service not found" # Write-Host "Abortting !!" -ForegroundColor RED return } $serviceName = $oneService.Name $configFile = $oneService.PathName -replace "\.exe", ".dll.config" -replace '\"', '' if (Test-Path $configFile) { $config = [xml](Get-Content $configFile) $portNode = Select-Xml -Xml $config -XPath "/configuration/appSettings/add[@key='Port']/@value" $portValue = $portNode.Node.value $Value = "$baseUrl$portValue/" $Results[$service] = $Value $originalServiceNames[$service]=$serviceName }else{ Write-Error "Config file for $service not found" # Write-Error "Abortting !!" return } } $hostIpS = $Results.Values $services = $Results.Keys # $originalNames = $originalServiceNames.Values Write-Output "Starting monitor for the following services" # Write-Host $originalServiceNames.Values -ForegroundColor Green # Write-Host "Corresponding endpoints: " # Write-Host $hostIpS -ForegroundColor Green $combinedList = for ($i = 0; $i -lt $hostIpS.Count; $i++) { [PSCustomObject]@{ Services = $services[$i] Endpoints = $Results[$services[$i]] } } $combinedList | Format-Table -AutoSize $restarting =@{} $failureCount = @{} while ($true) { foreach ($service in $services) { $hostIp = $Results[$service] if ($restarting.ContainsKey($service)) { Write-Output "$service is being restarted" if (Check-ServiceStatus -hostIp $hostIp -timeout $timeout) { $date = Get-Date Write-Output "[ $date ]Service on $service has restared" # $failureCount[$service] = 0 $restarting.Remove($service) } continue } $cpuUsage = Check-ServiceCpu $service -ErrorAction Ignore if ((Check-ServiceStatus -hostIp $hostIp -timeout $timeout) -and ( $cpuUsage -le $thresholdCpu)) { $date = Get-Date Write-Output "[ $date ]$service is running, consuming $cpuUsage% cpu" $failureCount[$service] = 0 } else { $failureCount[$service]++ $oneServiceFaliurCount = $failureCount[$service] $date = Get-Date Write-Output "[ $date ]$service failed $oneServiceFaliurCount health checks consecutively" if ($oneServiceFaliurCount -ge $failureBeforeRestart){ $restarting[$service]=$hostIp Stop-Service -Name $service Start-Service -Name $service $failureCount[$service] = 0 Write-Output "sending mail" $subject = "Tisane admin alert [$hostName]" $instanceName = $originalServiceNames[$service] $date = Get-Date $body = "[$instanceName] running on [$hostName ($machine)] was restarted on [$date] after health check failed" try { Send-Email -body $body -subject -$subject Write-Output "[ $date ] Email Sent" }catch{ Write-Output "[ $date ] Could not send email" } } } } # Sleep for 120 seconds Start-Sleep -Seconds $interval } } #EndRegion '.\Public\Monitor-Tisane.ps1' 136 #Region '.\Public\Reset-EmailSettings.ps1' 0 function Reset-EmailSettings { <# .SYNOPSIS Resets the email settings to their default values. .DESCRIPTION The Reset-EmailSettings function resets the email settings by clearing the current values and setting them to their default values. .PARAMETER None This function does not accept any parameters. .EXAMPLE Reset-EmailSettings Resets the email settings to their default values. .NOTES #> Save-LampSetting -settingName 'emailTo' -settingValue $null Save-LampSetting -settingName 'smtpServer' -settingValue $null Save-LampSetting -settingName 'smtpPort' -settingValue '587' Save-LampSetting -settingName 'emailUsername' -settingValue $null Save-LampSetting -settingName 'emailPassword' -settingValue $null } #EndRegion '.\Public\Reset-EmailSettings.ps1' 24 #Region '.\Public\Send-Email.ps1' 0 function Send-Email() { <# .SYNOPSIS Sends an email using the configured SMTP settings. .DESCRIPTION The Send-Email function sends an email using the configured SMTP settings. It retrieves the necessary email parameters from the Lamp settings and sends the email using the Send-MailMessage cmdlet. .PARAMETER Body Specifies the body of the email. This parameter is optional. .PARAMETER Subject Specifies the subject of the email. This parameter is optional. .EXAMPLE Send-Email -Subject "Hello" -Body "This is the email body" Sends an email with the specified subject and body. .NOTES Run Setup-Email to set the smtp settings #> Param( [Parameter(Mandatory=$false, HelpMessage="Body: ")][String] $body, [Parameter(Mandatory=$false, HelpMessage="Subject: " )][String] $subject ) $emailUsername = Get-LampSetting -settingName 'emailUsername' -defaultValue '' $encryptedEmailPassword = Get-LampSetting -settingName 'emailPassword' -defaultValue '' if ([string]::IsNullOrEmpty($emailUsername) -or [string]::IsNullOrEmpty($encryptedEmailPassword)) { throw "Username or password is empty. Exiting." } $To = Get-LampSetting -settingName 'emailTo' -defaultValue '' $To = $To.Split(",") $smtpServer = Get-LampSetting -settingName 'smtpServer' -defaultValue 'mail.tisane.ai' $smtpPort = Get-LampSetting -settingName 'smtpPort' -defaultValue '587' try { $secureEmailPassword = ConvertTo-SecureString -String $encryptedEmailPassword -ErrorAction Stop $emailCredential = New-Object System.Management.Automation.PSCredential($emailUsername, $secureEmailPassword) Send-MailMessage -To $To -From $emailUsername -Subject $subject -Body $body -Credential $emailCredential -SmtpServer $smtpServer -Port $smtpPort -WarningAction Ignore } catch { throw "Failed to send email: $($_.Exception.Message)" } } # $body = "THIS IS TEST BODY" # $subject = "TEST SUBJECT" # Send-Email -body $body -subject $subject # for ($i = 0; $i -lt 10; $i++) { # try { # Send-Email -body $body -subject $subject # Write-Output "[ $date ] Email Sent" # } catch { # $errorMessage = $_.Exception.Message # Write-Output "[ $date ] Could not send email. Error: $errorMessage" # } # Start-Sleep -Seconds 1 # Optional: Add a delay between iterations # } #EndRegion '.\Public\Send-Email.ps1' 64 #Region '.\Public\Setup-Email.ps1' 0 function Setup-Email { <# .SYNOPSIS Configures email settings for sending alerts. .DESCRIPTION The Setup-Email function allows you to configure email settings for sending alerts. It prompts you to provide the necessary information, such as comma-delimited email addresses to send alerts to, SMTP server, SMTP port, and sender email account credentials. Once the settings are configured, it sends a test email to verify the configuration. .PARAMETER None This function does not accept any parameters. .EXAMPLE Setup-Email Configures email settings for sending alerts. Prompts for email addresses, SMTP server, SMTP port, and sender email account credentials. .NOTES You must have the necessary permissions and access to the SMTP server to successfully send emails. #> Write-Host "Comma-delimited email addresses to send alerts to:" $To = Read-Host $To = $To.Split(",") Save-LampSetting -settingName 'emailTo' -settingValue $To $smtpServer = Read-Host "SMTP server" $smtpPort = Read-Host "SMTP port (default: 587)" Save-LampSetting -settingName 'smtpServer' -settingValue $smtpServer Save-LampSetting -settingName 'smtpPort' -settingValue $smtpPort if ([string]::IsNullOrEmpty($smtpServer)) { $smtpServer = Get-LampSetting -settingName 'smtpServer' -defaultValue '' } if ([string]::IsNullOrEmpty($smtpPort)) { $smtpPort = Get-LampSetting -settingName 'smtpPort' -defaultValue '587' } $emailUsername = Get-LampSetting -settingName 'emailUsername' -defaultValue '' $encryptedEmailPassword = Get-LampSetting -settingName 'emailPassword' -defaultValue '' if ([string]::IsNullOrEmpty($emailUsername)){ # Write-Host "in if" # $credential = Get-Credential -Message "Sender email account credentials" $credential = $host.ui.PromptForCredential("Sender email account credentials", "Sender email account credentials", "", "") $emailUsername = $credential.UserName $secureEmailPassword = $credential.Password $encryptedEmailPassword = ConvertFrom-SecureString -SecureString $secureEmailPassword Save-LampSetting -settingName 'emailUsername' -settingValue $emailUsername Save-LampSetting -settingName 'emailPassword' -settingValue $encryptedEmailPassword }else{ # Write-Host "in else" $secureEmailPassword = ConvertTo-SecureString -String $encryptedEmailPassword } # $emailPassword = [System.Net.NetworkCredential]::new("", $secureEmailPassword).Password $emailCredential = New-Object System.Management.Automation.PSCredential($emailUsername, $secureEmailPassword) $date = Get-Date $subject = "Tisane admin test email" $body = "This is a test email sent by Monitor-Tisane script [ $date ]" Write-Host "Email settings : " Write-Host "To: $To" Write-Host "From: $emailUsername" Write-Host "smtpServer: $smtpServer" Write-Host "smtpPort: $smtpPort" try { Send-MailMessage -To $To -From $emailUsername -Subject $subject -Body $body -Credential $emailCredential -SmtpServer $smtpServer -Port $smtpPort } catch { Write-Host "An error occurred while sending the email:" -ForegroundColor Red Write-Host "Error message: $($_.Exception.Message)" -ForegroundColor Red Write-Host "Please reset the settings using Reset-EmailSettings, and run the Setup-Email again." -ForegroundColor Red return } # Send-MailMessage -To $To -From $emailUsername -Subject $subject -Body $body -Credential $emailCredential -SmtpServer $smtpServer -Port $smtpPort Write-Host "Test Email sent" -ForegroundColor Green Write-Host "Please check your inbox, if you did not receive the email, please reset the settings using Reset-EmailSettings, and run the Setup-Email again." } #EndRegion '.\Public\Setup-Email.ps1' 74 #Region '.\Public\Update-TisaneFromFTP.ps1' 0 function Update-TisaneFromFTP{ <# .SYNOPSIS Updates the Tisane software from an FTP server. .DESCRIPTION The Update-TisaneFromFTP function downloads the latest Tisane software files from an FTP server and updates the Tisane installation on the local machine. It can be used to update both the Tisane data files and the Tisane Web Service. .PARAMETER user The FTP user name required to connect to the FTP server. .PARAMETER password The FTP password required to authenticate the FTP user. .PARAMETER ftp The FTP host name or IP address. .PARAMETER copyOnly Specifies whether to copy the updated files without re-registering the Tisane service. By default, this parameter is set to $false. .EXAMPLE Update-TisaneFromFTP -user "ftpuser" -password "ftppassword" -ftp "ftp.example.com" Downloads the latest Tisane software files from the FTP server "ftp.example.com" using the FTP user "ftpuser" and the specified password. The function updates the Tisane installation on the local machine. #> [CmdletBinding()] Param( [Parameter(Mandatory = $true, valueFromPipeline=$true, HelpMessage="FTP user: ")][String] $user, [Parameter(Mandatory = $true, HelpMessage="FTP password: ")][String] $password, [Parameter(Mandatory = $true, HelpMessage="FTP host: ")][String] $ftp, [Parameter(Mandatory = $false, HelpMessage="Copy only, no need to reregister the service: ")][Boolean] $copyOnly ) $DOWNLOAD_FOLDER = "C:/Users/Administrator/Downloads/Tisane" $TISANE_ROOT = "C:/Tisane" $webclient = New-Object System.Net.WebClient if(-not(Test-Path($DOWNLOAD_FOLDER))) { # file with path $path doesn't exist mkdir $DOWNLOAD_FOLDER } $webclient.Credentials = New-Object System.Net.NetworkCredential("$user@$ftp", $password) $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_db.zip") Write-Host "Downloading Tisane data to $DOWNLOAD_FOLDER..." -ForegroundColor Green $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/tisane_db.zip") Stop-Service "Tisane Runtime *" Write-Host "Downloading Tisane Web Service to $DOWNLOAD_FOLDER..." -ForegroundColor Green $uri = New-Object System.Uri("ftp://ftp.$ftp/tisane_ws.zip") $webclient.DownloadFile($uri, "$DOWNLOAD_FOLDER/tisane_ws.zip") if(Test-Path($TISANE_ROOT)) { #mkdir $TISANE_ROOT #Remove-Item -Path "$TISANE_ROOT/" -Recurse # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\.+[.]sst' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -Assembly "System.IO.Compression.Filesystem" # WE HAVE TO USE Ionic Zip because the standard compression libraries crash with very large archives [System.Reflection.Assembly]::LoadFrom("$DOWNLOAD_FOLDER/Ionic.Zip.dll") $zipFile = New-Object Ionic.Zip.ZipFile("$DOWNLOAD_FOLDER/tisane_db.zip") #[System.IO.Compression.ZipFile]::ExtractToDirectory("$DOWNLOAD_FOLDER/tisane_db.zip", $TISANE_ROOT, $true) Write-Host "Extracting Tisane data to $TISANE_ROOT..." -ForegroundColor Green #Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER/tisane_db.zip" -DestinationPath $TISANE_ROOT -Force (Get-Service "Tisane *").WaitForStatus('Stopped') $zipFile.ExtractAll($TISANE_ROOT, 1) # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\LOG[.]old.+' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $services = Get-Service "Tisane Runtime *" $instances = $services.length For ($i=1; $i -le $instances; $i++) { $formattedI = $i | % tostring 00 Write-Host "Updating instance under $TISANE_ROOT/instance$formattedI" -ForegroundColor Green Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER/tisane_ws.zip" -DestinationPath "$TISANE_ROOT/instance$formattedI" -Force if (-not $copyOnly) { Start-Process -FilePath "$TISANE_ROOT/instance$formattedI/Tisane.Runtime.Service.exe" -ArgumentList "-r" -Wait } } Start-Service "Tisane Runtime *" } #EndRegion '.\Public\Update-TisaneFromFTP.ps1' 94 #Region '.\Public\Update-TisaneFromLocalZips.ps1' 0 function Update-TisaneFromLocalZips{ Stop-Service "Tisane Runtime *" $DOWNLOAD_FOLDER = "C:/Users/Administrator/Downloads/Tisane" $TISANE_ROOT = "C:/Tisane" #Add-Type -AssemblyName System.IO.Compression.FileSystem #Add-Type -Assembly "System.IO.Compression.Filesystem" # WE HAVE TO USE Ionic Zip because the standard compression libraries crash with very large archives [System.Reflection.Assembly]::LoadFrom("$DOWNLOAD_FOLDER/Ionic.Zip.dll") $zipFile = New-Object Ionic.Zip.ZipFile("$DOWNLOAD_FOLDER/tisane_db.zip") #[System.IO.Compression.ZipFile]::ExtractToDirectory("$DOWNLOAD_FOLDER/tisane_db.zip", $TISANE_ROOT, $true) Write-Host "Extracting Tisane data to $TISANE_ROOT..." -ForegroundColor Green #Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER/tisane_db.zip" -DestinationPath $TISANE_ROOT -Force $zipFile.ExtractAll($TISANE_ROOT, 1) # dir $TISANE_ROOT -Recurse | Where-Object { $_.FullName -imatch '^C:\\tisane\\([^\\]+)\\LOG[.]old.+' } | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $services = Get-Service "Tisane Runtime *" $instances = $services.length For ($i=1; $i -le $instances; $i++) { $formattedI = $i | % tostring 00 Write-Host "Updating instance under $TISANE_ROOT/instance$formattedI" -ForegroundColor Green Expand-Archive -LiteralPath "$DOWNLOAD_FOLDER/tisane_ws.zip" -DestinationPath "$TISANE_ROOT/instance$formattedI" -Force Start-Process -FilePath "$TISANE_ROOT/instance$formattedI/Tisane.Runtime.Service.exe" -ArgumentList "-r" -Wait } Start-Service "Tisane Runtime *" } #EndRegion '.\Public\Update-TisaneFromLocalZips.ps1' 37 |