/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System.Collections.Generic; using System.Collections.ObjectModel; using Microsoft.Win32; using System.Security; using System.IO; using System.Reflection; using System.Text; using System.Globalization; using Regex = System.Text.RegularExpressions.Regex; using Dbg = System.Management.Automation.Diagnostics; using Microsoft.PowerShell.Commands; namespace System.Management.Automation { internal static class RegistryStrings { /// /// Root key path under HKLM /// internal const string MonadRootKeyPath = "Software\\Microsoft\\PowerShell"; /// /// Root key name /// internal const string MonadRootKeyName = "PowerShell"; /// /// Key for monad engine /// internal const string MonadEngineKey = "PowerShellEngine"; // Name for various values under PSEngine internal const string MonadEngine_ApplicationBase = "ApplicationBase"; internal const string MonadEngine_ConsoleHostAssemblyName = "ConsoleHostAssemblyName"; internal const string MonadEngine_ConsoleHostModuleName = "ConsoleHostModuleName"; internal const string MonadEngine_RuntimeVersion = "RuntimeVersion"; internal const string MonadEngine_MonadVersion = "PowerShellVersion"; /// /// Key under which all the mshsnapin live /// internal const string MshSnapinKey = "PowerShellSnapIns"; //Name of various values for each mshsnapin internal const string MshSnapin_ApplicationBase = "ApplicationBase"; internal const string MshSnapin_AssemblyName = "AssemblyName"; internal const string MshSnapin_ModuleName = "ModuleName"; internal const string MshSnapin_MonadVersion = "PowerShellVersion"; internal const string MshSnapin_CustomPSSnapInType = "CustomPSSnapInType"; internal const string MshSnapin_BuiltInTypes = "Types"; internal const string MshSnapin_BuiltInFormats = "Formats"; internal const string MshSnapin_Description = "Description"; internal const string MshSnapin_Version = "Version"; internal const string MshSnapin_Vendor = "Vendor"; internal const string MshSnapin_DescriptionResource = "DescriptionIndirect"; internal const string MshSnapin_VendorResource = "VendorIndirect"; internal const string MshSnapin_LogPipelineExecutionDetails = "LogPipelineExecutionDetails"; //Name of default mshsnapins internal const string CoreMshSnapinName = "Microsoft.PowerShell.Core"; internal const string HostMshSnapinName = "Microsoft.PowerShell.Host"; internal const string ManagementMshSnapinName = "Microsoft.PowerShell.Management"; internal const string SecurityMshSnapinName = "Microsoft.PowerShell.Security"; internal const string UtilityMshSnapinName = "Microsoft.PowerShell.Utility"; } /// /// Contains information about a mshsnapin /// public class PSSnapInInfo { internal PSSnapInInfo ( string name, bool isDefault, string applicationBase, string assemblyName, string moduleName, Version psVersion, Version version, Collection types, Collection formats, string descriptionFallback, string vendorFallback, string customPSSnapInType ) { if (string.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentNullException("name"); } if (string.IsNullOrEmpty(applicationBase)) { throw PSTraceSource.NewArgumentNullException("applicationBase"); } if (string.IsNullOrEmpty(assemblyName)) { throw PSTraceSource.NewArgumentNullException("assemblyName"); } if (string.IsNullOrEmpty(moduleName)) { throw PSTraceSource.NewArgumentNullException("moduleName"); } if (psVersion == null) { throw PSTraceSource.NewArgumentNullException("psVersion"); } #if CORECLR // CustomPSSnapIn Not Supported On CSS. // CustomPSSnapIn derives from System.Configuration.Install, which is not in CoreCLR. if (customPSSnapInType != null) { throw PSTraceSource.NewArgumentException( "customPSSnapInType", MshSnapInCmdletResources.CustomPSSnapInNotSupportedInPowerShellCore); } #endif if (version == null) { version = new Version("0.0"); } if (types == null) { types = new Collection(); } if (formats == null) { formats = new Collection(); } if (descriptionFallback == null) { descriptionFallback = String.Empty; } if (vendorFallback == null) { vendorFallback = String.Empty; } Name = name; IsDefault = isDefault; ApplicationBase = applicationBase; AssemblyName = assemblyName; ModuleName = moduleName; PSVersion = psVersion; Version = version; Types = types; Formats = formats; CustomPSSnapInType = customPSSnapInType; _descriptionFallback = descriptionFallback; _vendorFallback = vendorFallback; } internal PSSnapInInfo ( string name, bool isDefault, string applicationBase, string assemblyName, string moduleName, Version psVersion, Version version, Collection types, Collection formats, string description, string descriptionFallback, string vendor, string vendorFallback, string customPSSnapInType ) : this(name, isDefault, applicationBase, assemblyName, moduleName, psVersion, version, types, formats, descriptionFallback, vendorFallback, customPSSnapInType) { _description = description; _vendor = vendor; } internal PSSnapInInfo ( string name, bool isDefault, string applicationBase, string assemblyName, string moduleName, Version psVersion, Version version, Collection types, Collection formats, string description, string descriptionFallback, string descriptionIndirect, string vendor, string vendorFallback, string vendorIndirect, string customPSSnapInType ) : this(name, isDefault, applicationBase, assemblyName, moduleName, psVersion, version, types, formats, description, descriptionFallback, vendor, vendorFallback, customPSSnapInType) { // add descriptionIndirect and vendorIndirect only if the mshsnapin is a default mshsnapin if (isDefault) { _descriptionIndirect = descriptionIndirect; _vendorIndirect = vendorIndirect; } } /// /// Unique Name of the mshsnapin /// public string Name { get; } /// /// Is this mshsnapin default mshsnapin /// public bool IsDefault { get; } /// /// Retuns applicationbase for mshsnapin /// public string ApplicationBase { get; } /// /// Strong name of mshSnapIn assembly /// public string AssemblyName { get; } /// /// Name of PSSnapIn module /// public string ModuleName { get; } internal string AbsoluteModulePath { get { if (String.IsNullOrEmpty(ModuleName) || Path.IsPathRooted(ModuleName)) { return ModuleName; } else if (!File.Exists(Path.Combine(ApplicationBase, ModuleName))) { return Path.GetFileNameWithoutExtension(ModuleName); } return Path.Combine(ApplicationBase, ModuleName); } } /// /// Type of custom mshsnapin. /// internal string CustomPSSnapInType { get; } /// /// Monad version used by mshsnapin /// public Version PSVersion { get; } /// /// Version of mshsnapin /// public Version Version { get; } /// /// Collection of file names containing types information for PSSnapIn. /// public Collection Types { get; } /// /// Collection of file names containing format information for PSSnapIn /// public Collection Formats { get; } private string _descriptionIndirect; private string _descriptionFallback = String.Empty; private string _description; /// /// Description of mshsnapin /// public string Description { get { if (_description == null) { LoadIndirectResources(); } return _description; } } private string _vendorIndirect; private string _vendorFallback = String.Empty; private string _vendor; /// /// Vendor of mshsnapin /// public string Vendor { get { if (_vendor == null) { LoadIndirectResources(); } return _vendor; } } /// /// Get/set whether to log Pipeline Execution Detail events. /// public bool LogPipelineExecutionDetails { get; set; } = false; /// /// Overrides ToString /// /// /// Name of the PSSnapIn /// public override string ToString() { return Name; } internal RegistryKey MshSnapinKey { get { RegistryKey mshsnapinKey = null; try { mshsnapinKey = PSSnapInReader.GetMshSnapinKey(Name, PSVersion.Major.ToString(CultureInfo.InvariantCulture)); } catch (ArgumentException) { } catch (SecurityException) { } catch (System.IO.IOException) { } return mshsnapinKey; } } internal void LoadIndirectResources() { using (RegistryStringResourceIndirect resourceReader = RegistryStringResourceIndirect.GetResourceIndirectReader()) { LoadIndirectResources(resourceReader); } } internal void LoadIndirectResources(RegistryStringResourceIndirect resourceReader) { if (IsDefault) { // For default mshsnapins..resource indirects are hardcoded.. // so dont read from the registry _description = resourceReader.GetResourceStringIndirect( AssemblyName, ModuleName, _descriptionIndirect); _vendor = resourceReader.GetResourceStringIndirect( AssemblyName, ModuleName, _vendorIndirect); } else { RegistryKey mshsnapinKey = MshSnapinKey; if (mshsnapinKey != null) { _description = resourceReader.GetResourceStringIndirect( mshsnapinKey, RegistryStrings.MshSnapin_DescriptionResource, AssemblyName, ModuleName); _vendor = resourceReader.GetResourceStringIndirect( mshsnapinKey, RegistryStrings.MshSnapin_VendorResource, AssemblyName, ModuleName); } } if (String.IsNullOrEmpty(_description)) { _description = _descriptionFallback; } if (String.IsNullOrEmpty(_vendor)) { _vendor = _vendorFallback; } } internal PSSnapInInfo Clone() { PSSnapInInfo cloned = new PSSnapInInfo(Name, IsDefault, ApplicationBase, AssemblyName, ModuleName, PSVersion, Version, new Collection(Types), new Collection(Formats), _description, _descriptionFallback, _descriptionIndirect, _vendor, _vendorFallback, _vendorIndirect, CustomPSSnapInType ); return cloned; } /// /// Returns true if the PSSnapIn Id is valid. A PSSnapIn is valid iff it contains only /// "Alpha Numeric","-","_","." characters. /// /// PSSnapIn Id to validate internal static bool IsPSSnapinIdValid(string psSnapinId) { if (String.IsNullOrEmpty(psSnapinId)) { return false; } return Regex.IsMatch(psSnapinId, "^[A-Za-z0-9-_\x2E]*$"); } /// /// Validates the PSSnapIn Id. A PSSnapIn is valid iff it contains only /// "Alpha Numeric","-","_","." characters. /// /// PSSnapIn Id to validate /// /// 1. Specified PSSnapIn is not valid /// internal static void VerifyPSSnapInFormatThrowIfError(string psSnapinId) { // PSSnapIn do not conform to the naming convention..so throw // argument exception if (!IsPSSnapinIdValid(psSnapinId)) { throw PSTraceSource.NewArgumentException("mshSnapInId", MshSnapInCmdletResources.InvalidPSSnapInName, psSnapinId); } // Valid SnapId..Just return return; } } /// /// Internal class to read information about a mshsnapin /// internal static class PSSnapInReader { /// /// Reads all registered mshsnapin for all monad versions. /// /// /// A collection of PSSnapInInfo objects /// /// /// User doesn't have access to monad/mshsnapin registration information /// /// /// Monad key is not installed /// internal static Collection ReadAll() { Collection allMshSnapins = new Collection(); RegistryKey monadRootKey = GetMonadRootKey(); string[] versions = monadRootKey.GetSubKeyNames(); if (versions == null) { return allMshSnapins; } // PS V3 snapin information is stored under 1 registry key.. // so no need to iterate over twice. Collection filterdVersions = new Collection(); foreach (string version in versions) { string temp = PSVersionInfo.GetRegisteryVersionKeyForSnapinDiscovery(version); if (string.IsNullOrEmpty(temp)) { temp = version; } if (!filterdVersions.Contains(temp)) { filterdVersions.Add(temp); } } foreach (string version in filterdVersions) { if (string.IsNullOrEmpty(version)) { continue; } //found a key which is not version if (!MeetsVersionFormat(version)) { continue; } Collection oneVersionMshSnapins = null; try { oneVersionMshSnapins = ReadAll(monadRootKey, version); } //If we cannot get information for one version, continue with other //versions catch (SecurityException) { } catch (ArgumentException) { } if (oneVersionMshSnapins != null) { foreach (PSSnapInInfo info in oneVersionMshSnapins) { allMshSnapins.Add(info); } } } return allMshSnapins; } /// /// Version should be integer (1, 2, 3 etc) /// /// /// private static bool MeetsVersionFormat(string version) { bool r = true; try { LanguagePrimitives.ConvertTo(version, typeof(int), CultureInfo.InvariantCulture); } catch (PSInvalidCastException) { r = false; } return r; } /// /// Reads all registered mshsnapin for specified psVersion /// /// /// A collection of PSSnapInInfo objects /// /// /// User doesn't have permission to read MonadRoot or Version /// /// /// MonadRoot or Version key doesn't exist. /// internal static Collection ReadAll(string psVersion) { if (string.IsNullOrEmpty(psVersion)) { throw PSTraceSource.NewArgumentNullException("psVersion"); } RegistryKey monadRootKey = GetMonadRootKey(); return ReadAll(monadRootKey, psVersion); } /// /// Reads all the mshsnapins for a given psVersion /// /// /// The User doesn't have required permission to read the registry key for this version. /// /// /// Specified version doesn't exist. /// /// /// User doesn't have permission to read specified version /// private static Collection ReadAll(RegistryKey monadRootKey, string psVersion) { Dbg.Assert(monadRootKey != null, "caller should validate the information"); Dbg.Assert(!string.IsNullOrEmpty(psVersion), "caller should validate the information"); Collection mshsnapins = new Collection(); RegistryKey versionRoot = GetVersionRootKey(monadRootKey, psVersion); RegistryKey mshsnapinRoot = GetMshSnapinRootKey(versionRoot, psVersion); //get name of all mshsnapin for this version string[] mshsnapinIds = mshsnapinRoot.GetSubKeyNames(); foreach (string id in mshsnapinIds) { if (string.IsNullOrEmpty(id)) { continue; } try { mshsnapins.Add(ReadOne(mshsnapinRoot, id)); } //If we cannot read some mshsnapins, we should contiune catch (SecurityException) { } catch (ArgumentException) { } } return mshsnapins; } /// /// Read mshsnapin for specified mshsnapinId and psVersion /// /// /// MshSnapin info object /// /// /// The user does not have the permissions required to read the /// registry key for one of the following: /// 1) Monad /// 2) PSVersion /// 3) MshSnapinId /// /// /// 1) Monad key is not present /// 2) VersionKey is not present /// 3) MshSnapin key is not present /// 4) MshSnapin key is not valid /// internal static PSSnapInInfo Read(string psVersion, string mshsnapinId) { if (string.IsNullOrEmpty(psVersion)) { throw PSTraceSource.NewArgumentNullException("psVersion"); } if (string.IsNullOrEmpty(mshsnapinId)) { throw PSTraceSource.NewArgumentNullException("mshsnapinId"); } // PSSnapIn Reader wont service invalid mshsnapins // Monad has specific restrictions on the mshsnapinid like // mshsnapinid should be A-Za-z0-9.-_ etc. PSSnapInInfo.VerifyPSSnapInFormatThrowIfError(mshsnapinId); RegistryKey rootKey = GetMonadRootKey(); RegistryKey versionRoot = GetVersionRootKey(rootKey, psVersion); RegistryKey mshsnapinRoot = GetMshSnapinRootKey(versionRoot, psVersion); return ReadOne(mshsnapinRoot, mshsnapinId); } /// /// Reads the mshsnapin info for a specific key under specific monad version /// /// /// ReadOne will never create a default PSSnapInInfo object. /// /// /// The user does not have the permissions required to read the /// registry key for specified mshsnapin. /// /// /// 1) Specified mshsnapin is not installed. /// 2) Specified mshsnapin is not correctly installed. /// private static PSSnapInInfo ReadOne(RegistryKey mshSnapInRoot, string mshsnapinId) { Dbg.Assert(!string.IsNullOrEmpty(mshsnapinId), "caller should validate the parameter"); Dbg.Assert(mshSnapInRoot != null, "caller should validate the parameter"); RegistryKey mshsnapinKey; mshsnapinKey = mshSnapInRoot.OpenSubKey(mshsnapinId); if (mshsnapinKey == null) { s_mshsnapinTracer.TraceError("Error opening registry key {0}\\{1}.", mshSnapInRoot.Name, mshsnapinId); throw PSTraceSource.NewArgumentException("mshsnapinId", MshSnapinInfo.MshSnapinDoesNotExist, mshsnapinId); } string applicationBase = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_ApplicationBase, true); string assemblyName = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_AssemblyName, true); string moduleName = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_ModuleName, true); Version monadVersion = ReadVersionValue(mshsnapinKey, RegistryStrings.MshSnapin_MonadVersion, true); Version version = ReadVersionValue(mshsnapinKey, RegistryStrings.MshSnapin_Version, false); string description = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_Description, false); if (description == null) { s_mshsnapinTracer.WriteLine("No description is specified for mshsnapin {0}. Using empty string for description.", mshsnapinId); description = string.Empty; } string vendor = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_Vendor, false); if (vendor == null) { s_mshsnapinTracer.WriteLine("No vendor is specified for mshsnapin {0}. Using empty string for description.", mshsnapinId); vendor = string.Empty; } bool logPipelineExecutionDetails = false; string logPipelineExecutionDetailsStr = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_LogPipelineExecutionDetails, false); if (!String.IsNullOrEmpty(logPipelineExecutionDetailsStr)) { if (String.Compare("1", logPipelineExecutionDetailsStr, StringComparison.OrdinalIgnoreCase) == 0) logPipelineExecutionDetails = true; } string customPSSnapInType = ReadStringValue(mshsnapinKey, RegistryStrings.MshSnapin_CustomPSSnapInType, false); if (string.IsNullOrEmpty(customPSSnapInType)) { customPSSnapInType = null; } Collection types = ReadMultiStringValue(mshsnapinKey, RegistryStrings.MshSnapin_BuiltInTypes, false); Collection formats = ReadMultiStringValue(mshsnapinKey, RegistryStrings.MshSnapin_BuiltInFormats, false); s_mshsnapinTracer.WriteLine("Successfully read registry values for mshsnapin {0}. Constructing PSSnapInInfo object.", mshsnapinId); PSSnapInInfo mshSnapinInfo = new PSSnapInInfo(mshsnapinId, false, applicationBase, assemblyName, moduleName, monadVersion, version, types, formats, description, vendor, customPSSnapInType); mshSnapinInfo.LogPipelineExecutionDetails = logPipelineExecutionDetails; return mshSnapinInfo; } /// /// Gets multistring value for name /// /// /// /// /// /// /// if value is not present and mandatory is true /// private static Collection ReadMultiStringValue(RegistryKey mshsnapinKey, string name, bool mandatory) { object value = mshsnapinKey.GetValue(name); if (value == null) { // If this key should be present..throw error if (mandatory) { s_mshsnapinTracer.TraceError("Mandatory property {0} not specified for registry key {1}", name, mshsnapinKey.Name); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.MandatoryValueNotPresent, name, mshsnapinKey.Name); } else { return null; } } // value cannot be null here... string[] msv = value as string[]; if (msv == null) { //Check if the value is in string format string singleValue = value as string; if (singleValue != null) { msv = new string[1]; msv[0] = singleValue; } } if (msv == null) { if (mandatory) { s_mshsnapinTracer.TraceError("Cannot get string/multi-string value for mandatory property {0} in registry key {1}", name, mshsnapinKey.Name); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.MandatoryValueNotInCorrectFormatMultiString, name, mshsnapinKey.Name); } else { return null; } } s_mshsnapinTracer.WriteLine("Successfully read property {0} from {1}", name, mshsnapinKey.Name); return new Collection(msv); } /// /// Get the value for name /// /// /// /// /// /// /// if no value is available and mandatory is true. /// internal static string ReadStringValue(RegistryKey mshsnapinKey, string name, bool mandatory) { Dbg.Assert(!string.IsNullOrEmpty(name), "caller should validate the parameter"); Dbg.Assert(mshsnapinKey != null, "Caller should validate the parameter"); object value = mshsnapinKey.GetValue(name); if (value == null && mandatory == true) { s_mshsnapinTracer.TraceError("Mandatory property {0} not specified for registry key {1}", name, mshsnapinKey.Name); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.MandatoryValueNotPresent, name, mshsnapinKey.Name); } string s = value as string; if (string.IsNullOrEmpty(s) && mandatory == true) { s_mshsnapinTracer.TraceError("Value is null or empty for mandatory property {0} in {1}", name, mshsnapinKey.Name); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.MandatoryValueNotInCorrectFormat, name, mshsnapinKey.Name); } s_mshsnapinTracer.WriteLine("Successfully read value {0} for property {1} from {2}", s, name, mshsnapinKey.Name); return s; } internal static Version ReadVersionValue(RegistryKey mshsnapinKey, string name, bool mandatory) { string temp = ReadStringValue(mshsnapinKey, name, mandatory); if (temp == null) { s_mshsnapinTracer.TraceError("Cannot read value for property {0} in registry key {1}", name, mshsnapinKey.ToString()); Dbg.Assert(!mandatory, "mandatory is true, ReadStringValue should have thrown exception"); return null; } Version v; try { v = new Version(temp); } catch (ArgumentOutOfRangeException) { s_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name); } catch (ArgumentException) { s_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name); } catch (OverflowException) { s_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name); } catch (FormatException) { s_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp); throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name); } s_mshsnapinTracer.WriteLine("Successfully converted string {0} to version format.", v); return v; } internal static void ReadRegistryInfo(out Version assemblyVersion, out string publicKeyToken, out string culture, out string architecture, out string applicationBase, out Version psVersion) { applicationBase = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID); Dbg.Assert(!string.IsNullOrEmpty(applicationBase), string.Format(CultureInfo.CurrentCulture, "{0} is empty or null", RegistryStrings.MonadEngine_ApplicationBase)); // Get the PSVersion from Utils..this is hardcoded psVersion = PSVersionInfo.PSVersion; Dbg.Assert(psVersion != null, string.Format(CultureInfo.CurrentCulture, "{0} is null", RegistryStrings.MonadEngine_MonadVersion)); // Get version number in x.x.x.x format // This information is available from the exeucting assembly // // PROBLEM: The following code assumes all assemblies have the same version, // culture, publickeytoken...This will break the scenarios where only one of // the assemblies is patched. ie., all monad assemblies should have the // same version number. Assembly currentAssembly = typeof(PSSnapInReader).GetTypeInfo().Assembly; assemblyVersion = currentAssembly.GetName().Version; byte[] publicTokens = currentAssembly.GetName().GetPublicKeyToken(); if (publicTokens.Length == 0) { throw PSTraceSource.NewArgumentException("PublicKeyToken", MshSnapinInfo.PublicKeyTokenAccessFailed); } publicKeyToken = ConvertByteArrayToString(publicTokens); // save some cpu cycles by hardcoding the culture to neutral // assembly should never be targeted to a particular culture culture = "neutral"; // Hardcoding the architecture MSIL as PowerShell assemblies are architecture neutral, this should // be changed if the assumption is broken. Preferred hardcoded string to using (for perf reasons): // string architecture = currentAssembly.GetName().ProcessorArchitecture.ToString() architecture = "MSIL"; } /// /// PublicKeyToken is in the form of byte[]. Use this function to convert to a string /// /// array of byte's /// internal static string ConvertByteArrayToString(byte[] tokens) { Dbg.Assert(tokens != null, "Input tokens should never be null"); StringBuilder tokenBuilder = new StringBuilder(tokens.Length * 2); foreach (byte b in tokens) { tokenBuilder.Append(b.ToString("x2", CultureInfo.InvariantCulture)); } return tokenBuilder.ToString(); } /// /// Reads core snapin for monad engine /// /// /// A PSSnapInInfo object /// internal static PSSnapInInfo ReadCoreEngineSnapIn() { Version assemblyVersion, psVersion; string publicKeyToken = null; string culture = null; string architecture = null; string applicationBase = null; ReadRegistryInfo(out assemblyVersion, out publicKeyToken, out culture, out architecture, out applicationBase, out psVersion); // System.Management.Automation formats & types files Collection types = new Collection(new string[] { "types.ps1xml", "typesv3.ps1xml" }); Collection formats = new Collection(new string[] {"Certificate.format.ps1xml","DotNetTypes.format.ps1xml","FileSystem.format.ps1xml", "Help.format.ps1xml","HelpV3.format.ps1xml","PowerShellCore.format.ps1xml","PowerShellTrace.format.ps1xml", "Registry.format.ps1xml"}); string strongName = string.Format(CultureInfo.InvariantCulture, "{0}, Version={1}, Culture={2}, PublicKeyToken={3}, ProcessorArchitecture={4}", s_coreSnapin.AssemblyName, assemblyVersion, culture, publicKeyToken, architecture); string moduleName = Path.Combine(applicationBase, s_coreSnapin.AssemblyName + ".dll"); PSSnapInInfo coreMshSnapin = new PSSnapInInfo(s_coreSnapin.PSSnapInName, true, applicationBase, strongName, moduleName, psVersion, assemblyVersion, types, formats, null, s_coreSnapin.Description, s_coreSnapin.DescriptionIndirect, null, null, s_coreSnapin.VendorIndirect, null); SetSnapInLoggingInformation(coreMshSnapin); return coreMshSnapin; } /// /// Reads all registered mshsnapins for currently executing monad engine /// /// /// A collection of PSSnapInInfo objects /// internal static Collection ReadEnginePSSnapIns() { Version assemblyVersion, psVersion; string publicKeyToken = null; string culture = null; string architecture = null; string applicationBase = null; ReadRegistryInfo(out assemblyVersion, out publicKeyToken, out culture, out architecture, out applicationBase, out psVersion); // System.Management.Automation formats & types files Collection smaFormats = new Collection(new string[] {"Certificate.format.ps1xml","DotNetTypes.format.ps1xml","FileSystem.format.ps1xml", "Help.format.ps1xml","HelpV3.format.ps1xml","PowerShellCore.format.ps1xml","PowerShellTrace.format.ps1xml", "Registry.format.ps1xml"}); Collection smaTypes = new Collection(new string[] { "types.ps1xml", "typesv3.ps1xml" }); // create default mshsnapininfo objects.. Collection engineMshSnapins = new Collection(); for (int item = 0; item < DefaultMshSnapins.Count; item++) { DefaultPSSnapInInformation defaultMshSnapinInfo = DefaultMshSnapins[item]; string strongName = string.Format(CultureInfo.InvariantCulture, "{0}, Version={1}, Culture={2}, PublicKeyToken={3}, ProcessorArchitecture={4}", defaultMshSnapinInfo.AssemblyName, assemblyVersion.ToString(), culture, publicKeyToken, architecture); Collection formats = null; Collection types = null; if (defaultMshSnapinInfo.AssemblyName.Equals("System.Management.Automation", StringComparison.OrdinalIgnoreCase)) { formats = smaFormats; types = smaTypes; } else if (defaultMshSnapinInfo.AssemblyName.Equals("Microsoft.PowerShell.Commands.Diagnostics", StringComparison.OrdinalIgnoreCase)) { types = new Collection(new string[] { "GetEvent.types.ps1xml" }); formats = new Collection(new string[] { "Event.format.ps1xml", "Diagnostics.format.ps1xml" }); } else if (defaultMshSnapinInfo.AssemblyName.Equals("Microsoft.WSMan.Management", StringComparison.OrdinalIgnoreCase)) { formats = new Collection(new string[] { "WSMan.format.ps1xml" }); } string moduleName = Path.Combine(applicationBase, defaultMshSnapinInfo.AssemblyName + ".dll"); if (File.Exists(moduleName)) { moduleName = Path.Combine(applicationBase, defaultMshSnapinInfo.AssemblyName + ".dll"); } else { moduleName = defaultMshSnapinInfo.AssemblyName; } PSSnapInInfo defaultMshSnapin = new PSSnapInInfo(defaultMshSnapinInfo.PSSnapInName, true, applicationBase, strongName, moduleName, psVersion, assemblyVersion, types, formats, null, defaultMshSnapinInfo.Description, defaultMshSnapinInfo.DescriptionIndirect, null, null, defaultMshSnapinInfo.VendorIndirect, null); SetSnapInLoggingInformation(defaultMshSnapin); engineMshSnapins.Add(defaultMshSnapin); } return engineMshSnapins; } /// /// Enable Snapin logging based on group policy /// private static void SetSnapInLoggingInformation(PSSnapInInfo psSnapInInfo) { IEnumerable names; ModuleCmdletBase.ModuleLoggingGroupPolicyStatus status = ModuleCmdletBase.GetModuleLoggingInformation(out names); if (status != ModuleCmdletBase.ModuleLoggingGroupPolicyStatus.Undefined) { SetSnapInLoggingInformation(psSnapInInfo, status, names); } } /// /// Enable Snapin logging based on group policy /// private static void SetSnapInLoggingInformation(PSSnapInInfo psSnapInInfo, ModuleCmdletBase.ModuleLoggingGroupPolicyStatus status, IEnumerable moduleOrSnapinNames) { if (((status & ModuleCmdletBase.ModuleLoggingGroupPolicyStatus.Enabled) != 0) && moduleOrSnapinNames != null) { foreach (string currentGPModuleOrSnapinName in moduleOrSnapinNames) { if (string.Equals(psSnapInInfo.Name, currentGPModuleOrSnapinName, StringComparison.OrdinalIgnoreCase)) { psSnapInInfo.LogPipelineExecutionDetails = true; } else if (WildcardPattern.ContainsWildcardCharacters(currentGPModuleOrSnapinName)) { WildcardPattern wildcard = WildcardPattern.Get(currentGPModuleOrSnapinName, WildcardOptions.IgnoreCase); if (wildcard.IsMatch(psSnapInInfo.Name)) { psSnapInInfo.LogPipelineExecutionDetails = true; } } } } } /// /// Get the key to monad root /// /// /// /// Caller doesn't have access to monad registration information. /// /// /// Monad registration information is not available. /// internal static RegistryKey GetMonadRootKey() { RegistryKey rootKey = Registry.LocalMachine.OpenSubKey(RegistryStrings.MonadRootKeyPath); if (rootKey == null) { //This should never occur because this code is running //because monad is installed. { well this can occur if someone //deletes the registry key after starting monad Dbg.Assert(false, "Root Key of Monad installation is not present"); throw PSTraceSource.NewArgumentException("monad", MshSnapinInfo.MonadRootRegistryAccessFailed); } return rootKey; } /// /// Get the registry key to PSEngine. /// /// RegistryKey /// Major version in string format. /// /// Monad registration information is not available. /// internal static RegistryKey GetPSEngineKey(string psVersion) { RegistryKey rootKey = GetMonadRootKey(); // root key wont be null Dbg.Assert(rootKey != null, "Root Key of Monad installation is not present"); RegistryKey versionRootKey = GetVersionRootKey(rootKey, psVersion); // version root key wont be null Dbg.Assert(versionRootKey != null, "Version Rootkey of Monad installation is not present"); RegistryKey psEngineParentKey = rootKey.OpenSubKey(psVersion); if (psEngineParentKey == null) { throw PSTraceSource.NewArgumentException("monad", MshSnapinInfo.MonadEngineRegistryAccessFailed); } RegistryKey psEngineKey = psEngineParentKey.OpenSubKey(RegistryStrings.MonadEngineKey); if (psEngineKey == null) { throw PSTraceSource.NewArgumentException("monad", MshSnapinInfo.MonadEngineRegistryAccessFailed); } return psEngineKey; } /// /// Gets the version root key for specified monad version /// /// /// /// /// /// Caller doesn't have permission to read the version key /// /// /// specified psVersion key is not present /// internal static RegistryKey GetVersionRootKey(RegistryKey rootKey, string psVersion) { Dbg.Assert(!string.IsNullOrEmpty(psVersion), "caller should validate the parameter"); Dbg.Assert(rootKey != null, "caller should validate the parameter"); string versionKey = PSVersionInfo.GetRegisteryVersionKeyForSnapinDiscovery(psVersion); RegistryKey versionRoot = rootKey.OpenSubKey(versionKey); if (versionRoot == null) { throw PSTraceSource.NewArgumentException("psVersion", MshSnapinInfo.SpecifiedVersionNotFound, versionKey); } return versionRoot; } /// /// Gets the mshsnapin root key for specified monad version /// /// /// /// /// /// Caller doesn't have permission to read the mshsnapin key /// /// /// mshsnapin key is not present /// private static RegistryKey GetMshSnapinRootKey(RegistryKey versionRootKey, string psVersion) { Dbg.Assert(versionRootKey != null, "caller should validate the parameter"); RegistryKey mshsnapinRoot = versionRootKey.OpenSubKey(RegistryStrings.MshSnapinKey); if (mshsnapinRoot == null) { throw PSTraceSource.NewArgumentException("psVersion", MshSnapinInfo.NoMshSnapinPresentForVersion, psVersion); } return mshsnapinRoot; } /// /// Gets the mshsnapin key for specified monad version and mshsnapin name /// /// /// /// /// /// Caller doesn't have permission to read the mshsnapin key /// /// /// mshsnapin key is not present /// internal static RegistryKey GetMshSnapinKey(string mshSnapInName, string psVersion) { RegistryKey monadRootKey = GetMonadRootKey(); RegistryKey versionRootKey = GetVersionRootKey(monadRootKey, psVersion); RegistryKey mshsnapinRoot = versionRootKey.OpenSubKey(RegistryStrings.MshSnapinKey); if (mshsnapinRoot == null) { throw PSTraceSource.NewArgumentException("psVersion", MshSnapinInfo.NoMshSnapinPresentForVersion, psVersion); } RegistryKey mshsnapinKey = mshsnapinRoot.OpenSubKey(mshSnapInName); return mshsnapinKey; } #region Default MshSnapins related structure /// /// This structure is meant to hold mshsnapin information for default mshsnapins. /// This is private only. /// private struct DefaultPSSnapInInformation { // since this is a private structure..making it as simple as possible public string PSSnapInName; public string AssemblyName; public string Description; public string DescriptionIndirect; public string VendorIndirect; public DefaultPSSnapInInformation(string sName, string sAssemblyName, string sDescription, string sDescriptionIndirect, string sVendorIndirect) { PSSnapInName = sName; AssemblyName = sAssemblyName; Description = sDescription; DescriptionIndirect = sDescriptionIndirect; VendorIndirect = sVendorIndirect; } } private static DefaultPSSnapInInformation s_coreSnapin = new DefaultPSSnapInInformation("Microsoft.PowerShell.Core", "System.Management.Automation", null, "CoreMshSnapInResources,Description", "CoreMshSnapInResources,Vendor"); /// /// /// private static IList DefaultMshSnapins { get { if (s_defaultMshSnapins == null) { lock (s_syncObject) { if (s_defaultMshSnapins == null) { s_defaultMshSnapins = new List() { #if !UNIX new DefaultPSSnapInInformation("Microsoft.PowerShell.Diagnostics", "Microsoft.PowerShell.Commands.Diagnostics", null, "GetEventResources,Description", "GetEventResources,Vendor"), #endif new DefaultPSSnapInInformation("Microsoft.PowerShell.Host", "Microsoft.PowerShell.ConsoleHost", null, "HostMshSnapInResources,Description","HostMshSnapInResources,Vendor"), s_coreSnapin, new DefaultPSSnapInInformation("Microsoft.PowerShell.Utility", "Microsoft.PowerShell.Commands.Utility", null, "UtilityMshSnapInResources,Description","UtilityMshSnapInResources,Vendor"), new DefaultPSSnapInInformation("Microsoft.PowerShell.Management", "Microsoft.PowerShell.Commands.Management", null, "ManagementMshSnapInResources,Description","ManagementMshSnapInResources,Vendor"), new DefaultPSSnapInInformation("Microsoft.PowerShell.Security", "Microsoft.PowerShell.Security", null, "SecurityMshSnapInResources,Description","SecurityMshSnapInResources,Vendor") }; #if !UNIX if (!Utils.IsWinPEHost()) { s_defaultMshSnapins.Add(new DefaultPSSnapInInformation("Microsoft.WSMan.Management", "Microsoft.WSMan.Management", null, "WsManResources,Description", "WsManResources,Vendor")); } #endif } } } return s_defaultMshSnapins; } } private static IList s_defaultMshSnapins = null; private static object s_syncObject = new object(); #endregion private static PSTraceSource s_mshsnapinTracer = PSTraceSource.GetTracer("MshSnapinLoadUnload", "Loading and unloading mshsnapins", false); } }