简体   繁体   English

尝试使用 RegenerateUserEnvironment 抛出访问冲突错误来创建演示

[英]Trying to create a demo using RegenerateUserEnvironment throwing Access violation error

I am trying to make use of RegenerateUserEnvironment method so that I can refresh environment variables without restarting the instance.我正在尝试使用RegenerateUserEnvironment方法,这样我就可以在不重新启动实例的情况下刷新环境变量。 However, it ends up with an access violation error.但是,它最终会出现访问冲突错误。 I am not sure but to me, a process updating its own memory should not cause an error.我不确定,但对我来说,更新自己的进程 memory 不应该导致错误。

Things I tried:我尝试过的事情:

  1. Passing the actual token of current process.传递当前进程的实际令牌。 No chance.没有机会。
  2. Duplicating current token with all possible permissions.使用所有可能的权限复制当前令牌。 No chance.没有机会。
  3. Running as administrator, in case it is about SeDebugPrivilege or similar, but no chance.以管理员身份运行,以防它是关于SeDebugPrivilege或类似的,但没有机会。

Any ideas?有任何想法吗?

Code:代码:

using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using Microsoft.Win32;

namespace EnvVarControl
{
    internal static partial class Program
    {
        #region Pinvoke
        public const uint STANDARD_RIGHTS_READ = 0x00020000;
        public const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
        public const uint TOKEN_ADJUST_DEFAULT = 0x0080;
        public const uint TOKEN_ADJUST_GROUPS = 0x0040;
        public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
        public const uint TOKEN_ADJUST_SESSIONID = 0x0100;
        public const uint TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
            TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
            TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
            TOKEN_ADJUST_SESSIONID;

        public const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
        public const uint TOKEN_DUPLICATE = 0x0002;
        public const uint TOKEN_IMPERSONATE = 0x0004;
        public const uint TOKEN_QUERY = 0x0008;
        public const uint TOKEN_QUERY_SOURCE = 0x0010;
        public const uint TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY;

        public enum SECURITY_IMPERSONATION_LEVEL
        {
            SecurityAnonymous,
            SecurityIdentification,
            SecurityImpersonation,
            SecurityDelegation
        }

        public enum TOKEN_TYPE
        {
            TokenPrimary = 1,
            TokenImpersonation = 2
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int Length;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }

