Refactor PowerShell Core to use the default CoreCLR loader instead (#3903)
Remove the code that spins up our own assembly load context. Keep the code that registers our `Resolve` method to the default loader's `Resolving` event, so that we can continue to do special assembly resolution as needed (such as the GAC probing logic needed for consuming FullCLR PS modules). Essentially, the assembly `Microsoft.PowerShell.CoreCLR.AssemblyLoadContext.dll` is not needed anymore, the remaining code should be moved to S.M.A.dll. However, that will break DSC and other native hosts that are hosting powershell. So this assembly is kept for now.
This commit is contained in:
parent
73548532bc
commit
8ae6c5bb3b
@ -80,7 +80,7 @@ namespace Microsoft.PowerShell.Cim
|
||||
|
||||
internal void Copy(SecureString source, int offset)
|
||||
{
|
||||
IntPtr plainTextString = ClrFacade.SecureStringToCoTaskMemUnicode(source);
|
||||
IntPtr plainTextString = Marshal.SecureStringToCoTaskMemUnicode(source);
|
||||
try
|
||||
{
|
||||
unsafe
|
||||
|
@ -641,7 +641,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
//assigning to tempmodule to rethrow for exceptions on 64 bit machines
|
||||
tempmodule = pmodule;
|
||||
WriteObject(ClrFacade.GetProcessModuleFileVersionInfo(pmodule), true);
|
||||
WriteObject(pmodule.FileVersionInfo, true);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException exception)
|
||||
@ -658,7 +658,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
if (exception.HResult == 299)
|
||||
{
|
||||
WriteObject(ClrFacade.GetProcessModuleFileVersionInfo(tempmodule), true);
|
||||
WriteObject(tempmodule.FileVersionInfo, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -710,7 +710,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
//if fileversion of each process is to be displayed
|
||||
try
|
||||
{
|
||||
WriteObject(ClrFacade.GetProcessModuleFileVersionInfo(PsUtils.GetMainModule(process)), true);
|
||||
WriteObject(PsUtils.GetMainModule(process).FileVersionInfo, true);
|
||||
}
|
||||
catch (InvalidOperationException exception)
|
||||
{
|
||||
@ -726,7 +726,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
if (exception.HResult == 299)
|
||||
{
|
||||
WriteObject(ClrFacade.GetProcessModuleFileVersionInfo(PsUtils.GetMainModule(process)), true);
|
||||
WriteObject(PsUtils.GetMainModule(process).FileVersionInfo, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1966,7 +1966,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
//UseNewEnvironment
|
||||
if (_UseNewEnvironment)
|
||||
{
|
||||
ClrFacade.GetProcessEnvironment(startInfo).Clear();
|
||||
startInfo.EnvironmentVariables.Clear();
|
||||
LoadEnvironmentVariable(startInfo, Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine));
|
||||
LoadEnvironmentVariable(startInfo, Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User));
|
||||
}
|
||||
@ -2173,7 +2173,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
private void LoadEnvironmentVariable(ProcessStartInfo startinfo, IDictionary EnvironmentVariables)
|
||||
{
|
||||
var processEnvironment = ClrFacade.GetProcessEnvironment(startinfo);
|
||||
var processEnvironment = startinfo.EnvironmentVariables;
|
||||
foreach (DictionaryEntry entry in EnvironmentVariables)
|
||||
{
|
||||
if (processEnvironment.ContainsKey(entry.Key.ToString()))
|
||||
@ -2373,12 +2373,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static byte[] ConvertEnvVarsToByteArray(
|
||||
#if CORECLR
|
||||
IDictionary<string, string> sd)
|
||||
#else
|
||||
StringDictionary sd)
|
||||
#endif
|
||||
private static byte[] ConvertEnvVarsToByteArray(StringDictionary sd)
|
||||
{
|
||||
string[] array = new string[sd.Count];
|
||||
byte[] bytes = null;
|
||||
@ -2497,7 +2492,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
creationFlags |= 0x00000004;
|
||||
|
||||
IntPtr AddressOfEnvironmentBlock = IntPtr.Zero;
|
||||
var environmentVars = ClrFacade.GetProcessEnvironment(startinfo);
|
||||
var environmentVars = startinfo.EnvironmentVariables;
|
||||
if (environmentVars != null)
|
||||
{
|
||||
if (this.UseNewEnvironment)
|
||||
@ -2647,7 +2642,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
internal bool AssignProcessToJobObject(Process process)
|
||||
{
|
||||
// Add the process to the job object
|
||||
bool result = NativeMethods.AssignProcessToJobObject(_jobObjectHandle, ClrFacade.GetRawProcessHandle(process));
|
||||
bool result = NativeMethods.AssignProcessToJobObject(_jobObjectHandle, process.Handle);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2054,7 +2054,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
if (null != Credential)
|
||||
{
|
||||
username = Credential.UserName;
|
||||
password = ClrFacade.SecureStringToCoTaskMemUnicode(Credential.Password);
|
||||
password = Marshal.SecureStringToCoTaskMemUnicode(Credential.Password);
|
||||
}
|
||||
|
||||
// Create the service
|
||||
|
@ -964,7 +964,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
Assembly assembly = LoadAssemblyHelper(assemblyName);
|
||||
if (assembly == null)
|
||||
{
|
||||
assembly = LoadFrom(ResolveAssemblyName(assemblyName, false));
|
||||
assembly = Assembly.LoadFrom(ResolveAssemblyName(assemblyName, false));
|
||||
}
|
||||
|
||||
if (passThru)
|
||||
@ -1276,7 +1276,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
ms.Flush();
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
Assembly assembly = LoadFrom(ms);
|
||||
Assembly assembly = Assembly.Load(ms.ToArray());
|
||||
CheckTypesForDuplicates(assembly);
|
||||
if (passThru)
|
||||
{
|
||||
@ -1292,7 +1292,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
if (passThru)
|
||||
{
|
||||
Assembly assembly = LoadFrom(outputAssembly);
|
||||
Assembly assembly = Assembly.LoadFrom(outputAssembly);
|
||||
CheckTypesForDuplicates(assembly);
|
||||
WriteTypes(assembly);
|
||||
}
|
||||
@ -1318,16 +1318,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
ErrorNumber = d.Id
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
private Assembly LoadFrom(Stream assembly)
|
||||
{
|
||||
return ClrFacade.LoadFrom(assembly);
|
||||
}
|
||||
|
||||
private Assembly LoadFrom(string path)
|
||||
{
|
||||
return ClrFacade.LoadFrom(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1955,7 +1945,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
foreach (string path in paths)
|
||||
{
|
||||
generatedTypes.AddRange(ClrFacade.LoadFrom(path).GetTypes());
|
||||
generatedTypes.AddRange(Assembly.LoadFrom(path).GetTypes());
|
||||
}
|
||||
}
|
||||
// Load the assembly by name
|
||||
|
@ -285,7 +285,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
try
|
||||
{
|
||||
culture = ClrFacade.GetCultureInfo(_uiculture);
|
||||
culture = CultureInfo.GetCultureInfo(_uiculture);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
|
@ -1079,8 +1079,8 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
#endif
|
||||
|
||||
ClrFacade.SetCurrentThreadUiCulture(this.CurrentUICulture);
|
||||
ClrFacade.SetCurrentThreadCulture(this.CurrentCulture);
|
||||
Thread.CurrentThread.CurrentUICulture = this.CurrentUICulture;
|
||||
Thread.CurrentThread.CurrentCulture = this.CurrentCulture;
|
||||
// BUG: 610329. Tell PowerShell engine to apply console
|
||||
// related properties while launching Pipeline Execution
|
||||
// Thread.
|
||||
|
@ -9,6 +9,7 @@ using System.Management.Automation.Internal;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Management.Automation.Tracing;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
#if CORECLR
|
||||
using System.Runtime.InteropServices;
|
||||
@ -65,8 +66,8 @@ namespace Microsoft.PowerShell
|
||||
// The currentUICulture returned NativeCultureResolver supports this non
|
||||
// traditional fallback on Vista. So it is important to set currentUICulture
|
||||
// in the beginning before we do anything.
|
||||
ClrFacade.SetCurrentThreadUiCulture(NativeCultureResolver.UICulture);
|
||||
ClrFacade.SetCurrentThreadCulture(NativeCultureResolver.Culture);
|
||||
Thread.CurrentThread.CurrentUICulture = NativeCultureResolver.UICulture;
|
||||
Thread.CurrentThread.CurrentCulture = NativeCultureResolver.Culture;
|
||||
|
||||
RunspaceConfigForSingleShell configuration = null;
|
||||
PSConsoleLoadException warning = null;
|
||||
|
@ -19,7 +19,7 @@ namespace System.Management.Automation
|
||||
/// <summary>
|
||||
/// The powershell custom AssemblyLoadContext implementation
|
||||
/// </summary>
|
||||
internal partial class PowerShellAssemblyLoadContext : AssemblyLoadContext
|
||||
internal partial class PowerShellAssemblyLoadContext
|
||||
{
|
||||
#region Resource_Strings
|
||||
|
||||
@ -31,11 +31,7 @@ namespace System.Management.Automation
|
||||
// When the first attempt fails, we again need to retrieve the resource string to construct another exception, which ends up with an infinite loop.
|
||||
private const string BaseFolderDoesNotExist = "The base directory '{0}' does not exist.";
|
||||
private const string ManifestDefinitionDoesNotMatch = "Could not load file or assembly '{0}' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.";
|
||||
private const string AssemblyPathDoesNotExist = "Could not load file or assembly '{0}' or one of its dependencies. The system cannot find the file specified.";
|
||||
private const string InvalidAssemblyExtensionName = "Could not load file or assembly '{0}' or one of its dependencies. The file specified is not a DLL file.";
|
||||
private const string AbsolutePathRequired = "Absolute path information is required.";
|
||||
private const string SingletonAlreadyInitialized = "The singleton of PowerShellAssemblyLoadContext has already been initialized.";
|
||||
private const string UseResolvingEventHandlerOnly = "PowerShellAssemblyLoadContext was initialized to use its 'Resolving' event handler only.";
|
||||
|
||||
#endregion Resource_Strings
|
||||
|
||||
@ -44,14 +40,14 @@ namespace System.Management.Automation
|
||||
/// <summary>
|
||||
/// Initialize a singleton of PowerShellAssemblyLoadContext
|
||||
/// </summary>
|
||||
internal static PowerShellAssemblyLoadContext InitializeSingleton(string basePaths, bool useResolvingHandlerOnly)
|
||||
internal static PowerShellAssemblyLoadContext InitializeSingleton(string basePaths)
|
||||
{
|
||||
lock (s_syncObj)
|
||||
{
|
||||
if (Instance != null)
|
||||
throw new InvalidOperationException(SingletonAlreadyInitialized);
|
||||
|
||||
Instance = new PowerShellAssemblyLoadContext(basePaths, useResolvingHandlerOnly);
|
||||
Instance = new PowerShellAssemblyLoadContext(basePaths);
|
||||
return Instance;
|
||||
}
|
||||
}
|
||||
@ -60,96 +56,52 @@ namespace System.Management.Automation
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="basePaths">
|
||||
/// Base directory paths that are separated by semicolon ';'.
|
||||
/// They will be the default paths to probe assemblies.
|
||||
/// Base directory paths that are separated by semicolon ';'. They will be the default paths to probe assemblies.
|
||||
/// The passed-in argument could be null or an empty string, in which case there is no default paths to probe assemblies.
|
||||
/// </param>
|
||||
/// <param name="useResolvingHandlerOnly">
|
||||
/// Indicate whether this instance is going to be used as a
|
||||
/// full fledged ALC, or only its 'Resolve' handler is going
|
||||
/// to be used.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// When <paramref name="useResolvingHandlerOnly"/> is true, we will register to the 'Resolving' event of the default
|
||||
/// load context with our 'Resolve' method, and depend on the default load context to resolve/load assemblies for PS.
|
||||
/// This mode is used when TPA list of the native host only contains .NET Core libraries.
|
||||
/// In this case, TPA binder will be consulted before hitting our resolving logic. The binding order of Assembly.Load is:
|
||||
/// TPA binder --> Resolving event
|
||||
///
|
||||
/// When <paramref name="useResolvingHandlerOnly"/> is false, we will use this instance as a full fledged load context
|
||||
/// to resolve/load assemblies for PS. This mode is used when TPA list of the native host contains both .NET Core libraries
|
||||
/// and PS assemblies.
|
||||
/// In this case, our Load override will kick in before consulting the TPA binder. The binding order of Assembly.Load is:
|
||||
/// Load override --> TPA binder --> Resolving event
|
||||
/// </remarks>
|
||||
private PowerShellAssemblyLoadContext(string basePaths, bool useResolvingHandlerOnly)
|
||||
private PowerShellAssemblyLoadContext(string basePaths)
|
||||
{
|
||||
#region Validation
|
||||
// FIRST: Validate and populate probing paths
|
||||
if (string.IsNullOrEmpty(basePaths))
|
||||
{
|
||||
throw new ArgumentNullException("basePaths");
|
||||
}
|
||||
|
||||
_basePaths = basePaths.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int i = 0; i < _basePaths.Length; i++)
|
||||
{
|
||||
string basePath = _basePaths[i];
|
||||
if (!Directory.Exists(basePath))
|
||||
{
|
||||
string message = string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
BaseFolderDoesNotExist,
|
||||
basePath);
|
||||
throw new ArgumentException(message, "basePaths");
|
||||
}
|
||||
_basePaths[i] = basePath.Trim();
|
||||
}
|
||||
#endregion Validation
|
||||
|
||||
// FIRST: Add basePaths to probing paths
|
||||
_probingPaths = new List<string>(_basePaths);
|
||||
|
||||
// NEXT: Initialize the CoreCLR type catalog dictionary [OrdinalIgnoreCase]
|
||||
_coreClrTypeCatalog = InitializeTypeCatalog();
|
||||
|
||||
// LAST: Handle useResolvingHandlerOnly flag
|
||||
_useResolvingHandlerOnly = useResolvingHandlerOnly;
|
||||
_activeLoadContext = useResolvingHandlerOnly ? Default : this;
|
||||
if (useResolvingHandlerOnly)
|
||||
{
|
||||
Default.Resolving += Resolve;
|
||||
_probingPaths = Array.Empty<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
var tempSet = new HashSet<string>(_coreClrTypeCatalog.Values, StringComparer.OrdinalIgnoreCase);
|
||||
_tpaSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Microsoft.PowerShell.CoreCLR.AssemblyLoadContext" };
|
||||
foreach (string tpa in tempSet)
|
||||
_probingPaths = basePaths.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int i = 0; i < _probingPaths.Length; i++)
|
||||
{
|
||||
string shortName = tpa.Substring(0, tpa.IndexOf(','));
|
||||
_tpaSet.Add(shortName);
|
||||
string basePath = _probingPaths[i];
|
||||
if (!Directory.Exists(basePath))
|
||||
{
|
||||
string message = string.Format(CultureInfo.CurrentCulture, BaseFolderDoesNotExist, basePath);
|
||||
throw new ArgumentException(message, "basePaths");
|
||||
}
|
||||
_probingPaths[i] = basePath.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
// NEXT: Initialize the CoreCLR type catalog dictionary [OrdinalIgnoreCase]
|
||||
_coreClrTypeCatalog = InitializeTypeCatalog();
|
||||
_availableDotNetAssemblyNames = new Lazy<HashSet<string>>(
|
||||
() => new HashSet<string>(_coreClrTypeCatalog.Values, StringComparer.Ordinal));
|
||||
|
||||
// LAST: Register 'Resolving' handler on the default load context.
|
||||
AssemblyLoadContext.Default.Resolving += Resolve;
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
||||
#region Fields
|
||||
|
||||
private readonly bool _useResolvingHandlerOnly;
|
||||
private readonly AssemblyLoadContext _activeLoadContext;
|
||||
private readonly static object s_syncObj = new object();
|
||||
private readonly string[] _basePaths;
|
||||
// Initially, 'probingPaths' only contains psbase path. But every time we load an assembly through 'LoadFrom(string AssemblyPath)', we
|
||||
// add its parent path to 'probingPaths', so that we are able to support implicit loading of an assembly from the same place where the
|
||||
// requesting assembly is located.
|
||||
// We don't need to worry about removing any paths from 'probingPaths', because once an assembly is loaded, it won't be unloaded until
|
||||
// the current process exits, and thus the assembly itself and its parent folder cannot be deleted or renamed.
|
||||
private readonly List<string> _probingPaths;
|
||||
private readonly string[] _probingPaths;
|
||||
private readonly string[] _extensions = new string[] { ".ni.dll", ".dll" };
|
||||
// CoreCLR type catalog dictionary
|
||||
// - Key: namespace qualified type name (FullName)
|
||||
// - Value: strong name of the TPA that contains the type represented by Key.
|
||||
private readonly Dictionary<string, string> _coreClrTypeCatalog;
|
||||
private readonly HashSet<string> _tpaSet;
|
||||
private readonly string[] _extensions = new string[] { ".ni.dll", ".dll" };
|
||||
private readonly Lazy<HashSet<string>> _availableDotNetAssemblyNames;
|
||||
|
||||
/// <summary>
|
||||
/// Assembly cache across the AppDomain
|
||||
@ -180,38 +132,71 @@ namespace System.Management.Automation
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the namespace-qualified type names of all available .NET Core types shipped with PowerShell Core.
|
||||
/// This is used for type name auto-completion in PS engine.
|
||||
/// </summary>
|
||||
internal IEnumerable<string> AvailableDotNetTypeNames
|
||||
{
|
||||
get { return _coreClrTypeCatalog.Keys; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the assembly names of all available .NET Core assemblies shipped with PowerShell Core.
|
||||
/// This is used for type name auto-completion in PS engine.
|
||||
/// </summary>
|
||||
internal HashSet<string> AvailableDotNetAssemblyNames
|
||||
{
|
||||
get { return _availableDotNetAssemblyNames.Value; }
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Events
|
||||
#region Internal_Methods
|
||||
|
||||
/// <summary>
|
||||
/// Assembly load event
|
||||
/// Get the current loaded assemblies
|
||||
/// </summary>
|
||||
internal event Action<Assembly> AssemblyLoad;
|
||||
|
||||
#endregion Events
|
||||
|
||||
#region Protected_Internal_Methods
|
||||
|
||||
/// <summary>
|
||||
/// Implement the AssemblyLoadContext.Load(AssemblyName). Search the requested assembly in probing paths.
|
||||
/// Search the file "[assemblyName.Name][.ni].dll" in probing paths. If the file is found and it matches the requested AssemblyName, load it with LoadFromAssemblyPath.
|
||||
/// </summary>
|
||||
protected override Assembly Load(AssemblyName assemblyName)
|
||||
internal IEnumerable<Assembly> GetAssembly(string namespaceQualifiedTypeName)
|
||||
{
|
||||
if (_useResolvingHandlerOnly)
|
||||
throw new NotSupportedException(UseResolvingEventHandlerOnly);
|
||||
// If 'namespaceQualifiedTypeName' is specified and it's a CoreCLR framework type,
|
||||
// then we only return that specific TPA assembly.
|
||||
if (!string.IsNullOrEmpty(namespaceQualifiedTypeName))
|
||||
{
|
||||
if (_coreClrTypeCatalog.TryGetValue(namespaceQualifiedTypeName, out string tpaStrongName))
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Assembly[] { GetTrustedPlatformAssembly(tpaStrongName) };
|
||||
}
|
||||
catch (FileNotFoundException) { }
|
||||
}
|
||||
}
|
||||
|
||||
// We let the default context load the assemblies included in the type catalog as there
|
||||
// appears to be a bug in .NET with method resolution with system libraries loaded by our
|
||||
// context and not the default. We use the short name because some packages have inconsistent
|
||||
// versions between reference and runtime assemblies.
|
||||
if (_tpaSet.Contains(assemblyName.Name))
|
||||
return null;
|
||||
|
||||
return Resolve(this, assemblyName);
|
||||
// Otherwise, we return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the profile optimization root on the appropriate load context
|
||||
/// </summary>
|
||||
internal void SetProfileOptimizationRootImpl(string directoryPath)
|
||||
{
|
||||
AssemblyLoadContext.Default.SetProfileOptimizationRoot(directoryPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the profile optimization on the appropriate load context
|
||||
/// </summary>
|
||||
internal void StartProfileOptimizationImpl(string profile)
|
||||
{
|
||||
AssemblyLoadContext.Default.StartProfileOptimization(profile);
|
||||
}
|
||||
|
||||
#endregion Internal_Methods
|
||||
|
||||
#region Private_Methods
|
||||
|
||||
/// <summary>
|
||||
/// The handler for the Resolving event
|
||||
/// </summary>
|
||||
@ -235,7 +220,7 @@ namespace System.Management.Automation
|
||||
string asmCultureName = assemblyName.CultureName ?? string.Empty;
|
||||
string asmFilePath = null;
|
||||
|
||||
for (int i = 0; i < _probingPaths.Count; i++)
|
||||
for (int i = 0; i < _probingPaths.Length; i++)
|
||||
{
|
||||
string probingPath = _probingPaths[i];
|
||||
string asmCulturePath = Path.Combine(probingPath, asmCultureName);
|
||||
@ -247,7 +232,7 @@ namespace System.Management.Automation
|
||||
if (File.Exists(asmFilePath))
|
||||
{
|
||||
isAssemblyFileFound = true;
|
||||
AssemblyName asmNameFound = GetAssemblyName(asmFilePath);
|
||||
AssemblyName asmNameFound = AssemblyLoadContext.GetAssemblyName(asmFilePath);
|
||||
if (IsAssemblyMatching(assemblyName, asmNameFound))
|
||||
{
|
||||
isAssemblyFileMatching = true;
|
||||
@ -279,303 +264,9 @@ namespace System.Management.Automation
|
||||
}
|
||||
}
|
||||
|
||||
// Raise AssemblyLoad event
|
||||
OnAssemblyLoaded(asmLoaded);
|
||||
return asmLoaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load an IL or NI assembly from its file path.
|
||||
/// </summary>
|
||||
internal Assembly LoadFrom(string assemblyPath)
|
||||
{
|
||||
ValidateAssemblyPath(assemblyPath, "assemblyPath");
|
||||
|
||||
Assembly asmLoaded;
|
||||
AssemblyName assemblyName = GetAssemblyName(assemblyPath);
|
||||
|
||||
// Probe the assembly cache
|
||||
if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
|
||||
return asmLoaded;
|
||||
|
||||
// Prepare to load the assembly
|
||||
lock (s_syncObj)
|
||||
{
|
||||
// Probe the cache again in case it's already loaded
|
||||
if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
|
||||
return asmLoaded;
|
||||
|
||||
// Load the assembly through 'LoadFromNativeImagePath' or 'LoadFromAssemblyPath'
|
||||
asmLoaded = assemblyPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase)
|
||||
? _activeLoadContext.LoadFromNativeImagePath(assemblyPath, null)
|
||||
: _activeLoadContext.LoadFromAssemblyPath(assemblyPath);
|
||||
|
||||
if (asmLoaded != null)
|
||||
{
|
||||
// Add the loaded assembly to the cache
|
||||
s_assemblyCache.TryAdd(assemblyName.Name, asmLoaded);
|
||||
// Add its parent path to our probing paths
|
||||
string parentPath = Path.GetDirectoryName(assemblyPath);
|
||||
if (!_probingPaths.Contains(parentPath))
|
||||
{
|
||||
_probingPaths.Add(parentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Raise AssemblyLoad event
|
||||
OnAssemblyLoaded(asmLoaded);
|
||||
return asmLoaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load assembly from byte stream.
|
||||
/// </summary>
|
||||
internal Assembly LoadFrom(Stream assembly)
|
||||
{
|
||||
if (assembly == null)
|
||||
throw new ArgumentNullException("assembly");
|
||||
|
||||
Assembly asmLoaded;
|
||||
AssemblyName assemblyName = GetAssemblyName(assembly);
|
||||
|
||||
// Probe the assembly cache
|
||||
if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
|
||||
return asmLoaded;
|
||||
|
||||
// Prepare to load the assembly
|
||||
lock (s_syncObj)
|
||||
{
|
||||
// Probe the cache again in case it's already loaded
|
||||
if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
|
||||
return asmLoaded;
|
||||
|
||||
// Load the assembly through 'LoadFromStream'
|
||||
asmLoaded = _activeLoadContext.LoadFromStream(assembly);
|
||||
if (asmLoaded != null)
|
||||
{
|
||||
// Add the loaded assembly to the cache
|
||||
s_assemblyCache.TryAdd(assemblyName.Name, asmLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
// Raise AssemblyLoad event
|
||||
OnAssemblyLoaded(asmLoaded);
|
||||
return asmLoaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current loaded assemblies
|
||||
/// </summary>
|
||||
internal IEnumerable<Assembly> GetAssemblies(string namespaceQualifiedTypeName)
|
||||
{
|
||||
// If 'namespaceQualifiedTypeName' is specified and it's a CoreCLR framework type,
|
||||
// then we only return that specific TPA assembly.
|
||||
if (!string.IsNullOrEmpty(namespaceQualifiedTypeName))
|
||||
{
|
||||
string tpaStrongName;
|
||||
if (_coreClrTypeCatalog.TryGetValue(namespaceQualifiedTypeName, out tpaStrongName))
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Assembly[] { GetTrustedPlatformAssembly(tpaStrongName) };
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// It's possible that the type catalog generated in OPS contains more entries than
|
||||
// the one generated in windows build. This is because in OPS we have more freedom
|
||||
// to control what packages to depend on, such as Json.NET.
|
||||
// If we deploy the PSALC.dll generated from OPS to NanoServer, then it's possible
|
||||
// that 'GetTrustedPlatformAssembly(tpaStrongName)' may fail for such entries. In
|
||||
// this case, we ignore the exception and return our cached assemblies.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we return all assemblies from the AssemblyCache
|
||||
return s_assemblyCache.Values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try adding a new assembly to the cache
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is for adding a dynamic assembly to the cache.
|
||||
/// PowerShell generates dynamic assemblies by directly emitting IL, and this API
|
||||
/// is to add such assemblies to the cache so that types in them are discoverable.
|
||||
/// </remarks>
|
||||
internal bool TryAddAssemblyToCache(Assembly assembly)
|
||||
{
|
||||
AssemblyName asmName = assembly.GetName();
|
||||
bool success = s_assemblyCache.TryAdd(asmName.Name, assembly);
|
||||
// Raise AssemblyLoad event
|
||||
if (success) { OnAssemblyLoaded(assembly); }
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Probe for the assembly file with the specified short name for metadata analysis purpose
|
||||
/// </summary>
|
||||
internal string ProbeAssemblyFileForMetadataAnalysis(string assemblyShortName, string additionalSearchPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assemblyShortName))
|
||||
{
|
||||
throw new ArgumentNullException("assemblyShortName");
|
||||
}
|
||||
|
||||
bool useAdditionalSearchPath = false;
|
||||
if (!string.IsNullOrEmpty(additionalSearchPath))
|
||||
{
|
||||
if (!Path.IsPathRooted(additionalSearchPath))
|
||||
{
|
||||
throw new ArgumentException(AbsolutePathRequired, "additionalSearchPath");
|
||||
}
|
||||
useAdditionalSearchPath = Directory.Exists(additionalSearchPath);
|
||||
}
|
||||
|
||||
// Construct the probing paths for searching the specified assembly file
|
||||
string[] metadataProbingPaths = _basePaths;
|
||||
if (useAdditionalSearchPath)
|
||||
{
|
||||
var searchPaths = new List<string>() { additionalSearchPath };
|
||||
searchPaths.AddRange(_basePaths);
|
||||
metadataProbingPaths = searchPaths.ToArray();
|
||||
}
|
||||
|
||||
for (int i = 0; i < metadataProbingPaths.Length; i++)
|
||||
{
|
||||
string metadataProbingPath = metadataProbingPaths[i];
|
||||
for (int k = 0; k < _extensions.Length; k++)
|
||||
{
|
||||
string asmFileName = assemblyShortName + _extensions[k];
|
||||
string asmFilePath = Path.Combine(metadataProbingPath, asmFileName);
|
||||
if (File.Exists(asmFilePath))
|
||||
{
|
||||
return asmFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the namespace-qualified type names of all available CoreCLR .NET types.
|
||||
/// This is used for type name auto-completion in PS engine.
|
||||
/// </summary>
|
||||
internal IEnumerable<string> GetAvailableDotNetTypes()
|
||||
{
|
||||
return _coreClrTypeCatalog.Keys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the profile optimization root on the appropriate load context
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When using PS ALC as a full fledged ALC in OPS, we don't enable profile optimization.
|
||||
/// This is because PS assemblies will be recorded in the profile, and the next time OPS
|
||||
/// starts up, the default context will load the PS assemblies pretty early to ngen them
|
||||
/// in another CPU core, so our Load override won't track the loading of them, and thus
|
||||
/// OPS will fail to work.
|
||||
/// The root cause is that dotnet.exe put all PS assemblies in TPA list. If PS assemblies
|
||||
/// are not in TPA list, then we can enable profile optimization without a problem.
|
||||
/// </remarks>
|
||||
internal void SetProfileOptimizationRootImpl(string directoryPath)
|
||||
{
|
||||
if (_useResolvingHandlerOnly)
|
||||
_activeLoadContext.SetProfileOptimizationRoot(directoryPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the profile optimization on the appropriate load context
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When using PS ALC as a full fledged ALC in OPS, we don't enable profile optimization.
|
||||
/// This is because PS assemblies will be recorded in the profile, and the next time OPS
|
||||
/// starts up, the default context will load the PS assemblies pretty early to ngen them
|
||||
/// in another CPU core, so our Load override won't track the loading of them, and thus
|
||||
/// OPS will fail to work.
|
||||
/// The root cause is that dotnet.exe put all PS assemblies in TPA list. If PS assemblies
|
||||
/// are not in TPA list, then we can enable profile optimization without a problem.
|
||||
/// </remarks>
|
||||
internal void StartProfileOptimizationImpl(string profile)
|
||||
{
|
||||
if (_useResolvingHandlerOnly)
|
||||
_activeLoadContext.StartProfileOptimization(profile);
|
||||
}
|
||||
|
||||
#endregion Protected_Internal_Methods
|
||||
|
||||
#region Private_Methods
|
||||
|
||||
/// <summary>
|
||||
/// Handle the AssemblyLoad event
|
||||
/// </summary>
|
||||
private void OnAssemblyLoaded(Assembly assemblyLoaded)
|
||||
{
|
||||
Action<Assembly> assemblyLoadHandler = AssemblyLoad;
|
||||
if (assemblyLoaded != null && assemblyLoadHandler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
assemblyLoadHandler(assemblyLoaded);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Catch all exceptions, same behavior as AppDomain.AssemblyLoad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate assembly path value for the specified parameter
|
||||
/// </summary>
|
||||
private void ValidateAssemblyPath(string assemblyPath, string parameterName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(assemblyPath))
|
||||
{
|
||||
throw new ArgumentNullException(parameterName);
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(assemblyPath))
|
||||
{
|
||||
throw new ArgumentException(AbsolutePathRequired, parameterName);
|
||||
}
|
||||
|
||||
if (!File.Exists(assemblyPath))
|
||||
{
|
||||
ThrowFileNotFoundException(
|
||||
AssemblyPathDoesNotExist,
|
||||
assemblyPath);
|
||||
}
|
||||
|
||||
if (!string.Equals(Path.GetExtension(assemblyPath), ".DLL", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ThrowFileLoadException(
|
||||
InvalidAssemblyExtensionName,
|
||||
assemblyPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get AssemblyName of an assembly stream
|
||||
/// </summary>
|
||||
private AssemblyName GetAssemblyName(Stream assembly)
|
||||
{
|
||||
if (assembly == null)
|
||||
throw new ArgumentNullException("assembly");
|
||||
|
||||
string strongAssemblyName = null;
|
||||
using (PEReader peReader = new PEReader(assembly, PEStreamOptions.LeaveOpen | PEStreamOptions.PrefetchMetadata))
|
||||
{
|
||||
MetadataReader metadataReader = peReader.GetMetadataReader();
|
||||
strongAssemblyName = AssemblyMetadataHelper.GetAssemblyStrongName(metadataReader);
|
||||
}
|
||||
|
||||
assembly.Seek(0, SeekOrigin.Begin);
|
||||
return new AssemblyName(strongAssemblyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get the specified assembly from cache
|
||||
/// </summary>
|
||||
@ -689,8 +380,6 @@ namespace System.Management.Automation
|
||||
/// </summary>
|
||||
public class PowerShellAssemblyLoadContextInitializer
|
||||
{
|
||||
private static object[] s_emptyArray = new object[0];
|
||||
|
||||
/// <summary>
|
||||
/// Create a singleton of PowerShellAssemblyLoadContext.
|
||||
/// Then register to the Resolving event of the load context that loads this assembly.
|
||||
@ -708,106 +397,7 @@ namespace System.Management.Automation
|
||||
if (string.IsNullOrEmpty(basePaths))
|
||||
throw new ArgumentNullException("basePaths");
|
||||
|
||||
PowerShellAssemblyLoadContext.InitializeSingleton(basePaths, useResolvingHandlerOnly: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a singleton of PowerShellAssemblyLoadContext.
|
||||
/// Then load System.Management.Automation and call the WSManPluginManagedEntryWrapper delegate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is used by the native host of the PSRP plugin.
|
||||
/// </remarks>
|
||||
/// <param name="wkrPtrs">
|
||||
/// Passed to delegate.
|
||||
/// </param>
|
||||
public static int WSManPluginWrapper(IntPtr wkrPtrs)
|
||||
{
|
||||
string basePaths = System.IO.Path.GetDirectoryName(typeof(PowerShellAssemblyLoadContextInitializer).GetTypeInfo().Assembly.Location);
|
||||
string entryAssemblyName = "System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
|
||||
string entryTypeName = "System.Management.Automation.Remoting.WSManPluginManagedEntryWrapper";
|
||||
string entryMethodName = "InitPlugin";
|
||||
object[] args = { wkrPtrs };
|
||||
|
||||
var psLoadContext = PowerShellAssemblyLoadContext.InitializeSingleton(basePaths, useResolvingHandlerOnly: false);
|
||||
var entryAssembly = psLoadContext.LoadFromAssemblyName(new AssemblyName(entryAssemblyName));
|
||||
var entryType = entryAssembly.GetType(entryTypeName, throwOnError: true, ignoreCase: true);
|
||||
var methodInfo = entryType.GetMethod(entryMethodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);
|
||||
|
||||
return (int)methodInfo.Invoke(null, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a singleton of PowerShellAssemblyLoadContext.
|
||||
/// Then load the assembly containing the actual entry point using it.
|
||||
/// </summary>
|
||||
/// <param name="basePaths">
|
||||
/// Base directory paths that are separated by semicolon ';'.
|
||||
/// They will be the default paths to probe assemblies.
|
||||
/// </param>
|
||||
/// <param name="entryAssemblyName">
|
||||
/// Name of the assembly that contains the actual entry point.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The assembly that contains the actual entry point.
|
||||
/// </returns>
|
||||
public static Assembly InitializeAndLoadEntryAssembly(string basePaths, AssemblyName entryAssemblyName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(basePaths))
|
||||
throw new ArgumentNullException("basePaths");
|
||||
|
||||
if (entryAssemblyName == null)
|
||||
throw new ArgumentNullException("entryAssemblyName");
|
||||
|
||||
var psLoadContext = PowerShellAssemblyLoadContext.InitializeSingleton(basePaths, useResolvingHandlerOnly: false);
|
||||
return psLoadContext.LoadFromAssemblyName(entryAssemblyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a singleton of PowerShellAssemblyLoadContext.
|
||||
/// Then call into the actual entry point based on the given assembly name, type name, method name and arguments.
|
||||
/// </summary>
|
||||
/// <param name="basePaths">
|
||||
/// Base directory paths that are separated by semicolon ';'.
|
||||
/// They will be the default paths to probe assemblies.
|
||||
/// </param>
|
||||
/// <param name="entryAssemblyName">
|
||||
/// Name of the assembly that contains the actual entry point.
|
||||
/// </param>
|
||||
/// <param name="entryTypeName">
|
||||
/// Name of the type that contains the actual entry point.
|
||||
/// </param>
|
||||
/// <param name="entryMethodName">
|
||||
/// Name of the actual entry point method.
|
||||
/// </param>
|
||||
/// <param name="args">
|
||||
/// An array of arguments passed to the entry point method.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The return value of running the entry point method.
|
||||
/// </returns>
|
||||
public static object InitializeAndCallEntryMethod(string basePaths, AssemblyName entryAssemblyName, string entryTypeName, string entryMethodName, object[] args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(basePaths))
|
||||
throw new ArgumentNullException("basePaths");
|
||||
|
||||
if (entryAssemblyName == null)
|
||||
throw new ArgumentNullException("entryAssemblyName");
|
||||
|
||||
if (string.IsNullOrEmpty(entryTypeName))
|
||||
throw new ArgumentNullException("entryTypeName");
|
||||
|
||||
if (string.IsNullOrEmpty(entryMethodName))
|
||||
throw new ArgumentNullException("entryMethodName");
|
||||
|
||||
args = args ?? s_emptyArray;
|
||||
|
||||
var psLoadContext = PowerShellAssemblyLoadContext.InitializeSingleton(basePaths, useResolvingHandlerOnly: false);
|
||||
var entryAssembly = psLoadContext.LoadFromAssemblyName(entryAssemblyName);
|
||||
var entryType = entryAssembly.GetType(entryTypeName, throwOnError: true, ignoreCase: true);
|
||||
var methodInfo = entryType.GetMethod(entryMethodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);
|
||||
|
||||
return methodInfo.Invoke(null, args);
|
||||
PowerShellAssemblyLoadContext.InitializeSingleton(basePaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,8 @@ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace Microsoft.PowerShell.CoreCLR
|
||||
{
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Management.Automation;
|
||||
|
||||
/// <summary>
|
||||
/// AssemblyExtensions
|
||||
@ -19,19 +18,10 @@ namespace Microsoft.PowerShell.CoreCLR
|
||||
/// </summary>
|
||||
/// <param name="assemblyPath">The path of the file that contains the manifest of the assembly.</param>
|
||||
/// <returns>The loaded assembly.</returns>
|
||||
[ObsoleteAttribute("This method is obsolete. Call Assembly.LoadFrom instead", false)]
|
||||
public static Assembly LoadFrom(string assemblyPath)
|
||||
{
|
||||
return ClrFacade.LoadFrom(assemblyPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load an assembly given its byte stream
|
||||
/// </summary>
|
||||
/// <param name="assembly">The byte stream of assembly</param>
|
||||
/// <returns>The loaded assembly</returns>
|
||||
public static Assembly LoadFrom(Stream assembly)
|
||||
{
|
||||
return ClrFacade.LoadFrom(assembly);
|
||||
return Assembly.LoadFrom(assemblyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ namespace Microsoft.PowerShell.Cmdletization
|
||||
eb.DefineLiteral(name, integerValue);
|
||||
}
|
||||
|
||||
ClrFacade.CreateEnumType(eb);
|
||||
eb.CreateTypeInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,18 +35,10 @@ namespace System.Management.Automation
|
||||
{
|
||||
static CompletionCompleters()
|
||||
{
|
||||
#if CORECLR
|
||||
ClrFacade.AddAssemblyLoadHandler(UpdateTypeCacheOnAssemblyLoad);
|
||||
#else
|
||||
AppDomain.CurrentDomain.AssemblyLoad += UpdateTypeCacheOnAssemblyLoad;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
static void UpdateTypeCacheOnAssemblyLoad(Assembly loadedAssembly)
|
||||
#else
|
||||
private static void UpdateTypeCacheOnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
|
||||
#endif
|
||||
{
|
||||
// Just null out the cache - we'll rebuild it the next time someone tries to complete a type.
|
||||
// We could rebuild it now, but we could be loading multiple assemblies (e.g. dependent assemblies)
|
||||
@ -5862,34 +5854,11 @@ namespace System.Management.Automation
|
||||
|
||||
#endregion Process_TypeAccelerators
|
||||
|
||||
#region Process_LoadedAssemblies
|
||||
|
||||
var assembliesExcludingPSGenerated = ClrFacade.GetAssemblies();
|
||||
var allPublicTypes = assembliesExcludingPSGenerated.SelectMany(assembly =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return assembly.GetTypes().Where(TypeResolver.IsPublic);
|
||||
}
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
}
|
||||
return Type.EmptyTypes;
|
||||
});
|
||||
|
||||
foreach (var type in allPublicTypes)
|
||||
{
|
||||
HandleNamespace(entries, type.Namespace);
|
||||
HandleType(entries, type.FullName, type.Name, type);
|
||||
}
|
||||
|
||||
#endregion Process_LoadedAssemblies
|
||||
|
||||
#region Process_CoreCLR_TypeCatalog
|
||||
#if CORECLR
|
||||
// In CoreCLR, we have namespace-qualified type names of all available .NET types stored in TypeCatalog of the AssemblyLoadContext.
|
||||
// In CoreCLR, we have namespace-qualified type names of all available .NET Core types stored in TypeCatalog.
|
||||
// Populate the type completion cache using the namespace-qualified type names.
|
||||
foreach (string fullTypeName in ClrFacade.GetAvailableCoreClrDotNetTypes())
|
||||
foreach (string fullTypeName in ClrFacade.AvailableDotNetTypeNames)
|
||||
{
|
||||
var typeCompInString = new TypeCompletionInStringFormat { FullTypeName = fullTypeName };
|
||||
HandleNamespace(entries, typeCompInString.Namespace);
|
||||
@ -5898,6 +5867,32 @@ namespace System.Management.Automation
|
||||
#endif
|
||||
#endregion Process_CoreCLR_TypeCatalog
|
||||
|
||||
#region Process_LoadedAssemblies
|
||||
|
||||
foreach (Assembly assembly in ClrFacade.GetAssemblies())
|
||||
{
|
||||
#if CORECLR
|
||||
// Ignore the assemblies that are already covered by the type catalog
|
||||
if (ClrFacade.AvailableDotNetAssemblyNames.Contains(assembly.FullName)) { continue; }
|
||||
#endif
|
||||
try
|
||||
{
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
// Ignore non-public types
|
||||
if (!TypeResolver.IsPublic(type)) { continue; }
|
||||
|
||||
HandleNamespace(entries, type.Namespace);
|
||||
HandleType(entries, type.FullName, type.Name, type);
|
||||
}
|
||||
}
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Process_LoadedAssemblies
|
||||
|
||||
var grouping = entries.Values.GroupBy(t => t.Key.Count(c => c == '.')).OrderBy(g => g.Key).ToArray();
|
||||
var localTypeCache = new TypeCompletionMapping[grouping.Last().Key + 1][];
|
||||
foreach (var group in grouping)
|
||||
|
@ -7,6 +7,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Management.Automation.Language;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Reflection;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using Microsoft.PowerShell.Commands;
|
||||
|
||||
@ -227,7 +228,7 @@ namespace System.Management.Automation
|
||||
else if (Module.Path.EndsWith(StringLiterals.DependentWorkflowAssemblyExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Binary module (.dll)
|
||||
Module.SetVersion(ClrFacade.GetAssemblyName(Module.Path).Version);
|
||||
Module.SetVersion(AssemblyName.GetAssemblyName(Module.Path).Version);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1375,7 +1375,7 @@ namespace System.Management.Automation
|
||||
|
||||
try
|
||||
{
|
||||
loadedAssembly = ClrFacade.LoadFrom(filename);
|
||||
loadedAssembly = Assembly.LoadFrom(filename);
|
||||
return loadedAssembly;
|
||||
}
|
||||
catch (FileNotFoundException fileNotFound)
|
||||
|
@ -4467,7 +4467,7 @@ namespace System.Management.Automation.Runspaces
|
||||
{
|
||||
s_PSSnapInTracer.WriteLine("Loading assembly for psSnapIn {0}", fileName);
|
||||
|
||||
Assembly assembly = ClrFacade.LoadFrom(fileName);
|
||||
Assembly assembly = Assembly.LoadFrom(fileName);
|
||||
if (assembly == null)
|
||||
{
|
||||
s_PSSnapInTracer.TraceError("Loading assembly for psSnapIn {0} failed", fileName);
|
||||
@ -5543,7 +5543,7 @@ if($paths) {
|
||||
|
||||
try
|
||||
{
|
||||
AssemblyName assemblyName = ClrFacade.GetAssemblyName(psSnapInInfo.AbsoluteModulePath);
|
||||
AssemblyName assemblyName = AssemblyName.GetAssemblyName(psSnapInInfo.AbsoluteModulePath);
|
||||
|
||||
if (!string.Equals(assemblyName.FullName, psSnapInInfo.AssemblyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@ -5552,7 +5552,7 @@ if($paths) {
|
||||
throw new PSSnapInException(psSnapInInfo.Name, message);
|
||||
}
|
||||
|
||||
assembly = ClrFacade.LoadFrom(psSnapInInfo.AbsoluteModulePath);
|
||||
assembly = Assembly.LoadFrom(psSnapInInfo.AbsoluteModulePath);
|
||||
}
|
||||
catch (FileLoadException e)
|
||||
{
|
||||
|
@ -175,7 +175,7 @@ namespace System.Management.Automation
|
||||
|
||||
try
|
||||
{
|
||||
p = ClrFacade.SecureStringToCoTaskMemUnicode(ss);
|
||||
p = Marshal.SecureStringToCoTaskMemUnicode(ss);
|
||||
s = Marshal.PtrToStringUni(p);
|
||||
}
|
||||
finally
|
||||
|
@ -217,8 +217,8 @@ namespace System.Management.Automation.Runspaces
|
||||
finally
|
||||
{
|
||||
NestedPipelineExecutionThread = oldNestedPipelineThread;
|
||||
ClrFacade.SetCurrentThreadCulture(oldCurrentCulture);
|
||||
ClrFacade.SetCurrentThreadUiCulture(oldCurrentUICulture);
|
||||
Thread.CurrentThread.CurrentCulture = oldCurrentCulture;
|
||||
Thread.CurrentThread.CurrentUICulture = oldCurrentUICulture;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2370,7 +2370,7 @@ namespace System.Management.Automation.Language
|
||||
#endif
|
||||
if (File.Exists(assemblyFileName))
|
||||
{
|
||||
assembly = ClrFacade.LoadFrom(assemblyFileName);
|
||||
assembly = Assembly.LoadFrom(assemblyFileName);
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
@ -700,7 +700,7 @@ namespace System.Management.Automation.Remoting
|
||||
//Rooted path of dll is provided.
|
||||
assemblyPath = assemblyName;
|
||||
}
|
||||
result = ClrFacade.LoadFrom(assemblyPath);
|
||||
result = Assembly.LoadFrom(assemblyPath);
|
||||
}
|
||||
catch (FileLoadException e)
|
||||
{
|
||||
|
@ -348,7 +348,7 @@ namespace System.Management.Automation.Remoting.Client
|
||||
_cred.userName = name;
|
||||
if (null != pwd)
|
||||
{
|
||||
_cred.password = ClrFacade.SecureStringToCoTaskMemUnicode(pwd);
|
||||
_cred.password = Marshal.SecureStringToCoTaskMemUnicode(pwd);
|
||||
}
|
||||
|
||||
_data = MarshalledObject.Create<WSManUserNameCredentialStruct>(_cred);
|
||||
|
@ -383,7 +383,7 @@ namespace System.Management.Automation.Remoting
|
||||
if (Platform.IsWindows)
|
||||
{
|
||||
SafeWaitHandle safeWaitHandle = new SafeWaitHandle(requestDetails.shutdownNotificationHandle, false); // Owned by WinRM
|
||||
ClrFacade.SetSafeWaitHandle(eventWaitHandle, safeWaitHandle);
|
||||
eventWaitHandle.SafeWaitHandle = safeWaitHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1496,7 +1496,7 @@ namespace System.Management.Automation.Remoting
|
||||
if (retrievingLocaleSucceeded && ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT == localeData.Type))
|
||||
{
|
||||
CultureInfo uiCultureToUse = new CultureInfo(localeData.Text);
|
||||
ClrFacade.SetCurrentThreadUiCulture(uiCultureToUse);
|
||||
Thread.CurrentThread.CurrentUICulture = uiCultureToUse;
|
||||
}
|
||||
}
|
||||
// ignore if there is any exception constructing the culture..
|
||||
@ -1510,7 +1510,7 @@ namespace System.Management.Automation.Remoting
|
||||
if (retrievingDataLocaleSucceeded && ((uint)WSManNativeApi.WSManDataType.WSMAN_DATA_TYPE_TEXT == dataLocaleData.Type))
|
||||
{
|
||||
CultureInfo cultureToUse = new CultureInfo(dataLocaleData.Text);
|
||||
ClrFacade.SetCurrentThreadCulture(cultureToUse);
|
||||
Thread.CurrentThread.CurrentCulture = cultureToUse;
|
||||
}
|
||||
}
|
||||
// ignore if there is any exception constructing the culture..
|
||||
|
@ -266,7 +266,7 @@ namespace System.Management.Automation.Remoting
|
||||
// Wrap the provided handle so it can be passed to the registration function
|
||||
SafeWaitHandle safeWaitHandle = new SafeWaitHandle(creationRequestDetails.shutdownNotificationHandle, false); // Owned by WinRM
|
||||
EventWaitHandle eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
ClrFacade.SetSafeWaitHandle(eventWaitHandle, safeWaitHandle);
|
||||
eventWaitHandle.SafeWaitHandle = safeWaitHandle;
|
||||
|
||||
// Register shutdown notification handle
|
||||
this.registeredShutDownWaitHandle = ThreadPool.RegisterWaitForSingleObject(
|
||||
|
@ -337,7 +337,7 @@ namespace System.Management.Automation.Remoting
|
||||
// Wrap the provided handle so it can be passed to the registration function
|
||||
SafeWaitHandle safeWaitHandle = new SafeWaitHandle(requestDetails.shutdownNotificationHandle, false); // Owned by WinRM
|
||||
EventWaitHandle eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
|
||||
ClrFacade.SetSafeWaitHandle(eventWaitHandle, safeWaitHandle);
|
||||
eventWaitHandle.SafeWaitHandle = safeWaitHandle;
|
||||
|
||||
_registeredShutDownWaitHandle = ThreadPool.RegisterWaitForSingleObject(
|
||||
eventWaitHandle,
|
||||
|
@ -379,7 +379,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
destPaths.Add(module.ModuleBase);
|
||||
|
||||
#if !CORECLR // Side-By-Side directories are not present in OneCore environments.
|
||||
if (IsSystemModule(module.ModuleName) && ClrFacade.Is64BitOperatingSystem())
|
||||
if (IsSystemModule(module.ModuleName) && Environment.Is64BitOperatingSystem)
|
||||
{
|
||||
string path = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID).Replace("System32", "SysWOW64");
|
||||
|
||||
|
@ -246,7 +246,7 @@ namespace System.Management.Automation.Runspaces
|
||||
if (assembly == null)
|
||||
throw PSTraceSource.NewArgumentNullException("assembly");
|
||||
|
||||
object[] attributes = ClrFacade.GetCustomAttributes<RunspaceConfigurationTypeAttribute>(assembly);
|
||||
object[] attributes = assembly.GetCustomAttributes(typeof(RunspaceConfigurationTypeAttribute), false);
|
||||
|
||||
if (attributes == null || attributes.Length == 0)
|
||||
{
|
||||
|
@ -1345,9 +1345,6 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent
|
||||
<data name="CantActivateDocumentInPowerShellCore" xml:space="preserve">
|
||||
<value>Cannot run a document in PowerShell Core: {0}.</value>
|
||||
</data>
|
||||
<data name="LoadContextNotInitialized" xml:space="preserve">
|
||||
<value>'PowerShellAssemblyLoadContext' is not initialized.</value>
|
||||
</data>
|
||||
<data name="MultipleTypeConstraintsOnMethodParam" xml:space="preserve">
|
||||
<value>Multiple type constraints are not allowed on a method parameter.</value>
|
||||
</data>
|
||||
|
@ -85,7 +85,7 @@ namespace Microsoft.PowerShell
|
||||
|
||||
if (s.Length > 0)
|
||||
{
|
||||
IntPtr ptr = ClrFacade.SecureStringToCoTaskMemUnicode(s);
|
||||
IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(s);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -1565,7 +1565,7 @@ namespace System.Management.Automation
|
||||
{
|
||||
var processModule = PsUtils.GetMainModule(currentProcess);
|
||||
hostname = string.Concat("PowerShell_", processModule.FileName, "_",
|
||||
ClrFacade.GetProcessModuleFileVersionInfo(processModule).ProductVersion);
|
||||
processModule.FileVersionInfo.ProductVersion);
|
||||
}
|
||||
catch (ComponentModel.Win32Exception)
|
||||
{
|
||||
|
@ -640,7 +640,7 @@ namespace System.Management.Automation.Runspaces
|
||||
|
||||
try
|
||||
{
|
||||
AssemblyName assemblyName = ClrFacade.GetAssemblyName(mshsnapinInfo.AbsoluteModulePath);
|
||||
AssemblyName assemblyName = AssemblyName.GetAssemblyName(mshsnapinInfo.AbsoluteModulePath);
|
||||
if (string.Compare(assemblyName.FullName, mshsnapinInfo.AssemblyName, StringComparison.OrdinalIgnoreCase) != 0)
|
||||
{
|
||||
string message = StringUtil.Format(ConsoleInfoErrorStrings.PSSnapInAssemblyNameMismatch, mshsnapinInfo.AbsoluteModulePath, mshsnapinInfo.AssemblyName);
|
||||
@ -648,7 +648,7 @@ namespace System.Management.Automation.Runspaces
|
||||
throw new PSSnapInException(mshsnapinInfo.Name, message);
|
||||
}
|
||||
|
||||
assembly = ClrFacade.LoadFrom(mshsnapinInfo.AbsoluteModulePath);
|
||||
assembly = Assembly.LoadFrom(mshsnapinInfo.AbsoluteModulePath);
|
||||
}
|
||||
catch (FileLoadException e)
|
||||
{
|
||||
|
@ -10,7 +10,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management.Automation.Language;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@ -37,6 +36,18 @@ namespace System.Management.Automation
|
||||
/// </summary>
|
||||
internal static class ClrFacade
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize powershell AssemblyLoadContext and register the 'Resolving' event, if it's not done already.
|
||||
/// If powershell is hosted by a native host such as DSC, then PS ALC might be initialized via 'SetPowerShellAssemblyLoadContext' before loading S.M.A.
|
||||
/// </summary>
|
||||
static ClrFacade()
|
||||
{
|
||||
if (PowerShellAssemblyLoadContext.Instance == null)
|
||||
{
|
||||
PowerShellAssemblyLoadContext.InitializeSingleton(string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We need it to avoid calling lookups inside dynamic assemblies with PS Types, so we exclude it from GetAssemblies().
|
||||
/// We use this convention for names to archive it.
|
||||
@ -45,20 +56,6 @@ namespace System.Management.Automation
|
||||
|
||||
#region Process
|
||||
|
||||
/// <summary>
|
||||
/// Facade for ProcessModule FileVersionInfo
|
||||
/// </summary>
|
||||
/// <param name="processModule"></param>
|
||||
/// <returns>FileVersionInfo</returns>
|
||||
internal static FileVersionInfo GetProcessModuleFileVersionInfo(ProcessModule processModule)
|
||||
{
|
||||
#if CORECLR
|
||||
return FileVersionInfo.GetVersionInfo(processModule.FileName);
|
||||
#else
|
||||
return processModule.FileVersionInfo;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for Process.Handle to get SafeHandle
|
||||
/// </summary>
|
||||
@ -73,46 +70,6 @@ namespace System.Management.Automation
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for Process.Handle to get raw handle
|
||||
/// </summary>
|
||||
internal static IntPtr GetRawProcessHandle(Process process)
|
||||
{
|
||||
#if CORECLR
|
||||
try
|
||||
{
|
||||
return process.SafeHandle.DangerousGetHandle();
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// It's possible that the process has already exited when we try to get its handle.
|
||||
// In that case, InvalidOperationException will be thrown from Process.SafeHandle,
|
||||
// and we return the invalid zero pointer.
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
#else
|
||||
return process.Handle;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
/// <summary>
|
||||
/// Facade for ProcessStartInfo.Environment
|
||||
/// </summary>
|
||||
internal static IDictionary<string, string> GetProcessEnvironment(ProcessStartInfo startInfo)
|
||||
{
|
||||
return startInfo.Environment;
|
||||
}
|
||||
#else
|
||||
/// <summary>
|
||||
/// Facade for ProcessStartInfo.EnvironmentVariables
|
||||
/// </summary>
|
||||
internal static System.Collections.Specialized.StringDictionary GetProcessEnvironment(ProcessStartInfo startInfo)
|
||||
{
|
||||
return startInfo.EnvironmentVariables;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion Process
|
||||
|
||||
#region Marshal
|
||||
@ -171,32 +128,9 @@ namespace System.Management.Automation
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for SecureStringToCoTaskMemUnicode
|
||||
/// </summary>
|
||||
internal static IntPtr SecureStringToCoTaskMemUnicode(SecureString s)
|
||||
{
|
||||
#if CORECLR
|
||||
return SecureStringMarshal.SecureStringToCoTaskMemUnicode(s);
|
||||
#else
|
||||
return Marshal.SecureStringToCoTaskMemUnicode(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Marshal
|
||||
|
||||
#region Assembly
|
||||
/// <summary>
|
||||
/// Facade for AssemblyName.GetAssemblyName(string)
|
||||
/// </summary>
|
||||
internal static AssemblyName GetAssemblyName(string assemblyPath)
|
||||
{
|
||||
#if CORECLR // AssemblyName.GetAssemblyName(assemblyPath) is not in CoreCLR
|
||||
return AssemblyLoadContext.GetAssemblyName(assemblyPath);
|
||||
#else
|
||||
return AssemblyName.GetAssemblyName(assemblyPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static IEnumerable<Assembly> GetAssemblies(TypeResolutionState typeResolutionState, TypeName typeName)
|
||||
{
|
||||
@ -217,112 +151,29 @@ namespace System.Management.Automation
|
||||
/// </param>
|
||||
internal static IEnumerable<Assembly> GetAssemblies(string namespaceQualifiedTypeName = null)
|
||||
{
|
||||
return
|
||||
#if CORECLR
|
||||
return PSAssemblyLoadContext.GetAssemblies(namespaceQualifiedTypeName);
|
||||
#else
|
||||
return AppDomain.CurrentDomain.GetAssemblies().Where(a => !(a.FullName.Length > 0 && a.FullName[0] == FIRST_CHAR_PSASSEMBLY_MARK));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for Assembly.LoadFrom
|
||||
/// </summary>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom")]
|
||||
internal static Assembly LoadFrom(string assemblyPath)
|
||||
{
|
||||
#if CORECLR
|
||||
return PSAssemblyLoadContext.LoadFrom(assemblyPath);
|
||||
#else
|
||||
return Assembly.LoadFrom(assemblyPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for EnumBuilder.CreateTypeInfo
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In Core PowerShell, we need to track the dynamic assemblies that powershell generates.
|
||||
/// </remarks>
|
||||
internal static void CreateEnumType(EnumBuilder enumBuilder)
|
||||
{
|
||||
#if CORECLR
|
||||
// Create the enum type and add the dynamic assembly to assembly cache.
|
||||
TypeInfo enumTypeinfo = enumBuilder.CreateTypeInfo();
|
||||
PSAssemblyLoadContext.TryAddAssemblyToCache(enumTypeinfo.Assembly);
|
||||
#else
|
||||
enumBuilder.CreateTypeInfo();
|
||||
PSAssemblyLoadContext.GetAssembly(namespaceQualifiedTypeName) ??
|
||||
#endif
|
||||
AppDomain.CurrentDomain.GetAssemblies().Where(a => !(a.FullName.Length > 0 && a.FullName[0] == FIRST_CHAR_PSASSEMBLY_MARK));
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
/// <summary>
|
||||
/// Probe (look for) the assembly file with the specified short name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In Core PowerShell, we need to analyze the metadata of assembly files for binary modules. Sometimes we
|
||||
/// need to find an assembly file that is referenced by the assembly file that is being processed. To find
|
||||
/// the reference assembly file, we need to probe the PSBase and the additional searching path if it's specified.
|
||||
/// </remarks>
|
||||
internal static string ProbeAssemblyPath(string assemblyShortName, string additionalSearchPath = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(assemblyShortName))
|
||||
{
|
||||
throw new ArgumentNullException("assemblyShortName");
|
||||
}
|
||||
|
||||
return PSAssemblyLoadContext.ProbeAssemblyFileForMetadataAnalysis(assemblyShortName, additionalSearchPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the namespace-qualified type names of all available CoreCLR .NET types.
|
||||
/// Get the namespace-qualified type names of all available .NET Core types shipped with PowerShell Core.
|
||||
/// This is used for type name auto-completion in PS engine.
|
||||
/// </summary>
|
||||
internal static IEnumerable<string> GetAvailableCoreClrDotNetTypes()
|
||||
{
|
||||
return PSAssemblyLoadContext.GetAvailableDotNetTypes();
|
||||
}
|
||||
internal static IEnumerable<string> AvailableDotNetTypeNames => PSAssemblyLoadContext.AvailableDotNetTypeNames;
|
||||
|
||||
/// <summary>
|
||||
/// Load assembly from byte stream.
|
||||
/// Get the assembly names of all available .NET Core assemblies shipped with PowerShell Core.
|
||||
/// This is used for type name auto-completion in PS engine.
|
||||
/// </summary>
|
||||
internal static Assembly LoadFrom(Stream assembly)
|
||||
{
|
||||
return PSAssemblyLoadContext.LoadFrom(assembly);
|
||||
}
|
||||
internal static HashSet<string> AvailableDotNetAssemblyNames => PSAssemblyLoadContext.AvailableDotNetAssemblyNames;
|
||||
|
||||
/// <summary>
|
||||
/// Add the AssemblyLoad handler
|
||||
/// </summary>
|
||||
internal static void AddAssemblyLoadHandler(Action<Assembly> handler)
|
||||
{
|
||||
PSAssemblyLoadContext.AssemblyLoad += handler;
|
||||
}
|
||||
|
||||
private static PowerShellAssemblyLoadContext PSAssemblyLoadContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PowerShellAssemblyLoadContext.Instance == null)
|
||||
{
|
||||
throw new InvalidOperationException(ParserStrings.LoadContextNotInitialized);
|
||||
}
|
||||
return PowerShellAssemblyLoadContext.Instance;
|
||||
}
|
||||
}
|
||||
private static PowerShellAssemblyLoadContext PSAssemblyLoadContext => PowerShellAssemblyLoadContext.Instance;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Facade for Assembly.GetCustomAttributes
|
||||
/// </summary>
|
||||
internal static object[] GetCustomAttributes<T>(Assembly assembly)
|
||||
{
|
||||
#if CORECLR // Assembly.GetCustomAttributes(Type, Boolean) is not in CORE CLR
|
||||
return assembly.GetCustomAttributes(typeof(T)).ToArray();
|
||||
#else
|
||||
return assembly.GetCustomAttributes(typeof(T), false);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Assembly
|
||||
|
||||
#region Encoding
|
||||
@ -592,48 +443,6 @@ namespace System.Management.Automation
|
||||
|
||||
#endregion Security
|
||||
|
||||
#region Culture
|
||||
|
||||
/// <summary>
|
||||
/// Facade for CultureInfo.GetCultureInfo(string).
|
||||
/// </summary>
|
||||
internal static CultureInfo GetCultureInfo(string cultureName)
|
||||
{
|
||||
#if CORECLR
|
||||
return new CultureInfo(cultureName);
|
||||
#else
|
||||
return CultureInfo.GetCultureInfo(cultureName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for setting CurrentCulture for the CurrentThread
|
||||
/// </summary>
|
||||
internal static void SetCurrentThreadCulture(CultureInfo cultureInfo)
|
||||
{
|
||||
#if CORECLR
|
||||
CultureInfo.CurrentCulture = cultureInfo;
|
||||
#else
|
||||
// Setters for 'CultureInfo.CurrentCulture' is introduced in .NET 4.6
|
||||
Thread.CurrentThread.CurrentCulture = cultureInfo;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for setting CurrentUICulture for the CurrentThread
|
||||
/// </summary>
|
||||
internal static void SetCurrentThreadUiCulture(CultureInfo uiCultureInfo)
|
||||
{
|
||||
#if CORECLR
|
||||
CultureInfo.CurrentUICulture = uiCultureInfo;
|
||||
#else
|
||||
// Setters for 'CultureInfo.CurrentUICulture' is introduced in .NET 4.6
|
||||
Thread.CurrentThread.CurrentUICulture = uiCultureInfo;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion Culture
|
||||
|
||||
#region Misc
|
||||
|
||||
/// <summary>
|
||||
@ -716,19 +525,6 @@ namespace System.Management.Automation
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manual implementation of the is 64bit processor check
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static bool Is64BitOperatingSystem()
|
||||
{
|
||||
#if CORECLR
|
||||
return (8 == IntPtr.Size); // Pointers are 8 bytes on 64-bit machines
|
||||
#else
|
||||
return Environment.Is64BitOperatingSystem;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for FormatterServices.GetUninitializedObject.
|
||||
///
|
||||
@ -768,20 +564,6 @@ namespace System.Management.Automation
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for setting WaitHandle.SafeWaitHandle.
|
||||
/// </summary>
|
||||
/// <param name="waitHandle"></param>
|
||||
/// <param name="value"></param>
|
||||
internal static void SetSafeWaitHandle(WaitHandle waitHandle, SafeWaitHandle value)
|
||||
{
|
||||
#if CORECLR
|
||||
waitHandle.SetSafeWaitHandle(value);
|
||||
#else
|
||||
waitHandle.SafeWaitHandle = value;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Facade for ProfileOptimization.SetProfileRoot
|
||||
/// </summary>
|
||||
|
@ -995,7 +995,7 @@ namespace System.Management.Automation.Internal
|
||||
|
||||
if (_rsaCryptoProvider.CanEncrypt)
|
||||
{
|
||||
IntPtr ptr = ClrFacade.SecureStringToCoTaskMemUnicode(secureString);
|
||||
IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(secureString);
|
||||
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
|
@ -424,7 +424,7 @@ using System.Runtime.Loader;
|
||||
|
||||
namespace System.Management.Automation
|
||||
{{
|
||||
internal partial class PowerShellAssemblyLoadContext : AssemblyLoadContext
|
||||
internal partial class PowerShellAssemblyLoadContext
|
||||
{{
|
||||
private Dictionary<string, string> InitializeTypeCatalog()
|
||||
{{
|
||||
|
@ -3,7 +3,6 @@ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
--********************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Management.Automation;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.PowerShell
|
||||
@ -21,19 +20,7 @@ namespace Microsoft.PowerShell
|
||||
/// </param>
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
#if CORECLR
|
||||
// PowerShell has to set the ALC here, since we don't own the native host
|
||||
string appBase = System.IO.Path.GetDirectoryName(typeof(ManagedPSEntry).GetTypeInfo().Assembly.Location);
|
||||
return (int)PowerShellAssemblyLoadContextInitializer.
|
||||
InitializeAndCallEntryMethod(
|
||||
appBase,
|
||||
new AssemblyName("Microsoft.PowerShell.ConsoleHost, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"),
|
||||
"Microsoft.PowerShell.UnmanagedPSEntry",
|
||||
"Start",
|
||||
new object[] { string.Empty, args, args.Length });
|
||||
#else
|
||||
return UnmanagedPSEntry.Start(string.Empty, args, args.Length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user