--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Loader;
+
+namespace System
+{
+ internal static class StartupHookProvider
+ {
+ private const string StartupHookTypeName = "StartupHook";
+ private const string InitializeMethodName = "Initialize";
+
+ // Parse a string specifying a list of assemblies and types
+ // containing a startup hook, and call each hook in turn.
+ private static void ProcessStartupHooks()
+ {
+ string startupHooksVariable = (string)AppContext.GetData("STARTUP_HOOKS");
+ if (startupHooksVariable == null)
+ {
+ return;
+ }
+
+ // Parse startup hooks variable
+ string[] startupHooks = startupHooksVariable.Split(Path.PathSeparator);
+ foreach (string startupHook in startupHooks)
+ {
+ if (String.IsNullOrEmpty(startupHook))
+ {
+ throw new ArgumentException(SR.Argument_InvalidStartupHookSyntax);
+ }
+ if (PathInternal.IsPartiallyQualified(startupHook))
+ {
+ throw new ArgumentException(SR.Argument_AbsolutePathRequired);
+ }
+ }
+
+ // Call each hook in turn
+ foreach (string startupHook in startupHooks)
+ {
+ CallStartupHook(startupHook);
+ }
+ }
+
+ // Load the specified assembly, and call the specified type's
+ // "static void Initialize()" method.
+ private static void CallStartupHook(string assemblyPath)
+ {
+ Debug.Assert(!String.IsNullOrEmpty(assemblyPath));
+ Debug.Assert(!PathInternal.IsPartiallyQualified(assemblyPath));
+
+ Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
+ Debug.Assert(assembly != null);
+ Type type = assembly.GetType(StartupHookTypeName, throwOnError: true);
+
+ // Look for a static method without any parameters
+ MethodInfo initializeMethod = type.GetMethod(InitializeMethodName,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static,
+ null, // use default binder
+ Type.EmptyTypes, // parameters
+ null); // no parameter modifiers
+
+ bool wrongSignature = false;
+ if (initializeMethod == null)
+ {
+ // There weren't any static methods without
+ // parameters. Look for any methods with the correct
+ // name, to provide precise error handling.
+ try
+ {
+ // This could find zero, one, or multiple methods
+ // with the correct name.
+ initializeMethod = type.GetMethod(InitializeMethodName,
+ BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Static | BindingFlags.Instance);
+ }
+ catch (AmbiguousMatchException)
+ {
+ // Found multiple
+ Debug.Assert(initializeMethod == null);
+ wrongSignature = true;
+ }
+ if (initializeMethod != null)
+ {
+ // Found one
+ wrongSignature = true;
+ }
+ else
+ {
+ // Didn't find any
+ throw new MissingMethodException(StartupHookTypeName, InitializeMethodName);
+ }
+ }
+ else if (initializeMethod.ReturnType != typeof(void))
+ {
+ wrongSignature = true;
+ }
+
+ if (wrongSignature)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidStartupHookSignature,
+ StartupHookTypeName + Type.Delimiter + InitializeMethodName,
+ assemblyPath));
+ }
+
+ Debug.Assert(initializeMethod != null &&
+ initializeMethod.IsStatic &&
+ initializeMethod.ReturnType == typeof(void) &&
+ initializeMethod.GetParameters().Length == 0);
+
+ initializeMethod.Invoke(null, null);
+ }
+ }
+}
}
}
+static void RunStartupHooks()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ INJECT_FAULT(COMPlusThrowOM(););
+ }
+ CONTRACTL_END;
+
+ MethodDescCallSite processStartupHooks(METHOD__STARTUP_HOOK_PROVIDER__PROCESS_STARTUP_HOOKS);
+ processStartupHooks.Call(NULL);
+}
+
INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads)
{
CONTRACTL
RunMainPre();
-
// Set the root assembly as the assembly that is containing the main method
// The root assembly is used in the GetEntryAssembly method that on CoreCLR is used
// to get the TargetFrameworkMoniker for the app
AppDomain * pDomain = pThread->GetDomain();
pDomain->SetRootAssembly(pMeth->GetAssembly());
+
+ RunStartupHooks();
+
hr = RunMain(pMeth, 1, &iRetVal, stringArgs);
}
}
DEFINE_FIELD_U(rgiLastFrameFromForeignExceptionStackTrace, StackFrameHelper, rgiLastFrameFromForeignExceptionStackTrace)
DEFINE_FIELD_U(iFrameCount, StackFrameHelper, iFrameCount)
+DEFINE_CLASS(STARTUP_HOOK_PROVIDER, System, StartupHookProvider)
+DEFINE_METHOD(STARTUP_HOOK_PROVIDER, PROCESS_STARTUP_HOOKS, ProcessStartupHooks, SM_RetVoid)
+
DEFINE_CLASS(STREAM, IO, Stream)
DEFINE_METHOD(STREAM, BEGIN_READ, BeginRead, IM_ArrByte_Int_Int_AsyncCallback_Object_RetIAsyncResult)
DEFINE_METHOD(STREAM, END_READ, EndRead, IM_IAsyncResult_RetInt)