我的应用程序需要在运行时设置SQL别名,如果它检测到别名未设置。 现在我有它生成一个临时Reg文件并通过regedit.exe运行它,但是因为我的应用程序是32位(它必须是因为我正在使用一些32位dll,我无法获得64位版本)windows当我运行regedit到版本%windir%\SysWow64\regedit.exe而不是%windir%\regedit.exe时,正在进行重定向。
这会导致我尝试写入[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo]键被重定向到32位子文件夹,并且我显式写入32位子文件夹, [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo]我不知道他们要去哪里。
通常,为了解决这个问题,您只需使用%windir%\sysnative\xxxx.exe但sysnative重定向到System32文件夹而不是根目录窗口文件夹,这是regedit所在的位置。
有没有办法解决这个问题,而无需编写自定义程序来提升并自行完成?
这是我当前的代码,即失败。
static void CreateAliases() { using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) { using (var key = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo")) { CheckKeys(key); } } try { using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) { using (var key = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo")) { CheckKeys(key); } } } catch { //Catch failues if it is 32 bit only. } } private static void CheckKeys(RegistryKey key) { //check to see if the key exists. if (key == null) { AddKeys(); return; } var value = key.GetValue(@"wi\sql2008"); if (value == null || value.ToString() != String.Concat("DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2008Port)) { AddKeys(); return; } value = key.GetValue(@"wi\sql2005"); if (value == null || value.ToString() != String.Concat("DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2005Port)) { AddKeys(); return; } } static private void AddKeys() { string file = System.IO.Path.GetTempFileName(); using(StreamWriter sw = new StreamWriter(file)) { sw.WriteLine("Windows Registry Editor Version 5.00"); sw.WriteLine(); sw.WriteLine(@"[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo]"); sw.WriteLine(String.Concat("\"wi\\\\sql2005\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2005Port,'"')); sw.WriteLine(String.Concat("\"wi\\\\sql2008\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2008Port,'"')); sw.WriteLine(); sw.WriteLine(@"[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo]"); sw.WriteLine(String.Concat("\"wi\\\\sql2005\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2005Port, '"')); sw.WriteLine(String.Concat("\"wi\\\\sql2008\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2008Port, '"')); } WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool IsAdmin = principal.IsInRole("BUILTIN\\Administrators"); string regedit; if (Environment.Is64BitProcess) { regedit = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "regedit"); } else { regedit = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "sysnative", "regedit"); //regedit.exe does not exist in sysnative. } if (IsAdmin) { var proc = Process.Start(new ProcessStartInfo(regedit, String.Concat("/s ", file))); proc.WaitForExit(); } else { MessageBox.Show("Updating registry keys for WI alias, this must be run as administrator"); var proc = Process.Start(new ProcessStartInfo(regedit, String.Concat("/s ", file)) { Verb = "runas", UseShellExecute = true }); proc.WaitForExit(); } File.Delete(file); }这是生成的临时文件。
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo] "wi\\sql2005"="DBMSSOCN,wi,49224" "wi\\sql2008"="DBMSSOCN,wi,49681" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo] "wi\\sql2005"="DBMSSOCN,wi,49224" "wi\\sql2008"="DBMSSOCN,wi,49681"My app needs to set up a SQL alias when it runs if it detects the alias is not set up. Right now I have it generate a temp Reg File and and run it through regedit.exe, however because my app is 32 bit (it must be as I am interoping with some 32 bit dll's that I can not get 64 bit versions for) windows is doing redirection when I run regedit to the version %windir%\SysWow64\regedit.exe instead of %windir%\regedit.exe.
This causes the keys I attempt to write to [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo] to be redirected to the 32 bit sub folder, and my explicit writes to the 32 bit sub-folder, [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo] I have no clue where they are going.
Normally to get around this you would just use %windir%\sysnative\xxxx.exe but sysnative redirects to the System32 folder not the root windows folder, which is where regedit resides.
Is there a way to solve this issue without writing a custom program to elevate and do it itself?
Here is my current code, that is failing.
static void CreateAliases() { using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) { using (var key = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo")) { CheckKeys(key); } } try { using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)) { using (var key = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo")) { CheckKeys(key); } } } catch { //Catch failues if it is 32 bit only. } } private static void CheckKeys(RegistryKey key) { //check to see if the key exists. if (key == null) { AddKeys(); return; } var value = key.GetValue(@"wi\sql2008"); if (value == null || value.ToString() != String.Concat("DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2008Port)) { AddKeys(); return; } value = key.GetValue(@"wi\sql2005"); if (value == null || value.ToString() != String.Concat("DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2005Port)) { AddKeys(); return; } } static private void AddKeys() { string file = System.IO.Path.GetTempFileName(); using(StreamWriter sw = new StreamWriter(file)) { sw.WriteLine("Windows Registry Editor Version 5.00"); sw.WriteLine(); sw.WriteLine(@"[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo]"); sw.WriteLine(String.Concat("\"wi\\\\sql2005\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2005Port,'"')); sw.WriteLine(String.Concat("\"wi\\\\sql2008\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2008Port,'"')); sw.WriteLine(); sw.WriteLine(@"[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo]"); sw.WriteLine(String.Concat("\"wi\\\\sql2005\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2005Port, '"')); sw.WriteLine(String.Concat("\"wi\\\\sql2008\"=\"DBMSSOCN,wi,", Properties.Settings.Default.wi_sql2008Port, '"')); } WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool IsAdmin = principal.IsInRole("BUILTIN\\Administrators"); string regedit; if (Environment.Is64BitProcess) { regedit = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "regedit"); } else { regedit = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "sysnative", "regedit"); //regedit.exe does not exist in sysnative. } if (IsAdmin) { var proc = Process.Start(new ProcessStartInfo(regedit, String.Concat("/s ", file))); proc.WaitForExit(); } else { MessageBox.Show("Updating registry keys for WI alias, this must be run as administrator"); var proc = Process.Start(new ProcessStartInfo(regedit, String.Concat("/s ", file)) { Verb = "runas", UseShellExecute = true }); proc.WaitForExit(); } File.Delete(file); }Here is the temp file that is being generated.
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo] "wi\\sql2005"="DBMSSOCN,wi,49224" "wi\\sql2008"="DBMSSOCN,wi,49681" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo] "wi\\sql2005"="DBMSSOCN,wi,49224" "wi\\sql2008"="DBMSSOCN,wi,49681"最满意答案
我将考虑使用SMO ServerAlias类创建服务器别名,然后您不必自己处理注册表访问。
I would look into creating a server alias using the SMO ServerAlias class instead, then you don't have to deal with the registry access yourself.
更多推荐
发布评论