MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Management.Automation.Internal;8using System.Management.Automation.Provider;9using System.Management.Automation.Runspaces;10 11using Dbg = System.Management.Automation;12 13#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings14#pragma warning disable 5650015 16namespace System.Management.Automation17{18 /// <summary>19 /// Holds the state of a Monad Shell session.20 /// </summary>21 internal sealed partial class SessionStateInternal22 {23 #region variables24 25 /// <summary>26 /// Add an new SessionStateVariable entry to this session state object...27 /// </summary>28 /// <param name="entry">The entry to add.</param>29 internal void AddSessionStateEntry(SessionStateVariableEntry entry)30 {31 PSVariable v = new PSVariable(entry.Name, entry.Value,32 entry.Options, entry.Attributes, entry.Description);33 v.Visibility = entry.Visibility;34 this.SetVariableAtScope(v, "global", true, CommandOrigin.Internal);35 }36 37 /// <summary>38 /// Get a variable out of session state. This interface supports39 /// the scope specifiers like "global:example"40 /// </summary>41 /// <param name="name">42 /// name of variable to look up43 /// </param>44 /// <param name="origin">45 /// Origin of the command making this request.46 /// </param>47 /// <returns>48 /// The specified variable.49 /// </returns>50 /// <exception cref="ArgumentNullException">51 /// If <paramref name="name"/> is null.52 /// </exception>53 internal PSVariable GetVariable(string name, CommandOrigin origin)54 {55 if (name == null)56 {57 throw PSTraceSource.NewArgumentNullException(nameof(name));58 }59 60 VariablePath variablePath = new VariablePath(name, VariablePathFlags.Variable | VariablePathFlags.Unqualified);61 SessionStateScope scope = null;62 63 PSVariable resultItem = GetVariableItem(variablePath, out scope, origin);64 65 return resultItem;66 }67 68 /// <summary>69 /// Get a variable out of session state. This interface supports70 /// the scope specifiers like "global:example"71 /// </summary>72 /// <param name="name">73 /// name of variable to look up74 /// </param>75 /// <returns>76 /// The specified variable.77 /// </returns>78 /// <exception cref="ArgumentNullException">79 /// If <paramref name="name"/> is null.80 /// </exception>81 internal PSVariable GetVariable(string name)82 {83 return GetVariable(name, CommandOrigin.Internal);84 }85 86 /// <summary>87 /// Get a variable out of session state. This interface supports88 /// the "namespace:name" syntax so you can do things like89 /// "env:PATH" or "global:example"90 /// </summary>91 /// <param name="name">92 /// name of variable to look up93 /// </param>94 /// <returns>95 /// The value of the specified variable.96 /// </returns>97 /// <exception cref="ArgumentNullException">98 /// If <paramref name="name"/> is null.99 /// </exception>100 /// <exception cref="ProviderNotFoundException">101 /// If the <paramref name="name"/> refers to a provider that could not be found.102 /// </exception>103 /// <exception cref="DriveNotFoundException">104 /// If the <paramref name="name"/> refers to a drive that could not be found.105 /// </exception>106 /// <exception cref="NotSupportedException">107 /// If the provider that the <paramref name="name"/> refers to does108 /// not support this operation.109 /// </exception>110 /// <exception cref="ProviderInvocationException">111 /// If the provider threw an exception.112 /// </exception>113 internal object GetVariableValue(string name)114 {115 if (name == null)116 {117 throw PSTraceSource.NewArgumentNullException(nameof(name));118 }119 120 VariablePath variablePath = new VariablePath(name);121 CmdletProviderContext context = null;122 SessionStateScope scope = null;123 124 object resultItem = GetVariableValue(variablePath, out context, out scope);125 126 return resultItem;127 }128 129 /// <summary>130 /// Get a variable out of session state. This interface supports131 /// the "namespace:name" syntax so you can do things like132 /// "env:PATH" or "global:example"133 /// </summary>134 /// <param name="name">135 /// name of variable to look up136 /// </param>137 /// <param name="defaultValue">138 /// value to return if you can't find Name or it returns null.139 /// </param>140 /// <returns>141 /// The value of the specified variable.142 /// </returns>143 /// <exception cref="ArgumentNullException">144 /// If <paramref name="name"/> is null.145 /// </exception>146 /// <exception cref="ProviderNotFoundException">147 /// If the <paramref name="name"/> refers to a provider that could not be found.148 /// </exception>149 /// <exception cref="DriveNotFoundException">150 /// If the <paramref name="name"/> refers to a drive that could not be found.151 /// </exception>152 /// <exception cref="NotSupportedException">153 /// If the provider that the <paramref name="name"/> refers to does154 /// not support this operation.155 /// </exception>156 /// <exception cref="ProviderInvocationException">157 /// If the provider threw an exception.158 /// </exception>159 internal object GetVariableValue(string name, object defaultValue)160 {161 object returnObject = GetVariableValue(name) ?? defaultValue;162 return returnObject;163 }164 165 /// <summary>166 /// Looks up the specified variable and returns the context under which167 /// the variable was found as well as the variable itself.168 /// </summary>169 /// <param name="variablePath">170 /// The VariablePath helper for the variable.171 /// </param>172 /// <param name="scope">173 /// The scope the variable was found in. Null if the variable wasn't found.174 /// </param>175 /// <param name="context">176 /// Returns the context under which the variable was found. The context will177 /// have the drive data already set. This will be null if the variable was178 /// not found.179 /// </param>180 /// <returns>181 /// The variable if it was found or null if it was not.182 /// </returns>183 /// <remarks>184 /// The <paramref name="variablePath"/> is first parsed to see if it contains a drive185 /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL")186 /// then only that scope is searched for the variable. If any other drive specifier187 /// is found the lookup goes in the following order.188 /// - current scope189 /// - each consecutive parent scope until the variable is found.190 /// - global scope191 /// </remarks>192 /// <exception cref="ArgumentNullException">193 /// If <paramref name="variablePath"/> is null.194 /// </exception>195 /// <exception cref="ProviderNotFoundException">196 /// If the <paramref name="variablePath"/> refers to a provider that could not be found.197 /// </exception>198 /// <exception cref="DriveNotFoundException">199 /// If the <paramref name="variablePath"/> refers to a drive that could not be found.200 /// </exception>201 /// <exception cref="NotSupportedException">202 /// If the provider that the <paramref name="variablePath"/> refers to does203 /// not support this operation.204 /// </exception>205 /// <exception cref="ProviderInvocationException">206 /// If the provider threw an exception.207 /// </exception>208 internal object GetVariableValue(209 VariablePath variablePath,210 out CmdletProviderContext context,211 out SessionStateScope scope)212 {213 context = null;214 scope = null;215 216 object result = null;217 if (variablePath.IsVariable)218 {219 PSVariable variable = GetVariableItem(variablePath, out scope);220 if (variable != null)221 {222 result = variable.Value;223 }224 }225 else226 {227 result = GetVariableValueFromProvider(variablePath, out context, out scope, _currentScope.ScopeOrigin);228 }229 230 return result;231 }232 233 /// <summary>234 /// Looks up the specified variable and returns the context under which235 /// the variable was found as well as the variable itself.236 /// </summary>237 /// <param name="variablePath">238 /// The VariablePath helper for the variable.239 /// </param>240 /// <param name="scope">241 /// The scope the variable was found in. Null if the variable wasn't found.242 /// </param>243 /// <param name="context">244 /// Returns the context under which the variable was found. The context will245 /// have the drive data already set. This will be null if the variable was246 /// not found.247 /// </param>248 /// <param name="origin">249 /// The origin of the caller of this API250 /// </param>251 /// <returns>252 /// The variable if it was found or null if it was not.253 /// </returns>254 /// <remarks>255 /// The <paramref name="variablePath"/> is first parsed to see if it contains a drive256 /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL")257 /// then only that scope is searched for the variable. If any other drive specifier258 /// is found the lookup goes in the following order.259 /// - current scope260 /// - each consecutive parent scope until the variable is found.261 /// - global scope262 /// </remarks>263 /// <exception cref="ArgumentNullException">264 /// If <paramref name="variablePath"/> is null.265 /// </exception>266 /// <exception cref="ProviderNotFoundException">267 /// If the <paramref name="variablePath"/> refers to a provider that could not be found.268 /// </exception>269 /// <exception cref="DriveNotFoundException">270 /// If the <paramref name="variablePath"/> refers to a drive that could not be found.271 /// </exception>272 /// <exception cref="NotSupportedException">273 /// If the provider that the <paramref name="variablePath"/> refers to does274 /// not support this operation.275 /// </exception>276 /// <exception cref="ProviderInvocationException">277 /// If the provider threw an exception.278 /// </exception>279#pragma warning disable 0162280 internal object GetVariableValueFromProvider(281 VariablePath variablePath,282 out CmdletProviderContext context,283 out SessionStateScope scope,284 CommandOrigin origin)285 {286 scope = null;287 288 if (variablePath == null)289 {290 throw PSTraceSource.NewArgumentNullException(nameof(variablePath));291 }292 293 Dbg.Diagnostics.Assert(294 !variablePath.IsVariable,295 "This method can only be used to retrieve provider content");296 297 context = null;298 299 DriveScopeItemSearcher searcher =300 new DriveScopeItemSearcher(301 this,302 variablePath);303 304 object result = null;305 306 do // false loop307 {308 if (!searcher.MoveNext())309 {310 break;311 }312 313 PSDriveInfo drive = ((IEnumerator<PSDriveInfo>)searcher).Current;314 315 if (drive == null)316 {317 break;318 }319 320 // Create a new CmdletProviderContext and set the drive data321 322 context = new CmdletProviderContext(this.ExecutionContext, origin);323 324 context.Drive = drive;325 326#if true327 // PSVariable get/set is the get/set of content in the provider328 329 Collection<IContentReader> readers = null;330 331 try332 {333 readers =334 GetContentReader(new string[] { variablePath.QualifiedName }, context);335 }336 // If the item is not found we just return null like the normal337 // variable semantics.338 catch (ItemNotFoundException)339 {340 break;341 }342 catch (DriveNotFoundException)343 {344 break;345 }346 catch (ProviderNotFoundException)347 {348 break;349 }350 catch (NotImplementedException notImplemented)351 {352 // First get the provider for the path.353 354 ProviderInfo providerInfo = null;355 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);356 357 throw NewProviderInvocationException(358 "ProviderCannotBeUsedAsVariable",359 SessionStateStrings.ProviderCannotBeUsedAsVariable,360 providerInfo,361 variablePath.QualifiedName,362 notImplemented,363 false);364 }365 catch (NotSupportedException notSupported)366 {367 // First get the provider for the path.368 369 ProviderInfo providerInfo = null;370 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);371 372 throw NewProviderInvocationException(373 "ProviderCannotBeUsedAsVariable",374 SessionStateStrings.ProviderCannotBeUsedAsVariable,375 providerInfo,376 variablePath.QualifiedName,377 notSupported,378 false);379 }380 381 if (readers == null || readers.Count == 0)382 {383 // The drive was found but the path was wrong or something so return null.384 // We don't want to continue searching if the provider didn't support content385 // or the path wasn't found.386 break;387 }388 389 if (readers.Count > 1)390 {391 // Since more than one path was resolved, this is an error.392 393 // Before throwing exception. Close the readers to avoid sharing violation.394 foreach (IContentReader r in readers)395 {396 r.Close();397 }398 399 PSArgumentException argException =400 PSTraceSource.NewArgumentException(401 "path",402 SessionStateStrings.VariablePathResolvedToMultiple,403 variablePath.QualifiedName);404 405 // First get the provider for the path.406 407 ProviderInfo providerInfo = null;408 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);409 410 throw NewProviderInvocationException(411 "ProviderVariableSyntaxInvalid",412 SessionStateStrings.ProviderVariableSyntaxInvalid,413 providerInfo,414 variablePath.QualifiedName,415 argException);416 }417 418 IContentReader reader = readers[0];419 420 try421 {422 // Read all the content423 IList resultList = reader.Read(-1);424 425 if (resultList != null)426 {427 if (resultList.Count == 0)428 {429 result = null;430 }431 else if (resultList.Count == 1)432 {433 result = resultList[0];434 }435 else436 {437 result = resultList;438 }439 }440 }441 catch (Exception e) // Third-party callout, catch-all OK442 {443 // First get the provider for the path.444 ProviderInfo providerInfo = null;445 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);446 447 ProviderInvocationException providerException =448 new ProviderInvocationException(449 "ProviderContentReadError",450 SessionStateStrings.ProviderContentReadError,451 providerInfo,452 variablePath.QualifiedName,453 e);454 455 throw providerException;456 }457 finally458 {459 reader.Close();460 }461 462#else463 try464 {465 GetItem(variablePath.LookupPath.ToString(), context);466 }467 catch (ItemNotFoundException)468 {469 break;470 }471 472 Collection<PSObject> items = context.GetAccumulatedObjects ();473 474 if (items != null &&475 items.Count > 0)476 {477 result = items[0];478 479 if (!items[0].basObjectIsEmpty)480 {481 result = items[0].BaseObject;482 }483 484 try485 {486 DictionaryEntry entry = (DictionaryEntry)result;487 result = entry.Value;488 }489 // Since DictionaryEntry is a value type we have to490 // try the cast and catch the exception to determine491 // if it is a DictionaryEntry type.492 catch (InvalidCastException)493 {494 }495 }496 497#endif498 break;499 } while (false);500 501 return result;502 }503#pragma warning restore 0162504 505 /// <summary>506 /// Looks up the specified variable and returns the context under which507 /// the variable was found as well as the variable itself.508 /// </summary>509 /// <param name="variablePath">510 /// The VariablePath helper for the variable.511 /// </param>512 /// <param name="scope">513 /// The scope the variable was found in. Null if the variable wasn't found.514 /// </param>515 /// <param name="origin">516 /// Origin of the command requesting this variable517 /// </param>518 /// <returns>519 /// The variable if it was found or null if it was not.520 /// </returns>521 /// <remarks>522 /// The <paramref name="variablePath"/> is first parsed to see if it contains a drive523 /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL")524 /// then only that scope is searched for the variable.525 /// - current scope526 /// - each consecutive parent scope until the variable is found.527 /// - global scope528 /// </remarks>529 /// <exception cref="ArgumentNullException">530 /// If <paramref name="variablePath"/> is null.531 /// </exception>532 internal PSVariable GetVariableItem(533 VariablePath variablePath,534 out SessionStateScope scope,535 CommandOrigin origin)536 {537 scope = null;538 539 if (variablePath == null)540 {541 throw PSTraceSource.NewArgumentNullException(nameof(variablePath));542 }543 544 Dbg.Diagnostics.Assert(variablePath.IsVariable, "Can't get variable w/ non-variable path");545 546 VariableScopeItemSearcher searcher =547 new VariableScopeItemSearcher(this, variablePath, origin);548 549 PSVariable result = null;550 551 if (searcher.MoveNext())552 {553 result = ((IEnumerator<PSVariable>)searcher).Current;554 scope = searcher.CurrentLookupScope;555 }556 557 return result;558 }559 560 /// <summary>561 /// Looks up the specified variable and returns the context under which562 /// the variable was found as well as the variable itself.563 /// </summary>564 /// <param name="variablePath">565 /// The VariablePath helper for the variable.566 /// </param>567 /// <param name="scope">568 /// The scope the variable was found in. Null if the variable wasn't found.569 /// </param>570 /// <returns>571 /// The variable if it was found or null if it was not.572 /// </returns>573 /// <remarks>574 /// The <paramref name="variablePath"/> is first parsed to see if it contains a drive575 /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL")576 /// then only that scope is searched for the variable.577 /// - current scope578 /// - each consecutive parent scope until the variable is found.579 /// - global scope580 /// </remarks>581 /// <exception cref="ArgumentNullException">582 /// If <paramref name="variablePath"/> is null.583 /// </exception>584 internal PSVariable GetVariableItem(585 VariablePath variablePath,586 out SessionStateScope scope)587 {588 return GetVariableItem(variablePath, out scope, CommandOrigin.Internal);589 }590 591 /// <summary>592 /// Get a variable out of session state. This interface supports593 /// the "namespace:name" syntax so you can do things like594 /// "env:PATH" or "global:example"595 /// </summary>596 /// <param name="name">597 /// name of variable to look up598 /// </param>599 /// <param name="scopeID">600 /// The ID of the scope to lookup the variable in.601 /// </param>602 /// <returns>603 /// The value of the specified variable.604 /// </returns>605 /// <exception cref="ArgumentNullException">606 /// If <paramref name="name"/> is null.607 /// </exception>608 /// <exception cref="ArgumentException">609 /// If <paramref name="scopeID"/> is less than zero, or not610 /// a number and not "script", "global", "local", or "private"611 /// </exception>612 /// <exception cref="ArgumentOutOfRangeException">613 /// If <paramref name="scopeID"/> is less than zero or greater than the number of currently614 /// active scopes.615 /// </exception>616 internal PSVariable GetVariableAtScope(string name, string scopeID)617 {618 if (name == null)619 {620 throw PSTraceSource.NewArgumentNullException(nameof(name));621 }622 623 VariablePath variablePath = new VariablePath(name);624 625 SessionStateScope lookupScope = null;626 627 // The lookup scope from above is ignored and the scope is retrieved by628 // ID.629 630 lookupScope = GetScopeByID(scopeID);631 632 PSVariable resultItem = null;633 634 if (variablePath.IsVariable)635 {636 resultItem = lookupScope.GetVariable(variablePath.QualifiedName);637 }638 639 return resultItem;640 }641 642 /// <summary>643 /// Get a variable out of session state. This interface supports644 /// the "namespace:name" syntax so you can do things like645 /// "env:PATH" or "global:example"646 /// </summary>647 /// <param name="name">648 /// name of variable to look up649 /// </param>650 /// <param name="scopeID">651 /// The ID of the scope to lookup the variable in.652 /// </param>653 /// <returns>654 /// The value of the specified variable.655 /// </returns>656 /// <exception cref="ArgumentNullException">657 /// If <paramref name="name"/> is null.658 /// </exception>659 /// <exception cref="ArgumentException">660 /// If <paramref name="scopeID"/> is less than zero, or not661 /// a number and not "script", "global", "local", or "private"662 /// </exception>663 /// <exception cref="ArgumentOutOfRangeException">664 /// If <paramref name="scopeID"/> is less than zero or greater than the number of currently665 /// active scopes.666 /// </exception>667 /// <exception cref="ProviderNotFoundException">668 /// If the <paramref name="name"/> refers to a provider that could not be found.669 /// </exception>670 /// <exception cref="DriveNotFoundException">671 /// If the <paramref name="name"/> refers to a drive that could not be found.672 /// </exception>673 /// <exception cref="NotSupportedException">674 /// If the provider that the <paramref name="name"/> refers to does675 /// not support this operation.676 /// </exception>677 /// <exception cref="ProviderInvocationException">678 /// If the provider threw an exception.679 /// </exception>680 internal object GetVariableValueAtScope(string name, string scopeID)681 {682 if (name == null)683 {684 throw PSTraceSource.NewArgumentNullException(nameof(name));685 }686 687 VariablePath variablePath = new VariablePath(name);688 689 SessionStateScope lookupScope = null;690 691 // The lookup scope from above is ignored and the scope is retrieved by692 // ID.693 694 lookupScope = GetScopeByID(scopeID);695 696 object resultItem = null;697 698 if (variablePath.IsVariable)699 {700 resultItem = lookupScope.GetVariable(variablePath.QualifiedName);701 }702 else703 {704 PSDriveInfo drive = lookupScope.GetDrive(variablePath.DriveName);705 706 if (drive != null)707 {708 CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);709 context.Drive = drive;710 711#if true712 // PSVariable get/set is the get/set of content in the provider713 714 Collection<IContentReader> readers = null;715 716 try717 {718 readers =719 GetContentReader(new string[] { variablePath.QualifiedName }, context);720 }721 // If the item is not found we just return null like the normal722 // variable semantics.723 catch (ItemNotFoundException)724 {725 return null;726 }727 catch (DriveNotFoundException)728 {729 return null;730 }731 catch (ProviderNotFoundException)732 {733 return null;734 }735 catch (NotImplementedException notImplemented)736 {737 // First get the provider for the path.738 739 ProviderInfo providerInfo = null;740 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);741 742 throw NewProviderInvocationException(743 "ProviderCannotBeUsedAsVariable",744 SessionStateStrings.ProviderCannotBeUsedAsVariable,745 providerInfo,746 variablePath.QualifiedName,747 notImplemented,748 false);749 }750 catch (NotSupportedException notSupported)751 {752 // First get the provider for the path.753 754 ProviderInfo providerInfo = null;755 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);756 757 throw NewProviderInvocationException(758 "ProviderCannotBeUsedAsVariable",759 SessionStateStrings.ProviderCannotBeUsedAsVariable,760 providerInfo,761 variablePath.QualifiedName,762 notSupported,763 false);764 }765 766 if (readers == null || readers.Count == 0)767 {768 // The drive was found but the path was wrong or something so return null.769 // We don't want to continue searching if the provider didn't support content770 // or the path wasn't found.771 // Any errors should have been written to the error pipeline.772 return null;773 }774 775 if (readers.Count > 1)776 {777 foreach (IContentReader closeReader in readers)778 {779 closeReader.Close();780 }781 782 // Since more than one path was resolved, this is an error.783 784 PSArgumentException argException =785 PSTraceSource.NewArgumentException(786 "path",787 SessionStateStrings.VariablePathResolvedToMultiple,788 name);789 790 // First get the provider for the path.791 792 ProviderInfo providerInfo = null;793 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);794 795 throw NewProviderInvocationException(796 "ProviderVariableSyntaxInvalid",797 SessionStateStrings.ProviderVariableSyntaxInvalid,798 providerInfo,799 variablePath.QualifiedName,800 argException);801 }802 803 IContentReader reader = readers[0];804 805 try806 {807 // Read all the content808 IList resultList = reader.Read(-1);809 810 if (resultList != null)811 {812 if (resultList.Count == 0)813 {814 resultItem = null;815 }816 else if (resultList.Count == 1)817 {818 resultItem = resultList[0];819 }820 else821 {822 resultItem = resultList;823 }824 }825 }826 catch (Exception e) // Third-party callout, catch-all OK827 {828 // First get the provider for the path.829 830 ProviderInfo providerInfo = null;831 _ = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo);832 833 ProviderInvocationException providerException =834 new ProviderInvocationException(835 "ProviderContentReadError",836 SessionStateStrings.ProviderContentReadError,837 providerInfo,838 variablePath.QualifiedName,839 e);840 841 throw providerException;842 }843 finally844 {845 reader.Close();846 }847#else848 GetItem (variablePath.LookupPath.ToString (), context);849 850 Collection<PSObject> results = context.GetAccumulatedObjects ();851 852 if (results != null &853 results.Count > 0)854 {855 // Only return the first value. If the caller wants globbing856 // they need to call the GetItem method directly.857 858 if (!results[0].basObjectIsEmpty)859 {860 resultItem = results[0].BaseObject;861 }862 else863 {864 resultItem = results[0];865 }866 }867#endif868 }869 }870 871 // If we get a PSVariable or DictionaryEntry returned then we have to872 // grab the value from it and return that instead.873 874 if (resultItem != null)875 {876 PSVariable variable = resultItem as PSVariable;877 878 if (variable != null)879 {880 resultItem = variable.Value;881 }882 else883 {884 try885 {886 DictionaryEntry entry = (DictionaryEntry)resultItem;887 resultItem = entry.Value;888 }889 catch (InvalidCastException)890 {891 }892 }893 }894 895 return resultItem;896 }897 898 internal object GetAutomaticVariableValue(AutomaticVariable variable)899 {900 var scopeEnumerator = new SessionStateScopeEnumerator(CurrentScope);901 object result = AutomationNull.Value;902 foreach (var scope in scopeEnumerator)903 {904 result = scope.GetAutomaticVariableValue(variable);905 if (result != AutomationNull.Value)906 {907 break;908 }909 }910 911 return result;912 }913 914 /// <summary>915 /// Set a variable in session state. This interface supports916 /// the "namespace:name" syntax so you can do things like917 /// "$env:PATH = 'c:\windows'" or "$global:example = 13"918 /// </summary>919 /// <param name="name">920 /// The name of the item to set.921 /// </param>922 /// <param name="newValue">923 /// The new value of the item being set.924 /// </param>925 /// <param name="origin">926 /// The origin of the caller of this API...927 /// </param>928 /// <exception cref="ArgumentNullException">929 /// If <paramref name="name"/> is null.930 /// </exception>931 /// <exception cref="SessionStateUnauthorizedAccessException">932 /// If the variable is read-only or constant.933 /// </exception>934 /// <exception cref="ProviderNotFoundException">935 /// If the <paramref name="name"/> refers to a provider that could not be found.936 /// </exception>937 /// <exception cref="DriveNotFoundException">938 /// If the <paramref name="name"/> refers to a drive that could not be found.939 /// </exception>940 /// <exception cref="NotSupportedException">941 /// If the provider that the <paramref name="name"/> refers to does942 /// not support this operation.943 /// </exception>944 /// <exception cref="ProviderInvocationException">945 /// If the provider threw an exception.946 /// </exception>947 internal void SetVariableValue(string name, object newValue, CommandOrigin origin)948 {949 if (name == null)950 {951 throw PSTraceSource.NewArgumentNullException(nameof(name));952 }953 954 VariablePath variablePath = new VariablePath(name);955 956 SetVariable(variablePath, newValue, true, origin);957 }958 959 /// <summary>960 /// Set a variable in session state. This interface supports961 /// the "namespace:name" syntax so you can do things like962 /// "$env:PATH = 'c:\windows'" or "$global:example = 13"963 ///964 /// BUGBUG: this overload exists because a lot of tests in the965 /// testsuite use it. Those tests should eventually be fixed and this overload966 /// should be removed.967 /// </summary>968 /// <param name="name">969 /// The name of the item to set.970 /// </param>971 /// <param name="newValue">972 /// The new value of the item being set.973 /// </param>974 /// <exception cref="ArgumentNullException">975 /// If <paramref name="name"/> is null.976 /// </exception>977 /// <exception cref="SessionStateUnauthorizedAccessException">978 /// If the variable is read-only or constant.979 /// </exception>980 /// <exception cref="ProviderNotFoundException">981 /// If the <paramref name="name"/> refers to a provider that could not be found.982 /// </exception>983 /// <exception cref="DriveNotFoundException">984 /// If the <paramref name="name"/> refers to a drive that could not be found.985 /// </exception>986 /// <exception cref="NotSupportedException">987 /// If the provider that the <paramref name="name"/> refers to does988 /// not support this operation.989 /// </exception>990 /// <exception cref="ProviderInvocationException">991 /// If the provider threw an exception.992 /// </exception>993 internal void SetVariableValue(string name, object newValue)994 {995 SetVariableValue(name, newValue, CommandOrigin.Internal);996 }997 998 /// <summary>999 /// Set a variable in session state. This interface supports1000 /// the scope specifiers like "$global:example = 13"1001 /// </summary>1002 /// <param name="variable">1003 /// The variable to be set.1004 /// </param>1005 /// <param name="force">1006 /// If true, the variable is set even if it is ReadOnly.1007 /// </param>1008 /// <param name="origin">1009 /// The origin of the caller of this API1010 /// </param>1011 /// <returns>1012 /// A PSVariable object if <paramref name="variablePath"/> refers to a variable.1013 /// An PSObject if <paramref name="variablePath"/> refers to a provider path.1014 /// </returns>1015 /// <exception cref="ArgumentNullException">1016 /// If <paramref name="variable"/> is null.1017 /// </exception>1018 /// <exception cref="SessionStateUnauthorizedAccessException">1019 /// If the variable is read-only or constant.1020 /// </exception>1021 internal object SetVariable(PSVariable variable, bool force, CommandOrigin origin)1022 {1023 if (variable == null || string.IsNullOrEmpty(variable.Name))1024 {1025 throw PSTraceSource.NewArgumentException(nameof(variable));1026 }1027 1028 VariablePath variablePath = new VariablePath(variable.Name, VariablePathFlags.Variable | VariablePathFlags.Unqualified);1029 1030 return SetVariable(variablePath, variable, false, force, origin);1031 }1032 1033 /// <summary>1034 /// Set a variable using a pre-parsed variablePath object instead of a string.1035 /// </summary>1036 /// <param name="variablePath">1037 /// A pre-parsed variable path object for the variable in question.1038 /// </param>1039 /// <param name="newValue">1040 /// The value to set.1041 /// </param>1042 /// <param name="asValue">1043 /// If true, sets the variable value to newValue. If false, newValue must1044 /// be a PSVariable object and the item will be set rather than the value.1045 /// </param>1046 /// <param name="origin">1047 /// The origin of the caller1048 /// </param>1049 /// <returns>1050 /// A PSVariable object if <paramref name="variablePath"/> refers to a variable.1051 /// An PSObject if <paramref name="variablePath"/> refers to a provider path.1052 /// </returns>1053 /// <exception cref="ArgumentNullException">1054 /// If <paramref name="variablePath"/> is null.1055 /// </exception>1056 /// <exception cref="SessionStateUnauthorizedAccessException">1057 /// If the variable is read-only or constant.1058 /// </exception>1059 /// <exception cref="ProviderNotFoundException">1060 /// If the <paramref name="variablePath"/> refers to a provider that could not be found.1061 /// </exception>1062 /// <exception cref="DriveNotFoundException">1063 /// If the <paramref name="variablePath"/> refers to a drive that could not be found.1064 /// </exception>1065 /// <exception cref="NotSupportedException">1066 /// If the provider that the <paramref name="variablePath"/> refers to does1067 /// not support this operation.1068 /// </exception>1069 /// <exception cref="ProviderInvocationException">1070 /// If the provider threw an exception.1071 /// </exception>1072 internal object SetVariable(1073 VariablePath variablePath,1074 object newValue,1075 bool asValue,1076 CommandOrigin origin)1077 {1078 return SetVariable(variablePath, newValue, asValue, false, origin);1079 }1080 1081 /// <summary>1082 /// Set a variable using a pre-parsed variablePath object instead of a string.1083 /// </summary>1084 /// <param name="variablePath">1085 /// A pre-parsed variable path object for the variable in question.1086 /// </param>1087 /// <param name="newValue">1088 /// The value to set.1089 /// </param>1090 /// <param name="asValue">1091 /// If true, sets the variable value to newValue. If false, newValue must1092 /// be a PSVariable object and the item will be set rather than the value.1093 /// </param>1094 /// <param name="force">1095 /// If true, the variable is set even if it is ReadOnly.1096 /// </param>1097 /// <param name="origin">1098 /// The origin of the caller1099 /// </param>1100 /// <returns>1101 /// A PSVariable object if <paramref name="variablePath"/> refers to a variable.1102 /// An PSObject if <paramref name="variablePath"/> refers to a provider path.1103 /// </returns>1104 /// <exception cref="ArgumentNullException">1105 /// If <paramref name="variablePath"/> is null.1106 /// </exception>1107 /// <exception cref="SessionStateUnauthorizedAccessException">1108 /// If the variable is read-only or constant.1109 /// </exception>1110 /// <exception cref="ProviderNotFoundException">1111 /// If the <paramref name="variablePath"/> refers to a provider that could not be found.1112 /// </exception>1113 /// <exception cref="DriveNotFoundException">1114 /// If the <paramref name="variablePath"/> refers to a drive that could not be found.1115 /// </exception>1116 /// <exception cref="NotSupportedException">1117 /// If the provider that the <paramref name="variablePath"/> refers to does1118 /// not support this operation.1119 /// </exception>1120 /// <exception cref="ProviderInvocationException">1121 /// If the provider threw an exception.1122 /// </exception>1123 internal object SetVariable(1124 VariablePath variablePath,1125 object newValue,1126 bool asValue,1127 bool force,1128 CommandOrigin origin)1129 {1130 object result = null;1131 if (variablePath == null)1132 {1133 throw PSTraceSource.NewArgumentNullException(nameof(variablePath));1134 }1135 1136 CmdletProviderContext context = null;1137 SessionStateScope scope = null;1138 1139 if (variablePath.IsVariable)1140 {1141 // Make sure to set the variable in the appropriate scope1142 1143 if (variablePath.IsLocal || variablePath.IsUnscopedVariable)1144 {1145 scope = _currentScope;1146 }1147 else if (variablePath.IsScript)1148 {1149 scope = _currentScope.ScriptScope;1150 }1151 else if (variablePath.IsGlobal)1152 {1153 scope = GlobalScope;1154 }1155 else if (variablePath.IsPrivate)1156 {1157 scope = _currentScope;1158 }1159 1160 PSVariable varResult =1161 scope.SetVariable(1162 variablePath.QualifiedName,1163 newValue,1164 asValue,1165 force,1166 this,1167 origin);1168 1169 // If the name is scoped as private we need to mark the1170 // variable as private1171 1172 if (variablePath.IsPrivate && varResult != null)1173 {1174 varResult.Options |= ScopedItemOptions.Private;1175 }1176 1177 result = varResult;1178 }1179 else1180 {1181 // Use GetVariable to get the correct context for the set operation.1182 1183 // NTRAID#Windows OS Bugs-896768-2004/07/06-JeffJon1184 // There is probably a more efficient way to do this.1185 1186 GetVariableValue(variablePath, out context, out scope);1187#if true1188 // PSVariable get/set is the get/set of content in the provider1189 1190 Collection<IContentWriter> writers = null;1191 1192 try1193 {1194 if (context != null)1195 {1196 try1197 {1198 CmdletProviderContext clearContentContext = new CmdletProviderContext(context);1199 1200 // First clear the content if it is supported.