MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.ObjectModel;6using System.Management.Automation;7using System.Management.Automation.Provider;8 9using Dbg = System.Management.Automation;10 11namespace Microsoft.PowerShell.Commands12{13 /// <summary>14 /// This provider is the data accessor for shell functions. It uses15 /// the SessionStateProviderBase as the base class to produce a view on16 /// session state data.17 /// </summary>18 [CmdletProvider(FunctionProvider.ProviderName, ProviderCapabilities.ShouldProcess)]19 [OutputType(typeof(FunctionInfo), ProviderCmdlet = ProviderCmdlet.SetItem)]20 [OutputType(typeof(FunctionInfo), ProviderCmdlet = ProviderCmdlet.RenameItem)]21 [OutputType(typeof(FunctionInfo), ProviderCmdlet = ProviderCmdlet.CopyItem)]22 [OutputType(typeof(FunctionInfo), ProviderCmdlet = ProviderCmdlet.GetChildItem)]23 [OutputType(typeof(FunctionInfo), ProviderCmdlet = ProviderCmdlet.GetItem)]24 [OutputType(typeof(FunctionInfo), ProviderCmdlet = ProviderCmdlet.NewItem)]25 public sealed class FunctionProvider : SessionStateProviderBase26 {27 /// <summary>28 /// Gets the name of the provider.29 /// </summary>30 public const string ProviderName = "Function";31 32 #region Constructor33 34 /// <summary>35 /// The constructor for the provider that exposes variables to the user36 /// as drives.37 /// </summary>38 public FunctionProvider()39 {40 }41 42 #endregion Constructor43 44 #region DriveCmdletProvider overrides45 46 /// <summary>47 /// Initializes the function drive.48 /// </summary>49 /// <returns>50 /// An array of a single PSDriveInfo object representing the functions drive.51 /// </returns>52 protected override Collection<PSDriveInfo> InitializeDefaultDrives()53 {54 string description = SessionStateStrings.FunctionDriveDescription;55 56 PSDriveInfo functionDrive =57 new PSDriveInfo(58 DriveNames.FunctionDrive,59 ProviderInfo,60 string.Empty,61 description,62 null);63 64 Collection<PSDriveInfo> drives = new Collection<PSDriveInfo>();65 drives.Add(functionDrive);66 return drives;67 }68 69 #endregion DriveCmdletProvider overrides70 71 #region Dynamic Parameters72 73 /// <summary>74 /// Gets the dynamic parameters for the NewItem cmdlet.75 /// </summary>76 /// <param name="path">77 /// Ignored.78 /// </param>79 /// <param name="type">80 /// Ignored.81 /// </param>82 /// <param name="newItemValue">83 /// Ignored.84 /// </param>85 /// <returns>86 /// An instance of FunctionProviderDynamicParameters which is the dynamic parameters for87 /// NewItem.88 /// </returns>89 protected override object NewItemDynamicParameters(string path, string type, object newItemValue)90 {91 return new FunctionProviderDynamicParameters();92 }93 94 /// <summary>95 /// Gets the dynamic parameters for the NewItem cmdlet.96 /// </summary>97 /// <param name="path">98 /// Ignored.99 /// </param>100 /// <param name="value">101 /// Ignored.102 /// </param>103 /// <returns>104 /// An instance of FunctionProviderDynamicParameters which is the dynamic parameters for105 /// SetItem.106 /// </returns>107 protected override object SetItemDynamicParameters(string path, object value)108 {109 return new FunctionProviderDynamicParameters();110 }111 112 #endregion Dynamic Parameters113 114 #region protected members115 116 /// <summary>117 /// Gets a function from session state.118 /// </summary>119 /// <param name="name">120 /// The name of the function to retrieve.121 /// </param>122 /// <returns>123 /// A ScriptBlock that represents the function.124 /// </returns>125 internal override object GetSessionStateItem(string name)126 {127 Dbg.Diagnostics.Assert(128 !string.IsNullOrEmpty(name),129 "The caller should verify this parameter");130 131 CommandInfo function = SessionState.Internal.GetFunction(name, Context.Origin);132 133 return function;134 }135 136 /// <summary>137 /// Sets the function of the specified name to the specified value.138 /// </summary>139 /// <param name="name">140 /// The name of the function to set.141 /// </param>142 /// <param name="value">143 /// The new value for the function.144 /// </param>145 /// <param name="writeItem">146 /// If true, the item that was set should be written to WriteItemObject.147 /// </param>148#pragma warning disable 0162149 internal override void SetSessionStateItem(string name, object value, bool writeItem)150 {151 Dbg.Diagnostics.Assert(152 !string.IsNullOrEmpty(name),153 "The caller should verify this parameter");154 155 FunctionProviderDynamicParameters dynamicParameters =156 DynamicParameters as FunctionProviderDynamicParameters;157 158 CommandInfo modifiedItem = null;159 160 bool dynamicParametersSpecified = dynamicParameters != null && dynamicParameters.OptionsSet;161 162 if (value == null)163 {164 // If the value wasn't specified but the options were, just set the165 // options on the existing function.166 // If the options weren't specified, then remove the function167 168 if (dynamicParametersSpecified)169 {170 modifiedItem = (CommandInfo)GetSessionStateItem(name);171 172 if (modifiedItem != null)173 {174 SetOptions(modifiedItem, dynamicParameters.Options);175 }176 }177 else178 {179 RemoveSessionStateItem(name);180 }181 }182 else183 {184 do // false loop185 {186 // Unwrap the PSObject before binding it as a scriptblock...187 PSObject pso = value as PSObject;188 if (pso != null)189 {190 value = pso.BaseObject;191 }192 193 ScriptBlock scriptBlockValue = value as ScriptBlock;194 if (scriptBlockValue != null)195 {196 if (dynamicParametersSpecified)197 {198 modifiedItem = SessionState.Internal.SetFunction(name, scriptBlockValue,199 null, dynamicParameters.Options, Force, Context.Origin);200 }201 else202 {203 modifiedItem = SessionState.Internal.SetFunction(name, scriptBlockValue, null, Force, Context.Origin);204 }205 206 break;207 }208 209 FunctionInfo function = value as FunctionInfo;210 if (function != null)211 {212 ScopedItemOptions options = function.Options;213 214 if (dynamicParametersSpecified)215 {216 options = dynamicParameters.Options;217 }218 219 modifiedItem = SessionState.Internal.SetFunction(name, function.ScriptBlock, function, options, Force, Context.Origin);220 break;221 }222 223 string stringValue = value as string;224 if (stringValue != null)225 {226 ScriptBlock scriptBlock = ScriptBlock.Create(Context.ExecutionContext, stringValue);227 228 if (dynamicParametersSpecified)229 {230 modifiedItem = SessionState.Internal.SetFunction(name, scriptBlock, null, dynamicParameters.Options, Force, Context.Origin);231 }232 else233 {234 modifiedItem = SessionState.Internal.SetFunction(name, scriptBlock, null, Force, Context.Origin);235 }236 237 break;238 }239 240 throw PSTraceSource.NewArgumentException(nameof(value));241 } while (false);242 243 if (writeItem && modifiedItem != null)244 {245 WriteItemObject(modifiedItem, modifiedItem.Name, false);246 }247 }248 }249#pragma warning restore 0162250 251 private static void SetOptions(CommandInfo function, ScopedItemOptions options)252 {253 ((FunctionInfo)function).Options = options;254 }255 256 /// <summary>257 /// Removes the specified function from session state.258 /// </summary>259 /// <param name="name">260 /// The name of the function to remove from session state.261 /// </param>262 internal override void RemoveSessionStateItem(string name)263 {264 Dbg.Diagnostics.Assert(265 !string.IsNullOrEmpty(name),266 "The caller should verify this parameter");267 268 SessionState.Internal.RemoveFunction(name, Force);269 }270 271 /// <summary>272 /// Since items are often more than their value, this method should273 /// be overridden to provide the value for an item.274 /// </summary>275 /// <param name="item">276 /// The item to extract the value from.277 /// </param>278 /// <returns>279 /// The value of the specified item.280 /// </returns>281 /// <remarks>282 /// The default implementation will get283 /// the Value property of a DictionaryEntry284 /// </remarks>285 internal override object GetValueOfItem(object item)286 {287 Dbg.Diagnostics.Assert(288 item != null,289 "Caller should verify the item parameter");290 291 object value = item;292 293 FunctionInfo function = item as FunctionInfo;294 if (function != null)295 {296 value = function.ScriptBlock;297 }298 299 return value;300 }301 302 /// <summary>303 /// Gets a flattened view of the functions in session state.304 /// </summary>305 /// <returns>306 /// An IDictionary representing the flattened view of the functions in307 /// session state.308 /// </returns>309 internal override IDictionary GetSessionStateTable()310 {311 return (IDictionary)SessionState.Internal.GetFunctionTable();312 }313 314 /// <summary>315 /// Determines if the item can be renamed. Derived classes that need316 /// to perform a check should override this method.317 /// </summary>318 /// <param name="item">319 /// The item to verify if it can be renamed.320 /// </param>321 /// <returns>322 /// true if the item can be renamed or false otherwise.323 /// </returns>324 internal override bool CanRenameItem(object item)325 {326 bool result = false;327 328 FunctionInfo functionInfo = item as FunctionInfo;329 if (functionInfo != null)330 {331 if ((functionInfo.Options & ScopedItemOptions.Constant) != 0 ||332 ((functionInfo.Options & ScopedItemOptions.ReadOnly) != 0 && !Force))333 {334 SessionStateUnauthorizedAccessException e =335 new SessionStateUnauthorizedAccessException(336 functionInfo.Name,337 SessionStateCategory.Function,338 "CannotRenameFunction",339 SessionStateStrings.CannotRenameFunction);340 341 throw e;342 }343 344 result = true;345 }346 347 return result;348 }349 350 #endregion protected members351 }352 353 /// <summary>354 /// The dynamic parameter object for the FunctionProvider SetItem and NewItem commands.355 /// </summary>356 public class FunctionProviderDynamicParameters357 {358 /// <summary>359 /// Gets or sets the option parameter for the function.360 /// </summary>361 [Parameter]362 public ScopedItemOptions Options363 {364 get365 {366 return _options;367 }368 369 set370 {371 _optionsSet = true;372 _options = value;373 }374 }375 376 private ScopedItemOptions _options = ScopedItemOptions.None;377 378 /// <summary>379 /// Determines if the Options parameter was set.380 /// </summary>381 /// <value></value>382 internal bool OptionsSet383 {384 get { return _optionsSet; }385 }386 387 private bool _optionsSet;388 }389}390 