bin/projects/dbatools/dbatools/TabExpansion/TabExpansionHost.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
using System;
using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Threading; namespace Sqlcollaborative.Dbatools.TabExpansion { /// <summary> /// Class that handles the static fields supporting the dbatools TabExpansion implementation /// </summary> public static class TabExpansionHost { #region State information /// <summary> /// Field containing the scripts that were registered. /// </summary> public static ConcurrentDictionary<string, ScriptContainer> Scripts = new ConcurrentDictionary<string, ScriptContainer>(); /// <summary> /// The cache used by scripts utilizing TabExpansionPlusPlus in dbatools /// </summary> public static Hashtable Cache = new Hashtable(); /// <summary> /// List of instances and when they were last accessed /// </summary> public static ConcurrentDictionary<string, InstanceAccess> InstanceAccess = new ConcurrentDictionary<string, InstanceAccess>(); /// <summary> /// Scripts that build the cache and are suitable for synchronous execution /// </summary> public static List<ScriptBlock> TeppGatherScriptsFast = new List<ScriptBlock>(); /// <summary> /// Scripts that build the cache and are not suitable for synchronous execution /// </summary> public static List<ScriptBlock> TeppGatherScriptsSlow = new List<ScriptBlock>(); /// <summary> /// A list of all commands imported into dbatools /// </summary> public static List<FunctionInfo> DbatoolsCommands = new List<FunctionInfo>(); /// <summary> /// List of completion sets that should be processed into Tepp Assignments. Only populate this list on first import. /// </summary> public static List<TabCompletionSet> TabCompletionSets = new List<TabCompletionSet>(); /// <summary> /// Maps a TEPP scriptblock to a command and parameter /// </summary> public static Dictionary<string, Dictionary<string, ScriptContainer>> TeppAssignment = new Dictionary<string, Dictionary<string, ScriptContainer>>(); #endregion State information #region Utility methods /// <summary> /// Registers a new instance or updates an already existing one. Should only be called from Connect-SqlInstance and Connect-DbaSqlServer /// </summary> /// <param name="InstanceName">Name of the instance connected to</param> /// <param name="Connection">To connection object containing the relevant information for accessing the instance</param> /// <param name="IsSysAdmin">Whether the account connecting to the instnace has SA privileges</param> public static void SetInstance(string InstanceName, object Connection, bool IsSysAdmin) { string tempName = InstanceName.ToLower(); if (!InstanceAccess.ContainsKey(tempName)) { InstanceAccess tempAccess = new InstanceAccess(); tempAccess.InstanceName = tempName; tempAccess.LastAccess = DateTime.Now; tempAccess.ConnectionObject = Connection; tempAccess.IsSysAdmin = IsSysAdmin; InstanceAccess[tempName] = tempAccess; } else { InstanceAccess[tempName].LastAccess = DateTime.Now; if (IsSysAdmin & !InstanceAccess[tempName].IsSysAdmin) { InstanceAccess[tempName].ConnectionObject = Connection; InstanceAccess[tempName].IsSysAdmin = IsSysAdmin; } } } /// <summary> /// Returns the assigned scriptblock for a given parameter /// </summary> /// <param name="Command">The command that should be completed</param> /// <param name="Parameter">The parameter completion is provided for</param> /// <returns>Either the relevant script container or null</returns> public static ScriptContainer GetTeppScript(string Command, string Parameter) { if (TeppAssignment.ContainsKey(Command) && TeppAssignment[Command].ContainsKey(Parameter)) return TeppAssignment[Command][Parameter]; return null; } /// <summary> /// Assigns a registered script to the parameter of a command /// </summary> /// <param name="Command">The command for which to complete</param> /// <param name="Parameter">The parameter for which to complete</param> /// <param name="Script">To name of the script with which to complete</param> public static void SetTeppScript(string Command, string Parameter, string Script) { if (!Scripts.ContainsKey(Script)) return; if (!TeppAssignment.ContainsKey(Command)) TeppAssignment[Command] = new Dictionary<string, ScriptContainer>(); TeppAssignment[Command][Parameter] = Scripts[Script]; } /// <summary> /// Adds a completion set to the list of items to process /// </summary> /// <param name="Command">The command to complete for (accepts wildcard matching)</param> /// <param name="Parameter">The parameter to complete for (accepts wildcard matching)</param> /// <param name="Script">The script to register</param> public static void AddTabCompletionSet(string Command, string Parameter, string Script) { // Only import on the first import if (!dbaSystem.SystemHost.ModuleImported) TabCompletionSets.Add(new TabCompletionSet(Command, Parameter, Script)); } /// <summary> /// Processes the content of TabCompletionSets and Scripts into TappAssignments based on the DbatoolsCommands list. /// </summary> public static void CalculateTabExpansion() { foreach (FunctionInfo info in DbatoolsCommands) foreach (ParameterMetadata paramInfo in info.Parameters.Values) foreach (TabCompletionSet set in TabCompletionSets) if (set.Applies(info.Name, paramInfo.Name)) SetTeppScript(info.Name, paramInfo.Name, set.Script); } #endregion Utility methods #region Configuration /// <summary> /// Whether TEPP in its entirety is disabled /// </summary> public static bool TeppDisabled = false; /// <summary> /// Whether asynchronous TEPP updating should be disabled /// </summary> public static bool TeppAsyncDisabled = false; /// <summary> /// Whether synchronous TEPP updating should be disabled /// </summary> public static bool TeppSyncDisabled = true; /// <summary> /// The interval in which asynchronous TEPP cache updates are performed /// </summary> public static TimeSpan TeppUpdateInterval = new TimeSpan(0, 3, 0); /// <summary> /// After this timespan of no requests to a server, the updates to its cache are disabled. /// </summary> public static TimeSpan TeppUpdateTimeout = new TimeSpan(0, 0, 30); #endregion Configuration } } |