4

I am trying to find the COM port assigned to a USB device, through the registry using Silverlight, and have tried the following:

dynamic WshShell = AutomationFactory.CreateObject("WScript.Shell");
string strRegKeyUSB = @"HKLM\HARDWARE\DEVICEMAP\SERIALCOMM\\Device\USB_COM";
string strCOMValue = WshShell.RegRead(strRegKeyUSB);

This approach usually works 100%, but all Value names under the DEVICEMAP Key is "\Device\XXX" This causes the the "Path" to not be found, as the "\\" between SERIALCOMM and Device is not seen as valid (Throws Error: "Cannot find File Specified")

This, as far as I can see, only really leaves me with one option - P/Invoke, in Silverlight 5

I am using P/Invoke already for a SerialWrapper Class, to Open, Read, Write the COM Ports, and would like to include only the minimal needed to only read this one Key Value from the Registry - I have tried following some examples I have found, but not being strong in Interop, P/Invoke, etc. I am struggling to find only the portions I need.

If someone could please just give me a basic example, to only accomplish this (I do NOT need to write to the registry, or read QWORDS, or anything else - Only read this string value from only this specific key)

I have tried following the following post (Marshal.PtrToStructure in Silverlight) and it's answer, in relation to this (http://www.pinvoke.net/default.aspx/winspool.enumports), but have not been able to get this working, Most likely form a lack of REALLY understanding ;-)

enter image description here

enter image description here

enter image description here

4

2 回答 2

1

这是一个读取REG_SZ值的简单桌面应用程序。这是粗鲁和简单的。它将读取您想要的值。您可能必须使其适应 Silverlight。我不能帮你!

我希望这是有用的:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApplication1
{
    internal static class NativeMethods
    {
        public const int ERROR_SUCCESS = 0;

        public const uint HKEY_LOCAL_MACHINE = 0x80000002;

        public const int KEY_READ = 0x20019;

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
        public static extern int RegOpenKeyEx(
            UIntPtr hKey,
            string subKey,
            int ulOptions,
            int samDesired,
            out UIntPtr hkResult
        );

        [DllImport("advapi32.dll")]
        public static extern int RegCloseKey(
            UIntPtr hKey
        );

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
        public static extern int RegQueryValueEx(
            UIntPtr hKey,
            string lpValueName,
            int lpReserved,
            IntPtr type,
            IntPtr lpData,
            ref int lpcbData
        );
    }

    internal static class RegistryWrapper
    {
        private static void checkErrorCode(int errorCode)
        {
            if (errorCode != NativeMethods.ERROR_SUCCESS)
                throw new Win32Exception(errorCode);
        }

        public static string ReadRegString(UIntPtr rootKey, string subKey, string name)
        {
            UIntPtr hkey;
            checkErrorCode(NativeMethods.RegOpenKeyEx(rootKey, subKey, 0, NativeMethods.KEY_READ, out hkey));
            try
            {
                int cbData = 0;
                checkErrorCode(NativeMethods.RegQueryValueEx(hkey, name, 0, IntPtr.Zero, IntPtr.Zero, ref cbData));
                IntPtr ptr = Marshal.AllocHGlobal(cbData);
                try
                {
                    checkErrorCode(NativeMethods.RegQueryValueEx(hkey, name, 0, IntPtr.Zero, ptr, ref cbData));
                    return Marshal.PtrToStringUni(ptr, cbData / sizeof(char)).TrimEnd('\0');
                }
                finally
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
            finally
            {
                checkErrorCode(NativeMethods.RegCloseKey(hkey));
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(RegistryWrapper.ReadRegString((UIntPtr)NativeMethods.HKEY_LOCAL_MACHINE, @"HARDWARE\DEVICEMAP\SERIALCOMM", @"\Device\Serial0"));
        }
    }
}

更新

似乎在 SilverlightAllocHGlobalFreeHGlobal不可用。您可以 p/invoke to LocalAllocandLocalFree代替。或者你可以使用CoTaskMemAllocand CoTaskMemFree。这是前者的样子:

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr LocalAlloc(uint uFlags, UIntPtr uBytes);

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr LocalFree(IntPtr hMem);

像这样定义LMEM_FIXED

const uint LMEM_FIXED = 0x0000;

然后用这个替换调用AllocHGlobal

IntPtr ptr = LocalAlloc(LMEM_FIXED, cbData);

并将调用替换为FreeHGlobal

LocalFree(ptr);
于 2013-09-17T15:39:03.893 回答
0

非常感谢@Dave Heffernan,我终于让它工作了......

我在 Dave's Answer 的 RegistryWrapper 类中添加了以下代码:

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr LocalAlloc(uint uFlags, int size);

        internal static IntPtr AllocHGlobal(int size)
        {
            uint LPTR = (uint)0x0040;
            IntPtr hGlobal = LocalAlloc(LPTR, size);
            if (hGlobal == IntPtr.Zero)
            {
                throw new OutOfMemoryException("Unmanaged memory was not allocated.");
            }
            return hGlobal;
        }

这解决了 Marshal.AllocHGlobal 在 Silverlight 中不可用的限制。然后,我还将对 Marshal.AllocHGlobal 的引用更改为上面的本地 AllocHGlobal 方法。

于 2013-09-20T09:12:21.867 回答