Expose Environment.GetCommandLineArgs in mscorlib
authorPallavi Taneja <pallavit@microsoft.com>
Sun, 8 Nov 2015 23:34:22 +0000 (15:34 -0800)
committerPallavi Taneja <pallavit@microsoft.com>
Sun, 8 Nov 2015 23:34:22 +0000 (15:34 -0800)
[tfs-changeset: 1546251]

src/mscorlib/model.xml
src/mscorlib/src/System/Environment.cs
src/vm/corhost.cpp
src/vm/ecalllist.h
src/vm/metasig.h
src/vm/mscorlib.h

index 8369cff..fa84736 100644 (file)
       <Member Name="GetFolderPath(System.Environment+SpecialFolder)" Condition="FEATURE_LEGACYSURFACE" />
       <Member Name="GetEnvironmentVariable(System.String)" />
       <Member Name="GetEnvironmentVariables" />
+      <Member Name="GetCommandLineArgs" />
       <Member Name="SetEnvironmentVariable(System.String,System.String)" />
       <Member Name="ExpandEnvironmentVariables(System.String)" />
       <Member MemberType="Property" Name="OSVersion" />
       <Member MemberType="Property" Name="TickCount" />
       <Member MemberType="Property" Name="Version" />
       <Member MemberType="Property" Name="ExitCode" />
-      <Member Status="ImplRoot" Name="GetResourceStringLocal(System.String)" />      
+      <Member Status="ImplRoot" Name="GetResourceStringLocal(System.String)" />
+      <Member Status="ImplRoot" Name="SetCommandLineArgs(System.String[])" />
       <Member Name="FailFast(System.String)"  />
       <Member Name="FailFast(System.String,System.Exception)"  />
-         <Member Name="Exit(System.Int32)"  />
+      <Member Name="Exit(System.Int32)" />
       <Member Status="ApiFxInternal" Name="UnsafeGetFolderPath(System.Environment+SpecialFolder)"  Condition="FEATURE_LEGACYSURFACE" />
     </Type>
     <Type Name="System.Environment+SpecialFolder" Condition="FEATURE_LEGACYSURFACE">
index 09ad125..179525a 100644 (file)
@@ -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:
index 161b2a1..3b55987 100644 (file)
@@ -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]);
index 26bc4b9..1266615 100644 (file)
@@ -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)
index 6baf098..c64ab67 100644 (file)
@@ -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))
index 96656c3..d886509 100644 (file)
@@ -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)