Remove managed environment cache (#8604)
authorJeremy Kuhne <jeremy.kuhne@microsoft.com>
Tue, 13 Dec 2016 12:51:28 +0000 (04:51 -0800)
committerJan Kotas <jkotas@microsoft.com>
Tue, 13 Dec 2016 12:51:28 +0000 (04:51 -0800)
The PAL already caches- no need to do it in managed.
Fold the code back into Environment.cs.

src/mscorlib/mscorlib.shared.sources.props
src/mscorlib/src/System/Environment.Unix.cs [deleted file]
src/mscorlib/src/System/Environment.Win32.cs [deleted file]
src/mscorlib/src/System/Environment.cs

index 16dfd565c2bfb566e1c03b357537d9f0c4740069..4761b8d175c8104f9d2ed5cb02a43556d3502fab 100644 (file)
   <ItemGroup Condition="'$(TargetsUnix)' == 'true'">
     <SafehandleSources Include="$(CoreFxSourcesRoot)\Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs" />
     <FileStreamSources Include="$(CoreFxSourcesRoot)\System\IO\FileStream.Unix.cs" />
-    <SystemSources Include="$(BclSourcesRoot)\System\Environment.Unix.cs" />
   </ItemGroup>
   <ItemGroup Condition="'$(TargetsUnix)' != 'true'">
     <SafehandleSources Include="$(CoreFxSourcesRoot)\Microsoft\Win32\SafeHandles\SafeFileHandle.Windows.cs" />
     <FileStreamSources Include="$(CoreFxSourcesRoot)\System\IO\FileStream.Win32.cs" />
     <FileStreamSources Include="$(CoreFxSourcesRoot)\System\IO\FileStreamCompletionSource.Win32.cs" />
     <FileStreamSources Include="$(CoreFxSourcesRoot)\System\IO\Win32Marshal.cs" />
-    <SystemSources Include="$(BclSourcesRoot)\System\Environment.Win32.cs" />
   </ItemGroup>
   <ItemGroup>
     <IoSources Include="$(CoreFxSourcesRoot)\System\IO\Path.cs" />
diff --git a/src/mscorlib/src/System/Environment.Unix.cs b/src/mscorlib/src/System/Environment.Unix.cs
deleted file mode 100644 (file)
index 13fba7e..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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.Collections;
-using System.Collections.Generic;
-
-namespace System
-{
-    public static partial class Environment
-    {
-        private static readonly unsafe Lazy<Dictionary<string, string>> s_environ = new Lazy<Dictionary<string, string>>(() =>
-        {
-            // We cache on Unix as using the block isn't thread safe
-            return GetRawEnvironmentVariables();
-        });
-
-        private static string GetEnvironmentVariableCore(string variable)
-        {
-            // Ensure variable doesn't include a null char
-            int nullEnd = variable.IndexOf('\0');
-            if (nullEnd != -1)
-            {
-                variable = variable.Substring(0, nullEnd);
-            }
-
-            // Get the value of the variable
-            lock (s_environ)
-            {
-                string value;
-                return s_environ.Value.TryGetValue(variable, out value) ? value : null;
-            }
-        }
-
-        private static string GetEnvironmentVariableCore(string variable, EnvironmentVariableTarget target)
-        {
-            return target == EnvironmentVariableTarget.Process ?
-                GetEnvironmentVariableCore(variable) :
-                null;
-        }
-
-        private static IDictionary GetEnvironmentVariablesCore()
-        {
-            lock (s_environ)
-            {
-                return new Dictionary<string, string>(s_environ.Value);
-            }
-        }
-
-        private static IDictionary GetEnvironmentVariablesCore(EnvironmentVariableTarget target)
-        {
-            return target == EnvironmentVariableTarget.Process ?
-                GetEnvironmentVariablesCore() :
-                new Dictionary<string, string>();
-        }
-
-        private static void SetEnvironmentVariableCore(string variable, string value)
-        {
-            int nullEnd;
-
-            // Ensure variable doesn't include a null char
-            nullEnd = variable.IndexOf('\0');
-            if (nullEnd != -1)
-            {
-                variable = variable.Substring(0, nullEnd);
-            }
-
-            // Ensure value doesn't include a null char
-            if (value != null)
-            {
-                nullEnd = value.IndexOf('\0');
-                if (nullEnd != -1)
-                {
-                    value = value.Substring(0, nullEnd);
-                }
-            }
-
-            lock (s_environ)
-            {
-                // Remove the entry if the value is null, otherwise add/overwrite it
-                if (value == null)
-                {
-                    s_environ.Value.Remove(variable);
-                }
-                else
-                {
-                    s_environ.Value[variable] = value;
-                }
-            }
-        }
-
-        private static void SetEnvironmentVariableCore(string variable, string value, EnvironmentVariableTarget target)
-        {
-            if (target == EnvironmentVariableTarget.Process)
-            {
-                SetEnvironmentVariableCore(variable, value);
-            }
-            // other targets ignored
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/mscorlib/src/System/Environment.Win32.cs b/src/mscorlib/src/System/Environment.Win32.cs
deleted file mode 100644 (file)
index ac3c6a7..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-// 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 Microsoft.Win32;
-using System.Collections;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace System
-{
-    public static partial class Environment
-    {
-        private static string GetEnvironmentVariableCore(string variable)
-        {
-            if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
-            {
-                // Environment variable accessors are not approved modern API.
-                // Behave as if the variable was not found in this case.
-                return null;
-            }
-
-            StringBuilder sb = StringBuilderCache.Acquire(128); // A somewhat reasonable default size
-            int requiredSize = Win32Native.GetEnvironmentVariable(variable, sb, sb.Capacity);
-
-            if (requiredSize == 0 && Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND)
-            {
-                StringBuilderCache.Release(sb);
-                return null;
-            }
-
-            while (requiredSize > sb.Capacity)
-            {
-                sb.Capacity = requiredSize;
-                sb.Length = 0;
-                requiredSize = Win32Native.GetEnvironmentVariable(variable, sb, sb.Capacity);
-            }
-
-            return StringBuilderCache.GetStringAndRelease(sb);
-        }
-
-        private static string GetEnvironmentVariableCore(string variable, EnvironmentVariableTarget target)
-        {
-            if (target == EnvironmentVariableTarget.Process)
-                return GetEnvironmentVariableCore(variable);
-
-#if FEATURE_WIN32_REGISTRY
-            RegistryKey baseKey;
-            string keyName;
-
-            if (target == EnvironmentVariableTarget.Machine)
-            {
-                baseKey = Registry.LocalMachine;
-                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
-            }
-            else if (target == EnvironmentVariableTarget.User)
-            {
-                Debug.Assert(target == EnvironmentVariableTarget.User);
-                baseKey = Registry.CurrentUser;
-                keyName = "Environment";
-            }
-            else
-            {
-                throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
-            }
-
-            using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false))
-            {
-                return environmentKey?.GetValue(variable) as string;
-            }
-#else
-            throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
-#endif
-        }
-
-        private static IDictionary GetEnvironmentVariablesCore()
-        {
-            if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
-            {
-                // Environment variable accessors are not approved modern API.
-                // Behave as if no environment variables are defined in this case.
-                return new Hashtable(0);
-            }
-
-            return GetRawEnvironmentVariables();
-        }
-
-        private static IDictionary GetEnvironmentVariablesCore(EnvironmentVariableTarget target)
-        {
-            if (target == EnvironmentVariableTarget.Process)
-                return GetEnvironmentVariablesCore();
-
-#if FEATURE_WIN32_REGISTRY
-            RegistryKey baseKey;
-            string keyName;
-            if (target == EnvironmentVariableTarget.Machine)
-            {
-                baseKey = Registry.LocalMachine;
-                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
-            }
-            else if (target == EnvironmentVariableTarget.User)
-            {
-                Debug.Assert(target == EnvironmentVariableTarget.User);
-                baseKey = Registry.CurrentUser;
-                keyName = @"Environment";
-            }
-            else
-            {
-                throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
-            }
-
-            using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false))
-            {
-                var table = new Dictionary<string, string>();
-                if (environmentKey != null)
-                {
-                    foreach (string name in environmentKey.GetValueNames())
-                    {
-                        table.Add(name, environmentKey.GetValue(name, "").ToString());
-                    }
-                }
-                return table;
-            }
-#endif // FEATURE_WIN32_REGISTRY
-
-            throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
-        }
-
-        private static void SetEnvironmentVariableCore(string variable, string value)
-        {
-            // explicitly null out value if is the empty string.
-            if (string.IsNullOrEmpty(value) || value[0] == '\0')
-                value = null;
-
-            if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
-            {
-                // Environment variable accessors are not approved modern API.
-                // so we throw PlatformNotSupportedException.
-                throw new PlatformNotSupportedException();
-            }
-
-            if (!Win32Native.SetEnvironmentVariable(variable, value))
-            {
-                int errorCode = Marshal.GetLastWin32Error();
-
-                switch (errorCode)
-                {
-                    case Win32Native.ERROR_ENVVAR_NOT_FOUND:
-                        // Allow user to try to clear a environment variable
-                        return;
-                    case Win32Native.ERROR_FILENAME_EXCED_RANGE:
-                        // The error message from Win32 is "The filename or extension is too long",
-                        // which is not accurate.
-                        throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"));
-                    default:
-                        throw new ArgumentException(Win32Native.GetMessage(errorCode));
-                }
-            }
-        }
-
-        private static void SetEnvironmentVariableCore(string variable, string value, EnvironmentVariableTarget target)
-        {
-            if (target == EnvironmentVariableTarget.Process)
-            {
-                SetEnvironmentVariableCore(variable, value);
-                return;
-            }
-
-            // explicitly null out value if is the empty string.
-            if (string.IsNullOrEmpty(value) || value[0] == '\0')
-                value = null;
-
-#if FEATURE_WIN32_REGISTRY
-            RegistryKey baseKey;
-            string keyName;
-
-            if (target == EnvironmentVariableTarget.Machine)
-            {
-                baseKey = Registry.LocalMachine;
-                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
-            }
-            else if (target == EnvironmentVariableTarget.User)
-            {
-                Debug.Assert(target == EnvironmentVariableTarget.User);
-
-                // User-wide environment variables stored in the registry are limited to 255 chars for the environment variable name.
-                const int MaxUserEnvVariableLength = 255;
-                if (variable.Length >= MaxUserEnvVariableLength)
-                {
-                    throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"), nameof(variable));
-                }
-
-                baseKey = Registry.CurrentUser;
-                keyName = "Environment";
-            }
-            else
-            {
-                throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
-            }
-
-            using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: true))
-            {
-                if (environmentKey != null)
-                {
-                    if (value == null)
-                    {
-                        environmentKey.DeleteValue(variable, throwOnMissingValue: false);
-                    }
-                    else
-                    {
-                        environmentKey.SetValue(variable, value);
-                    }
-                }
-            }
-
-            // send a WM_SETTINGCHANGE message to all windows
-            IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
-            if (r == IntPtr.Zero) Debug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error());
-
-#else // FEATURE_WIN32_REGISTRY
-            throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
-#endif
-        }
-    }
-}
\ No newline at end of file
index 15801802f742f157045b44688074d3e6954812f8..835219a01ceb1c27d0867f192fdefc1ef6fd09cd 100644 (file)
@@ -1286,5 +1286,219 @@ namespace System {
             }
             return results;
         }
