From ecdc8e02190d826a80a8add2a60e8bf2352c6e5c Mon Sep 17 00:00:00 2001 From: Pallavi Taneja Date: Sun, 8 Nov 2015 15:34:22 -0800 Subject: [PATCH] Expose Environment.GetCommandLineArgs in mscorlib [tfs-changeset: 1546251] --- src/mscorlib/model.xml | 6 ++-- src/mscorlib/src/System/Environment.cs | 34 +++++++++++++++++--- src/vm/corhost.cpp | 59 ++++++++++++++++++++++++++++++++-- src/vm/ecalllist.h | 2 +- src/vm/metasig.h | 1 + src/vm/mscorlib.h | 1 + 6 files changed, 93 insertions(+), 10 deletions(-) diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml index 8369cff..fa84736 100644 --- a/src/mscorlib/model.xml +++ b/src/mscorlib/model.xml @@ -1962,6 +1962,7 @@ + @@ -1976,10 +1977,11 @@ - + + - + diff --git a/src/mscorlib/src/System/Environment.cs b/src/mscorlib/src/System/Environment.cs index 09ad125..179525a 100644 --- a/src/mscorlib/src/System/Environment.cs +++ b/src/mscorlib/src/System/Environment.cs @@ -564,7 +564,6 @@ namespace System { } } -#if !FEATURE_CORECLR /*==============================GetCommandLineArgs============================== **Action: Gets the command line and splits it appropriately to deal with whitespace, ** quotes, and escape characters. @@ -573,15 +572,34 @@ namespace System { **Exceptions: None. ==============================================================================*/ [System.Security.SecuritySafeCritical] // auto-generated - public static String[] GetCommandLineArgs() { + public static String[] GetCommandLineArgs() + { new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand(); +#if FEATURE_CORECLR + /* + * There are multiple entry points to a hosted app. + * The host could use ::ExecuteAssembly() or ::CreateDelegate option + * ::ExecuteAssembly() -> In this particular case, the runtime invokes the main + method based on the arguments set by the host, and we return those arguments + * + * ::CreateDelegate() -> In this particular case, the host is asked to create a + * delegate based on the appDomain, assembly and methodDesc passed to it. + * which the caller uses to invoke the method. In this particular case we do not have + * any information on what arguments would be passed to the delegate. + * So our best bet is to simply use the commandLine that was used to invoke the process. + * in case it is present. + */ + if(s_CommandLineArgs != null) + return s_CommandLineArgs; +#endif return GetCommandLineArgsNative(); } [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern String[] GetCommandLineArgsNative(); - + +#if !FEATURE_CORECLR // We need to keep this Fcall since it is used in AppDomain.cs. // If we call GetEnvironmentVariable from AppDomain.cs, we will use StringBuilder class. // That has side effect to change the ApartmentState of the calling Thread to MTA. @@ -590,7 +608,15 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String nativeGetEnvironmentVariable(String variable); #endif //!FEATURE_CORECLR - + +#if FEATURE_CORECLR + private static string[] s_CommandLineArgs = null; + private static void SetCommandLineArgs(string[] cmdLineArgs) + { + s_CommandLineArgs = cmdLineArgs; + } +#endif + /*============================GetEnvironmentVariable============================ **Action: **Returns: diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp index 161b2a1..3b55987 100644 --- a/src/vm/corhost.cpp +++ b/src/vm/corhost.cpp @@ -1217,6 +1217,58 @@ ErrExit: } #ifdef FEATURE_CORECLR +/* + * This method processes the arguments sent to the host which are then used + * to invoke the main method. + * Note - + * [0] - points to the assemblyName that has been sent by the host. + * The rest are the arguments sent to the assembly. + * Also note, this might not always return the exact same identity as the cmdLine + * used to invoke the method. + * + * For example :- + * ActualCmdLine - Foo arg1 arg2. + * (Host1) - Full_path_to_Foo arg1 arg2 +*/ +void SetCommandLineArgs(LPCWSTR pwzAssemblyPath, int argc, LPCWSTR* argv) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + struct _gc + { + PTRARRAYREF cmdLineArgs; + } gc; + + ZeroMemory(&gc, sizeof(gc)); + GCPROTECT_BEGIN(gc); + + gc.cmdLineArgs = (PTRARRAYREF)AllocateObjectArray(argc + 1 /* arg[0] should be the exe name*/, g_pStringClass); + OBJECTREF orAssemblyPath = StringObject::NewString(pwzAssemblyPath); + gc.cmdLineArgs->SetAt(0, orAssemblyPath); + + for (int i = 0; i < argc; ++i) + { + OBJECTREF argument = StringObject::NewString(argv[i]); + gc.cmdLineArgs->SetAt(i + 1, argument); + } + + MethodDescCallSite setCmdLineArgs(METHOD__ENVIRONMENT__SET_COMMAND_LINE_ARGS); + + ARG_SLOT args[] = + { + ObjToArgSlot(gc.cmdLineArgs), + }; + setCmdLineArgs.Call(args); + + GCPROTECT_END(); +} + HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, LPCWSTR pwzAssemblyPath, int argc, @@ -1280,12 +1332,13 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, { GCX_COOP(); + // Here we call the managed method that gets the cmdLineArgs array. + SetCommandLineArgs(pwzAssemblyPath, argc, argv); + PTRARRAYREF arguments = NULL; - GCPROTECT_BEGIN(arguments); - + arguments = (PTRARRAYREF)AllocateObjectArray(argc, g_pStringClass); - for (int i = 0; i < argc; ++i) { STRINGREF argument = StringObject::NewString(argv[i]); diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 26bc4b9..1266615 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -301,9 +301,9 @@ FCFuncStart(gEnvironmentFuncs) FCFuncElement("nativeGetEnvironmentVariable", SystemNative::_GetEnvironmentVariable) FCFuncElement("GetCompatibilityFlag", SystemNative::_GetCompatibilityFlag) QCFuncElement("GetCommandLine", SystemNative::_GetCommandLine) - FCFuncElement("GetCommandLineArgsNative", SystemNative::GetCommandLineArgs) FCFuncElement("GetResourceFromDefault", GetResourceFromDefault) #endif // !FEATURE_CORECLR + FCFuncElement("GetCommandLineArgsNative", SystemNative::GetCommandLineArgs) #if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) QCFuncElement("WinRTSupported", SystemNative::WinRTSupported) diff --git a/src/vm/metasig.h b/src/vm/metasig.h index 6baf098..c64ab67 100644 --- a/src/vm/metasig.h +++ b/src/vm/metasig.h @@ -552,6 +552,7 @@ DEFINE_METASIG(SM(Str_RetStr, s, s)) DEFINE_METASIG_T(SM(Str_CultureInfo_RetStr, s C(CULTURE_INFO), s)) DEFINE_METASIG_T(SM(Str_CultureInfo_RefBool_RetStr, s C(CULTURE_INFO) r(F), s)) DEFINE_METASIG(IM(Str_ArrStr_ArrStr_RetVoid, s a(s) a(s), v)) +DEFINE_METASIG(SM(ArrStr_RetVoid, a(s), v)) DEFINE_METASIG(IM(Str_RetVoid, s, v)) DEFINE_METASIG(SM(RefBool_RefBool_RetVoid, r(F) r(F), v)) DEFINE_METASIG_T(IM(Str_Exception_RetVoid, s C(EXCEPTION), v)) diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index 96656c3..d886509 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -676,6 +676,7 @@ DEFINE_CLASS(ENUM, System, Enum) DEFINE_CLASS(ENVIRONMENT, System, Environment) DEFINE_METHOD(ENVIRONMENT, GET_RESOURCE_STRING_LOCAL, GetResourceStringLocal, SM_Str_RetStr) +DEFINE_METHOD(ENVIRONMENT, SET_COMMAND_LINE_ARGS, SetCommandLineArgs, SM_ArrStr_RetVoid) #ifdef FEATURE_COMINTEROP DEFINE_CLASS(ERROR_WRAPPER, Interop, ErrorWrapper) -- 2.7.4