RegSetValueEx (advapi32)
Last changed: -64.238.244.146

.
Summary
Sets the data and type of a specified value under a registry key.

C# Signature:

[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegSetValueEx(
    IntPtr hKey,
    [MarshalAs(UnmanagedType.LPStr)] string lpValueName,
    int Reserved,
    Microsoft.Win32.RegistryValueKind dwType,
    [MarshalAs(UnmanagedType.LPStr)] string lpData,
    int cbData);

// Alternate definition - more correct
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
     UIntPtr hKey,
     [MarshalAs(UnmanagedType.LPStr)]
     string lpValueName,
     int Reserved,
     RegistryValueKind dwType,
     IntPtr lpData,
     int cbData);

VB Signature:

<System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError:=True)> _
    Friend Shared Function RegSetValueEx( _
    ByVal hKey As IntPtr, _
    ByVal lpValueName As String, _
    ByVal lpReserved As Integer, _
    ByVal lpType As Integer, _
    ByVal lpData As String, _
    ByVal lpcbData As Integer) As Integer
End Function

Declare Auto Function RegSetValueEx Lib "advapi32.dll" (
   ByVal hKey As IntPtr,
   ByVal lpValueName As String,
   ByVal Reserved As Integer,
   ByVal dwType As Integer,
   ByVal lpData As IntPtr,
   ByVal cbData As Integer
) As Integer

Alternative Managed API:

My.Computer.Registry.SetValue(KeyName, valueName, value, valueKind)
with signature:
   keyName As String
   valueName As String
   value As Object
   valueKind as RegistryValueKind

If you are getting an HKEY from some source without a managed equivalent, it converts to a .NET RegistryKey as:

IntPtr hKey = /* unmanaged function */
RegistryKey regKey = RegistryKey.FromHandle(new SafeRegistryHandle(hKey, true));

Provided you specify true in the SafeRegistryHandle constructor, there is then no need to call RegCloseKey either.

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

' Overloaded, see below
Public Sub SetValue(ByVal Name As String, ByVal Value As Object)
   SetValue(Name, Value, RegistryValueKind.Unknown)
End Sub

' Write a value to a key
Public Sub SetValue(ByVal Name As String, ByVal Value As Object, ByVal RegType As RegistryValueKind)
   Dim gch As GCHandle
   Dim ptr As IntPtr
   Dim ret, Size As Integer

   ' So we have to figure out the type
   If RegType = RegistryValueKind.Unknown Then
     Select Case Value.GetType.ToString
       Case "System.String"
     RegType = RegistryValueKind.String
       Case "System.Int32"
     RegType = RegistryValueKind.DWord
       Case "System.Int64"
     RegType = RegistryValueKind.QWord
       Case "System.String[]"
     RegType = RegistryValueKind.MultiString
       Case "System.Byte[]"
     RegType = RegistryValueKind.Binary
       Case Else
     ' convert it to a string
     RegType = RegistryValueKind.String
     Value = Value.ToString
     End Select
   End If

   Select Case RegType
     Case RegistryValueKind.Binary
       Dim temp() As Byte
       temp = DirectCast(Value, System.Byte())
       Size = temp.Length
       gch = GCHandle.Alloc(temp, GCHandleType.Pinned)
       ptr = Marshal.UnsafeAddrOfPinnedArrayElement(temp, 0)
     Case RegistryValueKind.DWord
       Dim temp As Integer = CInt(Value)
       Size = 4
       ptr = Marshal.AllocHGlobal(Size)
       Marshal.WriteInt32(ptr, 0, temp)
     Case RegistryValueKind.ExpandString
       Dim temp As String = CStr(Value)
       Size = (temp.Length + 1) * Marshal.SystemDefaultCharSize
       ptr = Marshal.StringToHGlobalAuto(temp)
     Case RegistryValueKind.MultiString
       Dim temp, lines() As String
       Dim index As Integer
       lines = DirectCast(Value, System.String())

       ' Calculate the total size, including the terminating null
       Size = 0
       For Each temp In lines
         Size += (temp.Length + 1) * Marshal.SystemDefaultCharSize
       Next
       Size += Marshal.SystemDefaultCharSize
       ptr = Marshal.AllocHGlobal(Size)

       index = 0
       For Each temp In lines
         Dim tempPtr As IntPtr
         Dim tempArray() As Char

         tempArray = temp.ToCharArray
         tempPtr = New IntPtr(ptr.ToInt64 + index)
         Marshal.Copy(tempArray, 0, tempPtr, tempArray.Length)
         index += (tempArray.Length + 1) * Marshal.SystemDefaultCharSize
       Next
     Case RegistryValueKind.QWord
       Dim temp As Long = CLng(Value)
       Size = 8
       ptr = Marshal.AllocHGlobal(Size)
       Marshal.WriteInt64(ptr, 0, temp)
     Case RegistryValueKind.String
       Dim temp As String = CStr(Value)
       Size = (temp.Length + 1) * Marshal.SystemDefaultCharSize
       ptr = Marshal.StringToHGlobalAuto(temp)
     Case Else
       Throw New ApplicationException("Registry type of " & RegType & " is not supported")
   End Select

   ' let's do it!
   ret = RegSetValueEx(hKey, Name, 0, RegType, ptr, Size)
   If ret <> 0 Then
     Throw New Win32Exception(ret)
   End If

   ' clean up
   If gch.IsAllocated Then
     gch.Free()
   Else
     Marshal.FreeHGlobal(ptr)
   End If
End Sub

C# alternate defintion example

    public bool SetNamedValue(string valName, object value, RegistryValueKind type)
    {
        UIntPtr hKey = UIntPtr.Zero;

        try
        {
        uint retVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registryPath, 0, WRITE_FLAG_MASK, out hKey);
        if (retVal == 0)
        {
            int size = 0;
            IntPtr pData = IntPtr.Zero;
            switch (type)
            {
            case RegistryValueKind.String:
                size = ((string)value).Length + 1;
                pData = Marshal.StringToHGlobalAnsi((string)value);
                break;
            case RegistryValueKind.DWord:
                size = Marshal.SizeOf(typeof(Int32));
                pData = Marshal.AllocHGlobal(size);
                Marshal.WriteInt32(pData, (int)value);
                break;
            case RegistryValueKind.QWord:
                size = Marshal.SizeOf(typeof(Int64));
                pData = Marshal.AllocHGlobal(size);
                Marshal.WriteInt64(pData, (long)value);
                break;
            }

            // Set the value
            retVal = RegSetValueEx(hKey, valName, 0, type, pData, size);
            if (retVal != 0)
            {
            Logger.WriteLog("Error writing value to '{0}\\{1}: 0x{2:x}, return code: {3}", registryPath, valName, Marshal.GetLastWin32Error(), retVal);
            return false;
            }
        }
        else
        {
            Logger.WriteLog("Error opening registry key HKLM\\{0}: {1:x}, return code: {2}", registryPath, Marshal.GetLastWin32Error(), retVal);
            return false;
        }
        }
        finally
        {
        if (hKey != UIntPtr.Zero)
        {
            RegCloseKey(hKey);
        }
        }

        return true;
    }

Documentation