+
+        private static string GetEnvironmentVariableCore(string variable)
+        {
+            if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
+            {
+                // Environment variable accessors are not approved modern API.
+                // Behave as if the variable was not found in this case.
+                return null;
+            }
+
+            StringBuilder sb = StringBuilderCache.Acquire(128); // A somewhat reasonable default size
+            int requiredSize = Win32Native.GetEnvironmentVariable(variable, sb, sb.Capacity);
+
+            if (requiredSize == 0 && Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND)
+            {
+                StringBuilderCache.Release(sb);
+                return null;
+            }
+
+            while (requiredSize > sb.Capacity)
+            {
+                sb.Capacity = requiredSize;
+                sb.Length = 0;
+                requiredSize = Win32Native.GetEnvironmentVariable(variable, sb, sb.Capacity);
+            }
+
+            return StringBuilderCache.GetStringAndRelease(sb);
+        }
+
+        private static string GetEnvironmentVariableCore(string variable, EnvironmentVariableTarget target)
+        {
+            if (target == EnvironmentVariableTarget.Process)
+                return GetEnvironmentVariableCore(variable);
+
+#if !FEATURE_WIN32_REGISTRY
+            return null;
+#else
+            RegistryKey baseKey;
+            string keyName;
+
+            if (target == EnvironmentVariableTarget.Machine)
+            {
+                baseKey = Registry.LocalMachine;
+                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
+            }
+            else if (target == EnvironmentVariableTarget.User)
+            {
+                Debug.Assert(target == EnvironmentVariableTarget.User);
+                baseKey = Registry.CurrentUser;
+                keyName = "Environment";
+            }
+            else
+            {
+                throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
+            }
+
+            using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false))
+            {
+                return environmentKey?.GetValue(variable) as string;
+            }
+#endif
+        }
+
+        private static IDictionary GetEnvironmentVariablesCore()
+        {
+            if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
+            {
+                // Environment variable accessors are not approved modern API.
+                // Behave as if no environment variables are defined in this case.
+                return new Dictionary<string, string>(0);
+            }
+
+            return GetRawEnvironmentVariables();
+        }
+
+        private static IDictionary GetEnvironmentVariablesCore(EnvironmentVariableTarget target)
+        {
+            if (target == EnvironmentVariableTarget.Process)
+                return GetEnvironmentVariablesCore();
+
+#if !FEATURE_WIN32_REGISTRY
+            // Without registry support we have nothing to return
+            return new Dictionary<string, string>(0);
+#else
+            RegistryKey baseKey;
+            string keyName;
+            if (target == EnvironmentVariableTarget.Machine)
+            {
+                baseKey = Registry.LocalMachine;
+                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
+            }
+            else if (target == EnvironmentVariableTarget.User)
+            {
+                Debug.Assert(target == EnvironmentVariableTarget.User);
+                baseKey = Registry.CurrentUser;
+                keyName = @"Environment";
+            }
+            else
+            {
+                throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
+            }
+
+            using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: false))
+            {
+                var table = new Dictionary<string, string>();
+                if (environmentKey != null)
+                {
+                    foreach (string name in environmentKey.GetValueNames())
+                    {
+                        table.Add(name, environmentKey.GetValue(name, "").ToString());
+                    }
+                }
+                return table;
+            }
+#endif // FEATURE_WIN32_REGISTRY
+        }
+
+        private static void SetEnvironmentVariableCore(string variable, string value)
+        {
+            // explicitly null out value if is the empty string.
+            if (string.IsNullOrEmpty(value) || value[0] == '\0')
+                value = null;
+
+            if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
+            {
+                // Environment variable accessors are not approved modern API.
+                // so we throw PlatformNotSupportedException.
+                throw new PlatformNotSupportedException();
+            }
+
+            if (!Win32Native.SetEnvironmentVariable(variable, value))
+            {
+                int errorCode = Marshal.GetLastWin32Error();
+
+                switch (errorCode)
+                {
+                    case Win32Native.ERROR_ENVVAR_NOT_FOUND:
+                        // Allow user to try to clear a environment variable
+                        return;
+                    case Win32Native.ERROR_FILENAME_EXCED_RANGE:
+                        // The error message from Win32 is "The filename or extension is too long",
+                        // which is not accurate.
+                        throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"));
+                    default:
+                        throw new ArgumentException(Win32Native.GetMessage(errorCode));
+                }
+            }
+        }
+
+        private static void SetEnvironmentVariableCore(string variable, string value, EnvironmentVariableTarget target)
+        {
+            if (target == EnvironmentVariableTarget.Process)
+            {
+                SetEnvironmentVariableCore(variable, value);
+                return;
+            }
+
+#if !FEATURE_WIN32_REGISTRY
+            // other targets ignored
+            return;
+#else
+            // explicitly null out value if is the empty string.
+            if (string.IsNullOrEmpty(value) || value[0] == '\0')
+                value = null;
+
+            RegistryKey baseKey;
+            string keyName;
+
+            if (target == EnvironmentVariableTarget.Machine)
+            {
+                baseKey = Registry.LocalMachine;
+                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
+            }
+            else if (target == EnvironmentVariableTarget.User)
+            {
+                Debug.Assert(target == EnvironmentVariableTarget.User);
+
+                // User-wide environment variables stored in the registry are limited to 255 chars for the environment variable name.
+                const int MaxUserEnvVariableLength = 255;
+                if (variable.Length >= MaxUserEnvVariableLength)
+                {
+                    throw new ArgumentException(GetResourceString("Argument_LongEnvVarValue"), nameof(variable));
+                }
+
+                baseKey = Registry.CurrentUser;
+                keyName = "Environment";
+            }
+            else
+            {
+                throw new ArgumentException(GetResourceString("Arg_EnumIllegalVal", (int)target));
+            }
+
+            using (RegistryKey environmentKey = baseKey.OpenSubKey(keyName, writable: true))
+            {
+                if (environmentKey != null)
+                {
+                    if (value == null)
+                    {
+                        environmentKey.DeleteValue(variable, throwOnMissingValue: false);
+                    }
+                    else
+                    {
+                        environmentKey.SetValue(variable, value);
+                    }
+                }
+            }
+
+            // send a WM_SETTINGCHANGE message to all windows
+            IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST),
+                Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
+
+            if (r == IntPtr.Zero) Debug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error());
+#endif // FEATURE_WIN32_REGISTRY
+        }
     }
 }