        [DllImport("advapi32.dll", SetLastError = true, EntryPoint = "DuplicateTokenEx")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, TOKEN_TYPE TokenType, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

        [LibraryImport("shell32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static partial bool RegenerateUserEnvironment(IntPtr hToken,
                                                     [MarshalAs(UnmanagedType.Bool)] bool bSet);
        #endregion Pinvoke

        public static void Main()
        {
            // Subscribe to the UserPreferenceChanged event
            SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged;

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }

        private static void CheckPathBeforeAndAfterRegenerateUserEnvironment()
        {
            // Get the value of the PATH environment variable before calling RegenerateUserEnvironment
            var pathBefore = Environment.GetEnvironmentVariable("PATH");
            Console.WriteLine($"BEFORE: {pathBefore}\n");

            RefreshEnvironmentVariables();

            // Get the value of the PATH environment variable after calling RegenerateUserEnvironment
            var pathAfter = Environment.GetEnvironmentVariable("PATH");

            Console.WriteLine($"AFTER: {pathAfter}\n");

            // Compare the two values of the PATH environment variable
            if (pathBefore != pathAfter)
            {
                Console.WriteLine("Warning: The value of the PATH environment variable has changed!");
            }
            else
            {
                Console.WriteLine("No change.");
            }
        }

        private static void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
        {
            // Check if the environment variables have changed
            if (e.Category == UserPreferenceCategory.General)
            {
                // Check the value of the PATH environment variable before and after calling RegenerateUserEnvironment
                CheckPathBeforeAndAfterRegenerateUserEnvironment();
            }
        }

        private static void RefreshEnvironmentVariables()
        {
            // Open the process token and duplicate
            var token = WindowsIdentity.GetCurrent().AccessToken.DangerousGetHandle();
            var duplicatededToken = DuplicateToken(token);

            // Call the RegenerateUserEnvironment function to update the environment variables
            if (!RegenerateUserEnvironment(duplicatededToken, true))
            {
                throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            }
        }

        private static nint DuplicateToken(nint token)
        {
            var sa = new SECURITY_ATTRIBUTES
            {
                bInheritHandle = false
            };
            sa.Length = Marshal.SizeOf(sa);
            sa.lpSecurityDescriptor = 0;

            const TOKEN_TYPE TokenType = TOKEN_TYPE.TokenPrimary;
            const SECURITY_IMPERSONATION_LEVEL SecurityImpersonation = SECURITY_IMPERSONATION_LEVEL.SecurityIdentification;
            var DupedToken = new IntPtr(0);

            if (!DuplicateTokenEx(token, TOKEN_ALL_ACCESS, ref sa, TokenType, SecurityImpersonation, ref DupedToken))
            {
                throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            }

            return DupedToken;
        }
    }
}

Error message:错误信息:


Exception thrown at ... (shell32.dll) in EnvVarControl.exe: ...: Access violation writing location ...

The RegenerateUserEnvironment function is used to update the environment block for the current process with the environment variables that are specified in the user's registry. RegenerateUserEnvironment function 用于使用用户注册表中指定的环境变量更新当前进程的环境块。 It should not cause an access violation error unless there is something wrong with the parameters that you are passing to it or with the way you are using it.它不应导致访问冲突错误,除非您传递给它的参数或您使用它的方式有问题。

To troubleshoot the issue, you might want to check the following:要解决此问题,您可能需要检查以下内容:

Make sure that you are using the correct syntax and parameters for the RegenerateUserEnvironment function. You can find more information about this function in the documentation: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-regenerateuserenvironment确保您为 RegenerateUserEnvironment function 使用正确的语法和参数。您可以在文档中找到有关此 function 的更多信息: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ nf-processthreadsapi-regenerateuserenvironment

Check if there are any other errors or warnings that are being logged in your application.检查您的应用程序中是否记录了任何其他错误或警告。 These might provide more context on what could be causing the access violation error.这些可能会提供有关可能导致访问冲突错误的更多上下文。

If you are using a debugger, you can try setting a breakpoint at the line where you are calling the RegenerateUserEnvironment function and examine the variables and the state of your application to see if there is anything unusual happening.如果您正在使用调试器,您可以尝试在调用 RegenerateUserEnvironment function 的行设置一个断点,并检查应用程序的变量和 state 以查看是否有任何异常发生。

Make sure that you are not trying to update the environment block of a process that you do not have permission to modify.确保您没有尝试更新您无权修改的进程的环境块。 You may need to run your application with elevated privileges (eg as an administrator) in order to be able to modify the environment block of certain processes.您可能需要以提升的权限(例如作为管理员)运行您的应用程序,以便能够修改某些进程的环境块。

I hope this helps.我希望这有帮助。 Let me know if you have any other questions or if you need further assistance.如果您有任何其他问题或需要进一步帮助,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试在C#中创建基本编译器,但出现访问冲突错误 - Trying to create basic compiler in C#, getting Access Violation Errors 递归错误访问冲突 - Recursive error access violation vtkParametricFunction中的访问冲突错误 - Access violation error in vtkParametricFunction 使用Windows窗体插入Access DB无效,但不会引发错误 - INSERT into Access DB using Windows Forms not working but not throwing an error 当我尝试启动程序时:(0xc0000005) '访问冲突' 错误 - When i'm trying to start the program: (0xc0000005) 'Access violation' error 尝试将JSON数据发送到服务器时出现语法错误或访问冲突异常 - Syntax error or access violation Exception when trying to send JSON Data to Server 尝试使用实体框架将记录插入SQL Server时违反主键错误 - Violation of Primary Key error when trying to insert record into SQL Server using Entity Framework 在尝试访问控制的cs页面中使用“this”时出错 - Error using 'this' in a cs page trying to access control ExtractToFile 抛出访问被拒绝错误? - ExtractToFile throwing Access Denied Error? 在多个线程中使用WebBrowser时发生访问冲突 - Access Violation when using WebBrowser in multiple threads
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM