Run the script with administrator privileges in C#

Since .Net is code safe, issues may occur when we want to use some unsafe code.

      For example: I want to modify the key value under the registry [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework] in the program. For general programs and X86 (32-bit) machines, it is generally okay. Basically, C# can do it. But when we create The Project is TestProjects, and the problem will be found when the program is run on an X64 (64-bit) machine. This is because:

On a 64-bit machine, there are two folders [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework] and [HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/.NETFramework]. There are many keys in the two folders that are the same, so if you If the key value you want to modify exists in these two folders, suppose you modify the key value InstallRoot key data(%systemdrive%/windows/microsoft.NET/Framework64/: here is just an example, it is best not to modify this key value). You will find that your code will run incorrectly.

     You will find that you have modified the value of the InstallRoot key under [HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/.NETFramework], but you cannot modify the value of the InstallRoot key under [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework].

With the following code,

        RegistryKey dotNetFrameworkKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE", true);
            string[] softWareSubKeys = dotNetFrameworkKey.GetSubKeyNames();
            foreach (string softwaresubkey in softWareSubKeys)
            {
                Console.WriteLine(softwaresubkey);
            }
            Console.ReadLine();

In debug mode you will find

string[] softWareSubKeys = dotNetFrameworkKey.GetSubKeyNames();

Instead of looking for the subfolders under SOFTWARE as expected, but directly looking for the folders under Wow6432Node, so you can’t find the key value under [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework] if you even search It can't be done and it's impossible to modify it.

Therefore, each modification can only be the key value under [HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/.NETFramework].

But what if I want to modify the key value under these two folders at the same time?

Here you can write a batch Test.reg file, its content is as follows


[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework]
"InstallRoot"=dword:C:/windows/microsoft.NET/Framework64/

[HKEY_LOCAL_MACHINE/SOFTWARE/Wow6432Node/Microsoft/.NETFramework]
"InstallRoot"=dword:C:/windows/microsoft.NET/Framework64/

 

Set the address of the Test.reg file server (to prevent local machine file loss) as //testserver/compat. At the same time, there is another password file, which is used to store the user's password.

Then you can use the following method to achieve:

            Process processOnly = new Process();
            StreamWriter swRegistry;
            swRegistry = File.CreateText(AppcompatExtend.APP_CLIENT_SCRIPTSDIR + @"/SetOnlyUseLatestCLR.bat");
            swRegistry.WriteLine("call {0}", @"//testserver/compat/Test.reg",);
            swRegistry.Close();
            string filepath =AppcompatExtend.APP_CLIENT_SCRIPTSDIR + @"/SetOnlyUseLatestCLR.bat";

            StreamReader srPassword = new StreamReader(@"//testserver/compat/password");
            string stringPassword = string.Empty;
          

           //Get the user's password

            while ((stringPassword = srPassword.ReadLine()) != null)
            {
                if (stringPassword.Contains(Environment.GetEnvironmentVariable("USERNAME")))
                {
                    stringPassword = stringPassword.Substring(stringPassword.LastIndexOf(' ') + 1);

                    break;
                }
            }
            srPassword.Close();


            ProcessStartInfo processInfo = new ProcessStartInfo();
            processInfo.FileName = filepath;
            processInfo.Domain = Environment.GetEnvironmentVariable("USERDOMAIN");
            processInfo.UserName = Environment.GetEnvironmentVariable("USERNAME");
            char[] charArr = stringPassword.ToCharArray();
            SecureString password;

            unsafe

           {
            fixed (char* pchar = charArr)
                   {
                         password = new SecureString(pchar, charArr.Length);
                   }

            }
            processInfo.Password = password;
            processInfo.UseShellExecute = false;
            processInfo.WindowStyle = ProcessWindowStyle.Hidden;
            processOnly = Process.Start(processInfo);
            processOnly.WaitForExit();

 

But here another question arises

Because char* is an unsafe code, it should be expressed as unsafe. When building, select the "Allow unsafe code" check box in the Build option under the project's Properites, so that the project can be built.

The generated files are OK on vista, XP, and win 7, but what about 2003server and 2008server? You will find that it will crash, why, this is because of the use of unsafe, so in order to solve this problem, you can modify the above code to:

             SecureString password;

                      foreach(char c in charArr)

                   {
                        password.AppendChar(c);

                   }

In this way, the unsafe code can be removed. Now all systems running OK on the server are available.

 

Note: If the currently logged-in user is not an administrator, just put

processInfo.Domain = Environment.GetEnvironmentVariable("USERDOMAIN");

 processInfo.UserName = Environment.GetEnvironmentVariable("USERNAME");

Just modify it, and you can get it from outside like a password.

 

 

 

 

Guess you like

Origin blog.csdn.net/tianyueWindbg/article/details/5843387