Issue #165 resolved

Set-RegistryKeyValue rejects unsigned integers larget than [int]::MaxValue

James Bennett
created an issue

Set-RegistryKeyValue -path $path -Name xx -DWORD 4294967295
results in the message "value is too large or small" for an Int.

Set-RegistryKeyValue -path $path -Name xx -DWORD 0xFFFFFFFF does work, presumably because PS casts it behind the scenes.

Technically, shouldn't the DWORD and QWORD parms be [uint32] and [uint64]?

Comments (8)

  1. Aaron Jensen repo owner

    In my testing, I've changed the type of the -DWord parameter to [object] and tried a bunch of different 32-bit number values. Negative int values get stored correctly, but always get returned as unsigned ints. Values seem to get stored correctly on the way in, but when they come out, bytes that would be converted to a negative int or a value greater than [int]::maxvalue are returned as unsigned integers. Very strange. Not sure if it is PowerShell doing this weird conversion or .NET.

  2. Aaron Jensen repo owner

    The .NET APIs (Microsoft.Win32.Registry.SetValue) requires an int32. It throws an exception if I try to pass a uint32.

    Set-RegistryKeyValue uses PowerShells Set-ItemProperty. Who knows what the registry provider is using to set the key's value.

  3. James Bennett reporter

    If it helps, this looks like it converts the Set-ItemProperty to a Uint (presumably if the INT conversion fails?)

    PS HKLM:\> trace-command -name * -PSHost -Option executionflow -Expression  { Set-ItemProperty -Path "HKLM:\Software" -n
    ame "MyKey4" -Type Dword -Value 4294967295 }
    

    and this code works too

    Microsoft.Win32.Registry.SetValue(key, name, System.UInt32.MaxValue);
    
  4. Aaron Jensen repo owner

    I think what I'll do is introduce -UDWord and -UQWord parameters, for passing in unsigned integers. Otherwise, if I change the type of the DWord and QWord parameters, that could potentially break backwards-compatability, which I try my hardest not to do.

  5. Aaron Jensen repo owner

    This should be part of Carbon 2.0. As a workaround, you can convert (not cast) the unsigned integer's bits to an int32:

        $bytes = [BitConverter]::GetBytes( $unsignedInt )
        $signedInt = [BitConverter]::ToInt32( $bytes, 0 )  # Or use `ToInt64` if you're working with 64-bit/QWord values
        Set-RegistryKeyValue -Path $Path -Name 'MyUnsignedDWord' -DWord $signedInt
    

    I've added this code sample to the docs, which will also get updated once 2.0 is out the door.

  6. Log in to comment