/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Management.Automation.Provider; using System.Management.Automation.Internal; using System.Management.Automation.Runspaces; using Dbg=System.Management.Automation; #pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings #pragma warning disable 56500 namespace System.Management.Automation { /// /// Holds the state of a Monad Shell session /// internal sealed partial class SessionStateInternal { #region variables /// /// Add an new SessionStateVariable entry to this session state object... /// /// The entry to add internal void AddSessionStateEntry(SessionStateVariableEntry entry) { PSVariable v = new PSVariable(entry.Name, entry.Value, entry.Options, entry.Attributes, entry.Description); v.Visibility = entry.Visibility; this.SetVariableAtScope(v, "global", true, CommandOrigin.Internal); } /// /// Get a variable out of session state. This interface supports /// the scope specifiers like "global:foobar" /// /// /// /// name of variable to look up /// /// /// /// Origin of the command making this request. /// /// /// /// The specified variable. /// /// /// /// If is null. /// /// internal PSVariable GetVariable(string name, CommandOrigin origin) { if (name == null) { throw PSTraceSource.NewArgumentNullException("name"); } VariablePath variablePath = new VariablePath(name, VariablePathFlags.Variable | VariablePathFlags.Unqualified); SessionStateScope scope = null; PSVariable resultItem = GetVariableItem(variablePath, out scope, origin); return resultItem; } // GetVariable /// /// Get a variable out of session state. This interface supports /// the scope specifiers like "global:foobar" /// /// /// /// name of variable to look up /// /// /// /// The specified variable. /// /// /// /// If is null. /// /// internal PSVariable GetVariable(string name) { return GetVariable(name, CommandOrigin.Internal); } // GetVariable /// /// Get a variable out of session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "env:PATH" or "global:foobar" /// /// /// /// name of variable to look up /// /// /// /// The value of the specified variable. /// /// /// /// If is null. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal object GetVariableValue(string name) { if (name == null) { throw PSTraceSource.NewArgumentNullException("name"); } VariablePath variablePath = new VariablePath(name); CmdletProviderContext context = null; SessionStateScope scope = null; object resultItem = GetVariableValue(variablePath, out context, out scope); return resultItem; } // GetVariableValue /// /// Get a variable out of session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "env:PATH" or "global:foobar" /// /// /// /// name of variable to look up /// /// /// /// value to return if you can't find Name or it returns null. /// /// /// /// The value of the specified variable. /// /// /// /// If is null. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal object GetVariableValue(string name, object defaultValue) { object returnObject = GetVariableValue(name); if (returnObject == null) { returnObject = defaultValue; } return returnObject; } // GetVariableValue /// /// Looks up the specified variable and returns the context under which /// the variable was found as well as the variable itself. /// /// /// /// The VariablePath helper for the variable. /// /// /// /// The scope the variable was found in. Null if the variable wasn't found. /// /// /// /// Returns the context under which the variable was found. The context will /// have the drive data already set. This will be null if the variable was /// not found. /// /// /// /// The variable if it was found or null if it was not. /// /// /// /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. If any other drive specifier /// is found the lookup goes in the following order. /// - current scope /// - each consecutive parent scope until the variable is found. /// - global scope /// /// /// /// If is null. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal object GetVariableValue( VariablePath variablePath, out CmdletProviderContext context, out SessionStateScope scope) { context = null; scope = null; object result = null; if (variablePath.IsVariable) { PSVariable variable = GetVariableItem(variablePath, out scope); if (variable != null) { result = variable.Value; } } else { result = GetVariableValueFromProvider(variablePath, out context, out scope, currentScope.ScopeOrigin); } return result; } /// /// Looks up the specified variable and returns the context under which /// the variable was found as well as the variable itself. /// /// /// /// The VariablePath helper for the variable. /// /// /// /// The scope the variable was found in. Null if the variable wasn't found. /// /// /// /// Returns the context under which the variable was found. The context will /// have the drive data already set. This will be null if the variable was /// not found. /// /// /// /// The origin of the caller of this API /// /// /// /// The variable if it was found or null if it was not. /// /// /// /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. If any other drive specifier /// is found the lookup goes in the following order. /// - current scope /// - each consecutive parent scope until the variable is found. /// - global scope /// /// /// /// If is null. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// #pragma warning disable 0162 internal object GetVariableValueFromProvider( VariablePath variablePath, out CmdletProviderContext context, out SessionStateScope scope, CommandOrigin origin) { scope = null; if (variablePath == null) { throw PSTraceSource.NewArgumentNullException("variablePath"); } Dbg.Diagnostics.Assert( !variablePath.IsVariable, "This method can only be used to retrieve provider content"); context = null; DriveScopeItemSearcher searcher = new DriveScopeItemSearcher( this, variablePath); object result = null; do // false loop { if (!searcher.MoveNext()) { break; } PSDriveInfo drive = ((IEnumerator)searcher).Current; if (drive == null) { break; } // Create a new CmdletProviderContext and set the drive data context = new CmdletProviderContext(this.ExecutionContext, origin); context.Drive = drive; #if true // PSVariable get/set is the get/set of content in the provider Collection readers = null; try { readers = GetContentReader(new string[] { variablePath.QualifiedName }, context); } // If the item is not found we just return null like the normal // variable semantics. catch (ItemNotFoundException) { break; } catch (DriveNotFoundException) { break; } catch (ProviderNotFoundException) { break; } catch (NotImplementedException notImplemented) { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderCannotBeUsedAsVariable", SessionStateStrings.ProviderCannotBeUsedAsVariable, providerInfo, variablePath.QualifiedName, notImplemented, false); } catch (NotSupportedException notSupported) { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderCannotBeUsedAsVariable", SessionStateStrings.ProviderCannotBeUsedAsVariable, providerInfo, variablePath.QualifiedName, notSupported, false); } if (readers == null || readers.Count == 0) { // The drive was found but the path was wrong or something so return null. // We don't want to continue searching if the provider didn't support content // or the path wasn't found. break; } if (readers.Count > 1) { // Since more than one path was resolved, this is an error. //Before throwing exception. Close the readers to avoid sharing violation. foreach (IContentReader r in readers) { r.Close(); } PSArgumentException argException = PSTraceSource.NewArgumentException( "path", SessionStateStrings.VariablePathResolvedToMultiple, variablePath.QualifiedName); // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderVariableSyntaxInvalid", SessionStateStrings.ProviderVariableSyntaxInvalid, providerInfo, variablePath.QualifiedName, argException); } IContentReader reader = readers[0]; try { // Read all the content IList resultList = reader.Read(-1); if (resultList != null) { if (resultList.Count == 0) { result = null; } else if (resultList.Count == 1) { result = resultList[0]; } else { result = resultList; } } } catch (Exception e) // Third-party callout, catch-all OK { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); CommandProcessorBase.CheckForSevereException(e); ProviderInvocationException providerException = new ProviderInvocationException( "ProviderContentReadError", SessionStateStrings.ProviderContentReadError, providerInfo, variablePath.QualifiedName, e); throw providerException; } finally { reader.Close(); } #else try { GetItem(variablePath.LookupPath.ToString(), context); } catch (ItemNotFoundException) { break; } Collection items = context.GetAccumulatedObjects (); if (items != null && items.Count > 0) { result = items[0]; if (!items[0].basObjectIsEmpty) { result = items[0].BaseObject; } try { DictionaryEntry entry = (DictionaryEntry)result; result = entry.Value; } // Since DictionaryEntry is a value type we have to // try the cast and catch the exception to determine // if it is a DictionaryEntry type. catch (InvalidCastException) { } } #endif break; } while (false); return result; } // GetVariableFromProvider #pragma warning restore 0162 /// /// Looks up the specified variable and returns the context under which /// the variable was found as well as the variable itself. /// /// /// /// The VariablePath helper for the variable. /// /// /// /// The scope the variable was found in. Null if the variable wasn't found. /// /// /// /// Origin of the command requesting this variable /// /// /// /// The variable if it was found or null if it was not. /// /// /// /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. /// - current scope /// - each consecutive parent scope until the variable is found. /// - global scope /// /// /// /// If is null. /// /// internal PSVariable GetVariableItem( VariablePath variablePath, out SessionStateScope scope, CommandOrigin origin) { scope = null; if (variablePath == null) { throw PSTraceSource.NewArgumentNullException("variablePath"); } Dbg.Diagnostics.Assert(variablePath.IsVariable, "Can't get variable w/ non-variable path"); VariableScopeItemSearcher searcher = new VariableScopeItemSearcher(this, variablePath, origin); PSVariable result = null; if (searcher.MoveNext()) { result = ((IEnumerator)searcher).Current; scope = searcher.CurrentLookupScope; } return result; } // GetVariableItem /// /// Looks up the specified variable and returns the context under which /// the variable was found as well as the variable itself. /// /// /// /// The VariablePath helper for the variable. /// /// /// /// The scope the variable was found in. Null if the variable wasn't found. /// /// /// /// The variable if it was found or null if it was not. /// /// /// /// The is first parsed to see if it contains a drive /// specifier or special scope. If a special scope is found ("LOCAL" or "GLOBAL") /// then only that scope is searched for the variable. /// - current scope /// - each consecutive parent scope until the variable is found. /// - global scope /// /// /// /// If is null. /// /// internal PSVariable GetVariableItem( VariablePath variablePath, out SessionStateScope scope) { return GetVariableItem(variablePath, out scope, CommandOrigin.Internal); } // GetVariableItem /// /// Get a variable out of session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "env:PATH" or "global:foobar" /// /// /// /// name of variable to look up /// /// /// /// The ID of the scope to lookup the variable in. /// /// /// /// The value of the specified variable. /// /// /// /// If is null. /// /// /// /// If is less than zero, or not /// a number and not "script", "global", "local", or "private" /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// internal PSVariable GetVariableAtScope(string name, string scopeID) { if (name == null) { throw PSTraceSource.NewArgumentNullException("name"); } VariablePath variablePath = new VariablePath(name); SessionStateScope lookupScope = null; // The lookup scope from above is ignored and the scope is retrieved by // ID. lookupScope = GetScopeByID(scopeID); PSVariable resultItem = null; if (variablePath.IsVariable) { resultItem = lookupScope.GetVariable(variablePath.QualifiedName); } return resultItem; } // GetVariable /// /// Get a variable out of session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "env:PATH" or "global:foobar" /// /// /// /// name of variable to look up /// /// /// /// The ID of the scope to lookup the variable in. /// /// /// /// The value of the specified variable. /// /// /// /// If is null. /// /// /// /// If is less than zero, or not /// a number and not "script", "global", "local", or "private" /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal object GetVariableValueAtScope(string name, string scopeID) { if (name == null) { throw PSTraceSource.NewArgumentNullException("name"); } VariablePath variablePath = new VariablePath(name); SessionStateScope lookupScope = null; // The lookup scope from above is ignored and the scope is retrieved by // ID. lookupScope = GetScopeByID(scopeID); object resultItem = null; if (variablePath.IsVariable) { resultItem = lookupScope.GetVariable(variablePath.QualifiedName); } else { PSDriveInfo drive = lookupScope.GetDrive(variablePath.DriveName); if (drive != null) { CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext); context.Drive = drive; #if true // PSVariable get/set is the get/set of content in the provider Collection readers = null; try { readers = GetContentReader(new string[] { variablePath.QualifiedName }, context); } // If the item is not found we just return null like the normal // variable semantics. catch (ItemNotFoundException) { return null; } catch (DriveNotFoundException) { return null; } catch (ProviderNotFoundException) { return null; } catch (NotImplementedException notImplemented) { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderCannotBeUsedAsVariable", SessionStateStrings.ProviderCannotBeUsedAsVariable, providerInfo, variablePath.QualifiedName, notImplemented, false); } catch (NotSupportedException notSupported) { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderCannotBeUsedAsVariable", SessionStateStrings.ProviderCannotBeUsedAsVariable, providerInfo, variablePath.QualifiedName, notSupported, false); } if (readers == null || readers.Count == 0) { // The drive was found but the path was wrong or something so return null. // We don't want to continue searching if the provider didn't support content // or the path wasn't found. // Any errors should have been written to the error pipeline. return null; } if (readers.Count > 1) { foreach (IContentReader closeReader in readers) { closeReader.Close(); } // Since more than one path was resolved, this is an error. PSArgumentException argException = PSTraceSource.NewArgumentException( "path", SessionStateStrings.VariablePathResolvedToMultiple, name); // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderVariableSyntaxInvalid", SessionStateStrings.ProviderVariableSyntaxInvalid, providerInfo, variablePath.QualifiedName, argException); } IContentReader reader = readers[0]; try { // Read all the content IList resultList = reader.Read(-1); if (resultList != null) { if (resultList.Count == 0) { resultItem = null; } else if (resultList.Count == 1) { resultItem = resultList[0]; } else { resultItem = resultList; } } } catch (Exception e) // Third-party callout, catch-all OK { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); CommandProcessorBase.CheckForSevereException(e); ProviderInvocationException providerException = new ProviderInvocationException( "ProviderContentReadError", SessionStateStrings.ProviderContentReadError, providerInfo, variablePath.QualifiedName, e); throw providerException; } finally { reader.Close(); } #else GetItem (variablePath.LookupPath.ToString (), context); Collection results = context.GetAccumulatedObjects (); if (results != null & results.Count > 0) { // Only return the first value. If the caller wants globbing // they need to call the GetItem method directly. if (!results[0].basObjectIsEmpty) { resultItem = results[0].BaseObject; } else { resultItem = results[0]; } } #endif } } // If we get a PSVariable or DictionaryEntry returned then we have to // grab the value from it and return that instead. if (resultItem != null) { PSVariable variable = resultItem as PSVariable; if (variable != null) { resultItem = variable.Value; } else { try { DictionaryEntry entry = (DictionaryEntry)resultItem; resultItem = entry.Value; } catch (InvalidCastException) { } } } // if resultItem != null return resultItem; } // GetVariableValueAtScope internal object GetAutomaticVariableValue(AutomaticVariable variable) { var scopeEnumerator = new SessionStateScopeEnumerator(CurrentScope); object result = AutomationNull.Value; foreach (var scope in scopeEnumerator) { result = scope.GetAutomaticVariableValue(variable); if (result != AutomationNull.Value) { break; } } return result; } /// /// Set a variable in session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "$env:PATH = 'c:\windows'" or "$global:foobar = 13" /// /// /// /// The name of the item to set. /// /// /// /// The new value of the item being set. /// /// /// /// The origin of the caller of this API... /// /// /// /// If is null. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal void SetVariableValue(string name, object newValue, CommandOrigin origin) { if (name == null) { throw PSTraceSource.NewArgumentNullException("name"); } VariablePath variablePath = new VariablePath(name); SetVariable(variablePath, newValue, true, origin); } /// /// Set a variable in session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "$env:PATH = 'c:\windows'" or "$global:foobar = 13" /// /// BUGBUG: this overload exists because a lot of tests in the /// testsuite use it. Those tests should eventually be fixed and this overload /// should be removed. /// /// /// /// The name of the item to set. /// /// /// /// The new value of the item being set. /// /// /// /// If is null. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal void SetVariableValue(string name, object newValue) { SetVariableValue(name, newValue, CommandOrigin.Internal); } /// /// Set a variable in session state. This interface supports /// the scope specifiers like "$global:foobar = 13" /// /// /// /// The variable to be set. /// /// /// /// If true, the variable is set even if it is ReadOnly. /// /// /// /// The origin of the caller of this API /// /// /// /// A PSVariable object if refers to a variable. /// An PSObject if refers to a provider path. /// /// /// /// If is null. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// internal object SetVariable(PSVariable variable, bool force, CommandOrigin origin) { if (variable == null || String.IsNullOrEmpty(variable.Name)) { throw PSTraceSource.NewArgumentException("variable"); } VariablePath variablePath = new VariablePath(variable.Name, VariablePathFlags.Variable | VariablePathFlags.Unqualified); return SetVariable(variablePath, variable, false, force, origin); } /// /// Set a variable useing a pre-parsed variablePath object instead of a string. /// /// /// /// A pre-parsed variable path object for the variable in question. /// /// /// /// The value to set. /// /// /// /// If true, sets the variable value to newValue. If false, newValue must /// be a PSVariable object and the item will be set rather than the value. /// /// /// /// The origin of the caller /// /// /// /// A PSVariable object if refers to a variable. /// An PSObject if refers to a provider path. /// /// /// /// If is null. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal object SetVariable( VariablePath variablePath, object newValue, bool asValue, CommandOrigin origin) { return SetVariable(variablePath, newValue, asValue, false, origin); } /// /// Set a variable useing a pre-parsed variablePath object instead of a string. /// /// /// /// A pre-parsed variable path object for the variable in question. /// /// /// /// The value to set. /// /// /// /// If true, sets the variable value to newValue. If false, newValue must /// be a PSVariable object and the item will be set rather than the value. /// /// /// /// If true, the variable is set even if it is ReadOnly. /// /// /// /// The origin of the caller /// /// /// /// A PSVariable object if refers to a variable. /// An PSObject if refers to a provider path. /// /// /// /// If is null. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal object SetVariable( VariablePath variablePath, object newValue, bool asValue, bool force, CommandOrigin origin) { object result = null; if (variablePath == null) { throw PSTraceSource.NewArgumentNullException("variablePath"); } CmdletProviderContext context = null; SessionStateScope scope = null; if (variablePath.IsVariable) { // Make sure to set the variable in the appropriate scope if (variablePath.IsLocal || variablePath.IsUnscopedVariable) { scope = currentScope; } else if (variablePath.IsScript) { scope = currentScope.ScriptScope; } else if (variablePath.IsGlobal) { scope = _globalScope; } else if (variablePath.IsPrivate) { scope = currentScope; } PSVariable varResult = scope.SetVariable( variablePath.QualifiedName, newValue, asValue, force, this, origin); // If the name is scoped as private we need to mark the // variable as private if (variablePath.IsPrivate && varResult != null) { varResult.Options = varResult.Options | ScopedItemOptions.Private; } result = varResult; } else { // Use GetVariable to get the correct context for the set operation. // NTRAID#Windows OS Bugs-896768-2004/07/06-JeffJon // There is probably a more efficient way to do this. GetVariableValue(variablePath, out context, out scope); #if true // PSVariable get/set is the get/set of content in the provider Collection writers = null; try { if (context != null) { try { CmdletProviderContext clearContentContext = new CmdletProviderContext(context); // First clear the content if it is supported. ClearContent(new string[] { variablePath.QualifiedName }, clearContentContext); } catch (NotSupportedException) { } catch (ItemNotFoundException) { } writers = GetContentWriter( new string[] { variablePath.QualifiedName }, context); context.ThrowFirstErrorOrDoNothing(true); } else { try { // First clear the content if it is supported. ClearContent(new string[] { variablePath.QualifiedName }, false, false); } catch (NotSupportedException) { } catch (ItemNotFoundException) { } writers = GetContentWriter( new string[] { variablePath.QualifiedName }, false, false); } } catch (NotImplementedException notImplemented) { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderCannotBeUsedAsVariable", SessionStateStrings.ProviderCannotBeUsedAsVariable, providerInfo, variablePath.QualifiedName, notImplemented, false); } catch (NotSupportedException notSupported) { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderCannotBeUsedAsVariable", SessionStateStrings.ProviderCannotBeUsedAsVariable, providerInfo, variablePath.QualifiedName, notSupported, false); } if (writers == null || writers.Count == 0) { ItemNotFoundException itemNotFound = new ItemNotFoundException( variablePath.QualifiedName, "PathNotFound", SessionStateStrings.PathNotFound); throw itemNotFound; } if (writers.Count > 1) { // Since more than one path was resolved, this is an error. foreach (IContentWriter w in writers) { w.Close(); } PSArgumentException argException = PSTraceSource.NewArgumentException( "path", SessionStateStrings.VariablePathResolvedToMultiple, variablePath.QualifiedName); // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); throw NewProviderInvocationException( "ProviderVariableSyntaxInvalid", SessionStateStrings.ProviderVariableSyntaxInvalid, providerInfo, variablePath.QualifiedName, argException); } IContentWriter writer = writers[0]; IList content = newValue as IList; if (content == null) { content = new object[] { newValue }; } try { writer.Write(content); } catch (Exception e) // Third-party callout, catch-all OK { // First get the provider for the path. ProviderInfo providerInfo = null; string unused = this.Globber.GetProviderPath(variablePath.QualifiedName, out providerInfo); CommandProcessorBase.CheckForSevereException(e); ProviderInvocationException providerException = new ProviderInvocationException( "ProviderContentWriteError", SessionStateStrings.ProviderContentWriteError, providerInfo, variablePath.QualifiedName, e); throw providerException; } finally { writer.Close(); } #else if (context != null) { context.Force = force; SetItem (variablePath.LookupPath.ToString (), newValue, context); context.ThrowFirstErrorOrDoNothing(true); } else { Collection setItemResult = SetItem (variablePath.LookupPath.ToString (), newValue); if (setItemResult != null && setItemResult.Count > 0) { result = setItemResult[0]; } } #endif } return result; } // SetVariable /// /// Set a variable in session state. /// /// /// /// The variable to set /// /// /// /// The ID of the scope to do the lookup in. The ID is either a zero based index /// of the scope tree with the current scope being zero, its parent scope /// being 1 and so on, or "global", "local", "private", or "script" /// /// /// /// If true, the variable is set even if it is ReadOnly. /// /// /// /// The origin of the caller /// /// /// /// If is null or its name is null or empty. /// or /// If is less than zero, or not /// a number and not "script", "global", "local", or "private" /// /// /// /// A PSVariable object if refers to a variable. /// An PSObject if refers to a provider path. /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// internal object SetVariableAtScope(PSVariable variable, string scopeID, bool force, CommandOrigin origin) { if (variable == null || String.IsNullOrEmpty(variable.Name)) { throw PSTraceSource.NewArgumentException("variable"); } SessionStateScope lookupScope = GetScopeByID(scopeID); return lookupScope.SetVariable( variable.Name, variable, false, force, this, origin); } // SetVariableAtScope #region NewVariable /// /// Creates a new variable. /// /// /// /// The variable to create /// /// /// /// If true, the variable is created even if it is ReadOnly. /// /// /// /// A PSVariable representing the variable that was created. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// internal object NewVariable(PSVariable variable, bool force) { if (variable == null || String.IsNullOrEmpty(variable.Name)) { throw PSTraceSource.NewArgumentException("variable"); } return this.CurrentScope.NewVariable( variable, force, this); } // NewVariable /// /// Creates a new variable in the specified scope /// /// /// /// The variable to create /// /// /// /// The ID of the scope to do the lookup in. The ID is either a zero based index /// of the scope tree with the current scope being zero, its parent scope /// being 1 and so on, or "global", "local", "private", or "script" /// /// /// /// If true, the variable is set even if it is ReadOnly. /// /// /// /// If is null or its name is null or empty. /// or /// If is less than zero, or not /// a number and not "script", "global", "local", or "private" /// /// /// /// A PSVariable representing the variable that was created. /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// If the variable is read-only or constant. /// /// /// /// If the maximum number of variables has been reached for this scope. /// /// internal object NewVariableAtScope(PSVariable variable, string scopeID, bool force) { if (variable == null || String.IsNullOrEmpty(variable.Name)) { throw PSTraceSource.NewArgumentException("variable"); } // The lookup scope from above is ignored and the scope is retrieved by // ID. SessionStateScope lookupScope = GetScopeByID(scopeID); return lookupScope.NewVariable( variable, force, this); } // NewVariableAtScope #endregion NewVariable /// /// Removes a variable from the variable table. /// /// /// /// The name of the variable to remove. /// /// /// /// If is null. /// /// /// /// if the variable is constant. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal void RemoveVariable(string name) { RemoveVariable(name, false); } /// /// Removes a variable from the variable table. /// /// /// /// The name of the variable to remove. /// /// /// /// If true, the variable will be removed even if its ReadOnly. /// /// /// /// If is null. /// /// /// /// if the variable is constant. /// /// /// /// If the refers to a provider that could not be found. /// /// /// /// If the refers to a drive that could not be found. /// /// /// /// If the provider that the refers to does /// not support this operation. /// /// /// /// If the provider threw an exception. /// /// internal void RemoveVariable(string name, bool force) { if (name == null) { throw PSTraceSource.NewArgumentNullException("name"); } VariablePath variablePath = new VariablePath(name); SessionStateScope scope = null; if (variablePath.IsVariable) { if (GetVariableItem(variablePath, out scope) != null) { scope.RemoveVariable(variablePath.QualifiedName, force); } } else { CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext); context.Force = force; RemoveItem(new string[] { variablePath.QualifiedName }, false, context); context.ThrowFirstErrorOrDoNothing(); } } // RemoveVariable /// /// Removes a variable from the variable table. /// /// /// /// The variable to remove. /// /// /// /// If is null. /// /// /// /// if the variable is constant. /// /// internal void RemoveVariable(PSVariable variable) { RemoveVariable(variable, false); } /// /// Removes a variable from the variable table. /// /// /// /// The variable to remove. /// /// /// /// If true, the variable will be removed even if its ReadOnly. /// /// /// /// If is null. /// /// /// /// if the variable is constant. /// /// internal void RemoveVariable(PSVariable variable, bool force) { if (variable == null) { throw PSTraceSource.NewArgumentNullException("variable"); } VariablePath variablePath = new VariablePath(variable.Name); SessionStateScope scope = null; if (GetVariableItem(variablePath, out scope) != null) { scope.RemoveVariable(variablePath.QualifiedName, force); } } // RemoveVariable /// /// Remove a variable from session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "env:PATH" or "global:foobar" /// /// /// /// name of variable to remove /// /// /// /// The ID of the scope to lookup the variable in. /// /// /// /// If is null. /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// /// if the variable is constant. /// /// /// /// If refers to an MSH path (not a variable) /// and the provider throws an exception. /// /// internal void RemoveVariableAtScope(string name, string scopeID) { RemoveVariableAtScope(name, scopeID, false); } /// /// Remove a variable from session state. This interface supports /// the "namespace:name" syntax so you can do things like /// "env:PATH" or "global:foobar" /// /// /// /// name of variable to remove /// /// /// /// The ID of the scope to lookup the variable in. /// /// /// /// If true, the variable will be removed even if its ReadOnly. /// /// /// /// If is null or empty. /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// if the variable is constant. /// /// /// /// If refers to an MSH path (not a variable) /// and the provider throws an exception. /// /// internal void RemoveVariableAtScope(string name, string scopeID, bool force) { if (String.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentException("name"); } VariablePath variablePath = new VariablePath(name); SessionStateScope lookupScope = null; // The lookup scope from above is ignored and the scope is retrieved by // ID. lookupScope = GetScopeByID(scopeID); if (variablePath.IsVariable) { lookupScope.RemoveVariable(variablePath.QualifiedName, force); } else { PSDriveInfo drive = lookupScope.GetDrive(variablePath.DriveName); if (drive != null) { CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext); context.Drive = drive; context.Force = force; RemoveItem(new string[] { variablePath.QualifiedName }, false, context); context.ThrowFirstErrorOrDoNothing(); } } } // RemoveVariableAtScope /// /// Remove a variable from session state. /// /// /// /// The variable to remove /// /// /// /// The ID of the scope to lookup the variable in. /// /// /// /// If is null. /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// if the variable is constant. /// /// internal void RemoveVariableAtScope(PSVariable variable, string scopeID) { RemoveVariableAtScope(variable, scopeID, false); } /// /// Remove a variable from session state. /// /// /// /// The variable to remove /// /// /// /// The ID of the scope to lookup the variable in. /// /// /// /// If true, the variable will be removed even if its ReadOnly. /// /// /// /// If is null. /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// /// /// if the variable is constant. /// /// internal void RemoveVariableAtScope(PSVariable variable, string scopeID, bool force) { if (variable == null) { throw PSTraceSource.NewArgumentNullException("variable"); } VariablePath variablePath = new VariablePath(variable.Name); // The lookup scope is retrieved by ID. SessionStateScope lookupScope = GetScopeByID(scopeID); lookupScope.RemoveVariable(variablePath.QualifiedName, force); } // RemoveVariableAtScope /// /// Gets a flattened view of the variables that are visible using /// the current scope as a reference and filtering the variables in /// the other scopes based on the scoping rules. /// /// /// /// An IDictionary representing the visible variables. /// /// internal IDictionary GetVariableTable() { SessionStateScopeEnumerator scopeEnumerator = new SessionStateScopeEnumerator(currentScope); Dictionary result = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (SessionStateScope scope in scopeEnumerator) { GetScopeVariableTable(scope, result, includePrivate: scope == currentScope); } return result; } private void GetScopeVariableTable(SessionStateScope scope, Dictionary result, bool includePrivate) { foreach (KeyValuePair entry in scope.Variables) { if (!result.ContainsKey(entry.Key)) { // Also check to ensure that the variable isn't private // and in a different scope PSVariable var = entry.Value; if (!var.IsPrivate || includePrivate) { result.Add(entry.Key, var); } } } foreach (var dottedScope in scope.DottedScopes) { dottedScope.GetVariableTable(result, includePrivate); } if (scope.LocalsTuple != null) { scope.LocalsTuple.GetVariableTable(result, includePrivate); } } /// /// Gets a flattened view of the variables that are visible using /// the current scope as a reference and filtering the variables in /// the other scopes based on the scoping rules. /// /// /// /// An IDictionary representing the visible variables. /// /// /// /// If is less than zero, or not /// a number and not "script", "global", "local", or "private" /// /// /// /// If is less than zero or greater than the number of currently /// active scopes. /// /// internal IDictionary GetVariableTableAtScope(string scopeID) { var result = new Dictionary(StringComparer.OrdinalIgnoreCase); GetScopeVariableTable(GetScopeByID(scopeID), result, includePrivate: true); return result; } /// /// List of variables to export from this session state object... /// internal List ExportedVariables { get { return _exportedVariables; } } private List _exportedVariables = new List(); #endregion variables } // SessionStateInternal class } #pragma warning restore 56500