使用 C# 应用程序在 WinCE 中保存注册表值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/57609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Save registry values in WinCE using a C# app
提问by odbasta
I'm working on a WinCE 6.0 system with a touchscreen that stores its calibration data (x-y location, offset, etc.) in the system registry (HKLM\HARDWARE\TOUCH). Right now, I'm placing the cal values into registry keys that get put into the OS image at build time. That works fine for the monitor that I get the original cal values from, but when I load this image into another system with a different monitor, the touchscreen pointer location is (understandably) off, because the two monitors do not have the same cal values.
我正在开发带有触摸屏的 WinCE 6.0 系统,该系统将其校准数据(xy 位置、偏移量等)存储在系统注册表 (HKLM\HARDWARE\TOUCH) 中。现在,我将 cal 值放入在构建时放入操作系统映像的注册表项中。这适用于我从中获取原始校准值的显示器,但是当我将此图像加载到另一个具有不同显示器的系统时,触摸屏指针位置(可以理解)关闭,因为两个显示器没有相同的校准值.
My problem is that I don't know how to properly store values into the registry so that they persist after a power cycle. See, I can recalibrate the screen on the second system, but the new values only exist in volatile memory. I suggested to my boss that we could just tell our customer to leave the power on the unit at all times -- that didn't go over well.
我的问题是我不知道如何将值正确存储到注册表中,以便它们在电源循环后仍然存在。看,我可以在第二个系统上重新校准屏幕,但新值仅存在于易失性内存中。我向我的老板建议我们可以告诉我们的客户始终保持设备的电源——这并不顺利。
I need advice on how to save the new constants into the registry, so that we can calibrate the monitors once before shipping them out to our customer, and not have to make separate OS images for each unit we build.
我需要有关如何将新常量保存到注册表中的建议,以便我们可以在将监视器发送给客户之前对其进行一次校准,而不必为我们构建的每个单元制作单独的操作系统映像。
A C# method that is known to work in CE6.0 would be helpful. Thanks.
已知可在 CE6.0 中使用的 AC# 方法会有所帮助。谢谢。
-Odbasta
-Odbasta
采纳答案by TheSmurf
I think what you're probably looking for is the Flush function of the RegistryKey class. This is normally not necessary (the registry is lazily-flushed by default), but if the power is turned off on the device before the system has a chance to do this, changes will be discarded:
我认为您可能正在寻找的是 RegistryKey 类的 Flush 函数。这通常不是必需的(默认情况下注册表是惰性刷新的),但是如果在系统有机会执行此操作之前关闭设备上的电源,更改将被丢弃:
http://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey.flush.aspx
http://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey.flush.aspx
This function is available in .NET Compact Framework version 2.0 and better.
此函数在 .NET Compact Framework 2.0 及更高版本中可用。
回答by odbasta
Follow-up on this question:
这个问题的后续:
Thanks DannySmurf, flushing the registry key was ultimately what needed to be done. However, there were a few steps that I was missing before reaching that stage. So, here's what came to light:
感谢 DannySmurf,最终需要完成的是刷新注册表项。然而,在到达那个阶段之前,我错过了几个步骤。所以,这就是曝光的事情:
- I was using a RAM-based registry, where by design the registry does not persist after a cold boot. I had to switch the registry to hive-based.
When switching to a hive-based registry structure, you need to make sure that the hive exists on a non-volatile medium. This is specified in the platform.reg file:
[HKEY_LOCAL_MACHINE\init\BootVars] "SystemHive"="\Hard Disk\system.hv" "ProfileDir"="\Documents and Settings" "RegistryFlags"=dword:1 ; Flush hive on every RegCloseKey call "SystemHiveInitialSize"=dword:19000 ; Initial size for hive-registry file "Start DevMgr"=dword:1
Once the system.hv file is on the hard disk (CF card in my case), the values in the registry will persist after a cold boot. Note that the system.hv file contains all the HKLM keys.
It's also important to note that any drivers that need to be initialized on boot have to be specified as such in the .reg files of the solution. For example, I had to make sure that the hard disk drivers (PCMCIA) were loaded before trying to read the system hive file from them. The way to do this is to add a directive in the following format around each driver init key:
;HIVE BOOT SECTION [HKEY_LOCAL_MACHINE\Drivers\PCCARD\PCMCIA\TEMPLATE\PCMCIA] "Dll"="pcmcia.dll" "NoConfig"=dword:1 "IClass"=multi_sz:"{6BEAB08A-8914-42fd-B33F-61968B9AAB32}=PCMCIA Card Services" "Flags"=dword:1000 ;END HIVE BOOT SECTION
- 我使用的是基于 RAM 的注册表,根据设计,注册表在冷启动后不会持续存在。我不得不将注册表切换到基于 hive 的。
切换到基于 hive 的注册表结构时,您需要确保 hive 存在于非易失性介质上。这是在 platform.reg 文件中指定的:
[HKEY_LOCAL_MACHINE\init\BootVars] "SystemHive"="\Hard Disk\system.hv" "ProfileDir"="\Documents and Settings" "RegistryFlags"=dword:1 ; Flush hive on every RegCloseKey call "SystemHiveInitialSize"=dword:19000 ; Initial size for hive-registry file "Start DevMgr"=dword:1
一旦 system.hv 文件位于硬盘(在我的例子中是 CF 卡)上,注册表中的值将在冷启动后保持不变。请注意,system.hv 文件包含所有 HKLM 密钥。
同样重要的是要注意,任何需要在启动时初始化的驱动程序都必须在解决方案的 .reg 文件中进行指定。例如,在尝试从中读取系统配置单元文件之前,我必须确保已加载硬盘驱动程序 (PCMCIA)。这样做的方法是在每个驱动程序初始化键周围添加以下格式的指令:
;HIVE BOOT SECTION [HKEY_LOCAL_MACHINE\Drivers\PCCARD\PCMCIA\TEMPLATE\PCMCIA] "Dll"="pcmcia.dll" "NoConfig"=dword:1 "IClass"=multi_sz:"{6BEAB08A-8914-42fd-B33F-61968B9AAB32}=PCMCIA Card Services" "Flags"=dword:1000 ;END HIVE BOOT SECTION
That, plus a lot of luck, is about it.
再加上很多运气,就是这样。
回答by odbasta
As I understood you need to know how to set a value to the registry during runtime. I hope the codes bellow can help you.
据我了解,您需要知道如何在运行时为注册表设置值。我希望下面的代码可以帮助你。
using Microsoft.Win32;
使用 Microsoft.Win32;
/// <summary>
/// store a key value in registry. if it don't exist it will be created.
/// </summary>
/// <param name="mainKey">the main key of key path</param>
/// <param name="subKey">the path below the main key</param>
/// <param name="keyName">the key name</param>
/// <param name="value">the value to be stored</param>
public static void SetRegistry(int mainKey, String subKey, String keyName, object value)
{
if (mainKey != CURRENT_USER && mainKey != LOCAL_MACHINE)
{
throw new ArgumentOutOfRangeException("mainKey", "\'mainKey\' argument can only be AppUtils.CURRENT_USER or AppUtils.LOCAL_MACHINE values");
}
if (subKey == null)
{
throw new ArgumentNullException("subKey", "\'subKey\' argument cannot be null");
}
if (keyName == null)
{
throw new ArgumentNullException("keyName", "\'keyName\' argument cannot be null");
}
const Boolean WRITABLE = true;
RegistryKey key = null;
if (mainKey == CURRENT_USER)
{
key = Registry.CurrentUser.OpenSubKey(subKey, WRITABLE);
if (key == null)
{
key = Registry.CurrentUser.CreateSubKey(subKey);
}
}
else if (mainKey == LOCAL_MACHINE)
{
key = Registry.LocalMachine.OpenSubKey(subKey, WRITABLE);
if (key == null)
{
key = Registry.LocalMachine.CreateSubKey(subKey);
}
}
key.SetValue(keyName, value);
}
/// <summary>
/// find a key value in registry. if it don't exist the default value will be returned.
/// </summary>
/// <param name="mainKey">the main key of key path</param>
/// <param name="subKey">the path below the main key</param>
/// <param name="keyName">the key name</param>
/// <param name="defaultValue">the value to be stored</param>
public static object GetRegistry(int mainKey, String subKey, String keyName, object defaultValue)
{
if (mainKey != CURRENT_USER && mainKey != LOCAL_MACHINE)
{
throw new ArgumentOutOfRangeException("mainKey", "\'mainKey\' argument can only be AppUtils.CURRENT_USER or AppUtils.LOCAL_MACHINE values");
}
if (subKey == null)
{
throw new ArgumentNullException("subKey", "\'subKey\' argument cannot be null");
}
if (keyName == null)
{
throw new ArgumentNullException("keyName", "\'keyName\' argument cannot be null");
}
RegistryKey key = Registry.CurrentUser.OpenSubKey(subKey);
if (mainKey == CURRENT_USER)
{
key = Registry.CurrentUser.OpenSubKey(subKey);
}
else if (mainKey == LOCAL_MACHINE)
{
key = Registry.LocalMachine.OpenSubKey(subKey);
}
object result = defaultValue;
if (key != null)
{
result = key.GetValue(keyName, defaultValue);
}
return result;
}