/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System.Globalization; using System.IO; using System.Xml; using System.Text; using System.Collections.ObjectModel; using System.Management.Automation.Internal; using System.Collections.Generic; namespace System.Management.Automation.Runspaces { /// /// Class that understands Monad Console File Format. The format for the console /// file is applied/read by this class only. /// /// Functionality: /// 1. Schema version verification check. /// 2. Data values for the content represented by Console file. Later this data /// is used by other components ( MshConsoleInfo ) to construct Monad Types ( like /// PSSnapInInfo ). /// 3. Owns responsibility to read/write Files. /// /// Risk: /// File Acces related security issues. /// /// Requires: /// Might require Permissions to read/write into files. /// /// internal class PSConsoleFileElement { #region Console format (xml) tags // Create constants for each of the xml tags private const string MSHCONSOLEFILE = "PSConsoleFile"; private const string CSCHEMAVERSION = "ConsoleSchemaVersion"; private const string CSCHEMAVERSIONNUMBER = "1.0"; private const string PSVERSION = "PSVersion"; private const string SNAPINS = "PSSnapIns"; private const string SNAPIN = "PSSnapIn"; private const string SNAPINNAME = "Name"; #endregion #region Data /// /// MonadVersion from the console file /// internal string MonadVersion { get; } /// /// List of MshSnapin IDs from the console file /// internal Collection PSSnapIns { get; } #endregion #region Constructor private PSConsoleFileElement(string version) { MonadVersion = version; // Dont make collections null... // making them null, wont be good for foreach statements PSSnapIns = new Collection(); } #endregion #region tracer private static readonly PSTraceSource s_mshsnapinTracer = PSTraceSource.GetTracer("MshSnapinLoadUnload", "Loading and unloading mshsnapins", false); #endregion #region Static Methods /// /// Writes MshConsoleInfo object in Monad Console format into the file specified by the . /// /// The absolute path of the file into which the content is saved. /// The version of PowerShell. /// The external snapins that are loaded in the console /// /// The path value is null. /// /// internal static void WriteToFile(string path, Version version, IEnumerable snapins) { Diagnostics.Assert(path != null, "Filename should not be null"); s_mshsnapinTracer.WriteLine("Saving console info to file {0}.", path); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.Encoding = Encoding.UTF8; using (Stream stream = new FileStream(path, FileMode.OpenOrCreate)) { // Generate xml for the consoleinfo object. using (XmlWriter writer = XmlWriter.Create(stream, settings)) { writer.WriteStartDocument(); writer.WriteStartElement(MSHCONSOLEFILE); writer.WriteAttributeString(CSCHEMAVERSION, CSCHEMAVERSIONNUMBER); writer.WriteStartElement(PSVERSION); writer.WriteString(version.ToString()); writer.WriteEndElement(); // MonadVersion writer.WriteStartElement(SNAPINS); foreach (PSSnapInInfo mshSnapIn in snapins) { writer.WriteStartElement(SNAPIN); writer.WriteAttributeString(SNAPINNAME, mshSnapIn.Name); writer.WriteEndElement(); } writer.WriteEndElement(); // MshSnapins writer.WriteEndElement(); // Monad_ConsoleFile writer.WriteEndDocument(); } } s_mshsnapinTracer.WriteLine("Saving console info succeeded."); } /// /// Reads a Monad Console file specified by and constructs /// a PSConsoleFileElement. /// /// The absolute path of the file to read from. /// A MShConsoleFileElement object that represents content of the console file. /// The return object wont be null. /// /// There is a load or parser error in the XML. /// /// internal static PSConsoleFileElement CreateFromFile(string path) { Diagnostics.Assert(path != null, "Filename should not be null"); s_mshsnapinTracer.WriteLine("Loading console info from file {0}.", path); XmlDocument doc = InternalDeserializer.LoadUnsafeXmlDocument( new FileInfo(path), false, /* ignore whitespace, comments, etc. */ null); /* default maxCharactersInDocument */ // Validate content if (doc[MSHCONSOLEFILE] == null) { s_mshsnapinTracer.TraceError("Console file {0} doesn't contain tag {1}.", path, MSHCONSOLEFILE); throw new XmlException( StringUtil.Format(ConsoleInfoErrorStrings.MonadConsoleNotFound, path)); } if ((doc[MSHCONSOLEFILE][PSVERSION] == null) || (string.IsNullOrEmpty(doc[MSHCONSOLEFILE][PSVERSION].InnerText))) { s_mshsnapinTracer.TraceError("Console file {0} doesn't contain tag {1}.", path, PSVERSION); throw new XmlException( StringUtil.Format(ConsoleInfoErrorStrings.MonadVersionNotFound, path)); } // This will never be null.. XmlElement xmlElement = (XmlElement)doc[MSHCONSOLEFILE]; if (xmlElement.HasAttribute(CSCHEMAVERSION)) { if (!xmlElement.GetAttribute(CSCHEMAVERSION).Equals(CSCHEMAVERSIONNUMBER, StringComparison.OrdinalIgnoreCase)) { string resourceTemplate = StringUtil.Format(ConsoleInfoErrorStrings.BadConsoleVersion, path); string message = string.Format(CultureInfo.CurrentCulture, resourceTemplate, CSCHEMAVERSIONNUMBER); s_mshsnapinTracer.TraceError(message); throw new XmlException(message); } } else { s_mshsnapinTracer.TraceError("Console file {0} doesn't contain tag schema version.", path); throw new XmlException( StringUtil.Format(ConsoleInfoErrorStrings.BadConsoleVersion, path)); } //process MonadVersion //This will never be null.. xmlElement = (XmlElement)doc[MSHCONSOLEFILE][PSVERSION]; // Construct PSConsoleFileElement as we seem to have valid data PSConsoleFileElement consoleFileElement = new PSConsoleFileElement(xmlElement.InnerText.Trim()); bool isPSSnapInsProcessed = false; bool isPSVersionProcessed = false; for (XmlNode mshSnapInsNode = doc["PSConsoleFile"].FirstChild; mshSnapInsNode != null; mshSnapInsNode = mshSnapInsNode.NextSibling) { if (mshSnapInsNode.NodeType == XmlNodeType.Comment) { // support comments inside a PSConsoleFile Element continue; } //populate mshsnapin information xmlElement = mshSnapInsNode as XmlElement; if (null == xmlElement) { throw new XmlException(ConsoleInfoErrorStrings.BadXMLFormat); } if (xmlElement.Name == PSVERSION) { if (isPSVersionProcessed) { s_mshsnapinTracer.TraceError("Console file {0} contains more than one msh versions", path); throw new XmlException(StringUtil.Format(ConsoleInfoErrorStrings.MultipleMshSnapinsElementNotSupported, PSVERSION)); } isPSVersionProcessed = true; continue; } if (xmlElement.Name != SNAPINS) { s_mshsnapinTracer.TraceError("Tag {0} is not supported in console file", xmlElement.Name); throw new XmlException(StringUtil.Format(ConsoleInfoErrorStrings.BadXMLElementFound, xmlElement.Name, MSHCONSOLEFILE, PSVERSION, SNAPINS)); } // PSSnapIns element is already processed. We dont support multiple // PSSnapIns elements if (isPSSnapInsProcessed) { s_mshsnapinTracer.TraceError("Console file {0} contains more than one mshsnapin lists", path); throw new XmlException(StringUtil.Format(ConsoleInfoErrorStrings.MultipleMshSnapinsElementNotSupported, SNAPINS)); } // We are about to process mshsnapins element..so we should not // process some more mshsnapins elements..this boolean keeps track // of this. isPSSnapInsProcessed = true; // decode all the child nodes of node... for (XmlNode mshSnapInNode = xmlElement.FirstChild; mshSnapInNode != null; mshSnapInNode = mshSnapInNode.NextSibling) { XmlElement mshSnapInElement = mshSnapInNode as XmlElement; if ((null == mshSnapInElement) || (mshSnapInElement.Name != SNAPIN)) { throw new XmlException( StringUtil.Format(ConsoleInfoErrorStrings.PSSnapInNotFound, mshSnapInNode.Name)); } string id = mshSnapInElement.GetAttribute(SNAPINNAME); if (string.IsNullOrEmpty(id)) { throw new XmlException(ConsoleInfoErrorStrings.IDNotFound); } consoleFileElement.PSSnapIns.Add(id); s_mshsnapinTracer.WriteLine("Found in mshsnapin {0} in console file {1}", id, path); } } return consoleFileElement; } #endregion } /// /// Class that manages(reads/writes) Monad Console files and constructs objects /// that represent data in the console files. /// /// Functionality: /// 1. Access point to the console files for Runspace and cmdlets /// 2. Depends on PSConsoleFileElement for reading/writing files /// /// internal class MshConsoleInfo { #region Private Data // Monad Version that this console file depends on. // MshSnapins that are not shipped with monad. private readonly Collection _externalPSSnapIns; // Monad specific mshsnapins private Collection _defaultPSSnapIns; // An internal representation that tells whether a console file is modified. // A string that stores fileName of the current consoleinfo object #endregion #region Class specific data private static readonly PSTraceSource s_mshsnapinTracer = PSTraceSource.GetTracer("MshSnapinLoadUnload", "Loading and unloading mshsnapins", false); #endregion #region Properties /// /// Monad Version that the console file depends on. /// internal Version PSVersion { get; } /// /// Returns the major version of current console. /// internal string MajorVersion { get { Diagnostics.Assert(PSVersion != null, "PSVersion is null"); return PSVersion.Major.ToString(System.Globalization.CultureInfo.InvariantCulture); } } /// /// List of mshsnapins that are available. This includes both the monad /// default mshsnapins as well as external mshsnapins as represented by the /// console file. /// /// /// The list returned is an ordered-list with default mshsnapins at the /// start followed by external mshsnapins in the order represented by the /// console file. /// internal Collection PSSnapIns { get { return MergeDefaultExternalMshSnapins(); } } /// /// List of external mshsnapins, as represented by the console file and cmdlets /// add-pssnapin,remove-pssnapin, that are available. /// internal Collection ExternalPSSnapIns { get { // externalPSSnapIns is never null Diagnostics.Assert(_externalPSSnapIns != null, "externalPSSnapIns is null"); return _externalPSSnapIns; } } /// /// A boolean which tells whether the console file is modified after it is read /// or created. /// /// /// Modification refers to addition/deletion operations of the external mshsnapins. /// internal bool IsDirty { get; private set; } /// /// A string representing the console file name of the current MshConsoleInfo object. /// If the filename is relative path, an absolute path will be constructed using /// Path.GetFullPath() /// /// /// Once a MshConsoleInfo object is constructed, a user may update the object by /// adding,removing mshsnapins. These operations directly effect the state of the /// MshConsoleInfo object but not update the console file. /// internal string Filename { get; private set; } #endregion #region Constructors /// /// Construct a MshConsoleInfo object for the Monad version specified. /// /// Monad Version. private MshConsoleInfo(Version version) { PSVersion = version; IsDirty = false; Filename = null; // Initialize list of mshsnapins.. _defaultPSSnapIns = new Collection(); _externalPSSnapIns = new Collection(); } #endregion #region Staic Methods /// /// Constructs a object for the /// current Monad version which is already started. /// /// /// One or more default mshsnapins cannot be loaded because the /// registry is not populated correctly. /// internal static MshConsoleInfo CreateDefaultConfiguration() { // Steps: // 1. Get the current Monad Version // 2. Create MshConsoleInfo object. // 3. Read default mshsnapins. MshConsoleInfo consoleInfo = new MshConsoleInfo(PSVersionInfo.PSVersion); try { consoleInfo._defaultPSSnapIns = PSSnapInReader.ReadEnginePSSnapIns(); } catch (PSArgumentException ae) { string message = ConsoleInfoErrorStrings.CannotLoadDefaults; // If we were unable to load default mshsnapins throw PSSnapInException s_mshsnapinTracer.TraceError(message); throw new PSSnapInException(message, ae); } catch (System.Security.SecurityException se) { string message = ConsoleInfoErrorStrings.CannotLoadDefaults; // If we were unable to load default mshsnapins throw PSSnapInException s_mshsnapinTracer.TraceError(message); throw new PSSnapInException(message, se); } return consoleInfo; } /// /// Constructs a object from a /// Monad console file. /// /// /// Monad console file name. If the filename is not absolute path. Then absolute path is /// constructed by using Path.GetFullPath() API. /// /// /// PSConsoleLoadException occurred while loading this console file. This object /// also contains specific PSSnapInExceptions that occurred while loading. /// /// /// One or more default mshsnapins cannot be loaded because the /// registry is not populated correctly. /// /// /// fileName is null. /// /// /// 1. fileName does not specify proper file extension. /// /// /// fileName contains one or more of the invalid characters defined in System.IO.Path.InvalidPathChars. /// /// /// Unable to load/parse the file specified by fileName. /// internal static MshConsoleInfo CreateFromConsoleFile(string fileName, out PSConsoleLoadException cle) { s_mshsnapinTracer.WriteLine("Creating console info from file {0}", fileName); // Construct default mshsnapins MshConsoleInfo consoleInfo = CreateDefaultConfiguration(); // Check whether the filename specified is an absolute path. string absolutePath = Path.GetFullPath(fileName); consoleInfo.Filename = absolutePath; // Construct externalPSSnapIns by loading file. consoleInfo.Load(absolutePath, out cle); s_mshsnapinTracer.WriteLine("Console info created successfully"); return consoleInfo; } #endregion #region Internal Instance Methods /// /// Saves the current object to a file specified /// by . IsDirty is set to false once file is saved. /// /// /// If path is not an absolute path, then an absolute path is constructed by /// using Path.GetFullPath() API. /// /// /// 1.Path does not specify proper file extension. /// /// /// 1. Path is null. /// /// /// path contains one or more of the invalid characters defined in System.IO.Path.InvalidPathChars. /// internal void SaveAsConsoleFile(string path) { if (null == path) { throw PSTraceSource.NewArgumentNullException("path"); } // Check whether the filename specified is an absolute path. string absolutePath = path; if (!Path.IsPathRooted(absolutePath)) { absolutePath = Path.GetFullPath(Filename); } // Ignore case when looking for file extension. if (!absolutePath.EndsWith(StringLiterals.PowerShellConsoleFileExtension, StringComparison.OrdinalIgnoreCase)) { s_mshsnapinTracer.TraceError("Console file {0} doesn't have the right extension {1}.", path, StringLiterals.PowerShellConsoleFileExtension); throw PSTraceSource.NewArgumentException("absolutePath", ConsoleInfoErrorStrings.BadConsoleExtension); } //ConsoleFileElement will write to file PSConsoleFileElement.WriteToFile(absolutePath, this.PSVersion, this.ExternalPSSnapIns); //update the console file variable Filename = absolutePath; IsDirty = false; } /// /// Saves the current object to its console file. /// IsDirty is set to false once file is saved. /// /// /// Msh is loaded with default mshsnapins. $console is currently empty. /// internal void Save() { if (null == Filename) { throw PSTraceSource.NewInvalidOperationException(ConsoleInfoErrorStrings.SaveDefaultError); } PSConsoleFileElement.WriteToFile(Filename, this.PSVersion, this.ExternalPSSnapIns); IsDirty = false; } /// /// Adds a mshsnapin specified by to the current list of /// mshsnapins. If the mshsnapin is successfully added, IsDirty property is set to true. /// /// ID of the mshsnapin which needs to be added. /// A object corresponding to mshSnapInID. /// PSSnapIn information must be present in the registry for this call to succeed. /// /// mshSnapInID is empty or null. /// /// /// PSSnapIn is already loaded. /// No PSSnapIn with given id found. /// PSSnapIn cannot be loaded. /// /// /// Caller doesn't have permission to read keys. /// internal PSSnapInInfo AddPSSnapIn(string mshSnapInID) { if (string.IsNullOrEmpty(mshSnapInID)) { PSTraceSource.NewArgumentNullException("mshSnapInID"); } // Check whether the mshsnapin is already present in defaultmshsnapins/externalMshSnapins if (IsDefaultPSSnapIn(mshSnapInID, _defaultPSSnapIns)) { s_mshsnapinTracer.TraceError("MshSnapin {0} can't be added since it is a default mshsnapin", mshSnapInID); throw PSTraceSource.NewArgumentException("mshSnapInID", ConsoleInfoErrorStrings.CannotLoadDefault); } if (IsActiveExternalPSSnapIn(mshSnapInID)) { s_mshsnapinTracer.TraceError("MshSnapin {0} is already loaded.", mshSnapInID); throw PSTraceSource.NewArgumentException("mshSnapInID", ConsoleInfoErrorStrings.PSSnapInAlreadyExists, mshSnapInID); } // Check whether the mshsnapin is present in the registry. PSSnapInInfo newPSSnapIn = PSSnapInReader.Read(this.MajorVersion, mshSnapInID); if (!Utils.IsPSVersionSupported(newPSSnapIn.PSVersion.ToString())) { s_mshsnapinTracer.TraceError("MshSnapin {0} and current monad engine's versions don't match.", mshSnapInID); throw PSTraceSource.NewArgumentException("mshSnapInID", ConsoleInfoErrorStrings.AddPSSnapInBadMonadVersion, newPSSnapIn.PSVersion.ToString(), PSVersion.ToString()); } // new mshsnapin will never be null //if this is a valid new mshsnapin,add this to external mshsnapins _externalPSSnapIns.Add(newPSSnapIn); s_mshsnapinTracer.WriteLine("MshSnapin {0} successfully added to consoleinfo list.", mshSnapInID); //Set IsDirty to true IsDirty = true; return newPSSnapIn; } /// /// Removes a mshsnapin specified by from the current /// list. /// /// ID of the mshsnapin which needs to be removed /// PSSnapInInfo object for the mshsnapin that is removed. /// MshSnapin is removed only from the console file. Registry entry /// is not touched. /// /// mshSnapInID is null. /// /// /// 1. mshSnapInID is either a default mshsnapin or not loaded. /// 2. mshSnapInId is not valid. /// internal PSSnapInInfo RemovePSSnapIn(string mshSnapInID) { if (string.IsNullOrEmpty(mshSnapInID)) { PSTraceSource.NewArgumentNullException("mshSnapInID"); } // Monad has specific restrictions on the mshsnapinid like // mshsnapinid should be A-Za-z0-9.-_ etc. PSSnapInInfo.VerifyPSSnapInFormatThrowIfError(mshSnapInID); PSSnapInInfo removedPSSnapIn = null; // Check external mshsnapins foreach (PSSnapInInfo mshSnapIn in _externalPSSnapIns) { if (string.Equals(mshSnapInID, mshSnapIn.Name, System.StringComparison.OrdinalIgnoreCase)) { // We found the mshsnapin..remove from the list and break removedPSSnapIn = mshSnapIn; _externalPSSnapIns.Remove(mshSnapIn); // The state of console file is changing..so set // dirty flag. IsDirty = true; break; } } if (removedPSSnapIn == null) { if (IsDefaultPSSnapIn(mshSnapInID, _defaultPSSnapIns)) { s_mshsnapinTracer.WriteLine("MshSnapin {0} can't be removed since it is a default mshsnapin.", mshSnapInID); throw PSTraceSource.NewArgumentException("mshSnapInID", ConsoleInfoErrorStrings.CannotRemoveDefault, mshSnapInID); } throw PSTraceSource.NewArgumentException("mshSnapInID", ConsoleInfoErrorStrings.CannotRemovePSSnapIn, mshSnapInID); } return removedPSSnapIn; } /// /// Searches for mshsnapin in either current console or registry as determined /// by . /// /// /// Id/WildcardPattern of the mshsnapin to search for. This can contain wildcard characters as /// represented by WildCardPattern. /// /// /// A boolean which determines whether to search in the current console or registry. /// /// A collection of mshsnapininfo objects. /// /// 1.Unable to read registry entries for mshsnapins. /// 2.Pattern specified is not valid. If pattern doesnt contain /// wildcard characters, this function checks for the validity /// of the mshsnapin name. /// /// /// Caller doesn't have permission to read keys. /// internal Collection GetPSSnapIn(string pattern, bool searchRegistry) { // We want to improve the search speed by noting whether we want // to perform wildcard search. bool doWildCardSearch = WildcardPattern.ContainsWildcardCharacters(pattern); if (!doWildCardSearch) { // Verify PSSnapInID.. // This will throw if it not a valid name PSSnapInInfo.VerifyPSSnapInFormatThrowIfError(pattern); } // Build the list to search..If searchRegistry is true get all mshsnapins available // from the registry, otherwise get mshsnapins from the current console. Collection listToSearch = searchRegistry ? PSSnapInReader.ReadAll() : PSSnapIns; // Create a list to return.. Collection listToReturn = new Collection(); // If there is nothing to search.. if (listToSearch == null) return listToReturn; if (!doWildCardSearch) { // We are not doing wildcard search.. foreach (PSSnapInInfo mshSnapIn in listToSearch) { if (string.Equals(mshSnapIn.Name, pattern, StringComparison.OrdinalIgnoreCase)) { listToReturn.Add(mshSnapIn); } } } else { WildcardPattern matcher = WildcardPattern.Get(pattern, WildcardOptions.IgnoreCase); // We are doing WildCard search foreach (PSSnapInInfo mshSnapIn in listToSearch) { if (matcher.IsMatch(mshSnapIn.Name)) { listToReturn.Add(mshSnapIn); } } } // return whatever we found..may be 0.. return listToReturn; } #endregion #region Private Methods /// /// Loads a Monad Console file specified by /// /// /// The absolute path from which the content is loaded. /// /// /// PSConsoleLoadException occurred while loading this console file. This object /// also contains specific PSSnapInExceptions that occurred while loading. /// /// /// A list of objects specified in the console file. /// /// /// Path is null. /// /// /// 1. Path does not specify proper file extension. /// 2. PSSnapInId doesnt contain valid characters. /// 3. Path is not an Absolute Path. /// Example of valid paths:"\\MyDir\\MyFile.txt" and "C:\\MyDir". /// /// /// path contains one or more of the invalid characters defined in System.IO.Path.InvalidPathChars. /// /// /// Unable to load/parse the file specified by path. /// private Collection Load(string path, out PSConsoleLoadException cle) { // Initialize the out parameter.. cle = null; s_mshsnapinTracer.WriteLine("Load mshsnapins from console file {0}", path); if (string.IsNullOrEmpty(path)) { throw PSTraceSource.NewArgumentNullException("path"); } // Check whether the path is an absolute path if (!Path.IsPathRooted(path)) { s_mshsnapinTracer.TraceError("Console file {0} needs to be a absolute path.", path); throw PSTraceSource.NewArgumentException("path", ConsoleInfoErrorStrings.PathNotAbsolute, path); } if (!path.EndsWith(StringLiterals.PowerShellConsoleFileExtension, StringComparison.OrdinalIgnoreCase)) { s_mshsnapinTracer.TraceError("Console file {0} needs to have {1} extension.", path, StringLiterals.PowerShellConsoleFileExtension); throw PSTraceSource.NewArgumentException("path", ConsoleInfoErrorStrings.BadConsoleExtension); } PSConsoleFileElement consoleFileElement; // exceptions are thrown to the caller consoleFileElement = PSConsoleFileElement.CreateFromFile(path); // consoleFileElement will never be null.. if (!Utils.IsPSVersionSupported(consoleFileElement.MonadVersion)) { s_mshsnapinTracer.TraceError("Console version {0} is not supported in current monad session.", consoleFileElement.MonadVersion); throw PSTraceSource.NewArgumentException("PSVersion", ConsoleInfoErrorStrings.BadMonadVersion, consoleFileElement.MonadVersion, PSVersion.ToString()); } // Create a store for exceptions Collection exceptions = new Collection(); foreach (string mshsnapin in consoleFileElement.PSSnapIns) { try { this.AddPSSnapIn(mshsnapin); } catch (PSArgumentException ae) { PSSnapInException sle = new PSSnapInException(mshsnapin, ae.Message, ae); // Eat ArgumentException and continue.. exceptions.Add(sle); } catch (System.Security.SecurityException se) { string message = ConsoleInfoErrorStrings.PSSnapInReadError; PSSnapInException sle = new PSSnapInException(mshsnapin, message, se); // Eat SecurityException and continue.. exceptions.Add(sle); } } // Before returning check whether there are any exceptions if (exceptions.Count > 0) { cle = new PSConsoleLoadException(this, exceptions); } // We are able to load console file and currently monad engine // can service this. So mark the isdirty flag. IsDirty = false; return _externalPSSnapIns; } /// /// Checks whether the mshsnapin is a default mshsnapin /// /// Id of the mshsnapin /// List of default mshsnapins /// True if PSSnapIn is default.False otherwise. internal static bool IsDefaultPSSnapIn(string mshSnapInID, IEnumerable defaultSnapins) { // Check whether the mshsnapin is present in defaultmshsnapins. foreach (PSSnapInInfo mshSnapIn in defaultSnapins) { if (string.Equals(mshSnapInID, mshSnapIn.Name, System.StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } /// /// Checks whether the mshsnapin is already loaded /// /// Id of the mshsnapin /// True if PSSnapIn is loaded.False otherwise. private bool IsActiveExternalPSSnapIn(string mshSnapInID) { // Check whether the mshsnapin is present in externalmshsnapins. foreach (PSSnapInInfo mshSnapIn in _externalPSSnapIns) { if (string.Equals(mshSnapInID, mshSnapIn.Name, System.StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } /// /// Constructs a new list of mshsnapins from default mshsnapins and external mshsnapins. /// /// A list of mshsnapins represented by the current console file private Collection MergeDefaultExternalMshSnapins() { //Default mshsnapins should never be null Diagnostics.Assert(_defaultPSSnapIns != null, "Default MshSnapins for the current console is empty"); Collection mshSnapIns = new Collection(); foreach (PSSnapInInfo mshSnapIn in _defaultPSSnapIns) { mshSnapIns.Add(mshSnapIn); } foreach (PSSnapInInfo mshSnapIn in _externalPSSnapIns) { mshSnapIns.Add(mshSnapIn); } return mshSnapIns; } #endregion } }