How to distinguish between multiple input devices in C# - c#

I have a barcode scanner (which acts like a keyboard) and of course I have a keyboard too hooked up to a computer. The software is accepting input from both the scanner and the keyboard. I need to accept only the scanner's input. The code is written in C#. Is there a way to "disable" input from the keyboard and only accept input from the scanner?
Note:
Keyboard is part of a laptop...so it cannot be unplugged. Also, I tried putting the following code
protected override Boolean ProcessDialogKey(System.Windows.Forms.Keys keyData)
{
return true;
}
But then along with ignoring the keystrokes from the keyboard, the barcode scanner input is also ignored.
I cannot have the scanner send sentinal characters as, the scanner is being used by other applications and adding a sentinal character stream would mean modifying other code.
Also, I cannot use the timing method of determining if the input came from a barcode scanner (if its a bunch of characters followed by a pause) since the barcodes scanned could potentially be single character barcodes.
Yes, I am reading data from a stream.
I am trying to follow along with the article: Distinguishing Barcode Scanners from the Keyboard in WinForms. However I have the following questions:
I get an error NativeMethods is inaccessible due to its protection level. It seems as though I need to import a dll; is this correct? If so, how do I do it?
Which protected override void WndProc(ref Message m) definition should I use, there are two implementations in the article?
Am getting an error related to [SecurityPermission( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] error CS0246: The type or namespace name 'SecurityPermission' could not be found (are you missing a using directive or an assembly reference?). How do I resolve this error?
There is also an error on the line containing: if ((from hardwareId in hardwareIds where deviceName.Contains(hardwareId) select hardwareId).Count() > 0) Error is error CS1026: ) expected.
Should I be placing all the code in the article in one .cs file called BarcodeScannerListener.cs?
Followup questions about C# solution source code posted by Nicholas Piasecki on http://nicholas.piasecki.name/blog/2009/02/distinguishing-barcode-scanners-from-the-keyboard-in-winforms/:
I was not able to open the solution in VS 2005, so I downloaded Visual C# 2008 Express Edition, and the code ran. However, after hooking up my barcode scanner and scanning a barcode, the program did not recognize the scan. I put a break point in OnBarcodeScanned method but it never got hit. I did change the App.config with the id of my Barcode scanner obtained using Device Manager. There seems to be 2 deviceNames with HID#Vid_0536&Pid_01c1 (which is obtained from Device Manager when the scanner is hooked up). I don't know if this is causing the scanning not to work. When iterating over the deviceNames, here is the list of devices I found (using the debugger):
"\??\HID#Vid_0536&Pid_01c1&MI_01#9&25ca5370&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
"\??\HID#Vid_0536&Pid_01c1&MI_00#9&38e10b9&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\HID#Vid_413c&Pid_2101&MI_00#8&1966e83d&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\HID#Vid_413c&Pid_3012#7&960fae0&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}"
"\??\Root#RDP_KBD#0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\ACPI#PNP0303#4&2f94427b&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\Root#RDP_MOU#0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}"
"\??\ACPI#PNP0F13#4&2f94427b&0#{378de44c-56ef-11d1-bc8c-00a0c91405dd}"
So there are 2 entries for HID#Vid_0536&Pid_01c1; could that be causing the scanning not to work?
OK so it seems that I had to figure out a way to not depend on the ASCII 0x04 character being sent by the scanner...since my scanner does not send that character. After that, the barcode scanned event is fired and the popup with the barcode is shown. So thanks Nicholas for your help.

