Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # "7Scan.ps1" - Copyright Tim Keal alias jargon 2025 03/14
- # This script scans for 7zip archives and lists file names matched by similarity threshold.
- # This script is for Powershell 7 ("pwsh.exe" not "Powershell.exe")
- # Locate 7-Zip dynamically if not in default location
- $SevenZipPath = (Get-Command 7z.exe -ErrorAction SilentlyContinue).Source
- if (-not $SevenZipPath) {
- $SevenZipPath = "C:\Program Files\7-Zip\7z.exe"
- }
- $debugMode = $false
- # Variable to control early exit
- $EarlyExit = 0
- $hits = @() # Initialize as an empty array instead of a hashtable
- $scannedArchives = @()
- $scannedFiles = @()
- function str_repeat {
- param (
- [string]$string,
- [int]$count
- )
- return ($string * $count) -join ''
- }
- function Convert-Type {
- param (
- [string]$typeString,
- [Parameter(Mandatory=$true)]
- [Object]$inputValue
- )
- # Extract type name if it's enclosed in brackets (e.g., "[int]" -> "int")
- if ($typeString -match "^\[(.+)\]$") {
- $typeString = $matches[1]
- }
- # Map common PowerShell type accelerators
- $typeMap = @{
- "int" = [int]
- "string" = [string]
- "bool" = [bool]
- "double" = [double]
- "datetime" = [datetime]
- "decimal" = [decimal]
- "guid" = [guid]
- "float" = [float]
- "char" = [char]
- "byte" = [byte]
- "sbyte" = [sbyte]
- "short" = [int16]
- "ushort" = [uint16]
- "uint" = [uint32]
- "long" = [int64]
- "ulong" = [uint64]
- }
- # Determine target type
- $targetType = $typeMap[$typeString] ?? [System.Type]::GetType("System.$typeString")
- if (-not $targetType) {
- throw "Invalid type string: $typeString"
- }
- # Attempt conversion using PowerShell's built-in conversion
- try {
- return [System.Management.Automation.LanguagePrimitives]::ConvertTo($inputValue, $targetType)
- } catch {
- throw "Failed to convert value '$inputValue' to type '$typeString'. Error: $_"
- }
- }
- function barLog {
- param (
- [string]$line
- )
- if ($line -cmatch "{{ ([a-z]+) bar }}") {
- switch ($matches[1]) {
- "single" { $line = str_repeat -string "-" -count 36 }
- "double" { $line = str_repeat -string "=" -count 36 }
- }
- }
- return $line
- }
- function writeLog {
- param (
- [string]$path = "",
- [string]$line = "{{ double bar }}",
- [string]$color = "Yellow",
- [string]$cast = "",
- [string]$append = 1
- )
- if ($path -eq "") { return }
- if ($line -eq "") { return }
- $line = barLog -line $line
- echoLog -line $line -color $color -cast $cast -path $path
- if ($cast -ne "") { $line = "$($cast): $($line)" }
- if ($append -eq 1) {
- Add-Content -Path $path -Value "$($line)`r`n"
- } else {
- Set-Content -Path $path -Value "$($line)`r`n"
- }
- }
- function debugLog {
- param (
- [string]$line = "",
- [string]$color = "Cyan",
- [string]$cast = "Debug",
- [string]$path = "",
- [string]$append = 0
- )
- if ($global:debugMode -eq $false) { return }
- $line = barLog -line $line
- $color = "Cyan"
- $cast = "Debug"
- echoLog -line $line -color $color -cast $cast -path $path -append $append
- }
- function echoLog {
- param (
- [string]$line = "",
- [string]$color = "Yellow",
- [string]$cast = "",
- [string]$path = "",
- [string]$append = 0
- )
- if ($line -eq "") { return }
- $line = barLog -line $line
- if ($color -eq "") { $color = "White" }
- if ($cast -ne "") { $line = "$($cast): $($line)" }
- Write-Host "$($line)" -ForegroundColor $color
- }
- # Function to safely load JSON files
- function Get-SafeJsonContent {
- param (
- [string]$FilePath
- )
- if (-not (Test-Path $FilePath -PathType Leaf)) {
- echoLog -line "Missing JSON file - $FilePath" -color "Yellow" -cast "Warning"
- return @() # Return empty array
- }
- try {
- return (Get-Content -Path $FilePath -Raw | ConvertFrom-Json)
- } catch {
- echoLog -line "Invalid JSON format in $($FilePath)" -color "Red" -cast "Error"
- return @()
- }
- }
- $cleanPatterns = (Get-SafeJsonContent "Setup\Patterns.json")
- # Validate 7-Zip installation
- if (-not (Test-Path $SevenZipPath -PathType Leaf)) {
- echoLog -line "7-Zip not found. Please install it or adjust the path." -color "Red" -cast "Error"
- Read-Host "Press Enter to exit"
- exit 1
- }
- echoLog -line "7-Zip found: $($SevenZipPath)" -color "Green" -cast ""
- function EarlyExit {
- # Check if a key is pressed
- if ([System.Console]::KeyAvailable) {
- $key = [System.Console]::ReadKey($true) # Read the key without displaying it
- if ($key.Key -eq "Escape") {
- $global:EarlyExit = 1
- }
- }
- return $global:EarlyExit
- }
- function archiveAbout {
- param (
- [object]$archiveNameOnly = ""
- )
- if ($archiveNameOnly -match $global:config.timestampPattern) {
- $timestamp = $matches[0]
- } else {
- $timestamp = "NO_TIMESTAMP"
- }
- $pattern = "^(.*?)[\-\s]+" + [regex]::Escape($timestamp)
- if ($archiveNameOnly -match $pattern) {
- $project = $matches[1]
- $project = $project -replace "-", " "
- } else {
- $project = "UNKNOWN_PROJECT"
- }
- $cleanedName = ($archiveNameOnly -replace $pattern, "" -replace "\s{2,}", " " -replace "^\s+|\s+$", "")
- $pattern = '.*\((.*?)\).*'
- if ($cleanedName -cmatch $pattern) {
- $cleanedName = $matches[1]
- }
- foreach ($p in $cleanPatterns) {
- $cleanedName = ($cleanedName -replace $p, " " -replace "\s{2,}", " " -replace "^\s+|\s+$", "")
- }
- foreach ($p in $global:config.titleCasePattern) {
- $cleanedName = ($cleanedName -replace $p, { Convert-UpperCaseSeries $_.Value })
- }
- $cleanedName = $cleanedName.Trim()
- $archiveNameOnly = $archiveNameOnly -replace "\\", "/"
- if ($archiveNameOnly -match "^(.+)\/([^\/]+)$") {
- $archivePathOnly = $matches[1]
- $archiveBaseOnly = $matches[2]
- } else {
- # echoLog -line "Regex did not match. Check `$archiveNameOnly." -color "Red" -cast "Debug"
- $archivePathOnly = ""
- $archiveBaseOnly = ""
- }
- # Return as an object
- return [PSCustomObject]@{
- archiveNameOnly = $archiveNameOnly
- archivePathOnly = $archivePathOnly
- archiveBaseOnly = $archiveBaseOnly
- cleanedName = $cleanedName
- project = $project
- timestamp = $timestamp
- }
- }
- function fileNameOnly {
- param (
- [string]$line
- )
- $fileNameOnly = ($line -replace '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\s+\S+\s+\d+\s+', '')
- if ($fileNameOnly -match '^\s*$' -or $line -match 'D\.\.\.\.') { return $False }
- if ( $fileNameOnly -match "^(.*(\\|\/)){0,}\.($($global:config.searchBlacklist))((\\|\/).*){0,}$" ) { return $False }
- $fileNameOnly = $fileNameOnly -replace "\\", "/"
- $FileFullName = $fileNameOnly
- if ($fileNameOnly -match '([^\\\/]+)$') {
- $fileNameOnly = $matches[1]
- }
- if ($fileNameOnly -match '^.*\.([^\.]+)$') {
- $fileExtOnly = $matches[1]
- }
- if ($fileNameOnly -match '^(.*)\.[^\.]+$') {
- $fileNameOnly = $matches[1]
- }
- # Return as an object
- return [PSCustomObject]@{
- FileFullName = $FileFullName
- FileNameOnly = $fileNameOnly
- FileExtOnly = $fileExtOnly
- }
- }
- function Convert-UpperCaseSeries {
- param (
- [string]$inputString
- )
- if ($inputString.Length -gt 1) {
- return $inputString.Substring(0,1) + $inputString.Substring(1).ToLower()
- }
- return $inputString
- }
- # Function to calculate Levenshtein Distance as a percentile
- function Get-LevenshteinSimilarity {
- param (
- [string]$source,
- [string]$target,
- [string]$flags = "ickd",
- [double]$percentileTolerance = 0.0 # Default to 0 (no early exit)
- # case (i)nsensitive
- # (c)ontains
- # (k)eywords
- # Levenshtein (d)istance
- )
- # case (i)nsensitive
- if($flags.Contains("i")) {
- $source = $source.ToLower()
- $target = $target.ToLower()
- }
- $sourceLength = $source.Length
- $targetLength = $target.Length
- if ($sourceLength -eq 0 -and $targetLength -eq 0) { return 100.000000 }
- if ($sourceLength -ne 0 -and $targetLength -eq 0) { return 0.000000 }
- # (c)ontains
- if($flags.Contains("c")) {
- if ($target.Contains($source)) { return 100.000000 }
- }
- # (k)eywords
- if($flags.Contains("k")) {
- # Split the source string into an array of keywords
- $keywords = $source -split '\s+'
- if ($keywords.Count -gt 0) {
- # Count the number of keywords that appear in the target string
- $count = ($keywords | Where-Object { $target -match "\b$_\b" }).Count
- if ($count -gt 0) {
- return $count / $keywords.Count * 100.000000
- }
- }
- }
- # Levenshtein (d)istance
- if($flags.Contains("d")) {
- $distanceMatrix = @()
- for ($i = 0; $i -le $sourceLength; $i++) {
- $distanceMatrix += ,(@(0) * ($targetLength + 1))
- }
- for ($i = 0; $i -le $sourceLength; $i++) { $distanceMatrix[$i][0] = $i }
- for ($j = 0; $j -le $targetLength; $j++) { $distanceMatrix[0][$j] = $j }
- for ($i = 1; $i -le $sourceLength; $i++) {
- for ($j = 1; $j -le $targetLength; $j++) {
- $cost = if ($source[$i - 1] -eq $target[$j - 1]) { 0 } else { 1 }
- $delete = $distanceMatrix[$i - 1][$j] + 1
- $insert = $distanceMatrix[$i][$j - 1] + 1
- $substitute = $distanceMatrix[$i - 1][$j - 1] + $cost
- $distanceMatrix[$i][$j] = [math]::Min([math]::Min($delete, $insert), $substitute)
- }
- # Early exit condition:
- $maxLength = [math]::Max($sourceLength, $targetLength)
- $currentDistance = $distanceMatrix[$i][$targetLength]
- $projectedSimilarity = ((1 - ($currentDistance / $maxLength)) * 100)
- if ($projectedSimilarity -lt $percentileTolerance) {
- return 0.000000
- }
- }
- $distance = $distanceMatrix[$sourceLength][$targetLength]
- $maxLength = [math]::Max($sourceLength, $targetLength)
- $similarity = ((1 - ($distance / $maxLength)) * 100)
- return [math]::Round($similarity, 8)
- }
- return 0.000000
- }
- # Function to scan inside .7z files that meet archive similarity criteria
- function Scan-Archives {
- param (
- [string]$archiveExt = "7z"
- )
- if ((EarlyExit) -eq 1) { return }
- # $basePath = Resolve-Path -Path $global:config.searchPath
- $basePath = $global:config.searchPath
- $basePath = $basePath -replace "\\", "/"
- if ($basePath -match "^(.+)[\\\/]([^\\\/]+)$") {
- $archivePathOnly = $matches[1]
- $archiveBaseOnly = $matches[2]
- } else {
- # echoLog -line "Regex did not match. Check `$archiveNameOnly." -color "Red" -cast "Debug"
- $archivePathOnly = ""
- $archiveBaseOnly = ""
- }
- echoLog -line "$($archiveBaseOnly)" -color "Yellow" -cast "Scanning"
- try {
- $archives = Get-ChildItem -Path $basePath -Filter "*.$($archiveExt)" -Recurse -File | ForEach-Object {
- $archive = $_
- if ((EarlyExit) -eq 1) {
- throw
- }
- if ($archive.FullName -match ".*(\/|\\)\.($($global:config.searchBlacklist))(\/|\\).*") {
- echoLog -line "$($archive.FullName)" -color "Red" -cast "Blacklisted"
- # Use 'return' to effectively 'continue' to the next item
- return
- }
- $archiveFullName = $archive.FullName
- $archiveFullName -match "^(.+)[\\\/]([^\\\/]+)$"
- $archivePathOnly = $matches[1]
- $archiveBaseOnly = $matches[2]
- echoLog -line "$($archiveBaseOnly)" -color "Yellow" -cast "Crawling"
- Scan-Archive -archive $archive.FullName
- }
- }
- catch {
- return
- }
- }
- function Scan-Archive {
- param (
- [string]$archive = ""
- )
- $global:scannedArchives += $archive
- if ((EarlyExit) -eq 1) { return }
- if ($archive -eq "") { return }
- $partsArchive = (archiveAbout -archive $archive)
- $archiveSimilarity = (Get-LevenshteinSimilarity -source $global:config.archiveTestString -target $partsArchive.cleanedName -flags $global:config.archiveFlags -percentileTolerance $global:config.archiveThreshold)
- $formattedArchiveSimilarity = $archiveSimilarity.ToString("000.00000000")
- $dumpName = "$($formattedArchiveSimilarity)% > $($partsArchive.archiveBaseOnly) > $($partsArchive.timestamp) > $($partsArchive.cleanedName)"
- if ($archiveSimilarity -lt $global:config.archiveThreshold) {
- echoLog -line "Did not meet or exceed archival tolerance of $($global:config.archiveThreshold)% -- is $($archiveSimilarity)% for $($partsArchive.archiveBaseOnly) > $($partsArchive.timestamp) > $($partsArchive.cleanedName)" -color "Red" -cast "Skipping"
- }
- echoLog -line "$($partsArchive.archiveBaseOnly)" -color "Yellow" -cast "Scanning"
- $output = (& $SevenZipPath l -ba "$($archive)" 2>$null)
- foreach ($line in $output) {
- if ((EarlyExit) -eq 1) { break }
- $partsFile = ( fileNameOnly -line $line )
- if ($partsFile -eq $False) { continue }
- if ($partsFile.fileExtOnly -notmatch "^(?:$($global:config.searchExtensions))$") {
- # echoLog -line "$($partsFile.fileExtOnly) > $($partsFile.fileNameOnly)" -color "Red" -cast "Skipping"
- continue
- }
- # echoLog -line "$($partsFile.fileExtOnly) > $($partsFile.fileNameOnly)" -color "Blue" -cast "Checking"
- $similarity = (Get-LevenshteinSimilarity -source $global:config.searchTerm -target $partsFile.fileNameOnly -flags $global:config.searchFlags -percentileTolerance $global:config.searchThreshold)
- $formattedSimilarity = $similarity.ToString("000.00000000")
- $matchString = "$($formattedSimilarity)% > $($partsArchive.archiveBaseOnly) > $($partsFile.fileExtOnly) > $($partsFile.fileNameOnly)"
- $global:scannedFiles += $partsFile.FileFullName
- if ($similarity -ge $global:config.searchThreshold) {
- $global:hits += "$($formattedSimilarity)% > $($partsArchive.archiveNameOnly) > $($partsFile.FileFullName)"
- # Ensure we are adding to an array
- echoLog -line "$($global:hits.Count) > $($matchString)" -color "Green" -cast "Found"
- }else{
- # echoLog -line "Did not meet or exceed filepath tolerance of $($global:config.searchThreshold)% -- is $($similarity)% for $($partsFile.archiveBaseOnly) > $($partsFile.fileExtOnly) > $($partsFile.fileNameOnly)" -color "Red" -cast "Failed"
- }
- }
- }
- function Json-Results {
- param (
- [array]$results
- )
- $arr = @() # Initialize as an array
- foreach ($result in $results) {
- $parts = $result -split " > "
- # Ensure we have enough parts to avoid index errors
- if ($parts.Count -ge 3) {
- $score = $parts[0] -replace "%", "" # Remove % symbol
- $obj = @{
- score = $score
- archive = $parts[1]
- file = $parts[2]
- }
- $arr += $obj # Append object to array
- }
- }
- # Convert the array to a JSON string
- $jsonString = $arr | ConvertTo-Json -Depth 1
- return $jsonString
- }
- function Save-Results {
- param (
- [array]$hits
- )
- $path = "Results/$($global:config.configFile)"
- if (-Not (Test-Path -Path $path)) {
- New-Item -Path $path -ItemType Directory | Out-Null
- }
- $ts = Get-Date -Format "$($global:config.timestampLayout)"
- $outputPrefix = "Results/$($global:config.configFile)/$($global:config.configFile) $($ts)"
- $outputFile = "$($outputPrefix).txt"
- $jsonOutputFile = "$($outputPrefix).json"
- $json = (Json-Results -results $hits)
- Set-Content -Path $jsonOutputFile -Value $json
- writeLog -path $outputFile -line "7Scan Archive Results" -color "White" -cast "" -append 0
- # Ensure the Results directory exists
- if (-not (Test-Path -Path "Results")) {
- New-Item -ItemType Directory -Path "Results" | Out-Null
- }
- # Ensure $hits is an array before sorting
- $sortedHits = $hits | Sort-Object {
- $similarity = 0
- if ($_ -match '^(\d+\.\d+)%') {
- $similarity = [double]$matches[1]
- }
- $similarity
- } -Descending
- $archivesCount = $global:scannedArchives.Count # Ensure proper counting
- $filesCount = $global:scannedFiles.Count # Ensure proper counting
- $hitCount = $sortedHits.Count # Ensure proper counting
- echoLog -line "$($hitCount) results to $($outputFile)" -color "Green" -cast "Saving"
- # Write to output file
- writeLog -path $outputFile -line "7Scan Archive Results" -color "White" -cast "" -append 0
- writeLog -path $outputFile -line "{{ single bar }}" -color "Green" -cast ""
- writeLog -path $outputFile -line "$($filesCount) files in $($archivesCount) archives" -color "White" -cast "Scanned"
- writeLog -path $outputFile -line "$($hits.Count)" -color "White" -cast "Hits"
- writeLog -path $outputFile -line "{{ single bar }}" -color "Blue" -cast ""
- # Dynamically write config settings
- foreach ($key in $global:config.Keys) {
- writeLog -path $outputFile -line "$($key): $($global:config[$key])" -color "White" -cast ""
- }
- writeLog -path $outputFile -line "{{ double bar }}" -color "Green" -cast ""
- writeLog -path $outputFile -line ($sortedHits -join "`r`n") -color "White" -cast ""
- writeLog -path $outputFile -line "{{ double bar }}" -color "Green" -cast ""
- writeLog -path $outputFile -line "$($hitCount) scanned results saved to $($outputFile)" -color "White" -cast ""
- }
- function Convert-Type {
- param (
- [string]$typeString,
- [string]$inputValue
- )
- switch ($typeString) {
- "int" { return [int]$inputValue }
- "bool" { return [bool]$inputValue }
- "float" { return [float]$inputValue }
- "string" { return [string]$inputValue }
- default { return $inputValue }
- }
- }
- function Ini-Config {
- param (
- [string]$configFile = "Default"
- )
- # Ensure the global config exists
- if (-not $global:config) {
- $global:config = @{}
- }
- # Assign configuration properties
- $global:config.configFile = $configFile
- $global:config.configPath = "Config/$($global:config.configFile) Config.json"
- # Debugging: Print config path before proceeding
- debugLog -line "Config path set to '$($global:config.configPath)'" -color "Cyan" -cast "Debug"
- # Check if the config file exists
- if (-Not (Test-Path $global:config.configPath)) {
- debugLog -line "Config file not found: $($global:config.configPath)" -color "Red" -cast "Error"
- return $false
- }
- return $true
- }
- function Load-Config {
- param (
- [bool]$PromptUser = $true
- )
- # Ensure the global config exists
- if (-not $global:config) {
- debugLog -line "Global config is not initialized!" -color "Red" -cast "Error"
- return $false
- }
- # Debugging: Print config before JSON loading
- debugLog -line "Checking configPath at start of Load-Config: '$($global:config.configPath)'" -color "Yellow" -cast "Debug"
- # Ensure the config path is set
- if (-not $global:config.configPath) {
- debugLog -line "Config path is not set properly at Load-Config start!" -color "Red" -cast "Error"
- return $false
- }
- # Debugging: Print config just before reading JSON
- debugLog -line "Attempting to load config from '$($global:config.configPath)'" -color "Yellow" -cast "Debug"
- # Check if the config file exists
- if (-Not (Test-Path $global:config.configPath)) {
- debugLog -line "Config file not found: $($global:config.configPath)" -color "Red" -cast "Error"
- return $false
- }
- try {
- # Read JSON file
- $rawJson = Get-Content -Path $global:config.configPath -Raw
- # Debugging: Print file contents
- debugLog -line "Raw JSON Data: $($rawJson)" -color "Cyan" -cast "Debug"
- if (-not $rawJson) {
- debugLog -line "Config file is empty or unreadable!" -color "Red" -cast "Error"
- return $false
- }
- $parsedJson = $rawJson | ConvertFrom-Json
- # Debugging: Print parsed JSON
- debugLog -line "Parsed JSON: $(($parsedJson | ConvertTo-Json -Compress))" -color "Cyan" -cast "Debug"
- if (-not $parsedJson) {
- debugLog -line "Error: Failed to parse JSON file!" -color "Red" -cast "Error"
- return $false
- }
- # Special case for configFile (allows reloading)
- if ($parsedJson.PSObject.Properties.Name -contains "configFile") {
- $entry = $parsedJson.configFile
- if ($entry -is [array] -and $entry.Count -ge 2) {
- $defaultValue = $entry[1]
- # Debugging: Print before modifying config path
- debugLog -line "Before modifying configPath: '$($global:config.configPath)'" -color "Cyan" -cast "Debug"
- # User input for config file selection
- if ($PromptUser) {
- $userInput = Read-Host "Choose a config file (default: '$($defaultValue)')"
- $global:config.configFile = if ($userInput) { $userInput } else { $defaultValue }
- } else {
- $global:config.configFile = $defaultValue
- }
- # ✅ Fix: Prevent overwriting configPath with an empty string
- if ($global:config.configFile -and $global:config.configFile -ne "") {
- $global:config.configPath = "Config/$($global:config.configFile) Config.json"
- debugLog -line "Updated configPath: '$($global:config.configPath)'" -color "Cyan" -cast "Debug"
- } else {
- debugLog -line "Warning: configFile is empty. Retaining previous configPath." -color "Yellow" -cast "Debug"
- }
- # Revalidate config file existence
- if (-not (Test-Path $global:config.configPath)) {
- debugLog -line "Updated config file not found: $global:config.configPath" -color "Red" -cast "Error"
- return $false
- }
- }
- }
- # Debugging: Final config path after loading JSON
- debugLog -line "Final config path in Load-Config: '$($global:config.configPath)'" -color "Green" -cast "Debug"
- return $true
- }
- catch {
- debugLog -line "Error parsing config file: $_" -color "Red" -cast "Error"
- return $false
- }
- }
- function Process-Config {
- param (
- [bool]$PromptUser = $true
- )
- # Ensure the global config exists
- if (-not $global:config) {
- echoLog -line "Global config is not initialized!" -color "Red" -cast "Error"
- return $false
- }
- # Ensure the config path is set
- if (-not $global:config.configPath) {
- echoLog -line "Config path is not set properly at Load-Config start!" -color "Red" -cast "Error"
- return $false
- }
- debugLog -line "Attempting to load config from '$($global:config.configPath)'" -color "Yellow" -cast "Debug"
- # Check if the config file exists
- if (-Not (Test-Path $global:config.configPath)) {
- echoLog -line "Config file not found: $($global:config.configPath)" -color "Red" -cast "Error"
- return $false
- }
- try {
- # Read JSON file
- $rawJson = Get-Content -Path $global:config.configPath -Raw
- if (-not $rawJson) {
- echoLog -line "Config file is empty or unreadable!" -color "Red" -cast "Error"
- return $false
- }
- # Convert JSON to object
- $parsedJson = $rawJson | ConvertFrom-Json
- if (-not $parsedJson) {
- echoLog -line "Error: Failed to parse JSON file!" -color "Red" -cast "Error"
- return $false
- }
- # Process configuration
- foreach ($key in $parsedJson.PSObject.Properties.Name) {
- $valueArray = $parsedJson.$key # Expecting: ["type", "default_value"]
- # Validate the expected structure
- if ($valueArray -isnot [System.Array] -or $valueArray.Count -ne 2) {
- echoLog -line "Skipping invalid config entry: $key" -color "Red" -cast "Error"
- continue
- }
- $type = $valueArray[0] # Expected type
- $defaultValue = $valueArray[1] # Default value
- # Skip `configFile` after reading it
- if ($key -eq "configFile") {
- $global:config[$key] = $defaultValue
- continue
- }
- # Prompt user if necessary
- if ($PromptUser) {
- $userInput = Read-Host "Enter value for '$key' (default: '$defaultValue')"
- $finalValue = if ($userInput) { $userInput } else { $defaultValue }
- } else {
- $finalValue = $defaultValue
- }
- # Ensure type safety
- switch ($type) {
- "double" {
- $global:config[$key] = [double]$finalValue
- }
- "int" {
- $global:config[$key] = [int]$finalValue
- }
- "string" {
- $global:config[$key] = [string]$finalValue
- }
- default {
- echoLog -line "Unknown type '$type' for '$key', storing as string." -color "Yellow" -cast "Warning"
- $global:config[$key] = [string]$finalValue
- }
- }
- }
- return $true
- }
- catch {
- echoLog -line "Error parsing config file: $_" -color "Red" -cast "Error"
- return $false
- }
- }
- $config = @{}
- # Main Execution
- if (Ini-Config -configFile "Default") {
- debugLog -line "Confirming config path before Load-Config: '$($config.configPath)'" -color "Cyan" -cast "Debug"
- # Debugging: Print entire global config
- debugLog -line "Global Config Dump BEFORE Load-Config: $(($config | ConvertTo-Json -Compress))" -color "Cyan" -cast "Debug"
- if (Load-Config -PromptUser $true) {
- if (Process-Config -PromptUser $true) {
- Scan-Archives
- }
- }
- }
- else {
- debugLog -line "Ini-Config failed! Check why config path is not being set." -color "Red" -cast "Error"
- }
- Save-Results -hits $hits
- Read-Host "Press Enter to exit"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement