Functions/GenXdev.FileSystem/PSGenXdevCmdlet.Preferences.cs

// ################################################################################
// Part of PowerShell module : GenXdev.FileSystem
// Original cmdlet filename : PSGenXdevCmdlet.Preferences.cs
// Original author : René Vaessen / GenXdev
// Version : 1.302.2025
// ################################################################################
// Copyright (c) René Vaessen / GenXdev
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ################################################################################
 
 
 
using System.Collections;
using System.Collections.Concurrent;
using System.Management.Automation;
using Microsoft.PowerShell.Commands;
 
public abstract partial class PSGenXdevCmdlet : PSCmdlet
{
    protected string GetGenXdevPreference(string Name, string DefaultValue, string PreferencesDatabasePath, bool SessionOnly, bool ClearSession, bool SkipSession)
    {
        string globalVariableName = "GenXdevPreference_" + Name;
 
        if (ClearSession)
        {
            if (ShouldProcess("GenXdev.Data Module Configuration", "Clear session preference setting (Global variable)"))
            {
                // Use parameterized script to avoid escaping issues
                var clearVarScript = ScriptBlock.Create("param($VarName) Microsoft.PowerShell.Utility\\Set-Variable -Name $VarName -Value $null -Scope Global -Force");
                clearVarScript.Invoke(globalVariableName);
 
                WriteVerbose("Cleared session preference setting: " + globalVariableName);
            }
        }
 
        if (!SkipSession)
        {
            WriteVerbose("Checking session storage for preference '" + Name + "'");
 
            // Get global variable using Get-Variable cmdlet
            var getVarScript = ScriptBlock.Create("param($VarName) Microsoft.PowerShell.Utility\\Get-Variable -Name $VarName -Scope Global -ValueOnly -ErrorAction SilentlyContinue");
            var globalResult = getVarScript.Invoke(globalVariableName);
 
            if (globalResult.Count > 0 && globalResult[0] != null && !string.IsNullOrWhiteSpace(globalResult[0].ToString()))
            {
                string value = globalResult[0].ToString();
                WriteVerbose("Returning session value: " + value);
                return value;
            }
        }
 
        if (SessionOnly)
        {
            WriteVerbose("Using provided default value: " + DefaultValue);
            return DefaultValue;
        }
 
        var preferencesDatabasePath = GetPreferencesDatabasePath(PreferencesDatabasePath, SessionOnly, ClearSession, SkipSession);
 
        WriteVerbose("Using database path: " + preferencesDatabasePath);
 
        try
        {
            WriteVerbose("Checking local store for preference '" + Name + "'");
 
            string value = GetValueByKeyFromStore("GenXdev.PowerShell.Preferences", Name, null, "Local", preferencesDatabasePath)?.ToString();
 
            if (string.IsNullOrEmpty(value))
            {
                WriteVerbose("Preference not found locally, checking defaults store");
                value = GetValueByKeyFromStore("GenXdev.PowerShell.Preferences", Name, null, "Defaults", preferencesDatabasePath)?.ToString();
            }
 
            if (!string.IsNullOrEmpty(value))
            {
                WriteVerbose("Returning persistent value: " + value);
                return value;
            }
        }
        catch (Exception ex)
        {
            WriteVerbose("Error accessing preference stores: " + ex.Message);
        }
 
        WriteVerbose("Using provided default value: " + DefaultValue);
        return DefaultValue;
    }
 
