c# Registry System.Byte[] to string
I am currently writing a program that will read part of the windows system registry however some of the values of these keys are of type System.Byte[] when i try and decode these values I can produce a stri开发者_如何学运维ng that has some readable characters that makes but mostly the string is jiberish. I have tried several encoding types but none seem to produce the correct results. I am just wondering if there is anything that is known to fix this. this is the code i have
public void getMRU()
{
String mru = @"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU";
RegistryKey rk = Registry.CurrentUser.OpenSubKey(mru);
foreach (string skName in rk.GetSubKeyNames())
{
RegistryKey sk = rk.OpenSubKey(skName);
System.Text.Encoding enc = System.Text.Encoding.UTF8;
string myString = enc.GetString((Byte[])sk.GetValue("0"));
Console.WriteLine(myString)
}
}
The correct decoding and interpretation varies from key to key. For binary values there is no enforced format, applications are free to store any bytes they wish. You must know what you read in order to interpret it. If the key content is documented, then you can apply the documentation specifications to decode the content. If is undocumented, then you have no business reading it.
Perhaps this is no longer an issue, but to help anyone else who might encounter this problem consider the following:
A PIDL, or pointer to an item identifier list only exists in Windows NT 6.x (Vista, Win7) and actually starts at the desktop rather than C:\... (I believe this was done due to the introduction of "libraries"). Thus, you need special handling to extract a file path from a PIDL.
The following method, GetPathFromPIDL(), will take a registry key's (byte[]) byteCode
and covert it to a platform specific IntPtr
. Then we take the IntPtr
(given that it is a PIDL) and call the P/Invoke method SHGetPathFromIDListW(), which will put the string representation of the PIDL in our StringBuilder.
private string GetPathFromPIDL(byte[] byteCode)
{
//MAX_PATH = 260
StringBuilder builder = new StringBuilder(260);
IntPtr ptr = IntPtr.Zero;
GCHandle h0 = GCHandle.Alloc(byteCode, GCHandleType.Pinned);
try
{
ptr = h0.AddrOfPinnedObject();
}
finally
{
h0.Free();
}
SHGetPathFromIDListW(ptr, builder);
return builder.ToString();
}
Prototype for SHGetPathFromIDListW()
:
[DllImport("shell32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SHGetPathFromIDListW(IntPtr pidl, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszPath);
It's not guaranteed that the bytes that are stored in the registry for any value are necessarily encoded strings. If they were to be strings, then the type of the registry value would be just that, a string.
If it is a byte value, then it usually means that it is an encoding of some sort of data structure that is custom to the application, so you have to figure out what the format is for the application which owns the key that you are reading.
From the name of the registry key, I would guess that those blobs aren't encoded filename strings at all, but instead are PIDLs (or rather ITEMIDLISTs). A PIDL is a shell structure representing an entity in the shell namespace, which need not be a file (e.g. Control Panel).
If that's the case, you'll probably need to use the SHGetPathFromIDList API to convert the PIDL to a filesystem path: pass in the address of the byte[] array as the pidl parameter.
精彩评论