Code: Select all
# tckey_registry_keyfile_zipArchive_inlineByteArray.ps1 v0.5 2025-03-09
# https://ghisler.ch/board/viewtopic.php?t=84672
# classic license keyfile
$keyLicense = 'wincmd.key'
# archived license keyfile
$zipLicense = @('tcmdkey.zip','*.zip')
# root paths where to look for the license keyfile
$root = @($env:commander_path,$PSScriptRoot)
# registry paths where license key can be stored
$hkcu = "HKCU:\SOFTWARE\Ghisler\Total Commander"
$hklm = "HKLM:\SOFTWARE\Ghisler\Total Commander"
$node = "HKLM:\SOFTWARE\WOW6432Node\Ghisler\Total Commander"
# registry path where license key to be stored
$path = $hkcu
# license key registry entry name
$name = 'key'
# get license key from classic license keyfile
$file = Get-ChildItem -path $root -filter $keyLicense -recurse -force | select -first 1
# read classic keyfile contents into a byte array
if ($file) {
$bytes = [byte[]][IO.File]::ReadAllBytes($file)
$keyfile = $file.FullName.substring($PSScriptRoot.length+1)
$info = 'the classic keyfile: {0}' -f $keyfile}
# get license key from archived classic license keyfile
if (-not ($bytes)) {
$file = Get-ChildItem -path $root -include $zipLicense -recurse -force | select -first 1
if ($file) {
# read archive, open classic keyfile as a stream, and copy its contents into a byte array
$zip = [IO.Compression.ZipFile]::OpenRead($file)
$stream = ($zip.Entries | Where {$_.Name -eq $keyLicense}).Open()
$memory = [IO.MemoryStream]::new()
$stream.CopyTo($memory)
$bytes = $memory.ToArray()
$stream.Dispose();$memory.Dispose();$zip.Dispose()
$archive = $file.FullName.substring($PSScriptRoot.length+1)
$info = 'the archived keyfile: {0}' -f $archive}}
# get license key directly in this script from the inline byte array of comma-separated decimal bytes
# note: to make it work replace $null below with the valid comma-separated decimal bytes (e.g. 0,10,100...)
if (-not ($bytes)) {$bytes = @(
$null
)
$info = 'the inline byte array of comma-separated decimal bytes'}
# get license key directly in this script from the inline byte array converted from the hex string
# note: to make it work replace $null below with the valid hex string (e.g. 00,0a,64...)
if (-not ($bytes)) {$hex = @'
$null
'@
# define $bytes depending on the PowerShell version
if ($host.Version.Major -le 5) { # Windows PowerShell
$bytes = $hex.split(',').foreach{[byte]::Parse($_,'hex')}}
else { # Cross-Platform PowerShell
$bytes = [convert]::fromHexString($hex -replace ',')}
$info = 'the inline hex string'}
# if found, add the license key byte array to the registry
if ($bytes) {if (-not ($path|Test-Path)){New-Item -path $path -force}
Set-ItemProperty -path $path -name $name -value $bytes -type Binary -force # -WhatIf
# check how it went (displaying the first dozen of the license key bytes if found)
if ([BitConverter]::ToString((Get-ItemProperty -path $path).$name) -eq [BitConverter]::ToString($bytes)){
'TotalCommander license key'|Write-Host -f DarkCyan
'{0}...' -f ([BitConverter]::ToString($bytes).substring(0,35)).toLower()|Write-Host -f Cyan
'has been successfully added to the registry'|Write-Host -f DarkCyan
'from {0}' -f $info|Write-Host -f DarkCyan}}
else {
'No TotalCommander license keys have been found.'|Write-Host -f Yellow}
sleep -s 12
A. The way the script works by default
The script looks for a Total Commander license keyfile (named 'wincmd.key'):
- anywhere within the script root directory, and/or within the root path defined by the $env:commander_path variable (if the script started under the Total Commander running).
- within zip archives ('tcmdkey.zip', and any other '*.zip') anywhere within the script root directory, and/or within the root path defined by the $env:commander_path variable (same as above).
If the Total Commander license key is found:
- The script will read the license key as a byte array and put it into the registry
If several Total Commander license keys are found:
- The script will use only one of them (the first one found).
The script also can use a license key stored as a byte array directly in the script body.
- in the form of the decimal bytes (e.g. 0,10,100...)
- in the form of the hex string (i.e., exactly as the key seen in the registry, e.g. 00,0a,64...)
B. How does the script do that?
At first, it does some preparations (to say searches) behind the Get-ChildItem command(s).
Then it does the main job: reads the license as a byte array.
In the case of a standalone key file, it is as simple as that: [IO.File]::ReadAllBytes($file)
In the case of a packed keyfile, it is a bit complicated but still:
It will read the archive, open the classic keyfile from the archive as a stream, and copy its contents into a byte array.
If no standalone or packed keyfiles are there, the script can use the license key stored directly in its body as decimal bytes or hex string.
At the final stage, the script puts the license as a byte array into the registry behind the Set-ItemProperty command.
The script can also throw fancy colorful informative letters on your screen behind the Write-Host command(s).
C. for Customization?
Why not. A user can opt for a location to store the license key (HKLM, HKCU).
A user can modify/extend/contract arrays of places where the license keyfile is looked for, play with archive(s) and/or key file(s) naming(s), etc, regarding their specific preferences and approaches to such stuff.
Customization implies editing the script file manually in a text editor of your choice.
Notes
The script is tested under the cross-platform PowerShell (7+) and Windows PowerShell (5.1) on a Windows 10 Pro 64-bit machine.
Additional useful PowerShell scripts
tckey_registry_save.ps1 :: saves the Total Commander license key from the registry as a local file (in four formats).
tckey_registry_remove.ps1 :: removes the Total Commander license key from the registry.
History
[+] An option to add the license key into the registry directly from within the script body if the key is put there in the form of hex string (exactly as it is seen in the registry, e.g. 00,0a,64...).
2024-12-28 v0.3
[+] A message to inform a user of where the license has been retrieved from (a keyfile, and which one; an archive, and which one; an inline byte array, and which one).
2024-12-19 v0.1 script goes public.