    protected void SetGenXdevPreference(string Name, string Value, string PreferencesDatabasePath, bool SessionOnly, bool ClearSession, bool SkipSession)
    {
        string globalVariableName = "GenXdevPreference_" + Name;
 
        if (ClearSession)
        {
            if (ShouldProcess(Name, "Clear session variable"))
            {
                // Use parameterized script to avoid escaping issues
                var removeVarScript = ScriptBlock.Create("param($VarName) Microsoft.PowerShell.Utility\\Remove-Variable -Name $VarName -Scope Global -ErrorAction SilentlyContinue");
                removeVarScript.Invoke(globalVariableName);
            }
            return;
        }
 
        if (SessionOnly)
        {
            if (ShouldProcess(Name, "Set session-only preference"))
            {
                // Use parameterized script to avoid escaping issues
                var setVarScript = ScriptBlock.Create("param($VarName, $VarValue) Microsoft.PowerShell.Utility\\Set-Variable -Name $VarName -Value $VarValue -Scope Global -Force");
                setVarScript.Invoke(globalVariableName, Value);
 
                WriteVerbose("Set session-only preference: " + globalVariableName + " = " + Value);
            }
            return;
        }
 
        PreferencesDatabasePath = GetPreferencesDatabasePath(PreferencesDatabasePath, SessionOnly, ClearSession, SkipSession);
 
        WriteVerbose("Using database path: " + PreferencesDatabasePath);
 
        if (string.IsNullOrWhiteSpace(Value))
        {
            if (ShouldProcess(Name, "Remove preference from persistent storage"))
            {
                RemoveGenXdevPreference(Name, false, PreferencesDatabasePath, SessionOnly, ClearSession, true);
                WriteVerbose("Successfully removed preference '" + Name + "'");
            }
            return;
        }
 
        if (ShouldProcess(Name, "Set preference"))
        {
            SetValueByKeyInStore("GenXdev.PowerShell.Preferences", Name, Value, "Local", PreferencesDatabasePath);
            WriteVerbose("Successfully configured preference '" + Name + "' in GenXdev.Data module: [" + Value + "]");
        }
    }
 
    protected void RemoveGenXdevPreference(string Name, bool RemoveDefault, string PreferencesDatabasePath, bool SessionOnly, bool ClearSession, bool SkipSession)
    {
        string globalVariableName = "GenXdevPreference_" + Name;
 
        PreferencesDatabasePath = GetPreferencesDatabasePath(PreferencesDatabasePath, SessionOnly, ClearSession, SkipSession);
 
        WriteVerbose("Using database path: " + PreferencesDatabasePath);
        WriteVerbose("Starting preference removal for: " + Name);
 
        if (ClearSession)
        {
            if (ShouldProcess(Name, "Clear session variable"))
            {
                // Use parameterized script to avoid escaping issues
                var removeVarScript = ScriptBlock.Create("param($VarName) Microsoft.PowerShell.Utility\\Remove-Variable -Name $VarName -Scope Global -ErrorAction SilentlyContinue");
                removeVarScript.Invoke(globalVariableName);
            }
        }
 
        if (SessionOnly)
        {
            if (ShouldProcess(Name, "Remove session-only preference"))
            {
                // Use parameterized script to avoid escaping issues
                var removeVarScript = ScriptBlock.Create("param($VarName) Microsoft.PowerShell.Utility\\Remove-Variable -Name $VarName -Scope Global -ErrorAction SilentlyContinue");
                removeVarScript.Invoke(globalVariableName);
            }
            return;
        }
 
        if (ShouldProcess(Name, "Remove preference"))
        {
            if (!SkipSession)
            {
                // Use parameterized script to avoid escaping issues
                var removeVarScript = ScriptBlock.Create("param($VarName) Microsoft.PowerShell.Utility\\Remove-Variable -Name $VarName -Scope Global -ErrorAction SilentlyContinue");
                removeVarScript.Invoke(globalVariableName);
            }
 
            WriteVerbose("Removing preference " + Name + " from local store");
            RemoveKeyFromStore("GenXdev.PowerShell.Preferences", Name, "Local", PreferencesDatabasePath);
 
            if (RemoveDefault)
            {
                WriteVerbose("Removing preference " + Name + " from default store");
                RemoveKeyFromStore("GenXdev.PowerShell.Preferences", Name, "Defaults", PreferencesDatabasePath);
                SyncKeyValueStore("Defaults", PreferencesDatabasePath);
            }
        }
    }
 
