--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/smalltalk.ps1 Wed Jul 12 10:25:43 2017 +0200
@@ -0,0 +1,324 @@
+# This file inherits the licencing from the batch file. (MIT)
+# $executable ... stx.com or .exe
+# $log_file ... log file name with path
+# $log_file_encoding ... user defined encoding
+# $append_to_log ... should the log file be appended? (TRUE/FALSE)
+# $cmd_close ... sends either cmd /u /c (close cmd) or /u /k (cmd remains open)
+# $PowerShellVersion ... detected powershell version
+# $cmd_in_powershell ... should cmd.exe be used for stdout redirection? (TRUE/FALSE)
+param($executable, $log_file, $log_file_encoding, $append_to_log, $cmd_close, $PowerShellVersion, $cmd_in_powershell, $stx_manual_switch_detected);
+
+
+# ===========================================================================
+# Reading directly from environment - due to the issues with passing quotes =
+# ===========================================================================
+# StX switches which are build during batch file execution $env:stx_switch;
+$stx_switch = [environment]::GetEnvironmentVariable("stx_switch");
+# PowerShell version detected during batch file execution $env:powershell_version_all_functionality;
+$stx_powershell_version = [environment]::GetEnvironmentVariable("powershell_version_all_functionality");
+# getting line width for the log file
+$log_file_width = [environment]::GetEnvironmentVariable("stx.__numeric.log_file_width");
+
+
+# =======================================================
+# Adjust all variables to PowerShell style $true/$false =
+# =======================================================
+
+If ([environment]::GetEnvironmentVariable("stx.__binary.colored_stdout") -eq 'TRUE') {
+ $use_color = $true;
+} Else {
+ $use_color = $false;
+}
+
+If ($cmd_in_powershell -eq 'TRUE') {
+ $cmd_in_powershell = $true;
+} Else {
+ $cmd_in_powershell = $false;
+}
+
+If ($append_to_log -eq 'TRUE') {
+ $append_to_log = $true;
+} Else {
+ $append_to_log = $false;
+}
+
+If ($stx_manual_switch_detected -eq 'TRUE') {
+ $stx_manual_switch_detected = $true;
+} Else {
+ $stx_manual_switch_detected = $false;
+}
+
+If ($use_color) {
+ # fastest way to init empty Hastable
+ $saved_color = [System.Collections.Hashtable]@{};
+ # save colors for later restore
+ $window_private_data = (Get-Host).PrivateData;
+ $saved_color.Add('VerboseBackgroundColor', "$window_private_data.VerboseBackgroundColor") | Out-null; # Out-null for supressing the natural output
+ $saved_color.Add('VerboseForegroundColor', "$window_private_data.VerboseForegroundColor") | Out-null;
+ $saved_color.Add('WarningBackgroundColor', "$window_private_data.WarningBackgroundColor") | Out-null;
+ $saved_color.Add('WarningForegroundColor', "$window_private_data.WarningForegroundColor") | Out-null;
+ $saved_color.Add('ErrorBackgroundColor', "$window_private_data.ErrorBackgroundColor") | Out-null;
+ $saved_color.Add('ErrorForegroundColor', "$window_private_data.ErrorForegroundColor") | Out-null;
+ #setting the user specified colors
+ $window_private_data.VerboseBackgroundColor = [environment]::GetEnvironmentVariable("stx.stdout_VerboseBackgroundColor");
+ $window_private_data.VerboseForegroundColor = [environment]::GetEnvironmentVariable("stx.stdout_VerboseForegroundColor");
+ $window_private_data.WarningBackgroundColor = [environment]::GetEnvironmentVariable("stx.stdout_WarningBackgroundColor");
+ $window_private_data.WarningForegroundColor = [environment]::GetEnvironmentVariable("stx.stdout_WarningForegroundColor");
+ $window_private_data.ErrorBackgroundColor = [environment]::GetEnvironmentVariable("stx.stdout_ErrorBackgroundColor");
+ $window_private_data.ErrorForegroundColor = [environment]::GetEnvironmentVariable("stx.stdout_ErrorForegroundColor");
+} ElseIf ($cmd_in_powershell) {
+ $window_private_data = (Get-Host).PrivateData;
+ $window_private_data.VerboseBackgroundColor = 'Black';
+ $window_private_data.VerboseForegroundColor = 'Gray';
+}
+
+
+# ===========
+# Functions =
+# ===========
+
+# Function for correct $LASTEXITCODE to ERRORLEVEL passing
+function ExitWithCode {
+ param (
+ $exitcode
+ )
+ $host.SetShouldExit($exitcode);
+ EXIT;
+} # end ExitWithCode
+
+# Print User message using String Array $message
+function PrintMessage {
+ param(
+ [Parameter( `
+ Mandatory=$True, `
+ Valuefrompipeline = $true)]
+ [String]$message
+ )
+ begin {}
+ process {
+ foreach ($Message in $Message) {
+ # Write-Host Considered Harmful - see http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/
+ # first way how to correctly write it
+ #Write-host $message;
+ # highlights warning and error messages from StX VM!
+ If ($message -match '\[ERROR\]') {
+ $host.ui.WriteErrorLine("$message");
+ } ElseIf ($message -match '\[WARN\]') {
+ Write-Warning $message;
+ } Else {
+ Write-Verbose -Message $message -Verbose;
+ }
+ }
+ }
+ end {}
+} # end PrintMessage
+
+
+# To correctly simultinously write to stdout and log file when using out-file!
+# Colors the output based on string match
+function Tee-Host {
+ Param (
+ [Parameter(Mandatory=$true,
+ ValueFromPipeline=$true,
+ Position=0)]
+ $message
+ )
+ begin {}
+ Process {
+ # first way how to correctly write it
+ # -EV is short (an alias) for -ErrorVariable
+ If ($message -match '\[error\]') {
+ # this is printing error compatible with all PS versions
+ $host.ui.WriteErrorLine("$message");
+ } ElseIf ($message -match '\[warning\]') {
+ Write-Warning "$message";
+ } Else {
+ Write-Verbose -Message "$message" -Verbose;
+ }
+ # second correct way how to write it
+ #$VerbosePreference = "Continue"
+ #Write-Verbose $input_object;
+ return $message
+ }
+ end {}
+} # end Tee-Host
+
+function ExecuteCommand {
+ param(
+ $execute_command
+ )
+ try {
+ Invoke-Expression -Command:$execute_command
+ If ($lastexitcode -ne 0) {
+ $result = $result -join "`n";
+ throw "$result `n";
+ }
+ }
+ catch {
+ $window_private_data = (Get-Host).PrivateData;
+ # saving the original colors
+ $saved_background_color = $window_private_data.ErrorBackgroundColor
+ $saved_foreground_color = $window_private_data.ErrorForegroundColor
+ # setting the new colors
+ $window_private_data.ErrorBackgroundColor = 'White';
+ $window_private_data.ErrorForegroundColor = 'Red';
+
+ $host.ui.WriteErrorLine("[ERROR] happned in PowerShell (can be also stx.com) - See log file: $log_file.");
+ Write-Error "`n`n[ERROR] Error from PowerShell:`n`n $_" 2>> $log_file;
+
+ $window_private_data.ErrorBackgroundColor = $saved_background_color;
+ $window_private_data.ErrorForegroundColor = $saved_foreground_color;
+ }
+} # end ExecuteCommand
+
+
+# =============================
+# check if log file is locked =
+# =============================
+function Test-FileLock {
+ param (
+ [parameter(Mandatory=$true)][string]$path
+ )
+ $log_file = New-Object System.IO.FileInfo $path
+ If ((Test-Path -Path $path) -eq $false) {
+ return $false
+ }
+
+ try {
+ $log_file_stream = $log_file.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
+ If ($log_file_stream) {
+ $log_file_stream.Close()
+ }
+ $false
+ } catch {
+ # file is locked by a process.
+ return $true
+ }
+}
+
+
+# ========================================================================
+# Check if user did not start the PowerShell file directly - exit if yes =
+# ========================================================================
+If ([string]::IsNullOrEmpty($executable)) {
+ "`n", '[ERROR] You can not run this powershell script directly!', 'Execute batch file (.bat) instead.' | PrintMessage;
+ EXIT 1;
+}
+
+
+# ====================================
+# Checking the state of the log file =
+# ====================================
+# Must be done only once in the file in case
+# the file is unlocked before the second instance is closed
+$is_logfile_locked = Test-FileLock($log_file)
+
+# ================
+# Stdout logging =
+# ================
+If ($is_logfile_locked){
+ "`n", "[WARN] Log file $log_file in use.`n`n !!NO LOGGING will be available for this Smalltalk/X instance!!" | PrintMessage;
+ '[INFO] Press any key to continue ...' | PrintMessage;
+ # waits for pressing any key
+ $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-null;
+ $logging_function = "Tee-Host | Out-null";
+} Else {
+ If ($append_to_log) {
+ $logging_function = "Tee-Host | Out-File -Append -Encoding $log_file_encoding -FilePath $log_file -Width $log_file_width";
+ } Else {
+ $logging_function = "Tee-Host | Out-File -Encoding $log_file_encoding -FilePath $log_file -Width $log_file_width";
+ }
+}
+
+
+# ===========
+# Execution =
+# ===========
+# Decide which stdout use - either powershell.exe or cmd.exe
+If ($PowerShellVersion -ge $stx_powershell_version) {
+ # stdout output via powershell.exe
+ If (!$cmd_in_powershell) {
+ # --% was introduced in PowerShell 3.0, forces PowerShell to ignore all code afterwards
+ # redirection from 9 - combined (all output combined into a single - easy to redirect stream) from Powershell
+ # if manual switch detected force powershell to ignore all code afterwards
+ If ($stx_manual_switch_detected) {
+ $stx_switch = "--% $stx_switch";
+ }
+ $command = @"
+$executable $stx_switch 2>&1 | $logging_function;
+"@
+ # Due to the PowerShell bug produces FullyQualifiedErrorId : NativeCommandError in the log file -> you can ignore it.
+ # actual execution
+ ExecuteCommand -execute_command $command;
+ # stdout output via cmd.exe
+ } Else {
+ # check if manual switch detected
+ If ($stx_manual_switch_detected) {
+ # if manual switch detected force powershell to ignore all code afterwards
+ $stx_switch = "--% $stx_switch";
+ $command = @"
+cmd.exe $cmd_close $executable $stx_switch '2^>^&1' ^| $logging_function
+"@
+ } Else {
+ # must replace double quotes in order for the cmd.exe to work correctly - cmd.exe requirement
+ $stx_switch = $stx_switch -replace '"','^"';
+ $command = @"
+cmd.exe $cmd_close $executable $stx_switch '2>&1' | $logging_function
+"@
+ }
+
+ # Due to the PowerShell bug may produce an error: "FullyQualifiedErrorId : NativeCommandError" in the log file -> you can ignore it.
+ # actual execution
+ Write-verbose -message $command -verbose;
+ ExecuteCommand -execute_command $command;
+ } # end Else
+} Else { # legacy powershell - no manual switches available!
+ # stdout output via powershell.exe
+ If (!$cmd_in_powershell) {
+ $command = @"
+$executable $stx_switch 2>&1 | $logging_function
+"@
+ # Due to the PowerShell bug produces FullyQualifiedErrorId : NativeCommandError in the log file -> you can ignore it.
+ # actual execution
+ ExecuteCommand -execute_command $command;
+ # stdout output via cmd.exe
+ } Else {
+ # must replace double quotes in order for the cmd.exe to work correctly??
+ $stx_switch = $stx_switch -replace '"','^"';
+ $command = @"
+cmd.exe $cmd_close $executable $stx_switch '2>&1' | $logging_function
+"@
+ # Due to the PowerShell bug produces FullyQualifiedErrorId : NativeCommandError in the log file -> you can ignore it.
+ # actual execution
+ ExecuteCommand -execute_command $command;
+ }
+} # end if
+
+
+# =========================================
+# Add Separator when adding into the file =
+# =========================================
+If (!$is_logfile_locked){
+ If ($append_to_log) {
+ Write-Output "`r`n=================================================================================================`r`n" >> $log_file;
+ }
+}
+
+# ===============================
+# Restore original Shell colors =
+# ===============================
+#TODO:
+If ($use_color) {
+ $window_private_data = (Get-Host).PrivateData;
+ ForEach($item in $saved_color.GetEnumerator()) {
+ Set-Variable -name "$window_private_data.$($item.Key)" -Value "$($item.Value)";
+ }
+}
+
+
+# ======
+# Exit =
+# ======
+# Sending exit code to calling batch file
+"`n", "[INFO] Exiting from PowerShell with code $LASTEXITCODE" | PrintMessage;
+ExitWithCode -exitcode $LASTEXITCODE;
\ No newline at end of file