You could use the Raw Input API to distinguish between the keyboard and the scanner like I did recently. It doesn't matter how many keyboard or keyboard-like devices you have hooked up; you will see a WM_INPUT before the keystroke is mapped to a device-independent virtual key that you typically see in a KeyDown event.
Far easier is to do what others have recommended and configure the scanner to send sentinel characters before and after the barcode. (You usually do this by scanning special barcodes in the back of the scanner's user manual.) Then, your main form's KeyPreview event can watch those roll end and swallow the key events for any child control if it's in the middle of a barcode read. Or, if you wanted to be fancier, you could use a low-level keyboard hook with SetWindowsHookEx() to watch for those sentinels and swallow them there (advantage of this is you could still get the event even if your app didn't have focus).
I couldn't change the sentinel values on our barcode scanners among other things so I had to go the complicated route. Was definitely painful. Keep it simple if you can!
--
Your update, seven years later: If your use case is reading from a USB barcode scanner, Windows 10 has a nice, friendly API for this built-in in Windows.Devices.PointOfService.BarcodeScanner. It's a UWP/WinRT API, but you can use it from a regular desktop app as well; that's what I'm doing now. Here's some example code for it, straight from my app, to give you the gist:
{
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Windows.Devices.Enumeration;
using Windows.Devices.PointOfService;
using Windows.Storage.Streams;
using PosBarcodeScanner = Windows.Devices.PointOfService.BarcodeScanner;
public class BarcodeScanner : IBarcodeScanner, IDisposable
{
private ClaimedBarcodeScanner scanner;
public event EventHandler<BarcodeScannedEventArgs> BarcodeScanned;
~BarcodeScanner()
{
this.Dispose(false);
}
public bool Exists
{
get
{
return this.scanner != null;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public async Task StartAsync()
{
if (this.scanner == null)
{
var collection = await DeviceInformation.FindAllAsync(PosBarcodeScanner.GetDeviceSelector());
if (collection != null && collection.Count > 0)
{
var identity = collection.First().Id;
var device = await PosBarcodeScanner.FromIdAsync(identity);
if (device != null)
{
this.scanner = await device.ClaimScannerAsync();
if (this.scanner != null)
{
this.scanner.IsDecodeDataEnabled = true;
this.scanner.ReleaseDeviceRequested += WhenScannerReleaseDeviceRequested;
this.scanner.DataReceived += WhenScannerDataReceived;
await this.scanner.EnableAsync();
}
}
}
}
}
private void WhenScannerDataReceived(object sender, BarcodeScannerDataReceivedEventArgs args)
{
var data = args.Report.ScanDataLabel;
using (var reader = DataReader.FromBuffer(data))
{
var text = reader.ReadString(data.Length);
var bsea = new BarcodeScannedEventArgs(text);
this.BarcodeScanned?.Invoke(this, bsea);
}
}
private void WhenScannerReleaseDeviceRequested(object sender, ClaimedBarcodeScanner args)
{
args.RetainDevice();
}
private void Dispose(bool disposing)
{
if (disposing)
{
this.scanner = null;
}
}
}
}
Granted, you'll need a barcode scanner that supports the USB HID POS and isn't just a keyboard wedge. If your scanner is just a keyboard wedge, I recommend picking up something like a used Honeywell 4600G off eBay for like $25. Trust me, your sanity will be worth it.

What I did in a similar situation is distinguish between a scan and a user typing by looking at the speed of the input.
Lots of characters very close together then a pause is a scan. Anything else is keyboard input.
I don't know exactly your requirements, so maybe that won't do for you, but it's the best I've got :)

It depends on the way you are interacting with the device. Anyway it wont be a C# solution, it will be some other library. Are you reading data from a stream? If you are just taking keystrokes, there may be nothing you can do about it.

I know this is an old thread, found it by searching barcode scanning in WIN10.
Just a few notes in case someone needs it.
These scanners from Honeywell have several USB interfaces.
One is a keyboard + Hid Point of sales (composite device).
Also there are CDC-ACM (ComPort emulation) and Hid Point of sales (alone) + more.
By default the scanners expose a serial number, so the host can distinguish between many devices (I had once +20 connected). There is a command to disable the serial number though!
The newer models behave the same in this regard.
If you want to see it live, try my terminal program yat3 (free on my site).
It can open all the interfaces mentioned above and is tailored for such devices.
A word to use keyboard interfaces:
Only use them as a last resort. They are slow, less reliable when it comes to exotic characters. The only good use is if you want to enter data into existing applications. If you code anyway, then reading from ComPort/HidPos-Device is easier.

look at this: http://nate.dynalias.net/dev/keyboardredirector.rails (NOT AVAILABLE ANYMORE) works great!
Specify the keyboard and the keys you want to block, and it works like a charm!
Also take a look at this: http://www.oblita.com/interception.html
You can create a C# wrapper for it - it also works like a charm..

I think you might be able to distinguish multiple keyboards through DirectX API, or if that doesn't work, through raw input API.

I have successfully accomplished what you folks are looking for here. I have an application that receives all barcode character data from a Honeywell/Metrologic barcode scanner. No other application on the system receives the data from the scanner, and the keyboard continues to function normally.
My application uses a combination of raw input and the dreaded low-level keyboard hook system. Contrary to what is written here, I found that the wm_input message is received before the keyboard hook function is called. My code to process the wm_input message basically sets a boolean variable to specify whether or not the received character is from the scanner. The keyboard hook function, called immediately after the wm_input is processed, swallows the scanner’s pseudo-keyboard data, preventing the data from being received by other applications.
The keyboard hook function has to be placed in an dll since you want to intercept all system keyboard messages. Also, a memory mapped file has to be used for the wm_input processing code to communicate with the dll.

Related

C# MIDI Device Send CC Message to Reset Trigger

I have a LaunchPad MK3 Mini MIDI device that I'm looking to tie into a C# app I'm making, where pressing buttons will invoke a various functions within the app. After a bit of research, I landed on using the RtMidi.Core library (thru NuGet). And upon debugging, it appears that I'm able to fully listen to the device and react to events appropriately, and that's good.
I should also back up a bit as well. I'm quite inexperienced to using MIDI devices so a lot of the terminology and industry usage is a bit lost on me. But it's my understanding that a MIDI device can be modified so that the individual keys can be changed to perform a different MIDI event. In my case, I'm not using this for any musical purpose, so there is no need for Note/Piano type events. So I changed all the buttons to be Control Change, all of them with unique Channel/ControlNum combinations. It appears these CC buttons can be one of 3 "Pad Modes":
Momentary - Both KeyDown and KeyUp each will trigger a separate MIDI event
Toggle - Only KeyDown will trigger a MIDI event and each one will alternate between 0 and some specified non-zero value
Trigger - Only KeyDown will trigger a MIDI event, but it will always be the specified non-zero value
Now, as it pertains to my use cases. I'm looking to utilize the 'Trigger' Pad Mode type, as this will trigger some various code which will last a variable duration. My issue is, the MIDI device will change the LED keylight color to its ON color and it NEVER goes back to its initial state (as expected, tbh). So what I'm looking to do is after my 'certain function' is done executing, that it would 'reset' this trigger back to the initial state as its last course of action.
So, I create a ControlChangeMessage with the proper channel/control/value and send it to the MIDI device, but the LED color doesn't seem to change back to the original color. The ONLY thing that seems to reset its state is to unplug the USB power from the device and plug it back in.
For reference: The input and output device names I'm using are similar, but different, as indicated in the code below:
foreach (var inputDeviceInfo in MidiDeviceManager.Default.InputDevices)
{
Console.WriteLine($"Opening {inputDeviceInfo.Name}");
if (inputDeviceInfo.Name == "MIDIIN2 (LPMiniMK3 MIDI) ")
{
var inputDevice = inputDeviceInfo.CreateDevice();
devices.Add(inputDevice);
inputDevice.ControlChange += ControlChangeHandler;
inputDevice.Open();
}
}
foreach (var outputDeviceInfo in MidiDeviceManager.Default.OutputDevices)
{
Console.WriteLine($"Opening {outputDeviceInfo.Name}");
if (outputDeviceInfo.Name == "MIDIOUT2 (LPMiniMK3 MIDI) ")
{
var outputDevice = outputDeviceInfo.CreateDevice();
devicesOut.Add(outputDevice);
outputDevice.Open();
//while (!outputDevice.IsOpen) { }
ControlChangeMessage ccMsg = new ControlChangeMessage(RtMidi.Core.Enums.Channel.Channel3, 0, 0);
outputDevice.Send(ccMsg);
}
}
So from this, I'm really unsure why this wouldn't be working. Perhaps there is another MIDI library I could be using, or perhaps I'm just missing something with respect to how these MIDI devices work.

C# Serial Port Receive Only Ever Giving me a Single Character

Question Withdrawn. I found out that I was sending incorrect ASCII patterns and THIS was my problem versus any problems with the receiver. Receiving a single character was merely the echo back of my wrong command
Summary:
C# form app. Serial 38400:N81 no flow control. Talking to a custom device.
If I use Teraterm, everything's fine.
The device I attach to gives simple, immediate responses:
Type 'v' you get a version string "v1.34 02-18-16 17:22" where the v in that is the local echo of the typed command. There are other status commands which are similar, once a character is received by the device, it replies immediately.
In my C# application I have pretty much exactly what you see in this guide under the example:
https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived%28v=vs.110%29.aspx
Differences are that I'm at 38400 versus 9600 and I also do not set up the Handshake or the RtsEnable.
I've done this before so feeling stupid as to some obvious problem here. And I did do a bit of searching/following similar question links too.
Instead of receiving the version string, I receive one character '6'.
For a different command I also receive one character '8'. The notable thing here is that while '6' is part of my version string, '8' is never in the response for that other command.
Any suggestions on how I'd debug the ReadExisting() call?
I fully understand that a received string may arrive in fragments. The issue is that I always only ever receive the one character and nothing else. The event handler never sees any additional data. When I re-issue my version command I get the same '6' back I get before.
My event handler where I'm trying to test the receiver:
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Debug.WriteLine("Data Received: ");
Debug.Write(indata);
}
Under the debugger, indata.Length is 1.
Teraterm Port Settings:
I was suggested to look for errors and here's the code:
public event SerialErrorReceivedEventHandler ErrorReached;
protected virtual void OnReceiveError(SerialErrorReceivedEventArgs e)
{
SerialErrorReceivedEventHandler handler = ErrorReached;
if (handler != null)
{
handler(this, e);
}
Debug.WriteLine("Serial error");
}
I saw no errors.
Further comments were that the receiver needs to be run more than once. It is, when I issue a 'v' (just the v) I should see the version and 's' should give me status. Again, both work fine on Teraterm. I get 686868 if I issue vsvsvs or other matching patterns if I type like vvsss, I'll get 66888 in reply.
Other point is controlling this device if I issue r and s for run and stop, there is a LED on it which goes solid red (from intermittent flashing to indicate that it's running. I see it run and stop per my commands. So I know that I'm talking to the device in a proper/coherent fashion. Just still have troubles seeing valid receive data.
Some suggestions to try:
You're reading a string from the port, so if the data can't be readily interpreted as a string you may only get a fragment before it stops converting. Read into a byte array to be sure you are really seeing the data that you receive. Even if you think you should get a string, this lets you see what you are actually receiving.
Check your port settings. Symptoms of the wrong baud rate or encoding are frequently that you receive a reduced number of (possibly random, possibly repeatable) bytes of "garbage". This would be consistent with receiving characters that should not be in the response, and the string terminating early.
Remove all configuration options from your port, apart from setting the baud rate. Very few devices use anything other than 8n1 and attempting to set options can often screw the port up. If that doesn't work then start seeing additional options only if you have to.
Make sure you only open the port once and keep it open till you have finished talking to the device. (Repeatedly opening and closing the port I'd really five by accident, and would flush the data in it, interfering with your attempts to read)

ObjectDisposedException: Safe handle has been closed

So this is a rather small question with a big explanation. As is noted by the title I am getting an unhandled exception telling me my Safe handle has been closed. What I'll probably have to do is edit this post a few times with more and more code to help me diagnose what the problem is.
I'm using POS for .NET to make a Service Object for my RFID and MSR device. Although my devices are the same, I have 2 different Virtual COM Port chips that communicate to those devices. One by Silicon labs, the other by FTDI. I wanted to use the plug and play features with POS for .NET so I gave it both my Hardware ID's. Because it is plug and play I have the full hardware path available to me which I can then create a SafeFileHandle using a call to PInvoke and using that SafeFileHandle I create a FileStream. The FTDI chip doesn't let me talk to the devices directly like that so I have to get the friendly name of the device then use mutex to pull out the COM port then create a SerialPort instance. That step works fine and great. As a FYI I have tried to use the Friendly name of both chips to get the COM port and the Silicon Labs one (for some strange reason) doesn't get listed using SetupAPI.GetDeviceDetails using the Ports GUID. I'm not sure on that one since in Device Manager the Silicon labs Device Class Guid is the Ports GUID.
Well since both the SerialPort and the FileStream have a Stream object I decided to use that to read and write to that port. The problem with that is if I send a RFID command to the MSR device the MSR device doesn't respond back with anything. So if I use this code int fromReader = ReaderStream.ReadByte(); my thread is blocked. It's a blocking call and requires a minimum of 1 byte to proceed. So I looked around and it appears the only solution is to use a separate thread and set a timeout. If the timeout happens then abort the thread.
Thread t = new Thread(new ThreadStart(ReadFromStream));
t.Start();
if (!t.Join(timeout))
{
t.Abort();
}
(t.Abort has been surrounded with a try/catch to no avail, since it didn't fix the problem I removed it)
ReadFromStream is Abstract method in RFID Device. Here is one of the implementations
protected override void ReadFromStream()
{
var commandLength = USN3170Constants.MIN_RESPONSE_LENGTH;
var response = new System.Collections.Generic.List<byte>(USN3170Constants.MIN_RESPONSE_LENGTH);
for (int i = 0; i <= commandLength; i++)
{
int fromReader = ReaderStream.ReadByte();
if (fromReader == -1) break; //at end of stream
response.Add((byte)fromReader);
if (response.Count > USN3170Constants.DATA_LENGTH_INDEX && response[USN3170Constants.DATA_LENGTH_INDEX] > 0)
{
commandLength = response[USN3170Constants.DATA_LENGTH_INDEX] + 3;
}
}
streamBuffer = response.ToArray();
}
(int fromReader = ReaderStream.ReadByte(); was surrounded with a try/catch. Only thing it caught was the aborted thread exception, so I took it out)
The above code is where I suspect the problem lies. The strange thing is, though, is that I have a unit test which I feel mimics rather well the Microsoft Test App.
(FYI QUADPORT is the FTDI chipset)
PosExplorer posExplorer;
DeviceCollection smartCardRWs;
[Test]
public void TestQuadPortOpen()
{
posExplorer = new PosExplorer();
smartCardRWs = posExplorer.GetDevices(DeviceType.SmartCardRW, DeviceCompatibilities.CompatibilityLevel1);
//if using quadport one item is the MSR and the other is the RFID
//because of that one of them will fail. Currently the first Device in the collection is the the RFID, and the second is MSR
Assert.GreaterOrEqual(smartCardRWs.Count, 2);
//Hardware Id: QUADPORT\QUAD_SERIAL_INTERFACE
foreach(DeviceInfo item in smartCardRWs)
{
Assert.AreEqual("QUADPORT\\QUAD_SERIAL_INTERFACE", item.HardwareId);
}
SmartCardRW rfidDevice = (SmartCardRW)posExplorer.CreateInstance(smartCardRWs[0]);
SmartCardRW msrDevice = (SmartCardRW)posExplorer.CreateInstance(smartCardRWs[1]);
rfidDevice.Open();
Assert.AreNotEqual(ControlState.Closed, rfidDevice.State);
rfidDevice.Close();
try
{
msrDevice.Open();
Assert.Fail("MSR Device is not a RFID Device");
}
catch
{
Assert.AreEqual(ControlState.Closed, msrDevice.State);
}
rfidDevice = null;
msrDevice = null;
}
When I run that test I do not get the SafeFileHandle exception. In fact the test passes.
So I am at a loss as to how to track down this bug. Since I'll be using this Service Object in a different program that I am also creating I'll probably end up using this code from this test in that program. However I feel that the Microsoft Test App is more or less the "Golden Standard". Is it really... probably not. But it does work good for my purposes, SO I feel it is a problem with my code and not theirs.
Any tricks on how I can narrow this down? FYI I've tried using the debugger but walking the Open Code the error does not occur. I also walked the Update Status Timer and it also does not throw the error. Once I hit continue then I'll get the exception. I turned of Just My Code and Loaded Symbols and it tells me "Source Information is missing from teh debug information for this module"
This problem (and in particular the reference to a SerialPort instance) sounds suspiciously like the problem documented at http://connect.microsoft.com/VisualStudio/feedback/details/140018/serialport-crashes-after-disconnect-of-usb-com-port.
As I understand it, in the case of a non-permanent SerialPort (like one associated with a USB device, for example) when the port "goes away" unexpectedly the underlying Stream associated with it gets disposed. If there is an active read or write operation on the port at the time a subsequent call to SerialPort.Close can lead to the exception you mention, however the exception is occurring in Microsoft's code running on a different thread and cannot be caught from within your code. (It will still be seen by any "last chance" exception handler you have bound to the UnhandledException event on the AppDomain.)
There seem to be two basic workaround styles in the linked document. In both instances, after opening the port you store a reference to the BaseStream instance for the open port. One workaround then suppresses garbage collection on that base stream. The other explicitly calls Close on the base stream, capturing any exceptions thrown during that operation, before calling Close on the SerialPort.
EDIT: For what it's worth, under the .NET framework V4.5, it appears that none of the documented workarounds on the Microsoft Connect site fully resolve the problem although they may be reducing the frequency with which it occurs. :-(
I had the same error when I used a thread to read from a SerialPort. Calling Interrupt on the thread occasionally caused the uncatchable ObjectDisposedException. After hours of debugging and carefully reading this:
https://blogs.msdn.microsoft.com/bclteam/2006/10/10/top-5-serialport-tips-kim-hamilton/
I realized that the problem is just this:
NET 2.0 (and above) isn’t letting you get away with some things, such as attempting to cancel a SerialPort read by interrupting the thread accessing the SerialPort.
So before you call Thread.Interrupt() you have to close the COM... This will cause a catchable exception on the ReadByte operation.
Or you may use the ReadTimeout property on the SerialPort to avoid using a thread just to have a timeout.
I would like to post my case in which I had a similar issue trying to read from a serial port (virtual com driven by a Moxa RS232 to ethernet).
Since I did have no chance to catch the ObjectDisposedException, the only solution was to increase the ReadTimeout property which was originally set to -1 (continuous reading).
Setting the ReadTimeout to 100 millis solved this issue in my case.
EDIT
It is not the definitive solution: it can happen that if you close the application during a read attempt you can get the same uncatchable exception.
My final solution is to kill the process of the application directly in the FormClosing event :
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
Process p = Process.GetCurrentProcess();
p.Kill();
}
Please take a look at this:
https://github.com/jcurl/SerialPortStream
I replaced System.IO.Ports with RJPC.IO.Ports, fixed up a couple parameter differences in the initialization, and all the problems went away with this issue.

C# SendKeys.SendWait() doesn't always work

I am trying to make an application that sends keys to an external application, in this case aerofly FS. I have previously used the SendKeys.SendWait() method with succes, but this time, it doesn't quite work the way I want it to. I want to send a "G" keystroke to the application and testing it out with Notepad I do get G's. But in aerofly FS nothing is recieved at all. Pressing G on the keyboard does work though.
This is my code handling input data (from an Arduino) an sending the keystrokes,
private void handleData(string curData)
{
if (curData == "1")
SendKeys.SendWait("G");
else
{ }
}
I too have run into external applications where SendKeys didn't work for me.
As best I can tell, some applications, like applets inside a browser, expect to receive the key down, followed by a pause, followed by a key up, which I don't think can be done with SendKeys.
I have been using a C# wrapper to the AutoIt Library, and have found it quite easy to use.
Here's a link to quick guide I wrote for integrating AutoIt into a C# project.
Once you have the wrapper and references, you can send "G" with the following:
private void pressG()
{
AutoItX3Declarations.AU3_Send("{g}");
}
or with a pause,
private void pressG()
{
AutoItX3Declarations.AU3_Send("{g down}", 0);
AutoItX3Declarations.AU3_Sleep( 50 ); //wait 50 milliseconds
AutoItX3Declarations.AU3_Send("{g up}", 0);
}
AutoIt also allows you programmatically control the mouse.

C# Serial Connection: Get pin state

I am working with a codec and am trying to poll the state of RS232 serial pin 1 (CD high/low).
The code I have I think is right but I am second guessing myself and was hoping someone could confirm or correct me.
According to the the data sheet of the codec Pin 1 should be High when a call is active. I suspect i have done something wrong because while in a call I get a return of false (low).
This is a Windows Forms application and I am using System.IO.Ports
private void button4_Click(object sender, EventArgs e)
{
if (!serialPort1.IsOpen)
{
serialPort1.Open();
}
bool test = serialPort1.CDHolding;
if (test == false)
{
MessageBox.Show("Pin low");
}
else
{
MessageBox.Show("Pin high");
}
}
Also is there an easy way to show the actual voltage on the pin?
There really isn't much here we can tell you that you don't already know. Yes SerialPort.CDHolding "Gets the state of the Carrier Detect line for the port." I would first verify (electrically) the state of the pin, and then check that against what this property tells you. I'm guessing it is telling you the correct state.
When it comes to serial ports, I would always double check your pin-out; depending on the hardware and connector, they can be incredibly non-standard, and are easy to mess up.
You ask about showing the voltage on the pin. Do you mean programattically? No, that is impossible. That is a digital input line; once it hits the UART it is a digital signal, you cannot know the analog voltage.
Just as an additional tidbit, this property is actually just a wrapper that calls the Win32 GetCommModemStatus function, and returns true if bit 7 (decimal 128) is set.
Can you use the .PinChanged event instead? Or do you need to only poll on button press?

Categories