为什么尝试更新注册表值会失败?
Why does this Attempt to Update a Registry Value Fail?
我有这个代码:
RegistryKey myKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\Android Studio", true);
myKey.SetValue("StartMenuGroup", "Droidio", RegistryValueKind.String); // was "Android Studio" - change to "Droidio"
...我改编自 here.
运行 它,尽管会导致以下 NRE 转储:
*System.NullReferenceException was unhandled
_HResult=-2147467261
_message=Object reference not set to an instance of an object.
HResult=-2147467261
IsTransient=false
Message=Object reference not set to an instance of an object.
Source=Sandbox
StackTrace:
at Sandbox.Form1.button57_Click(Object sender, EventArgs e) in c:\HoldingTank\Sandbox\Form1.cs:line 2524
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Sandbox.Program.Main() in c:\HoldingTank\Sandbox\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:*
我正在尝试更新的注册表设置(作为测试;然后我会重新设置)在这里:
当注册表项明明存在时,这怎么会失败?
更新
我尝试了另一种方法,我改编自 here:
RegistryKey reg32key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry32);
RegistryKey reg_32bit_AppKey =
reg32key.OpenSubKey(@"HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio");
if (reg_32bit_AppKey != null)
{
MessageBox.Show(String.Format("value was {0}",
reg_32bit_AppKey.GetValue("StartMenuGroup").ToString()));
reg_32bit_AppKey.SetValue("StartMenuGroup", "Droidio");
MessageBox.Show(String.Format("value is now {0}",
reg_32bit_AppKey.GetValue("StartMenuGroup").ToString()));
}
else
{
MessageBox.Show("Cannot open registry");
}
...但是,虽然它没有崩溃,但我看到了“无法打开注册表”消息。
更新 2
有了这个(位数加倍):
RegistryKey reg64key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey reg_64bit_AppKey =
reg64key.OpenSubKey(@"HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio");
if (reg_64bit_AppKey != null)
{
MessageBox.Show(String.Format("value was {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio");
MessageBox.Show(String.Format("value is now {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
}
else
{
MessageBox.Show("Cannot open registry");
}
...我仍然得到“无法打开注册表”结果。
更新 3
好的,将代码更改为此(从替代尝试中删除 "HKEY_LOCAL_MACHINE"):
RegistryKey reg64key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey reg_64bit_AppKey = reg64key.OpenSubKey(@"SOFTWARE\Android
Studio");
if (reg_64bit_AppKey != null)
{
MessageBox.Show(String.Format("value was {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio");
MessageBox.Show(String.Format("value is now {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
}
else
{
MessageBox.Show("Cannot open registry");
}
...更改异常。首先,正如我所见,“价值是 Android Studio”
...但随后在下一行中断,即:
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio");
...与:
*System.UnauthorizedAccessException was unhandled
_HResult=-2147024891
_message=Cannot write to the registry key.
HResult=-2147024891
IsTransient=false
Message=Cannot write to the registry key.
Source=mscorlib
StackTrace:
at System.ThrowHelper.ThrowUnauthorizedAccessException(ExceptionResource resource)
at Microsoft.Win32.RegistryKey.EnsureWriteable()
at Microsoft.Win32.RegistryKey.SetValue(String name, Object value, RegistryValueKind valueKind)
at Microsoft.Win32.RegistryKey.SetValue(String name, Object value)
at Sandbox.Form1.button57_Click(Object sender, EventArgs e) in c:\HoldingTank\Sandbox\Form1.cs:line 2559
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentM
anager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Sandbox.Program.Main() in c:\HoldingTank\Sandbox\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object
state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state,
Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:*
那么为什么我可以读,但不能写?我 运行ning Visual Studio 2013 处于管理员模式,因为我 运行 此代码...
更新 4
现在是未授权访问问题。
这是 reg_64bit_AppKey 的值,因为我到达了设置值的行:
F10 通过它咳出 "Unauthorized access" 呜呜声[g]ing。
更新 5
正在创建包含以下内容的文件:
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio]
"StartMenuGroup"="Droidio"
...将其命名为“DroidioReg.reg”,然后从 Windows 中手动选择合并上下文菜单,Explorer 完成了我的预期(无论如何希望): 将 StartMenuGroup 的值更改为 "Droidio"。实际上,即使只是双击文件并在所有确认对话框中移动也可以。
所以,这是第 N 度的笨拙,但是否可以通过编程方式调用该文件的 "Merge" - IOW,将该文件放在手持设备上,然后在代码中执行它?用户是否必须浏览警告对话框,或者是否有办法以编程方式阻止显示这些对话框?
使用转义字符串而不是字符串文字。 OpenSubKey 方法似乎无法正确读取您的转义路径。
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Android Studio", true);
我在 Pwninstein 的评论中找到了克服访问权限侵犯的关键点 here - 只需将 "true" 附加到 OpenSubKey() 方法即可。
我被吓到了,但现在我可以吹嘘通过 tWotC(人群的智慧)组装的工作代码是:
RegistryKey reg64key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey reg_64bit_AppKey = reg64key.OpenSubKey(@"SOFTWARE\Android Studio", true);
if (reg_64bit_AppKey != null)
{
//MessageBox.Show(String.Format("value was {0}", reg_64bit_AppKey.GetValue("StartMenuGroup")));
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio", RegistryValueKind.String);
//MessageBox.Show(String.Format("value is now {0}", reg_64bit_AppKey.GetValue("StartMenuGroup")));
}
else
{
MessageBox.Show("Cannot open registry");
}
对于我的 真实 案例,我无疑需要使用 32 位版本,而不是 64 位版本,因为手持设备比 Joe Dirt 老,而且脾气暴躁两倍。
我有这个代码:
RegistryKey myKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\Android Studio", true);
myKey.SetValue("StartMenuGroup", "Droidio", RegistryValueKind.String); // was "Android Studio" - change to "Droidio"
...我改编自 here.
运行 它,尽管会导致以下 NRE 转储:
*System.NullReferenceException was unhandled
_HResult=-2147467261
_message=Object reference not set to an instance of an object.
HResult=-2147467261
IsTransient=false
Message=Object reference not set to an instance of an object.
Source=Sandbox
StackTrace:
at Sandbox.Form1.button57_Click(Object sender, EventArgs e) in c:\HoldingTank\Sandbox\Form1.cs:line 2524
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Sandbox.Program.Main() in c:\HoldingTank\Sandbox\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:*
我正在尝试更新的注册表设置(作为测试;然后我会重新设置)在这里:
当注册表项明明存在时,这怎么会失败?
更新
我尝试了另一种方法,我改编自 here:
RegistryKey reg32key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry32);
RegistryKey reg_32bit_AppKey =
reg32key.OpenSubKey(@"HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio");
if (reg_32bit_AppKey != null)
{
MessageBox.Show(String.Format("value was {0}",
reg_32bit_AppKey.GetValue("StartMenuGroup").ToString()));
reg_32bit_AppKey.SetValue("StartMenuGroup", "Droidio");
MessageBox.Show(String.Format("value is now {0}",
reg_32bit_AppKey.GetValue("StartMenuGroup").ToString()));
}
else
{
MessageBox.Show("Cannot open registry");
}
...但是,虽然它没有崩溃,但我看到了“无法打开注册表”消息。
更新 2
有了这个(位数加倍):
RegistryKey reg64key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey reg_64bit_AppKey =
reg64key.OpenSubKey(@"HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio");
if (reg_64bit_AppKey != null)
{
MessageBox.Show(String.Format("value was {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio");
MessageBox.Show(String.Format("value is now {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
}
else
{
MessageBox.Show("Cannot open registry");
}
...我仍然得到“无法打开注册表”结果。
更新 3
好的,将代码更改为此(从替代尝试中删除 "HKEY_LOCAL_MACHINE"):
RegistryKey reg64key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey reg_64bit_AppKey = reg64key.OpenSubKey(@"SOFTWARE\Android
Studio");
if (reg_64bit_AppKey != null)
{
MessageBox.Show(String.Format("value was {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio");
MessageBox.Show(String.Format("value is now {0}",
reg_64bit_AppKey.GetValue("StartMenuGroup").ToString()));
}
else
{
MessageBox.Show("Cannot open registry");
}
...更改异常。首先,正如我所见,“价值是 Android Studio”
...但随后在下一行中断,即:
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio");
...与:
*System.UnauthorizedAccessException was unhandled
_HResult=-2147024891
_message=Cannot write to the registry key.
HResult=-2147024891
IsTransient=false
Message=Cannot write to the registry key.
Source=mscorlib
StackTrace:
at System.ThrowHelper.ThrowUnauthorizedAccessException(ExceptionResource resource)
at Microsoft.Win32.RegistryKey.EnsureWriteable()
at Microsoft.Win32.RegistryKey.SetValue(String name, Object value, RegistryValueKind valueKind)
at Microsoft.Win32.RegistryKey.SetValue(String name, Object value)
at Sandbox.Form1.button57_Click(Object sender, EventArgs e) in c:\HoldingTank\Sandbox\Form1.cs:line 2559
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentM
anager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Sandbox.Program.Main() in c:\HoldingTank\Sandbox\Program.cs:line 19
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object
state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state,
Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:*
那么为什么我可以读,但不能写?我 运行ning Visual Studio 2013 处于管理员模式,因为我 运行 此代码...
更新 4
现在是未授权访问问题。
这是 reg_64bit_AppKey 的值,因为我到达了设置值的行:
F10 通过它咳出 "Unauthorized access" 呜呜声[g]ing。
更新 5
正在创建包含以下内容的文件:
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio]
"StartMenuGroup"="Droidio"
...将其命名为“DroidioReg.reg”,然后从 Windows 中手动选择合并上下文菜单,Explorer 完成了我的预期(无论如何希望): 将 StartMenuGroup 的值更改为 "Droidio"。实际上,即使只是双击文件并在所有确认对话框中移动也可以。
所以,这是第 N 度的笨拙,但是否可以通过编程方式调用该文件的 "Merge" - IOW,将该文件放在手持设备上,然后在代码中执行它?用户是否必须浏览警告对话框,或者是否有办法以编程方式阻止显示这些对话框?
使用转义字符串而不是字符串文字。 OpenSubKey 方法似乎无法正确读取您的转义路径。
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Android Studio", true);
我在 Pwninstein 的评论中找到了克服访问权限侵犯的关键点 here - 只需将 "true" 附加到 OpenSubKey() 方法即可。
我被吓到了,但现在我可以吹嘘通过 tWotC(人群的智慧)组装的工作代码是:
RegistryKey reg64key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey reg_64bit_AppKey = reg64key.OpenSubKey(@"SOFTWARE\Android Studio", true);
if (reg_64bit_AppKey != null)
{
//MessageBox.Show(String.Format("value was {0}", reg_64bit_AppKey.GetValue("StartMenuGroup")));
reg_64bit_AppKey.SetValue("StartMenuGroup", "Droidio", RegistryValueKind.String);
//MessageBox.Show(String.Format("value is now {0}", reg_64bit_AppKey.GetValue("StartMenuGroup")));
}
else
{
MessageBox.Show("Cannot open registry");
}
对于我的 真实 案例,我无疑需要使用 32 位版本,而不是 64 位版本,因为手持设备比 Joe Dirt 老,而且脾气暴躁两倍。