    protected string GetPreferencesDatabasePath(string PreferencesDatabasePath, bool SessionOnly, bool ClearSession, bool SkipSession)
    {
        if (ClearSession)
        {
            if (ShouldProcess("GenXdev.Data Module Configuration", "Clear session database path setting (Global variable)"))
            {
                // Use parameterized script to avoid escaping issues
                var clearVarScript = ScriptBlock.Create("Microsoft.PowerShell.Utility\\Set-Variable -Name 'PreferencesDatabasePath' -Value $null -Scope Global -Force");
                clearVarScript.Invoke();
 
                WriteVerbose("Cleared session database path setting: PreferencesDatabasePath");
            }
        }
 
        string resolvedDatabasePath = null;
 
        if (!string.IsNullOrWhiteSpace(PreferencesDatabasePath))
        {
            // Remove .db extension if present using native string operation
            string cleanPath = PreferencesDatabasePath.EndsWith(".db", StringComparison.OrdinalIgnoreCase)
                ? PreferencesDatabasePath.Substring(0, PreferencesDatabasePath.Length - 3)
                : PreferencesDatabasePath;
 
            resolvedDatabasePath = ExpandPath(cleanPath, true);
            WriteVerbose("Using provided database path: " + resolvedDatabasePath);
            return resolvedDatabasePath;
        }
 
        if (!SkipSession)
        {
            // Get global variable using Get-Variable cmdlet
            var getVarScript = ScriptBlock.Create("Microsoft.PowerShell.Utility\\Get-Variable -Name 'PreferencesDatabasePath' -Scope Global -ValueOnly -ErrorAction SilentlyContinue");
            var globalResult = getVarScript.Invoke();
 
            if (globalResult.Count > 0 && globalResult[0] != null && !string.IsNullOrWhiteSpace(globalResult[0].ToString()))
            {
                resolvedDatabasePath = ExpandPath(globalResult[0].ToString(), true);
                WriteVerbose("Using session database path: " + resolvedDatabasePath);
                return resolvedDatabasePath;
            }
        }
 
        if (!SessionOnly)
        {
            string defaultPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "GenXdev", "Preferences");
            resolvedDatabasePath = ExpandPath(defaultPath, true);
            WriteVerbose("Using default database path: " + resolvedDatabasePath);
            return resolvedDatabasePath;
        }
 
