Installation of a fresh/clean/independent/portable copy of Total Commander via its installer CLI mode [PowerShell]

English support forum

Moderators: white, Hacker, petermad, Stefan2

Post Reply
User avatar
beb
Senior Member
Senior Member
Posts: 435
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Installation of a fresh/clean/independent/portable copy of Total Commander via its installer CLI mode [PowerShell]

Post by *beb »

Here and there on this board when a user meets an issue, we often will see a piece of advice to try the new clean installation of the Total Commander to address it properly.
The thing is, a common user has no option for that, nor did I.
So I became interested in finding a way to do it easily, quickly, and steadily safely.
After a chain of experiments that finally proved to be a success (from my point of view), I came to a solution that fitted my needs.
So hereby I share my solution, and this is the primary point of my message.
Feel free to test it, use it, modify it, and do whatever you want.

Total Commander installer does not provide its common users with an explicit and unconditional option to install a clean copy of the program so far.
As soon as a valid existing configuration [ini] of the previously installed copy could be found [via the resident registry data] the installer (both in GUI/CLI modes) will always take the content from there.
I'm afraid that behavior is by design (to say a feature, not a bug).
Therefore, I made a script that overrides this behavior.

Caution:
I can do the custom installer repack but I am not interested in it and do not want to.
(see: https://www.ghisler.ch/wiki/index.php?title=Custom_installer)
Thus, had such a discussion emerged here I myself would contribute nothing to it (even though it may be useful for someone else).

Main notes:
[0] If Mr ghisler(Author) decides to fix the said installer behavior (by implementing corresponding explicit installer's options, e.g. for the CLI mode N or P0 - Not to use/imPort any data from the previous installations), the main script still may remain actual for those who'd want to have a bit customized .ini from the very start. And the informer subscript (which can be run standalone) can be helpful to give a user a piece of information on what data their Total Commander keeps in the AppData/Registry that they have no idea about.

[1] The entire installation time from start to finish on my ancient machines is within 0.2...0.4 seconds (200...400 milliseconds).
Not that long, I suppose.

[2] The Total Commander installer command in the script is as follows:
$installer /A1H1L1M0G0D0U0FRI0'".\"' $installFolder
where the script variables:

Code: Select all

$installer     : installer variable (e.g., "tcmd1103x32_64.exe", the freshest one currently)
$installFolder : install folder variable (under the naming template: "$env:Temp\TC_yyyyMMdd_HHmmss\totalcmd")
and the installer parameters breakdown/itemization:
(see https://www.ghisler.ch/wiki/index.php?title=Installer#Command_line_parameters)

Code: Select all

A1 : automatic
H1 : hidden
L1 : English language
M0 : no other languages
G0 : no Windows menu entries
D0 : no Desktop shortcuts
U0 : no updates to anything
F  : force a normal installation (ignore previous installation folders)
R  : no registry uninstall-related records
I0 : no registry .ini location-related records 
".\" : place configuration files (.ini) in the program folder
[3] The newly installed copy of Total Commander will go with the wincmd.ini of the following initial contents:
(the .ini file will be in the UTF-16 LE BOM encoding)

Code: Select all

[Configuration]
UseIniInProgramDir=7
DirUsageLocation=%commander_path%\Temp
IgnoreListFile=%commander_path%\Temp\tcignore.txt
ListName=%commander_path%\Temp\ftplist.txt
LogFile=%commander_path%\Temp\totalcmd.log
TabDir=%commander_path%\Temp
ThumbsLocation=%commander_path%\Temp
TreeFileLocation=%commander_path%\Temp\treeinfo%D%.wc
StartupScreen=0
UseRightButton=0
FirstTime=0
FirstTimeIconLib=0
UseNewDefFont=1
Please, share your ideas, on what else is a must to be there regarding genuine portability.

[4] The script has been tested on Windows PowerShell 5.1 and on cross-platform PowerShell 7.4+
Other notes
[5] The script implies optional usage of the informer subscript [tcmd_cli_setup_reporter_*.ps1] (which will be explained later, if needed).

[6] By default, the script is supposed to get launched from a subfolder of a directory where the Total Commander installer(s) reside.
Otherwise, you may need to type another path to the installer there, like $env:path +=";y:\our\installer\directory"

[7] The script uses "TC_yyyyMMdd_HHmmss/totalcmd" naming template for the target install folder within the Temp directory.
This grants no other copies (if any) of Total Commander could be affected by the new installation, even those installed with the script.
As an addition to that, the script still won't use the same folder even then:
If you manage to run the script more than once within the same second the installation will quit, while you will be offered to try again later (until the next second ticks).
Example script reports:
Scenario 1
conditions:
- bare main script (without informer subscript).
- no other Total Commander copies have been detected (no valid data leading to such copies present).
(either, this is a primary installation, or previous installation(s) is/are truly portable).
screen 1.1
Image: https://i.imgur.com/ub5Qh4Q.png
Scenario 2
conditions:
- main script with a brief informer subscript.
- no other Total Commander copies have been detected (as above).
screen 2.1
Image: https://i.imgur.com/vm4baCO.png
Scenario 3
conditions:
- main script with a brief informer subscript.
- valid data of a previous Total Commander copy have been detected.
screen 3.1
Image: https://i.imgur.com/U8NKqk2.png
screen 3.2
Image: https://i.imgur.com/H06pi5U.png
screen 3.3
Image: https://i.imgur.com/lTQFuJY.png
screen 3.4
Image: https://i.imgur.com/M6HlDps.png
screen 3.5
Image: https://i.imgur.com/hfj4Fln.png
screen 3.6
Image: https://i.imgur.com/rDgLnOs.png
screen 3.7
Image: https://i.imgur.com/YfOMcwg.png
screen 3.8
Image: https://i.imgur.com/JUbeEXf.png
Luckily, in case of the scenario 3, I compacted my original .ini, particularly by redirecting all the sections somewhere.
Still, as you can see, the Total Commander installer is dragging a whole lot of old data into my new .ini, which I didn't ask it to do, even though it (the installer) is unable to process all the data properly.

The script itself:
tcmd_cli_installer_v1.ps1

Code: Select all

[Diagnostics.Stopwatch]::StartNew()|Tee -var lap|Out-null
[Text.Encoding]::GetEncoding('Unicode')|Tee -var encoding|Out-null
Get-Date -format "yyyyMMdd_HHmmss"|Tee -var stamp|Out-null

.\tcmd_cli_setup_reporter_brief.ps1
#.\tcmd_cli_setup_reporter_verbose.ps1

$env:path     +=";$($pwd|split-path)"
$installer     = 'tcmd1103x32_64.exe'
$installFolder = $env:temp+'\TC_'+$stamp+'\totalcmd'
$ini           = $installFolder+'\wincmd.ini'
""
if ($installFolder|Test-path) {
Write-Host  'CAUTION:' -f DarkYellow
Write-Host -f Yellow  '$installFolder already exists'
Write-Host -f Yellow  '$installer is quitting...'
Write-Host -f Yellow  'Note: give it another try in a while.'
}
else {
Write-Host -f Yellow  'installation   : in progress...'

&{$PSNativeCommandArgumentPassing = 'Legacy'
& $installer /A1H1L1M0G0D0U0FRI0'".\"' $installFolder
}
""
Write-Host -f Cyan -no '$installer     : '
Write-Host -f Blue      $installer
Write-Host -f Cyan -no '$installFolder : '
Write-Host -f Blue      $installFolder
Write-Host -f Cyan -no '$ini expected  : '
Write-Host -f Blue      $ini
""
$installation     = Get-Process $($installer.split("."))[0]
if ($installation) {
Write-Host -f Yellow -no '$installer     : '
Write-Host -f Blue   -no  $installation.Name
Write-Host -f Yellow     ' is running...'}
Wait-Process           $installation -EA Silent
Write-Host -f Yellow -no '                 '
Write-Host -f Yellow -no 'checking for the '
Write-Host -f Blue   -no '$ini '
Write-Host -f Yellow -no 'in the '
Write-Host -f Blue   -no '$installFolder'
Write-Host -f Yellow -no '...'
""
while         (-not ($ini|Test-Path)) {}
function   ifLocked ($ini) {
try {
[IO.File]::OpenWrite($ini).Close();$false} catch {$true}
}
while     ((ifLocked $ini) -ne $false) {}

$config = (@"
[Configuration]
UseIniInProgramDir=7
DirUsageLocation=%commander_path%\Temp
IgnoreListFile=%commander_path%\Temp\tcignore.txt
ListName=%commander_path%\Temp\ftplist.txt
LogFile=%commander_path%\Temp\totalcmd.log
TabDir=%commander_path%\Temp
ThumbsLocation=%commander_path%\Temp
TreeFileLocation=%commander_path%\Temp\treeinfo%D%.wc
StartupScreen=0
UseRightButton=0
FirstTime=0
FirstTimeIconLib=0
UseNewDefFont=1
"@)
""
if ($ini|Test-Path) {
Write-Host 'ATTENTION' -f DarkYellow
Write-Host -f DarkRed '$ini found with the following resident content:'
[IO.File]::ReadAllText($ini)}
else {
Write-Host 'ATTENTION' -f DarkYellow
Write-Host -f DarkRed '$ini not found; creating one...'}
New-Item $ini -type file -force > $null
""
Write-Host -f Yellow  'customization  : in progress...'
[IO.File]::WriteAllLines($ini,$config,$encoding)
""
Write-Host 'INFORMATION' -f DarkYellow
Write-Host -f Green   'resulting $ini content:'
[IO.File]::ReadAllText($ini)|Out-host
}
""
.\tcmd_cli_setup_reporter_brief.ps1
#.\tcmd_cli_setup_reporter_verbose.ps1
""
$lap.Stop()
Write-Host -f Cyan ("Elapsed time   : {0:ss}.{0:fff}" -f $lap.Elapsed) -no;" (script v1)"
""
pause
The setup informer subscript (brief edition):
tcmd_cli_setup_reporter_brief.ps1

Code: Select all

$ghislerAppData  = @("$env:AppData\Ghisler","$env:LocalAppData\Ghisler")
$ghislerRegistry = [ordered]@{
"HKCU:\SOFTWARE\Ghisler"            ="HKCU:\SOFTWARE\GhislerBackup"
"HKLM:\SOFTWARE\Ghisler"            ="HKLM:\SOFTWARE\GhislerBackup"
"HKLM:\SOFTWARE\WOW6432Node\Ghisler"="HKLM:\SOFTWARE\WOW6432Node\GhislerBackup"}
$max             =   -($ghislerAppData+$ghislerRegistry|Measure -Maximum -Property Length).Maximum
# research AppData
Write-Host -f Cyan    '$AppData       : ' -no
Write-Host -f Yellow  'checking for resident data...'
$ghislerAppData|foreach {
if              (-not ($PSitem|Test-Path)) {
"{0,$max}" -f          $PSitem|Tee -var noData|Out-null
Write-Host -f DarkGray $noData -no;' : does not exist; no action required'
}
else {
# report AppData
"{0,$max}" -f          $PSitem|Tee -var Data|Out-null
Write-Host -f DarkRed  $Data -no
Write-Host -f Yellow  ' : contains data!'
$entry = Get-ChildItem $PSitem -recurse
foreach               ($item in $entry) {
"{0,$max}" -f          $item.FullName|Tee -var dataItem|Out-null
Write-Host -f DarkMag  $dataItem}
}}
# research Registry
Write-Host -f Cyan    '$Registry      : ' -no
Write-Host -f Yellow  'checking for resident data...'
foreach               ($key in $ghislerRegistry.keys) {
"{0,$max}" -f          $key|Tee -var keyOut|Out-null
if              (-not ($key|Test-Path)) {
Write-Host             $keyOut -f DarkGray -no;' : does not exist; no action required'}
else {
Write-Host             $keyOut -f Red -no
Write-Host  -f Yellow ' : contains data!'
Get-ChildItem          $key -recurse |foreach {
$regItem             = $PSitem.toString()
$regItem             = $regItem -replace 'HKEY.*USER\\','HKCU:' -replace 'HKEY.*MACHINE\\','HKLM:'
$regValues           = @()
(Get-ItemProperty      $regItem).PSobject.Properties|Where Name -notin PSPath,PSProvider,PSDrive,PSParentPath|Select Name,Value|
foreach {
$keyName             = $_.name
$keyValue            = $_.value
if   (                 $keyName -eq 'PSChildName') {
$subKey = $key + '\' + $keyValue}
else {
$regValues         += "{0,-11} = {1}" -f $keyName, $keyValue}
}
Write-Host -f Red      $subKey
$regValues|Sort-Object|foreach {
Write-Host -f Magenta  $_
}}}}

if (-not $MyInvocation.PSCommandPath) {pause}


Edit 2024-03-15: initial .ini content update.
Edit 2024-03-25: initial .ini content update.
Last edited by beb on 2024-03-25, 21:50 UTC, edited 3 times in total.
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10
User avatar
beb
Senior Member
Senior Member
Posts: 435
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Installation of a fresh/clean/independent/portable copy of Total Commander via its installer CLI mode [PowerShell]

Post by *beb »

Added to the initial .ini content:

Code: Select all

ThumbsLocation=
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10
User avatar
petermad
Power Member
Power Member
Posts: 14809
Joined: 2003-02-05, 20:24 UTC
Location: Denmark
Contact:

Re: Installation of a fresh/clean/independent/portable copy of Total Commander via its installer CLI mode [PowerShell]

Post by *petermad »

2beb
I am surprised to see that you recommend:
UseRightButton=0

IMHO the right button selection is one of the most important benefits of TC compared to for example Explorer. Using left mouse selection and - after having made several selections in the panel - the horror if I accidentally click in the panel and ALL the selections are lost!


Other entries you might consider adding to the initial ini:
TreeFileLocation
listname
TabDir
LogFile
License #524 (1994)
Danish Total Commander Translator
TC 11.03 32+64bit on Win XP 32bit & Win 7, 8.1 & 10 (22H2) 64bit, 'Everything' 1.5.0.1371a
TC 3.50 on Android 6 & 13
Try: TC Extended Menus | TC Languagebar | TC Dark Help | PHSM-Calendar
User avatar
beb
Senior Member
Senior Member
Posts: 435
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Installation of a fresh/clean/independent/portable copy of Total Commander via its installer CLI mode [PowerShell]

Post by *beb »

quot homines tot sententiae
petermad wrote: 2024-03-15, 11:19 UTC I am surprised to see that you recommend:
UseRightButton=0
IMHO the right button selection is one of the most important benefits of TC...
Wow, what a great illustration of the saying, 'so many men, so many opinions.'
My IMHO, on the contrary, has been assuring me from the very first day - there is no more annoying feature of TC than the flipped mice buttons.
Surely, you and the others with the same approach are free to strip off UseRightButton=0 from there since it's not your style.
Moreover, I did not recommend anything here.
I just shared my experience on how to quickly install a clean copy of Total Commander, which also includes some basic .ini entries.
Then, I asked fellow users to share their ideas regarding .ini content.
Of course, it's up to an end user whatever .ini parameters they would finally prefer.

So, thank you very much for your input.
Definitely, I will dive into the TreeFileLocation, listname, TabDir, LogFile parameters details.
Cheers.
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10
User avatar
beb
Senior Member
Senior Member
Posts: 435
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Installation of a fresh/clean/independent/portable copy of Total Commander via its installer CLI mode [PowerShell]

Post by *beb »

wincmd.ini initial contents updated as follows:

Code: Select all

[Configuration]
UseIniInProgramDir=7
DirUsageLocation=%commander_path%\Temp
IgnoreListFile=%commander_path%\Temp\tcignore.txt
ListName=%commander_path%\Temp\ftplist.txt
LogFile=%commander_path%\Temp\totalcmd.log
TabDir=%commander_path%\Temp
ThumbsLocation=%commander_path%\Temp
TreeFileLocation=%commander_path%\Temp\treeinfo%D%.wc
StartupScreen=0
UseRightButton=0
FirstTime=0
FirstTimeIconLib=0
UseNewDefFont=1
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10
Post Reply