mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 12:45:47 +00:00
1454 lines
55 KiB
C#
1454 lines
55 KiB
C#
/********************************************************************++
|
|
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;
|
|
using Microsoft.PowerShell;
|
|
|
|
namespace System.Management.Automation
|
|
{
|
|
internal static class RegistryStrings
|
|
{
|
|
/// <summary>
|
|
/// Root key path under HKLM
|
|
/// </summary>
|
|
internal const string MonadRootKeyPath = "Software\\Microsoft\\PowerShell";
|
|
|
|
/// <summary>
|
|
/// Root key name
|
|
/// </summary>
|
|
internal const string MonadRootKeyName = "PowerShell";
|
|
|
|
/// <summary>
|
|
/// Key for monad engine
|
|
/// </summary>
|
|
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";
|
|
|
|
/// <summary>
|
|
/// Key under which all the mshsnapin live
|
|
/// </summary>
|
|
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";
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Contains information about a mshsnapin
|
|
/// </summary>
|
|
public class PSSnapInInfo
|
|
{
|
|
internal PSSnapInInfo
|
|
(
|
|
string name,
|
|
bool isDefault,
|
|
string applicationBase,
|
|
string assemblyName,
|
|
string moduleName,
|
|
Version psVersion,
|
|
Version version,
|
|
Collection<string> types,
|
|
Collection<string> 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<string>();
|
|
}
|
|
|
|
if (formats == null)
|
|
{
|
|
formats = new Collection<string>();
|
|
}
|
|
|
|
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<string> types,
|
|
Collection<string> formats,
|
|
string description,
|
|
string descriptionFallback,
|
|
string vendor,
|
|
string vendorFallback,
|
|
string customPSSnapInType
|
|
)
|
|
: this(name, isDefault, applicationBase, assemblyName, moduleName, psVersion, version, types, formats, descriptionFallback, vendorFallback, customPSSnapInType)
|
|
{
|
|
this._description = description;
|
|
this._vendor = vendor;
|
|
}
|
|
|
|
internal PSSnapInInfo
|
|
(
|
|
string name,
|
|
bool isDefault,
|
|
string applicationBase,
|
|
string assemblyName,
|
|
string moduleName,
|
|
Version psVersion,
|
|
Version version,
|
|
Collection<string> types,
|
|
Collection<string> 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)
|
|
{
|
|
this._descriptionIndirect = descriptionIndirect;
|
|
this._vendorIndirect = vendorIndirect;
|
|
}
|
|
}
|
|
|
|
private string _name;
|
|
/// <summary>
|
|
/// Unique Name of the mshsnapin
|
|
/// </summary>
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
return _name;
|
|
}
|
|
}
|
|
|
|
private bool _isDefault;
|
|
/// <summary>
|
|
/// Is this mshsnapin default mshsnapin
|
|
/// </summary>
|
|
public bool IsDefault
|
|
{
|
|
get
|
|
{
|
|
return _isDefault;
|
|
}
|
|
}
|
|
|
|
private string _applicationBase;
|
|
/// <summary>
|
|
/// Retuns applicationbase for mshsnapin
|
|
/// </summary>
|
|
public string ApplicationBase
|
|
{
|
|
get
|
|
{
|
|
return _applicationBase;
|
|
}
|
|
}
|
|
|
|
private string _assemblyName;
|
|
/// <summary>
|
|
/// Strong name of mshSnapIn assembly
|
|
/// </summary>
|
|
public string AssemblyName
|
|
{
|
|
get
|
|
{
|
|
return _assemblyName;
|
|
}
|
|
}
|
|
|
|
private string _moduleName;
|
|
/// <summary>
|
|
/// Name of PSSnapIn module
|
|
/// </summary>
|
|
public string ModuleName
|
|
{
|
|
get
|
|
{
|
|
return _moduleName;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
private string _customPSSnapInType;
|
|
/// <summary>
|
|
/// Type of custom mshsnapin.
|
|
/// </summary>
|
|
internal string CustomPSSnapInType
|
|
{
|
|
get
|
|
{
|
|
return _customPSSnapInType;
|
|
}
|
|
}
|
|
|
|
private Version _psVersion;
|
|
/// <summary>
|
|
/// Monad version used by mshsnapin
|
|
/// </summary>
|
|
public Version PSVersion
|
|
{
|
|
get
|
|
{
|
|
return _psVersion;
|
|
}
|
|
}
|
|
|
|
private Version _version;
|
|
/// <summary>
|
|
/// Version of mshsnapin
|
|
/// </summary>
|
|
public Version Version
|
|
{
|
|
get
|
|
{
|
|
return _version;
|
|
}
|
|
}
|
|
|
|
private Collection<string> _types;
|
|
/// <summary>
|
|
/// Collection of file names containing types information for PSSnapIn.
|
|
/// </summary>
|
|
public Collection<string> Types
|
|
{
|
|
get
|
|
{
|
|
return _types;
|
|
}
|
|
}
|
|
|
|
private Collection<string> _formats;
|
|
/// <summary>
|
|
/// Collection of file names containing format information for PSSnapIn
|
|
/// </summary>
|
|
public Collection<string> Formats
|
|
{
|
|
get
|
|
{
|
|
return _formats;
|
|
}
|
|
}
|
|
|
|
private string _descriptionIndirect;
|
|
private string _descriptionFallback = String.Empty;
|
|
private string _description;
|
|
/// <summary>
|
|
/// Description of mshsnapin
|
|
/// </summary>
|
|
public string Description
|
|
{
|
|
get
|
|
{
|
|
if (_description == null)
|
|
{
|
|
LoadIndirectResources();
|
|
}
|
|
return _description;
|
|
}
|
|
}
|
|
|
|
private string _vendorIndirect;
|
|
private string _vendorFallback = String.Empty;
|
|
private string _vendor;
|
|
/// <summary>
|
|
/// Vendor of mshsnapin
|
|
/// </summary>
|
|
public string Vendor
|
|
{
|
|
get
|
|
{
|
|
if (_vendor == null)
|
|
{
|
|
LoadIndirectResources();
|
|
}
|
|
return _vendor;
|
|
}
|
|
}
|
|
|
|
private bool _logPipelineExecutionDetails = false;
|
|
|
|
/// <summary>
|
|
/// Get/set whether to log Pipeline Execution Detail events.
|
|
/// </summary>
|
|
public bool LogPipelineExecutionDetails
|
|
{
|
|
get
|
|
{
|
|
return _logPipelineExecutionDetails;
|
|
}
|
|
set
|
|
{
|
|
_logPipelineExecutionDetails = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overrides ToString
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Name of the PSSnapIn
|
|
/// </returns>
|
|
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<string>(Types),
|
|
new Collection<string>(Formats), _description,
|
|
_descriptionFallback, _descriptionIndirect, _vendor, _vendorFallback, _vendorIndirect,
|
|
_customPSSnapInType
|
|
);
|
|
|
|
return cloned;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Returns true if the PSSnapIn Id is valid. A PSSnapIn is valid iff it contains only
|
|
/// "Alpha Numeric","-","_","." characters.
|
|
/// </summary>
|
|
/// <param name="psSnapinId">PSSnapIn Id to validate</param>
|
|
static internal bool IsPSSnapinIdValid(string psSnapinId)
|
|
{
|
|
if (String.IsNullOrEmpty(psSnapinId))
|
|
{
|
|
return false;
|
|
}
|
|
return Regex.IsMatch(psSnapinId, "^[A-Za-z0-9-_\x2E]*$");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validates the PSSnapIn Id. A PSSnapIn is valid iff it contains only
|
|
/// "Alpha Numeric","-","_","." characters.
|
|
/// </summary>
|
|
/// <param name="psSnapinId">PSSnapIn Id to validate</param>
|
|
/// <exception cref="PSArgumentException">
|
|
/// 1. Specified PSSnapIn is not valid
|
|
/// </exception>
|
|
static internal 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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Internal class to read information about a mshsnapin
|
|
/// </summary>
|
|
internal static class PSSnapInReader
|
|
{
|
|
/// <summary>
|
|
/// Reads all registered mshsnapin for all monad versions.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A collection of PSSnapInInfo objects
|
|
/// </returns>
|
|
/// <exception cref="SecurityException">
|
|
/// User doesn't have access to monad/mshsnapin registration information
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// Monad key is not installed
|
|
/// </exception>
|
|
static internal
|
|
Collection<PSSnapInInfo>
|
|
ReadAll()
|
|
{
|
|
Collection<PSSnapInInfo> allMshSnapins = new Collection<PSSnapInInfo>();
|
|
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<string> filterdVersions = new Collection<string>();
|
|
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<PSSnapInInfo> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Version should be integer (1, 2, 3 etc)
|
|
/// </summary>
|
|
/// <param name="version"></param>
|
|
/// <returns></returns>
|
|
private
|
|
static
|
|
bool MeetsVersionFormat(string version)
|
|
{
|
|
bool r = true;
|
|
try
|
|
{
|
|
LanguagePrimitives.ConvertTo(version, typeof(int), CultureInfo.InvariantCulture);
|
|
}
|
|
catch (PSInvalidCastException)
|
|
{
|
|
r = false;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Reads all registered mshsnapin for specified psVersion
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A collection of PSSnapInInfo objects
|
|
/// </returns>
|
|
/// <exception cref="SecurityException">
|
|
/// User doesn't have permission to read MonadRoot or Version
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// MonadRoot or Version key doesn't exist.
|
|
/// </exception>
|
|
static internal
|
|
Collection<PSSnapInInfo>
|
|
ReadAll(string psVersion)
|
|
{
|
|
if (string.IsNullOrEmpty(psVersion))
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("psVersion");
|
|
}
|
|
RegistryKey monadRootKey = GetMonadRootKey();
|
|
return ReadAll(monadRootKey, psVersion);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads all the mshsnapins for a given psVersion
|
|
/// </summary>
|
|
/// <exception cref="SecurityException">
|
|
/// The User doesn't have required permission to read the registry key for this version.
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// Specified version doesn't exist.
|
|
/// </exception>
|
|
/// <exception cref="SecurityException">
|
|
/// User doesn't have permission to read specified version
|
|
/// </exception>
|
|
static private
|
|
Collection<PSSnapInInfo>
|
|
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<PSSnapInInfo> mshsnapins = new Collection<PSSnapInInfo>();
|
|
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;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Read mshsnapin for specified mshsnapinId and psVersion
|
|
/// </summary>
|
|
/// <returns>
|
|
/// MshSnapin info object
|
|
/// </returns>
|
|
/// <exception cref="SecurityException">
|
|
/// The user does not have the permissions required to read the
|
|
/// registry key for one of the following:
|
|
/// 1) Monad
|
|
/// 2) PSVersion
|
|
/// 3) MshSnapinId
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// 1) Monad key is not present
|
|
/// 2) VersionKey is not present
|
|
/// 3) MshSnapin key is not present
|
|
/// 4) MshSnapin key is not valid
|
|
/// </exception>
|
|
static internal
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Reads the mshsnapin info for a specific key under specific monad version
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// ReadOne will never create a default PSSnapInInfo object.
|
|
/// </remarks>
|
|
/// <exception cref="SecurityException">
|
|
/// The user does not have the permissions required to read the
|
|
/// registry key for specified mshsnapin.
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// 1) Specified mshsnapin is not installed.
|
|
/// 2) Specified mshsnapin is not correctly installed.
|
|
/// </exception>
|
|
static private
|
|
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)
|
|
{
|
|
_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)
|
|
{
|
|
_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)
|
|
{
|
|
_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<string> types = ReadMultiStringValue(mshsnapinKey, RegistryStrings.MshSnapin_BuiltInTypes, false);
|
|
Collection<string> formats = ReadMultiStringValue(mshsnapinKey, RegistryStrings.MshSnapin_BuiltInFormats, false);
|
|
|
|
_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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets multistring value for name
|
|
/// </summary>
|
|
/// <param name="mshsnapinKey"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="mandatory"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ArgumentException">
|
|
/// if value is not present and mandatory is true
|
|
/// </exception>
|
|
static private
|
|
Collection<string>
|
|
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)
|
|
{
|
|
_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)
|
|
{
|
|
_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;
|
|
}
|
|
}
|
|
|
|
_mshsnapinTracer.WriteLine("Successfully read property {0} from {1}",
|
|
name, mshsnapinKey.Name);
|
|
return new Collection<string>(msv);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the value for name
|
|
/// </summary>
|
|
/// <param name="mshsnapinKey"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="mandatory"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ArgumentException">
|
|
/// if no value is available and mandatory is true.
|
|
/// </exception>
|
|
static internal
|
|
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)
|
|
{
|
|
_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)
|
|
{
|
|
_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);
|
|
}
|
|
|
|
_mshsnapinTracer.WriteLine("Successfully read value {0} for property {1} from {2}",
|
|
s, name, mshsnapinKey.Name);
|
|
return s;
|
|
}
|
|
|
|
static internal
|
|
Version
|
|
ReadVersionValue(RegistryKey mshsnapinKey, string name, bool mandatory)
|
|
{
|
|
string temp = ReadStringValue(mshsnapinKey, name, mandatory);
|
|
if (temp == null)
|
|
{
|
|
_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)
|
|
{
|
|
_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp);
|
|
throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name);
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp);
|
|
throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name);
|
|
}
|
|
catch (OverflowException)
|
|
{
|
|
_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp);
|
|
throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name);
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
_mshsnapinTracer.TraceError("Cannot convert value {0} to version format", temp);
|
|
throw PSTraceSource.NewArgumentException("name", MshSnapinInfo.VersionValueInCorrect, name, mshsnapinKey.Name);
|
|
}
|
|
|
|
_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)
|
|
{
|
|
if (Platform.UsesCodeSignedAssemblies())
|
|
{
|
|
throw PSTraceSource.NewArgumentException("PublicKeyToken", MshSnapinInfo.PublicKeyTokenAccessFailed);
|
|
}
|
|
else
|
|
{
|
|
// Platform note: set this to null when code signed assemblies are
|
|
// unsupported (rather than blank)
|
|
publicKeyToken = "null";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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";
|
|
}
|
|
|
|
/// <summary>
|
|
/// PublicKeyToken is in the form of byte[]. Use this function to convert to a string
|
|
/// </summary>
|
|
/// <param name="tokens">array of byte's</param>
|
|
/// <returns></returns>
|
|
static internal 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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads core snapin for monad engine
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A PSSnapInInfo object
|
|
/// </returns>
|
|
static internal 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<string> types = new Collection<string>(new string[] { "types.ps1xml", "typesv3.ps1xml" });
|
|
Collection<string> formats = new Collection<string>(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"});
|
|
|
|
// If code signing is not supported, the token must be set to "null"
|
|
if (!Platform.UsesCodeSignedAssemblies())
|
|
{
|
|
publicKeyToken = "null";
|
|
}
|
|
|
|
string strongName = string.Format(CultureInfo.InvariantCulture, "{0}, Version={1}, Culture={2}, PublicKeyToken={3}, ProcessorArchitecture={4}",
|
|
CoreSnapin.AssemblyName, assemblyVersion, culture, publicKeyToken, architecture);
|
|
|
|
string moduleName = Path.Combine(applicationBase, CoreSnapin.AssemblyName + ".dll");
|
|
|
|
PSSnapInInfo coreMshSnapin = new PSSnapInInfo(CoreSnapin.PSSnapInName, true, applicationBase,
|
|
strongName, moduleName, psVersion, assemblyVersion, types, formats, null,
|
|
CoreSnapin.Description, CoreSnapin.DescriptionIndirect, null, null,
|
|
CoreSnapin.VendorIndirect, null);
|
|
SetSnapInLoggingInformation(coreMshSnapin);
|
|
|
|
return coreMshSnapin;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads all registered mshsnapins for currently executing monad engine
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A collection of PSSnapInInfo objects
|
|
/// </returns>
|
|
static internal Collection<PSSnapInInfo> 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<string> smaFormats = new Collection<string>(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<string> smaTypes = new Collection<string>(new string[] { "types.ps1xml", "typesv3.ps1xml" });
|
|
|
|
// create default mshsnapininfo objects..
|
|
Collection<PSSnapInInfo> engineMshSnapins = new Collection<PSSnapInInfo>();
|
|
|
|
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<string> formats = null;
|
|
Collection<string> 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<string>(new string[] { "GetEvent.types.ps1xml" });
|
|
formats = new Collection<string>(new string[] { "Event.format.ps1xml","Diagnostics.format.ps1xml" });
|
|
}
|
|
else if (defaultMshSnapinInfo.AssemblyName.Equals("Microsoft.WSMan.Management", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
formats = new Collection<string>(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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable Snapin logging based on group policy
|
|
/// </summary>
|
|
private static void SetSnapInLoggingInformation(PSSnapInInfo psSnapInInfo)
|
|
{
|
|
IEnumerable<String> names;
|
|
ModuleCmdletBase.ModuleLoggingGroupPolicyStatus status = ModuleCmdletBase.GetModuleLoggingInformation(out names);
|
|
if (status != ModuleCmdletBase.ModuleLoggingGroupPolicyStatus.Undefined)
|
|
{
|
|
SetSnapInLoggingInformation(psSnapInInfo, status, names);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enable Snapin logging based on group policy
|
|
/// </summary>
|
|
private static void SetSnapInLoggingInformation(PSSnapInInfo psSnapInInfo, ModuleCmdletBase.ModuleLoggingGroupPolicyStatus status, IEnumerable<string> 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the key to monad root
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <exception cref="SecurityException">
|
|
/// Caller doesn't have access to monad registration information.
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// Monad registration information is not available.
|
|
/// </exception>
|
|
static internal
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the registry key to PSEngine.
|
|
/// </summary>
|
|
/// <returns>RegistryKey</returns>
|
|
/// <param name="psVersion">Major version in string format.</param>
|
|
/// <exception cref="ArgumentException">
|
|
/// Monad registration information is not available.
|
|
/// </exception>
|
|
static internal
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the version root key for specified monad version
|
|
/// </summary>
|
|
/// <param name="rootKey"></param>
|
|
/// <param name="psVersion"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="SecurityException">
|
|
/// Caller doesn't have permission to read the version key
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// specified psVersion key is not present
|
|
/// </exception>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the mshsnapin root key for specified monad version
|
|
/// </summary>
|
|
/// <param name="versionRootKey"></param>
|
|
/// <param name="psVersion"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="SecurityException">
|
|
/// Caller doesn't have permission to read the mshsnapin key
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// mshsnapin key is not present
|
|
/// </exception>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the mshsnapin key for specified monad version and mshsnapin name
|
|
/// </summary>
|
|
/// <param name="mshSnapInName"></param>
|
|
/// <param name="psVersion"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="SecurityException">
|
|
/// Caller doesn't have permission to read the mshsnapin key
|
|
/// </exception>
|
|
/// <exception cref="ArgumentException">
|
|
/// mshsnapin key is not present
|
|
/// </exception>
|
|
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
|
|
|
|
/// <summary>
|
|
/// This structure is meant to hold mshsnapin information for default mshsnapins.
|
|
/// This is private only.
|
|
/// </summary>
|
|
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 CoreSnapin =
|
|
new DefaultPSSnapInInformation("Microsoft.PowerShell.Core", "System.Management.Automation", null,
|
|
"CoreMshSnapInResources,Description", "CoreMshSnapInResources,Vendor");
|
|
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
private static IList<DefaultPSSnapInInformation> DefaultMshSnapins
|
|
{
|
|
get
|
|
{
|
|
if (defaultMshSnapins == null)
|
|
{
|
|
lock (_syncObject)
|
|
{
|
|
if (defaultMshSnapins == null)
|
|
{
|
|
defaultMshSnapins = new List<DefaultPSSnapInInformation>()
|
|
{
|
|
#if !LINUX // Microsoft.PowerShell.Commands.Diagnostics.dll needs to be ported
|
|
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"),
|
|
|
|
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 !LINUX
|
|
if (!Utils.IsWinPEHost())
|
|
{
|
|
defaultMshSnapins.Add(new DefaultPSSnapInInformation("Microsoft.WSMan.Management", "Microsoft.WSMan.Management", null,
|
|
"WsManResources,Description", "WsManResources,Vendor"));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
return defaultMshSnapins;
|
|
}
|
|
}
|
|
private static IList<DefaultPSSnapInInformation> defaultMshSnapins = null;
|
|
private static object _syncObject = new object();
|
|
|
|
#endregion
|
|
|
|
static private PSTraceSource _mshsnapinTracer = PSTraceSource.GetTracer("MshSnapinLoadUnload", "Loading and unloading mshsnapins", false);
|
|
}
|
|
}
|
|
|
|
|