        string fallbackPath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "GenXdev", "Preferences");
        resolvedDatabasePath = ExpandPath(fallbackPath, true);
        WriteVerbose("Using fallback database path: " + resolvedDatabasePath);
        return resolvedDatabasePath;
    }
 
    protected void SetPreferencesDatabasePath(string PreferencesDatabasePath, bool SkipSession, bool SessionOnly, bool ClearSession)
    {
        if (ClearSession)
        {
            if (ShouldProcess("GenXdev.Data Module Configuration", "Clear session database path setting (Global variable)"))
            {
                // Use parameterized script to avoid escaping issues
                var clearVarScript = ScriptBlock.Create("Microsoft.PowerShell.Utility\\Set-Variable -Name 'PreferencesDatabasePath' -Value $null -Scope Global -Force");
                clearVarScript.Invoke();
 
                WriteVerbose("Cleared session database path setting: PreferencesDatabasePath");
            }
            return;
        }
 
        if (string.IsNullOrWhiteSpace(PreferencesDatabasePath))
        {
            throw new ArgumentException("PreferencesDatabasePath parameter is required when not using -ClearSession");
        }
 
        PreferencesDatabasePath = ExpandPath(PreferencesDatabasePath, true);
        WriteVerbose("Setting database path for GenXdev.Data module: [" + PreferencesDatabasePath + "]");
 
        if (ShouldProcess("GenXdev.Data Module Configuration", "Set database path to: [" + PreferencesDatabasePath + "]"))
        {
            // Use parameterized script to avoid escaping issues
            var setVarScript = ScriptBlock.Create("param($PathValue) Microsoft.PowerShell.Utility\\Set-Variable -Name 'PreferencesDatabasePath' -Value $PathValue -Scope Global -Force");
            setVarScript.Invoke(PreferencesDatabasePath);
 
            WriteVerbose("Set database path: PreferencesDatabasePath = " + PreferencesDatabasePath);
        }
    }
 
    protected void SetGenXdevDefaultPreference(string Name, string Value, string PreferencesDatabasePath, bool SessionOnly, bool ClearSession, bool SkipSession)
    {
        PreferencesDatabasePath = GetPreferencesDatabasePath(PreferencesDatabasePath, SessionOnly, ClearSession, SkipSession);
 
        WriteVerbose("Using database path: " + PreferencesDatabasePath);
        WriteVerbose("Starting Set-GenXdevDefaultPreference for '" + Name + "'");
 
        if (string.IsNullOrWhiteSpace(Value))
        {
            WriteVerbose("Removing default preference '" + Name + "' as value is empty");
 
            if (ShouldProcess(Name, "Remove default preference"))
            {
                RemoveGenXdevPreference(Name, true, PreferencesDatabasePath, SessionOnly, ClearSession, SkipSession);
            }
            return;
        }
 
        WriteVerbose("Setting default preference '" + Name + "' to: " + Value);
 
        if (ShouldProcess(Name, "Set default preference"))
        {
            SetValueByKeyInStore("GenXdev.PowerShell.Preferences", Name, Value, "Defaults", PreferencesDatabasePath);
            SyncKeyValueStore("Defaults", PreferencesDatabasePath);
            WriteVerbose("Successfully stored and synchronized preference '" + Name + "'");
        }
    }
 
    protected string[] GetGenXdevPreferenceNames(string PreferencesDatabasePath, bool SessionOnly, bool ClearSession, bool SkipSession)
    {
        var allKeys = new System.Collections.Generic.List<string>();
 
        if (ClearSession)
        {
            if (ShouldProcess("GenXdev.Data Module Configuration", "Clear session preference variables"))
            {
                // Use wildcard pattern for removing multiple variables
                var clearScript = ScriptBlock.Create("Microsoft.PowerShell.Utility\\Get-Variable -Name 'GenXdevPreference_*' -Scope Global -ErrorAction SilentlyContinue | Microsoft.PowerShell.Utility\\Remove-Variable -Force");
                clearScript.Invoke();
 
                WriteVerbose("Cleared session preference variables");
            }
        }
 
        if (!SkipSession)
        {
            WriteVerbose("Retrieving session variables for preference names");
 
            // Get variable names directly from Get-Variable
            var sessionVarsScript = ScriptBlock.Create("Microsoft.PowerShell.Utility\\Get-Variable -Name 'GenXdevPreference_*' -Scope Global -ErrorAction SilentlyContinue | Microsoft.PowerShell.Utility\\Select-Object -ExpandProperty Name");
            var sessionVars = sessionVarsScript.Invoke();
 
            var sessionKeys = new System.Collections.Generic.List<string>();
            foreach (var pvar in sessionVars)
            {
                string varName = pvar?.ToString();
                if (!string.IsNullOrEmpty(varName) && varName.StartsWith("GenXdevPreference_"))
                {
                    // Extract the preference name after the prefix
                    string key = varName.Substring("GenXdevPreference_".Length);
                    sessionKeys.Add(key);
                }
            }
 
            if (sessionKeys.Count > 0)
            {
                WriteVerbose("Found " + sessionKeys.Count + " preference names in session storage");
                allKeys.AddRange(sessionKeys);
            }
        }
 
        if (!SessionOnly)
        {
            WriteVerbose("Retrieving preference names from database stores");
            PreferencesDatabasePath = GetPreferencesDatabasePath(PreferencesDatabasePath, SessionOnly, ClearSession, SkipSession);
 
            WriteVerbose("Retrieving keys from local preferences store");
            var localKeys = GetStoreKeys("GenXdev.PowerShell.Preferences", "Local", PreferencesDatabasePath);
            if (localKeys != null && localKeys.Length > 0)
            {
                allKeys.AddRange(localKeys);
            }
 
            WriteVerbose("Retrieving keys from default preferences store");
            var defaultKeys = GetStoreKeys("GenXdev.PowerShell.Preferences", "Defaults", PreferencesDatabasePath);
            if (defaultKeys != null && defaultKeys.Length > 0)
            {
                allKeys.AddRange(defaultKeys);
            }
        }
 
        WriteVerbose("Merging and deduplicating keys from all sources");
        var uniqueKeys = allKeys.Distinct().OrderBy(key => key).ToArray();
        WriteVerbose("Found " + uniqueKeys.Length + " unique preference names");
 
        return uniqueKeys;
    }
}