Tweak Process.GetEnvironmentVariablesBlock (#49484)
authorStephen Toub <stoub@microsoft.com>
Fri, 12 Mar 2021 01:41:32 +0000 (20:41 -0500)
committerGitHub <noreply@github.com>
Fri, 12 Mar 2021 01:41:32 +0000 (20:41 -0500)
* Tweak Process.GetEnvironmentVariablesBlock

Mostly a cleanup (e.g. the comment refers to Windows 2000), but removes some interface dispatch as part of simplifying the code.

* Update src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs

index 2a5bd7e..0dfc4ae 100644 (file)
@@ -863,30 +863,23 @@ namespace System.Diagnostics
 
         private static string GetEnvironmentVariablesBlock(IDictionary<string, string> sd)
         {
-            // get the keys
-            string[] keys = new string[sd.Count];
-            sd.Keys.CopyTo(keys, 0);
-
-            // sort both by the keys
-            // Windows 2000 requires the environment block to be sorted by the key
-            // It will first converting the case the strings and do ordinal comparison.
+            // https://docs.microsoft.com/en-us/windows/win32/procthread/changing-environment-variables
+            // "All strings in the environment block must be sorted alphabetically by name. The sort is
+            //  case-insensitive, Unicode order, without regard to locale. Because the equal sign is a
+            //  separator, it must not be used in the name of an environment variable."
 
-            // We do not use Array.Sort(keys, values, IComparer) since it is only supported
-            // in System.Runtime contract from 4.20.0.0 and Test.Net depends on System.Runtime 4.0.10.0
-            // we workaround this by sorting only the keys and then lookup the values form the keys.
+            var keys = new string[sd.Count];
+            sd.Keys.CopyTo(keys, 0);
             Array.Sort(keys, StringComparer.OrdinalIgnoreCase);
 
-            // create a list of null terminated "key=val" strings
-            StringBuilder stringBuff = new StringBuilder();
-            for (int i = 0; i < sd.Count; ++i)
+            // Join the null-terminated "key=val\0" strings
+            var result = new StringBuilder(8 * keys.Length);
+            foreach (string key in keys)
             {
-                stringBuff.Append(keys[i]);
-                stringBuff.Append('=');
-                stringBuff.Append(sd[keys[i]]);
-                stringBuff.Append('\0');
+                result.Append(key).Append('=').Append(sd[key]).Append('\0');
             }
-            // an extra null at the end that indicates end of list will come from the string.
-            return stringBuff.ToString();
+
+            return result.ToString();
         }
     }
 }