After much head scratching I managed to find the com port number of the USB to RS232 converters on my system. I have 15 in the present system. What I now need to do is detect when one is connected or disconnected so that I can update my table. I can work out how to detect a USB Storage device but the same does not work for USB to RS232 converters. Does anyone have any idea on how I can detect this please?
Here is the code snippet I use to work out the com ports in use by the converters
private void btn_tst2_Click(object sender, EventArgs e)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
foreach (ManagementObject queryObj in searcher.Get())
{
rtxbx_output.AppendText(queryObj["Name"].ToString() +"\r");
}
}
You can make some sort of Thread or Task which queries the array returned from the method System.IO.Ports.SerialPort.GetPortNames(): when this array changes, or a new element is added, it means that a new serial port have been connected to the system.
Of course, it will return every serial port on your system, but then you can choose which of them are USB-RS232 converters with your code snippet.
You can make use of MSSerial_PortName Please find the snippet.
Note: This is not a working code, you have to make changes as per your requirement.
private void btn_tst2_Click(object sender, EventArgs e)
{
// connection to WMI rather than cimv2 namespace
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI",
"select * from MSSerial_PortName");
foreach (ManagementObject queryObj in searcher.Get())
{
queryObj["Active"]; // status
queryObj["InstanceName"];
queryObj["PortName"]; // port number
}
}
After much frustration I finally worked out how to achieve what I needed. I post the answer in case it gives a pointer to anyone in the future stuck in the same area. I include comments in the code. What I get at the end is a list of all the Com Ports and this is refreshed when one leaves or joins. The file dbt.h is found on your PC.
To make the code below work just make a solution with a Rich text box and two buttons.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Management; //used to perform WMI queries
using System.Threading;
using System.Runtime.InteropServices; // needed for marshalling
namespace MissionControl
{
public partial class Control : Form
{
public Control()
{
InitializeComponent();
}
// WndProc = Window Procedures: Every window has an associated window procedure — a function that processes all messages sent
// or posted to all windows of the class. All aspects of a window's appearance and behavior depend on the window procedure's
// response to these messages. see https://msdn.microsoft.com/en-us/library/ms632593%28v=vs.85%29.aspx
protected override void WndProc(ref Message m)
{
//you may find these definitions in dbt.h
const int WM_DEVICECHANGE = 0x0219; // in dbt.h, BroadcastSpecialMessage constants.
const int DBT_DEVICEARRIVAL = 0x8000; // system detected a device arrived see dbt.h
const int DBT_DEVICEREMOVECOMPLETE = 0x8004; //system detected a device removal see dbt.h
const int DBT_DEVTYP_PORT = 0x00000003; // serial, parallel in dbt.h
switch (m.Msg)
{
case WM_DEVICECHANGE:
switch (m.WParam.ToInt32())
{
case DBT_DEVICEARRIVAL:
{
// Get the DBT_DEVTYP* as defined in dbt.h
// We are looking for DBT_DEVTYP_PORT value = 3 which is Serial port
int devTypeA = Marshal.ReadInt32(m.LParam, 4);
if (devTypeA == DBT_DEVTYP_PORT)
{
rchtxbx_output.SelectedText = string.Empty;
rchtxbx_output.SelectionFont = new Font(rchtxbx_output.SelectionFont, FontStyle.Bold);
rchtxbx_output.SelectionColor = Color.Lime;
rchtxbx_output.AppendText("\rSerial Port Connected\r\rList of Current Ports\r");
}
else
{
// We should never get in here but just in case do somethign rather than fall over
rchtxbx_output.SelectedText = string.Empty;
rchtxbx_output.SelectionFont = new Font(rchtxbx_output.SelectionFont, FontStyle.Bold);
rchtxbx_output.SelectionColor = Color.Red;
rchtxbx_output.AppendText("Non-Serial Port Connected\r");
}
//To prevent cross threading we will start the function call in its own thread
// Create the thread object, passing in GetPortNum
//ThreadA is the arrival thread (just connected)
Thread ThreadA = new Thread(new ThreadStart(GetPortNum));
// Start the thread via a ThreadStart delegate
ThreadA.Start();
}
break;
case DBT_DEVICEREMOVECOMPLETE:
{
// Get the DBT_DEVTYP* as defined in dbt.h
// We are looking for DBT_DEVTYP_PORT value = 3 which is Serial port
int devTypeD = Marshal.ReadInt32(m.LParam, 4);
if (devTypeD == DBT_DEVTYP_PORT)
{
rchtxbx_output.SelectedText = string.Empty;
rchtxbx_output.SelectionFont = new Font(rchtxbx_output.SelectionFont, FontStyle.Bold);
rchtxbx_output.SelectionColor = Color.Lime;
rchtxbx_output.AppendText("\rSerial Port Disconnected\r\rList of Current Ports\r");
}
else
{
// We should never get in here but just in case do something rather than fall over
rchtxbx_output.SelectedText = string.Empty;
rchtxbx_output.SelectionFont = new Font(rchtxbx_output.SelectionFont, FontStyle.Bold);
rchtxbx_output.SelectionColor = Color.Red;
rchtxbx_output.AppendText("Non-Serial Port Disconneted\r");
}
//To prevent cross threading we will start the function call in its own thread
// Create the thread object, passing in GetPortNum
//ThreadD is the departure thread (disconnected)
Thread ThreadD = new Thread(new ThreadStart(GetPortNum));
// Start the thread via a ThreadStart delegate
ThreadD.Start();
}
break;
}
break;
}
//we detect the media arrival event
base.WndProc(ref m);
}
private void btn_close_Click(object sender, EventArgs e)
{
this.Close();
}
private void btn_clr_Click(object sender, EventArgs e)
{
rchtxbx_output.Clear();
}
private void GetPortNum()
{
//Windows Management Instrumentation (WMI) consists of a set of extensions to the Windows Driver Model that provides an
//operating system interface through which instrumented components provide information and notification.
// To work out the WMI to use, get the tool https://www.microsoft.com/en-us/download/details.aspx?id=8572
//GUID (or UUID) is an acronym for 'Globally Unique Identifier' (or 'Universally Unique Identifier'). It is a 128-bit
//integer number used to identify resources. The term GUID is generally used by developers working with Microsoft
//technologies, while UUID is used everywhere else.
// Get the list of ClassGUID from https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
string comportnum = "";
int textStart = 0;
char[] textEnd = { ')' };
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
foreach (ManagementObject queryObj in searcher.Get())
{
comportnum = queryObj["Name"].ToString(); // Get the name of the comm port
//Format the string to extract the comport number only
textStart = comportnum.IndexOf("(COM");
comportnum = comportnum.Remove(0, textStart + 4).TrimEnd(textEnd);
//To prevent cross threading use Invoke. We are writing to a control created in another thread.
rchtxbx_output.Invoke(new EventHandler(delegate
{
rchtxbx_output.SelectedText = string.Empty;
rchtxbx_output.SelectionFont = new Font(rchtxbx_output.SelectionFont, FontStyle.Bold);
rchtxbx_output.SelectionColor = Color.Lime; //set font colour
rchtxbx_output.AppendText("Comm Port = " + comportnum + "\r"); //add some text
rchtxbx_output.ScrollToCaret(); // move cursor to the end
}));
}
}
}
}
Related
I am using NAudio for a screen recording software I am designing and I need to know if it's possible to not only control the specific application's volume but also display a VU Meter for the application's sound.
I've Googled all over the place and it seems I can only get a VU Meter for the devices currently on my computer and set the volume for those devices.
Even though I am using NAudio, I am open to other solutions.
I asked the question in more detail after this question. I have since found the answer so I will leave the answer here for those who stumble upon it. Trying to use NAudio & CSCore has gotten me quite familiar with so please ask if you need further assistance.
This block of code uses CSCore and is a modified and commented version of the answer found here:Getting individual windows application current volume output level as visualized in audio Mixer
class PeakClass
{
static int CurrentProcessID = 0000;
private static void Main(string[] args)
{
//Basically gets your default audio device and session attached to it
using (var sessionManager = GetDefaultAudioSessionManager2(DataFlow.Render))
{
using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
{
//This will go through a list of all processes uses the device
//the code got two line above.
foreach (var session in sessionEnumerator)
{
//This block of code will get the peak value(value needed for VU Meter)
//For whatever process you need it for (I believe you can also check by name
//but I found that less reliable)
using (var session2 = session.QueryInterface<AudioSessionControl2>())
{
if(session2.ProcessID == CurrentProcessID)
{
using (var audioMeterInformation = session.QueryInterface<AudioMeterInformation>())
{
Console.WriteLine(audioMeterInformation.GetPeakValue());
}
}
}
//Uncomment this block of code if you need the peak values
//of all the processes
//
//using (var audioMeterInformation = session.QueryInterface<AudioMeterInformation>())
//{
// Console.WriteLine(audioMeterInformation.GetPeakValue());
//}
}
}
}
}
private static AudioSessionManager2 GetDefaultAudioSessionManager2(DataFlow dataFlow)
{
using (var enumerator = new MMDeviceEnumerator())
{
using (var device = enumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia))
{
Console.WriteLine("DefaultDevice: " + device.FriendlyName);
var sessionManager = AudioSessionManager2.FromMMDevice(device);
return sessionManager;
}
}
}
}
The following code block will allow you to change the volume of the device using NAudio
MMDevice VUDevice;
public void SetVolume(float vol)
{
if(vol > 0)
{
VUDevice.AudioEndpointVolume.Mute = false;
VUDevice.AudioEndpointVolume.MasterVolumeLevelScalar = vol;
}
else
{
VUDevice.AudioEndpointVolume.Mute = true;
}
Console.WriteLine(vol);
}
I have code from two different libraries only to answer the question I posted directly which was how to both set the volume and get VU Meter values (peak values). CSCore and NAudio are very similar so most of the code here is interchangeable.
Hi for the print method to work on excel i need the printername and the port name like this:
"printer On NE3" just as an example. The problem is, is that I use a virtual printer and the port is different, pretty much every time i need to use it.
The program needs to run in the background, so open dialog boxes to choose is not an option.
I have also tried to retrieve the port name from WMI with this:
protected string FindPrinterWithPort(string printerName)
{
StringBuilder query = new StringBuilder();
query.Append("SELECT * FROM Win32_Printer ");
query.Append("WHERE DeviceID = \""+printerName+"\"");
ObjectQuery objectQuery = new ObjectQuery(query.ToString());
var searcher = new ManagementObjectSearcher(objectQuery);
foreach (ManagementObject mo in searcher.Get())
{
return printerName +" On "+ mo["PortName"];
}
return string.Empty;
}
The portname i receive doing this gives me the full path to the virtual printer program.
I previously used the methods below to change printer for excel, and i alway knew they should be changed eventually, the code is neither fast nor good, but it worked for a while, until I made it multi-threaded and its just a big blockade. Because i need to lock these methods not to change the default printer in windows.
private bool SetPrinterForExcel(string printerName){
string[] ports = new string[]{"Ne00:", "Ne01:", "Ne02:", "Ne03:", "Ne04:",
"Ne05:", "Ne06:", "Ne07:", "Ne08:",
"Ne09:", "Ne10:", "Ne11:", "Ne12:",
"Ne13:", "Ne14:", "Ne15:", "Ne16:",
"LPT1:", "LPT2:", "File:", "SMC100:"};
foreach (string port in ports)
{
string printerWithPort = printerName + " On " + port;
bool success = SetAndTestPrinter(printerWithPort);
if(success)
return true;
}
return false;
}
private bool SetAndTestPrinter(string printerWithPort)
{
try
{
excel.ActivePrinter = printerWithPort;
return true;
}
catch
{
return false;
}
}
Any Idea how to retrieve the port, or is there a way from WMI query i can get the correct port.
Thanks in advance
Edit:
I have not gotten it work getting, what i have done to print now is change the default printer on windows and then just do the print method on my excel object. I Changed it by using:
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDefaultPrinter(string Name);
And i lock it method and print. I have thought about trying to do a lock and save the ActivePrinter, even tho i believe performance will properly just as bad. Because the lock will stay until the default printer is changed, which takes sometimes up to 1 second, in a multi-threaded envirorment thats is a very long lock.
string printernamewithPort = string.Empty;
lock (ActivePrinterLock)
{
SetDefaultPrinter(printername);
printernamewithPort = excel.ActivePrinter;
}
foreach (Worksheet worksheet in workbook.Worksheets)
{
worksheet.PageSetup.PaperSize = XlPaperSize.xlPaperA4;
worksheet.PageSetup.Orientation = XlPageOrientation.xlPortrait;
worksheet.PageSetup.FitToPagesWide = 1;
worksheet.PageSetup.FitToPagesTall = false;
worksheet.PrintOutEx(ActivePrinter: printernamewithPort,Collate: true, Preview: false, PrintToFile: false);
}
What i dunno is that, if the default printer changes right away from another thread, if it looses the port given to the virtual printer. I have not done proper testing of this. In normal circumstances it seems that my Method FindPrinterWithPort would work.
I have an application where I need to print a ticket. Each ticket must be unique. The application is windows forms and written entirely in c#. For our application we're using Samsung ML- 2525 laser monochromatic printers.
The flow is basically the following, the operator picks a product/ticket (which is unique) and then it presses a button that does 2 things:
Connects to a database and updates the product as used
Prints the ticket (this is done using System.Drawing and GDI+)
For some reason, every once in a while, the image that needs to be printed is not sent to the printer. It's a rare case, but it happens.
I tried to connect to the printer using Win32_Printer ( http://msdn.microsoft.com/en-us/library/Aa394363 ) but I can't get to get the current printer's state (online, offline, low toner, paper jam, etc). I can only check if the printer exists and that the paper size is installed correctly. I tried code similar to the following but it didn't work
private string MonitorPrintJobWmi()
{
var jobMessage = String.Empty;
var scope = new ManagementScope(ManagementPath.DefaultPath);
scope.Connect();
var selectQuery = new SelectQuery { QueryString = #"select * from Win32_PrintJob" };
var objSearcher = new ManagementObjectSearcher(scope, selectQuery);
var objCollection = objSearcher.Get();
foreach (var job in objCollection)
{
if (job != null)
{
jobMessage += String.Format("{0} \r\n", job["Name"].ToString());
jobMessage += String.Format("{0} \r\n", job["JobId"].ToString());
_jobId = Convert.ToInt32(job["JobId"]);
jobMessage += String.Format("{0} \r\n", job["JobStatus"].ToString());
jobMessage += String.Format("{0} \r\n", job["Status"].ToString());
}
}
return jobMessage;
}
I tried to get an API for the printer but I couldn't get a hold of it. By the way, the printer's software do indicate different errors in the windows toolbar.
My question is if anyone can lead me in the right direction as to how to connect to a printer and check if printing was successful.
Also, it would be helpful if someone know of some other specific printer in which I may accomplish this ie, changing hardware.
Thanks,
To get a list of print queues on the local machine, try PrintServer's GetPrintQueues method.
Once you have an instance of the PrintQueue object associated with the relevant printer, you can use it to access the printer's status (IsOffline, IsPaperOut, etc.). Also, you can use it to get a list of the jobs in the given queue (GetPrintJobInfoCollection) which then will allow you to get job-specific status information (IsInError, IsCompleted, IsBlocked, etc.).
Hope this helps!
After try to print your PrintDocument (System.Drawing.Printing), try to check status of printjobs.
First step: Initialize your printDocument.
Second step: Get your printer Name From System.Drawing.Printing.PrinterSettings.InstalledPrinters.Cast<string>();
And copy it into your printerDocument.PrinterSettings.PrinterName
Third step: Try to print and dispose.
printerDocument.Print();
printerDocument.Dispose();
Last step: Run the check in a Task (do NOT block UI thread).
Task.Run(()=>{
if (!IsPrinterOk(printerDocument.PrinterSettings.PrinterName,checkTimeInMillisec))
{
// failed printing, do something...
}
});
Here is the implementation:
private bool IsPrinterOk(string name,int checkTimeInMillisec)
{
System.Collections.IList value = null;
do
{
//checkTimeInMillisec should be between 2000 and 5000
System.Threading.Thread.Sleep(checkTimeInMillisec);
// or use Timer with Threading.Monitor instead of thread sleep
using (System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_PrintJob WHERE Name like '%" + name + "%'"))
{
value = null;
if (searcher.Get().Count == 0) // Number of pending document.
return true; // return because we haven't got any pending document.
else
{
foreach (System.Management.ManagementObject printer in searcher.Get())
{
value = printer.Properties.Cast<System.Management.PropertyData>().Where(p => p.Name.Equals("Status")).Select(p => p.Value).ToList();
break;
}
}
}
}
while (value.Contains("Printing") || value.Contains("UNKNOWN") || value.Contains("OK"));
return value.Contains("Error") ? false : true;
}
Good luck.
First off, I don't have any C# skills or experience. A friend of mine took a couple classes in college and was able to give me what I've got so far in this C# program.
I asked my friend to create a program that would look at WMI for the current logged on user's full name, then look at the RegisteredOwner value. If the full name is the same as the RegisteredOwner then the program quits (all silent), if the full name is different than the RegisteredOwner then the program would launch a form with some text and a yes/no option. If the user clicks yes, then the program sets the RegisteredOwner value to the logged on users full name, and if they click no, the program quits.
He delivered exactly what I asked for; however, it only runs if ran by a user with local admin rights and unfortunately, in my environment, no user is a local admin on their machine. When I presented the issue to him, he wasn't sure what he could do to resolve the problem, and after looking into this all day, I'm afraid there isn't much that can be done to resolve the issue and allow the program to be launched using the local users permissions.
So my question for you is do you know of a different way we could go with this program that would allow it to be run by a user without local admin rights? I would like to have the executable stored somewhere locally on the PC and then it in the startup items list of having something in the startup items list launch it. Maybe there's a way I can use a executable that works with non-local admin rights and then have it work with a windows service that's running under the System account?
When ran by a non local admin, nothing happens when you launch the script.
Below is the code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management;
using System.Security.Principal;
using Microsoft.Win32;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
bool compare;
public Form1()
{
InitializeComponent();
if (PreLoad())
compare = true;
else
{
this.Text = GetUser();
compare = false;
}
}
private bool PreLoad()
{
string temp = GetCaption(GetUser());
RegistryKey regKey1 = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
string keyString = regKey1.GetValue("RegisteredOwner").ToString();
if (temp == keyString)
return true;
else
return false;
}
private void btnYes_Click(object sender, EventArgs e)
{
MessageBox.Show("Are you sure?", "Confirmation", MessageBoxButtons.OKCancel);
string temp = GetCaption(GetUser());
DoRegistryEdit(temp);
lblShowAll.Text = "-Successfully registered the machine to: " + temp + " -";
//Refreshes the screen so that the status message displays
this.Refresh();
Thread.Sleep(5000);
this.Close();
}
private void btnNo_Click(object sender, EventArgs e)
{
//MessageBox.Show("Better change computers then!");
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
if (compare)
this.Close();
}
public string GetCaption(string userName)
{
String QueryStringTemp = "Select * from Win32_NetworkLoginProfile where Caption = '" + userName + "'";
System.Management.ObjectQuery oQuery = new ObjectQuery(QueryStringTemp);
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oQuery);
ManagementObjectCollection oReturnCollection = oSearcher.Get();
string capturedResults = "";
foreach (ManagementObject oReturn in oReturnCollection)
{
capturedResults += oReturn["FullName"].ToString();
}
return capturedResults;
}
public string GetUser()
{
System.Management.ObjectQuery oQuery = new ObjectQuery("Select * from Win32_ComputerSystem");
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oQuery);
ManagementObjectCollection oReturnCollection = oSearcher.Get();
string capturedResults = "";
foreach (ManagementObject oReturn in oReturnCollection)
{
capturedResults += oReturn["UserName"].ToString();
}
int hold = capturedResults.IndexOf("\\");
capturedResults = capturedResults.Substring(hold + 1);
return capturedResults;
}
public void DoRegistryEdit(string name)
{
RegistryKey masterKey = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
if (masterKey == null)
MessageBox.Show("Null Master Key!");
else
{
try
{
masterKey.SetValue("RegisteredOwner", name);
}
catch (Exception ex)
{
MessageBox.Show("Uh OH!" + ex);
}
finally
{
masterKey.Close();
}
}
}
}
}
Any advice and suggestions would be appreciated!
WMI is the killer here. I suppose the whole "Management" part of WMI forces it to run in the admin space.
I found this resource on the Web:
http://skysigal.xact-solutions.com/Blog/tabid/427/EntryId/417/C-Compact-Framework-Getting-the-Registered-Owner.aspx
I tested it out to see that it worked respectably well on my Win7 X86 box. Judging from other sources on the web, this should be good for most recent versions of Windows, including several mobile editions.
Good luck!
When opening a serial port, the device I am trying to access may not have a baudrate of 9600 set so I will have to go thru each baudrate until the device opens correctly.
What error, ArgumentOutOfRangeException or an IOException or some other, should I look for after performing the Port.Open ? Or do I perform this check using the PortOpen statement ?
Sorry to have to ask all of these simple questions, but I am unsure how else to get the information ?
Is there any way that I can tell how to use the PortOpen procedures correctly, including the error handling too, so that I dont have to keep asking everyone ?
Thanks, George.
IOException
InvalidOperationException
is what You should receive in case of errors.
Here You have great example in C#:
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx
You could find all exceptions explanation down there.
For more general advice, have a look at the System.IO.Ports namespace which has a more complete example. Personally I'd adapt what they have there to set your general port settings and then try a few different baud rates in debug mode (some bad, one known good). You'll very quickly see what a bad configuration gives vs a good one. I'm assuming you have access to test the device here?
It's worth noting that you won't see any problems with the call to open the port (just opening it will only test that you've set some parameters which the port supports). You'll start to see issues when you try and read/write to the device and it's there that you'll want to do the error checking for a valid baud rate.
[EDIT] Try something along these lines (NOTE: I've not tested this with any hardware but it at least compiles):
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO.Ports;
namespace SerialPortExperiments
{
class Program
{
public static void Main()
{
// Create a new SerialPort object with default settings.
SerialPort _serialPort = new SerialPort();
// Set some generic settings
SetBasicSettings(ref _serialPort);
// Try and find something valid
int baudRate = FindValidBaud(ref _serialPort);
if (baudRate > 0)
{
Console.WriteLine(String.Format("Found baudrate: {0}", baudRate));
}
else
{
Console.WriteLine("ERROR: Failed to identify baudrate");
}
}
public static void SetBasicSettings(ref SerialPort port)
{
port.PortName = "COM1";
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = 0;
port.Handshake = Handshake.None;
port.ReadTimeout = 500;
port.WriteTimeout = 500;
}
public static int FindValidBaud(ref SerialPort port)
{
bool buadrateIdentified = false;
// Pick some baudrates to try
List<int> baudrates = new List<int>();
baudrates.Add(9600);
baudrates.Add(19200);
// Try and open the port at each baud rate in turn, trying one write/read to verify success
for (int i = 0; i < baudrates.Count; i++)
{
// Pick a baud rate
port.BaudRate = baudrates[i];
// Try opening a connection and exchanging some data
port.Open();
buadrateIdentified = AttemptValidExchange(ref port);
port.Close();
if (buadrateIdentified)
{
return port.BaudRate;
}
}
return -1;
}
public static bool AttemptValidExchange(ref SerialPort port)
{
try
{
// Send a test command
port.Write("SOME_TEST_COMMAND");
// Check to see what the device responded with
const int expectedReturnLength = 1024;
byte[] buffer = new byte[expectedReturnLength];
port.Read(buffer, 0, expectedReturnLength);
if (buffer.ToString().Equals("EXPECTED_RETURN_VALUE"))
{
return true;
}
}
catch (TimeoutException) // NOTE: You'll probably need to catch other exceptions like parity errors here
{
}
return false;
}
}
}