Question

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.

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.

-Odbasta

Was it helpful?

Solution

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:

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.

OTHER TIPS

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:

  • 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
    

That, plus a lot of luck, is about it.

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;

    /// <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;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top