/********************************************************************++
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
}
}