I've been working on USB HID Device in embedded system and C# for a while. I decided to use USBHid library in C#. I got the ideal result with this library. But I have a problem. While defining the USB in the USBHid library, the following code is sufficient in the project of the library that I found on the internet.
public UsbHidDevice Device;
Device = new UsbHidDevice(vvvv,pppp);
However, when I use the same library, it asks me for an expression in the following format.
public UsbHidDevice Device; string vidandpid =
"\\hid#vid_0000&pid_0000&mi_00#a&0&000000000&1&0000#{eeof37d0-1963-47k4-aa41-74476db7uf49}";
Device = new UsbHidDevice(vidandpid);
I adapted this format for my own HID device, but without success. How should this string expression be? I am open to your views. Thank you from now.
How to find USB HID DevicePath?
I gave up on USBHID library and found solution with HidLibrary library. As far as I understand, HidLibrary falls short on some issues.
Here I am sharing the C# code that I linked with HidLibrary. Thank you for all the replies.
device = HidDevices.Enumerate(VendorID, ProductID).FirstOrDefault();
if (device != null)
{
device.OpenDevice();
device.Inserted += DeviceAttachedHandler;
device.Removed += DeviceRemovedHandler;
device.MonitorDeviceEvents = true;
device.ReadReport(myfunction);
}
else { RtBox_Feedback.AppendText("NOT DEVICE!"); }
\\hid#vid_0000&pid_0000&mi_00#a&0&000000000&1&0000#{eeof37d0-1963-47k4-aa41-74476db7uf49} - is a device interface for the {eeof37d0-1963-47k4-aa41-74476db7uf49} interface. It is almost always unique and semi-random for each device. It also may change if yore put device in another USB slot. This string may be used as path to open this "file" with CreateFile Win32 API and talk with device by means of interface-specific IOCTLs. More info here.
For HID devices Windows have another device interface GUID - GUID_DEVINTERFACE_HID - {4D1E55B2-F16F-11CF-88CB-001111000030}
You can use CM_Get_Device_Interface_ListW or SetupDiGetClassDevs/SetupDiEnumDeviceInterfaces/SetupDiGetDeviceInterfaceDetail APIs to enumerate device interfaces by interface GUID or by device Instance ID.
Mentioned "USBHid library in C#" may already have code that doing such enumeration and filtering by HID deivce VID/PID but I cannot say it for sure since you haven't added link to the code of this library. :)
UPS is Soltec Apa-650 with "megatec battery driver".
Even being in the device manager battery area, it doesn't appear in the Win32_Battery.
Status is available with Upsilon 2000 software (remaining, temperature, etc...).
But now I need to read these values from a C# program
First idea: After seeing the payload with Wireshark, I want to replay it with c#. Any Idea?
For example, I tried pinvoke
deviceHandle = Kernel32.CreateFile(deviceInstancePath, 0, Constants.FileShareRead | Constants.FileShareWrite, IntPtr.Zero, Constants.OpenExisting, 0, 0);
=> The handle is ok
var success = Kernel32.WriteFile( deviceInformation.WriteHandle, outputReportBuffer, outputReportBuffer.Length, ref numberOfBytesWritten, IntPtr.Zero);
=> The success returns false
Does anybody know where I can find the failing explanation?
Any help would be appreciated (sorry for my English, I'm a french guy)
Edit
Thank's to aja here is the answer about the failing explaination
Win32Exception a = new Win32Exception(Marshal.GetLastWin32Error());
Console.WriteLine(a.Message)
For a project i have to communicate with a netduino,
So i use serial communication to communicate with the netduino.
But here's my problem
I cannot find my Usb portname, i use this small piece of code to find the port names.
private void GetPortNames()
{
string[] ports = SerialPort.GetPortNames();
ComportListbox.DataSource = ports;
}
It doesnt show the usb port names.
What am i doeing wrong, or how can i fix this issue.
EDIT
Question edited:
Can i see the usbportname from my usbport where the NETduino is attached to. So i hope to see COM10 for example. I looked in the system managment and saw that the usb is called Port_#0001.Hub_#0001. How can i open this port.
If ComportListbox has an "add" method, why not just use that with a for loop.
foreach ( string portName in ports )
{
ComportListbox.Items.Add( portName );
}
If not, let me know and I will delete this answer.
Otherwise you may have to use a BindingList<string>. see: Binding List<T> to DataGridView in WinForm
Or you might even have to create an object that contains a string property for the binding name.
I am trying to programmatically create and destroy a network bridge on Windows 7. Technologically I would love to stay within the .Net 4 realm (PInvokes are fine, ofc), but utilizing C++ is an option.
My research so far turned up that for configuration, netsh-commands are the route to go. However, there seems to be no option to actually spin up a new bridge with them.
I am currently investigating this program that uses the INetCfg APIs, but it appears that the program or, more specifically, the APIs, are not able to (again) build a new bridge.
If anyone can contribute to solving the problem, any kind of help is greatly appreciated.
[Update:] It seems that newtork bridges are implemented using a driver which then binds to both devices. I cannot yet make much of that information, so still any help is appreciated.
I've found a solution that works for both bridge service and bridge adapter driver. I don't use UpdateDriverForPlugAndPlayDevices like devcon but I'm using DiInstallDevice instead.
However, installing the drivers for the first time in non interactive mode (without user interaction) is not possible. This is because there are no corresponding .cat files for the builtin bridge .inf files. Neither UpdateDriverForPlugAndPlayDevices nor DiInstallDevice nor DiInstallDriver is intended for manual driver installation where .inf file is already contained in %SystemRoot%\inf but not yet in %SystemRoot%\System32\DriverStore.
The files should be on the distribution media or in a vendor-created directory, not in a system location such as %SystemRoot%\inf
All of the mentioned installation methods will create a OEM copy of the .inf file and will install it in driver store. Because this OEM copy is initially not part of the driver store, windows will show a prompt dialog and ask for user interaction either force installing the driver or canceling. Subsequent driver installations is possible without any user interaction by the way. Also preinstalled drivers (see pnputil -a) can be installed in non interactive mode.
So this is my solution:
First a device entry in HKLM\System\CurrentControlSet\Enum\Root is created with the given hardware id as device name (ms_bridge, ms_bridgemp) with the help of SetupDiCreateDeviceInfo
The hardware id is assigned with SetupDiSetDeviceRegistryProperty
The driver list is builded by exactly the given single .inf file with the help of SetupDiSetDeviceInstallParams
Enumerating and preselecting driver with SetupDiSetSelectedDriver
Registering device with SetupDiCallClassInstaller(DIF_REGISTERDEVICE...)
Installing with DiInstallDevice
This is the full code:
HRESULT InstallDriver(const wchar_t* DriverInfFile, const wchar_t* HardwareId) {
HRESULT Hr = S_OK;
GUID ClassGUID;
wchar_t ClassName[MAX_CLASS_NAME_LEN] = {0};
if (SetupDiGetINFClass(DriverInfFile, &ClassGUID, ClassName, sizeof(ClassName) / sizeof(wchar_t), nullptr) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
return Hr;
}
HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, nullptr);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
return Hr;
}
SP_DEVINFO_DATA DeviceInfoData = {
sizeof(SP_DEVINFO_DATA), 0
};
if (SetupDiCreateDeviceInfo(DeviceInfoSet, HardwareId, &ClassGUID, nullptr, nullptr, DICD_GENERATE_ID, &DeviceInfoData) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
if (SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE) HardwareId, (DWORD) (wcslen(HardwareId) + 1) * sizeof(wchar_t)) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
SP_DEVINSTALL_PARAMS InstallParams = {sizeof(SP_DEVINSTALL_PARAMS), 0};
InstallParams.FlagsEx = DI_FLAGSEX_ALLOWEXCLUDEDDRVS | DI_FLAGSEX_ALWAYSWRITEIDS;
InstallParams.Flags = DI_QUIETINSTALL | DI_ENUMSINGLEINF;
wcscpy_s(InstallParams.DriverPath, DriverInfFile);
if (SetupDiSetDeviceInstallParams(DeviceInfoSet, &DeviceInfoData, &InstallParams) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
SP_DRVINFO_DATA DriverInfoData = {sizeof(SP_DRVINFO_DATA), 0};
if (SetupDiBuildDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
SetupDiDestroyDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER);
}
// Use first best driver (since specified by inf file)
if (SetupDiEnumDriverInfo(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER, 0, &DriverInfoData)) {
SetupDiSetSelectedDriver(DeviceInfoSet, &DeviceInfoData, &DriverInfoData);
}
if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
}
// TODO: Allow non interactive mode for drivers already contained in %SystemRoot%\inf directory
//BOOL PreviousMode = SetupSetNonInteractiveMode(TRUE);
if (Hr == S_OK) {
if (DiInstallDevice(nullptr, DeviceInfoSet, &DeviceInfoData, &DriverInfoData, 0, nullptr) == FALSE) {
Hr = HRESULT_FROM_SETUPAPI(GetLastError());
// Ensure that the device entry in \ROOT\ENUM\ will be removed...
SetupDiRemoveDevice(DeviceInfoSet, &DeviceInfoData);
}
}
//SetupSetNonInteractiveMode(PreviousMode);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return Hr;
}
Todo's: Find a way to install this bridge drivers from within %SystemRoot%\inf without creating OEM copies and without any user interaction.
You can gain read/write access to subversion repository at Sourceforge
Any additional information or suggestion for improvement is appreciated! Everyone please feel free to checkout/modify the code.
Basic commands:
bridgeutil.exe /install
bridgeutil.exe /uninstall
bridgeutil.exe /attach
bridgeutil.exe /detach
Examples:
bridgeutil.exe /attach "PCI\VEN_10EC&DEV_8169" /attach {5d624f94-8850-40c3-a3fa-a4fd2080baf3}\vwifimp
Attaches each Realtek 8169 Network Interface Cards and Microsoft Virtual Wifi Adapter to bridge. If the bridge is not installed yet, it will be installed first.
bridgeutil.exe /detach 1
Detaches adapter with id 1 from bridge.
To see a list of bridgeable adapters, just call bridgeutil.exe without any arguments.
It is actually possible to create and network bridges via the SetupAPI.
Using the DevCon Tool, destroying them is as easy as this...
devcon.exe remove ms_bridgemp
...while building bridges can be done with this command:
devcon.exe install "C:\Windows\inf\netbrdgm.inf" ms_bridgemp
DevCon is open source, so you can dig into the sources to see how it implements those commands (the DevCon Tool is essentially a CLI to the SetupAPI).
Please note: The commands relate to Windows 7. The approach is said to work on XP and I suppose it works on other Windows Versions, too, but the .INF-File might have a different name or the device ID might differ.
After much unsuccessful searching on the Internet I wrote and have been successfully using the following Windows Script Host script "BridgeConnections.vbs" to create a network bridge on Windows XP (this method also works on Windows 7 and Windows 8 with slight modifications). It can be run from the command prompt or from a batch file as follows:
C:\Temp> cscript BridgeConnections.vbs
File BridgeConnections.vbs:
' This VBScript opens the "Network Connections" control panel window,
' sends Ctrl+A ("Select All") and Alt+N ("Advanced" menu) and
' C ("Bridge Connections" menu command) keystrokes to it and then waits
' until the splash window "Please wait while Windows bridges the connections..."
' disappears from the screen
Dim WshShell, Count
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Exec("rundll32.exe shell32.dll,Control_RunDLL ncpa.cpl")
Count = 0
Do While Not WshShell.AppActivate("Network Connections") And Count < 10
Count = Count + 1
WScript.Sleep 1000
WScript.Echo "Waiting for the 'Network Connections' window... " & CStr(Count) & "s"
Loop
WshShell.SendKeys "^(a)"
WshShell.SendKeys "%(n)"
WshShell.SendKeys "c"
Count = 0
Do While Not WshShell.AppActivate("Network Bridge") And Count < 10
Count = Count + 1
WScript.Sleep 1000
WScript.Echo "Waiting for the 'Network Bridge' splash window... " & CStr(Count) & "s"
Loop
Count = 0
Do While WshShell.AppActivate("Network Bridge") And Count < 120
Count = Count + 1
WScript.Sleep 1000
WScript.Echo "Waiting for the 'Network Bridge' splash window to disappear... " & CStr(Count) & "s"
Loop
Likewise one could modify the script to "Delete" the bridge if required (make a single selection with Shift and navigate keys and send a different keystroke command). In my case I only need to bridge all available ethernet adapters from a batch file so the above method works just fine.
In my experience, the "slight" problem with the
devcon.exe install "C:\Windows\inf\netbrdgm.inf" ms_bridgemp
approach posted here earlier is that it would create an empty, "half-backed" bridge with no adapters in it. So you will still have to go to the Windows GUI and "Add" adapters it one by one manually before it becomes really usable.
The only fully automated solution that really works for me it the above script.
To do the same actions from a C++ or C# code without the script you'd need to know and call undocumented Shell Network Interfaces (NETSHELL.DLL) functions which in turn are called by the Explorer Shell when the user initiates the actions via list view item selection and context menu command in the Windows GUI. A C++ sample of calling into the Shell Network Interface for programmatically disabling/enabling a Network Adapter can be seen here. Unfortunately there is no sample yet for creating/removing the Network Bridge adapter. So until it becomes available I'll stick with the script.
Based on the bindview example, I put up an utilitary called bindbridge, which works as following:
Usage: bindbridge <deviceId> <bind|unbind>
The source can be found at https://github.com/OurGrid/OurVirt/tree/master/tools/win32/bindbridge, and it assumes the bridge device already exists - which can be created with devcon, as per previous answers - and its name to be ms_bridge, what can be easily changed in the sources.
I'm using it to programatically add tap interfaces to the bridge, so my command line is something in the lines of:
bindbridge ROOT\NET\0001 bind
It turns out that, unfortunately, there is no documented way of setting up a network bridge.
The code which does that is located inside hnetcfg.dll, and is invoked only by Windows Explorer. It installs bridge driver, and configures bridge interface.
It might be possible to call it yourself (using COM), but that would require reverse engineering and may break on any system update, so I recommend against doing that.
I am trying to use memcached with both a php (memcached) and C# (enyim) client.
I have a scenario where I want to CAS a value in php. To do this I am using the following code:
$memcached = new Memcached;
$memcached->addServer('localhost', 11211) or die ("Could not connect");
$memcached->setOption(Memcached::OPT_COMPRESSION, false); // the enyim client doesn't support compression
do {
$entries = $memcached->get($theKey, null, $cas);
if ($memcached->getResultCode() == Memcached::RES_NOTFOUND) {
$entry = somearray("foo");
$memcached->add($theKey, $entry);
} else {
$entries[] = "bar";
$memcached->cas($cas, $theKey, $entries);
}
}
while ($memcached->getResultCode() != Memcached::RES_SUCCESS AND $memcached->getResultCode() != Memcached::RES_END);
This works all well and fine to begin with.
But then, when the C# client CAS's the same value it goes wrong.
Php gives a warning at:
$entries = $memcached->get($theKey, null, $cas);
namely that:
PHP Warning: Memcached::get(): could not uncompress value in ... at line ...
And as a result an infinite loop occurs.
Now I tried to get the key from the memcached server via telnet and the data was right there.
In php I am also able to SET to this key without a problem.
I noticed one thing: after the php client has SET something, the flag was 0.
Now after the C# client has CAS'd the value, the flag was 274.
Is there some flag collision on the php lib going on? Or is it something else?
If anyone can help me resolve this problem I'd be gratefull!
lordstyx
[EDIT]
Well then. Since this question isn't getting an answer let me put it differently.
Is there a way to stop the C# client from setting flag 274?
So I eventually found an answer to my problem. It might not help all of you, because I switched from the Enyim to the BeIT memcached client (http://code.google.com/p/beitmemcached/)
Now to make the BeIT client compatible with the php client you have to change Serializer.cs
In the enum SerializedType I changed the number of "String" to 0 and ByteArray to 2, which gave this:
internal enum SerializedType : ushort
{
ByteArray = 2,
Object = 1,
String = 0, //mod: turned around the numbers for String and ByteArray so it is compatible with php client
Datetime = 3,
....
I believe I went with BeIT because I couldn't find or figure out how the flags worked in the Enyim client. If you understand how it work though, I'm sure that you can change that client in a same manner
If I am not wrong, mixing languages/platforms with memcached is a bad idea. See another question on similar topic.
For the record. Since the library is open source, then its possible to modify.
In the class Enyim.Caching.Memcached.DefaultTranscoder, change the function
public static uint TypeCodeToFlag(TypeCode code)
{
return (uint)((int)code | 0x0100);
}
to
public static uint TypeCodeToFlag(TypeCode code)
{
if (code == TypeCode.String)
{
return 0;
}
return (uint)((int)code | 0x0100);
}
274 = TypeCode.String | 0x0100
Since i don't know the memcache protocol then i don't know whats doing. However, php's memcache requires 0, so i set to zero when the variable defined is a string.
ps: beitmemcached hasn't be updated for a long while.