From 6a358ce70652d421b58a34deea6220f09b4c5cdd Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Thu, 2 Oct 2025 04:28:35 +1000 Subject: [PATCH] minor bin experiments --- bin/tclargs.cmd | 43 +++++++++++++++++++----- src/scriptapps/bits.pl | 75 ++++++++++++++++++++++++------------------ 2 files changed, 78 insertions(+), 40 deletions(-) diff --git a/bin/tclargs.cmd b/bin/tclargs.cmd index 080ab8b2..717f2184 100644 --- a/bin/tclargs.cmd +++ b/bin/tclargs.cmd @@ -940,6 +940,7 @@ if {$nextshelltype ne "tcl" && $nextshelltype ne "none"} { #maint: keep this munging in sync with zsh/bash and perl blocks which must also do msys mangling if {[regexp {^cmd$|^cmd[.]exe$} $cmdword]} { #need to deal with msys argument munging + puts stderr "cmd call via msys detected. performing translation of /c to //C" #for now we only deal with /C or /c - todo - other cmd.exe flags? #In this context we would usually only be using cmd.exe /c to launch older 'desktop' powershell to avoid spaced-argument problems - so we aren't expecting other flags set new_nextshellpath [list $cmdword] @@ -1236,13 +1237,14 @@ if [[ "$nextshelltype" != "bash" && "$nextshelltype" != "none" ]]; then #do not double quote cmdpattern - or it will be treated as literal string if [[ "$nextshellpath" =~ $cmdpattern ]]; then #for now - tell the user what's going on - echo "cmd call via msys detected. performing translation of /c to //c and escaping backslashes in script path" + echo "cmd call via msys detected. performing translation of /c to //c and escaping backslashes in script path" >&2 #flags to cmd.exe such as /c are interpreted by msys as looking like a unix path #review - for nextshellpath targets specified in the block for win32 - we don't expect unix paths (?) #what about other flags? - can we just double up all forward slashes? #maint: keep this munging in sync with the tcl block and perl block which must also do msys munging nextshellpath="${nextshellpath// \/[cC] / \/\/c }" # echo "new nextshellpath: ${nextshellpath}" + #review - #don't double quote this script=${script//\\/\\\\} fi @@ -1351,8 +1353,33 @@ if 0 { # -- unbalanced braces { } here *even in comments* will cause problems if there was no Tcl exit or return above # -- custom script should generally go below the begin_powershell_payload line # ## ### ### ### ### ### ### ### ### ### ### ### ### ### -function GetScriptName { $myInvocation.ScriptName } -$scriptname = GetScriptName +#$MyInvocation.ScriptName should probably be considered deprecated +# https://stackoverflow.com/questions/78511229/how-can-i-choose-between-myinvocation-scriptname-and-myinvocation-pscommandpat +$runningscriptname = $PSCommandPath +if (-not $MyInvocation.PSCommandPath) { + $callingscriptname = '' +} else { + $callingscriptname = $MyInvocation.PSCommandPath +} +#The problem with psmodulepath +#https://github.com/PowerShell/PowerShell/issues/18108 +# psmodulepath is shared by powershell and pwsh despite not all ps modules being compatible. +# It is futzed with by powershell/pwsh based on detecting the child process type. +# a psmodulepath that has been futzed with by pwsh will not work for a child powershell 5 process that isn't launched directly +#This is inherently unfriendly to situations where an intervening process may be something else such as cmd.exe,tcl,perl etc +# nevertheless, powershell/pwsh maintainers seem to have taken the MS-centric view of the world that such situations don't exist :/ +# +#symptoms of these shenannigans not working include things like Get-FileHash failing in powershell desktop +# +#We don't know if the original console was pwsh/powershell or cmd.exe, and we need to potentially divert to powershell 5 (desktop) +#via tcl or perl etc - or cmd.exe +if ($PSVersionTable.PSVersion.Major -le 5) { + # For Windows PowerShell, we want to remove any PowerShell 7 paths from PSModulePath + #snipped from https://github.com/PowerShell/DSC/pull/777/commits/af9b99a4d38e0cf1e54c4bbd89cbb6a8a8598c4e + #Presumably users are supposed to know not to have custom paths for powershell desktop containing a 'powershell' subfolder?? + $env:PSModulePath = ($env:PSModulePath -split ';' | Where-Object { $_ -notlike '*\powershell\*' }) -join ';' +} + function GetDynamicParamDictionary { [CmdletBinding()] param( @@ -1427,11 +1454,11 @@ function GetDynamicParamDictionary { #} #psmain @args #"Timestamp : {0,10:yyyy-MM-dd HH:mm:ss}" -f $(Get-Date) | write-host -"Script Name : {0}" -f $scriptname | write-host +#"Running Script Name : {0}" -f $runningscriptname | write-host "Powershell Version: {0}" -f $PSVersionTable.PSVersion.Major | write-host -"powershell args : {0}" -f ($args -join ", ") | write-host +#"powershell args : {0}" -f ($args -join ", ") | write-host # -- --- --- --- -$thisfileContent = Get-Content $scriptname -Raw +$thisfileContent = Get-Content $runningscriptname -Raw $startTag = ": <>" $endTag = ": <>" $pattern = "(?s)`n$startTag[^`n]*`n(.*?)`n$endTag" @@ -1530,7 +1557,7 @@ if ($match.Success) { } if (-not (("pwsh", "powershell", "") -contains $nextshell_type)) { #nextshell diversion exists for this platform - write-host "os: $os pwsh/powershell launching subshell of type: $nextshell_type shellpath: $nextshell_path on script $scriptname" + write-host "os: $os pwsh/powershell launching subshell of type: $nextshell_type shellpath: $nextshell_path on script $runningscriptname" # $arguments = @($($MyInvocation.MyCommand.Path)) # $arguments += $args @@ -1538,7 +1565,7 @@ if ($match.Success) { # $process = (Start-Process -FilePath $nextshell_path -ArgumentList $arguments -NoNewWindow -Wait) # Exit $process.ExitCode - & $nextshell_path $scriptname $args + & $nextshell_path $runningscriptname $args exit $LASTEXITCODE } } diff --git a/src/scriptapps/bits.pl b/src/scriptapps/bits.pl index fbc0d603..968004cc 100644 --- a/src/scriptapps/bits.pl +++ b/src/scriptapps/bits.pl @@ -1,33 +1,44 @@ - -eval { - use Win32::Service; -}; -if (exists $INC{'Win32/Service.pm'}) { - print "Win32::Service is loaded\n"; -} else { - print "Win32::Service is not loaded\n"; - print "Attempting to install from cpan..\n"; - use CPAN; - my $module = 'Win32::Service'; - eval { - CPAN::Shell->install($module); - }; - if ($@) { - print "Error installing $module: $@"; - } else { - print "$module installed\n"; - } -} -eval { - use Win32::Service; -}; -if ($@) { - print "Unable to load or install Win32::Service. error: $@\n"; -} else { - my $service = "BITS"; - if (Win32::Service::StartService('', $service)) { - print "$service started\n"; - } else { - print "Failed to start $service\n"; - } + +eval { + require Win32::Service; +}; +if (exists $INC{'Win32/Service.pm'}) { + print "perl Win32::Service module is loaded\n"; +} else { + print "perl Win32::Service module is not loaded\n"; + print "Attempting to install from cpan..\n"; + use CPAN; + my $module = 'Win32::Service'; + eval { + CPAN::Shell->install($module); + }; + if ($@) { + print "Error installing $module: $@"; + } else { + print "$module installed\n"; + } +} +$@ = ''; +eval { + require Win32::Service; +}; +if ($@) { + print "Unable to load or install perl Win32::Service module. error: $@\n"; +} else { + my $service = "BITS"; + if (Win32::Service::GetStatus('', $service, \%status)) { + if ($status{CurrentState} == SERVICE_RUNNING) { + print "Service '$service' is already running.\n"; + } else { + print "Attempting to start '$service' service\n"; + if (Win32::Service::StartService('', $service)) { + print "$service started\n"; + } else { + print "Failed to start '$service' service. Error $^E\n"; + print "Ensure this script is run from an elevated shell or use a script that elevates permission\n" + } + } + } else { + print "Failed to get status for '$service' service. Error $^E\n"; + } } \ No newline at end of file