C# - Read Parallel Port State (Simple Push Switch) - c#

I am updating in C# some software that was originally written in VC++ V1.0 for DOS6.
One aspect of the software is a check on the parallel port, where a simple push-button switch is connected. I don't currently know to which two pins the switch is connected, but I have the source for the old program, the relevant sections of which are below...
#define switch_mask 0x10
void main(int argc, char *argv[])
{
int NewState = 0, OldState = 0;
/* Check switch */
NewState = _bios_printer (_PRINTER_STATUS, 0, 0);
if (NewState != OldState)
{
checkParallelPort (NewState);
OldState = NewState;
}
}
void checkParallelPort (int portState)
{
int SwitchState;
/* Switch bit is Active LOW */
SwitchState = (portState & switch_mask) ? 1 : 0;
}
Now _bios_printer (within bios.h) is obviously not available to me in C#, but I'm struggling to find an alternative that can do this simple task.
Info on _bios_printer is here. I've done plenty of searching for reading/writing to/from the parallel port in .Net, but nothing seems to provide me with the port status.
Also, can you conclude from this code (and how it checks the 'status') where the two switch wires are connected on the DB25 plug?
I'd be grateful if anyone has some help/advice on this please.
Many thanks

It seems to be checking 'Error', pin 15. IIRC, this is pulled up internally, so your switch should pull down pin 15. Connect it between pins 15 and 18.
There are some drivers available that allow the reading of the I/O map ports. You will have to import and make DLL calls and then almost certainly poll the pin :((
I do wish this interface was dead and buried!

Thanks for the reply. Here's what I ended up with...
I used this tutorial on CodeProject...
http://www.codeproject.com/KB/vb/Inpout32_read.aspx
When converted to C#, I used something similar to below. (Apologies if there is an error - I 'paraphrased' the code below from what i've ended up with - it works for me!)
private void button1_Click(object sender, EventArgs e)
{
short InReg = 0x379; // Location of Port Status register
int NewState; // int named NewState
NewState = InpOut32_Declarations.Inp(InReg); //Now NewState has the values in 'Status port'
MessageBox.Show(NewState); //A popup will indicate the current value of NewState
}
static class InpOut32_Declarations
{
[DllImport("inpout32.dll", EntryPoint = "Inp32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
//Inp and Out declarations for port I/O using inpout32.dll.
public static extern int Inp(ushort PortAddress);
[DllImport("inpout32.dll", EntryPoint = "Out32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern void Out(ushort PortAddress, short Value);
}
Interestingly, as my Parallel Port starts at 0xE800 and not 0x378, I had to modify the source of inpout32.dll as the out32 method only accepts a short and 0xE800 is too big for a short! changed it to unsigned short.
Thanks for your help

Related

C# Inter-Application Communications through SendMessage

So after a lot of problems finding a proper way to make a way for my different processes to communicate, I cobbled together this:
public const uint HWND_BROADCAST = 0xffff;
[DllImport( "user32" )]
public static extern bool SendMessage(IntPtr hwnd, IntPtr msg, IntPtr wparam, IntPtr lparam);
[DllImport( "user32" )]
public static extern int RegisterWindowMessage(string message);
public static readonly uint WM_COPYDATA = (uint)RegisterWindowMessage( "WM_COPYDATA_DESKTOP_TODOLIST_9234892348932GIBBERISH" );
Which is used in the following way:
public static void SendMessage(string Message) {
SendMessage( (IntPtr)HWND_BROADCAST, (IntPtr)WM_COPYDATA, (IntPtr)Rawify( ref Message ), (IntPtr)Message.Length );
}
// Preparing the message for pointer-sending
public static IntPtr Rawify(ref string target) {
char[] CHARS = target.ToCharArray();
// Copy string to raw memory block of bytes
int count = target.Length;
IntPtr P = Marshal.AllocHGlobal( 2 * count );
for (int I = 0; I < count; I++) { Marshal.WriteInt16( (IntPtr)((int)P + I * 2), target[I] ); }
return P;
}
public static string Cook(IntPtr target, IntPtr length) {
int count = (int)length;
char[] CHARS = new char[count];
// Copy raw memory to char array->string
for (int I = 0; I < count; I++) { CHARS[I] = (char)Marshal.ReadInt16( (IntPtr)((int)target + I * 2) ); }
return new string( CHARS );
}
}
And on the receiving end
// Receiver for alternate applications
protected override void WndProc(ref Message m) {
if (m.Msg == Native.Messaging.WM_COPYDATA) { MessageBox.Show( "[" + Native.Messaging.Cook( m.WParam, m.LParam ) + "]" ); }
base.WndProc( ref m ); // Default handling
}
Now, all is peachy and I've tested thoroughly;
What happens is I've borrowed SendMessage from Runtime.InteropServices.
The message is sent successfully across.
However, it's limited to two pathetic IntPtr's.
So I decided the best thing to do is sent over a pointer to some unmanaged memory, and the size of that memory.
The sending is successful, however in the two different program instances, the pointer, apparently, doesn't point to the same place. It looks like the IntPtr that Marshal.AllocHGlobal is some arbitrary local pointer relevant only the current program, thus giving me exceptions for read/write access violations, or some random nulls, or some random other characters, and at some point I even sampled a random "l32.dll" string from somewhere. Spooky!
I only, and simply want to know how to get a Pointer, that would point to the SAME DATA, across two different applications. I'm so clueless where to even start searching for this answer, hence why I ask here.
Is there a way to get that pointer with Marshals, or I need something else.
I can figure out the details, I just need to be let known about some Pointer, that points to the same data if used in multiple programs.
Alternatively, if what I'm doing is grotesquely horrible and a bad idea, I'd like to be informed of alternatives, so long as they are not: Named pipes, RPC, Memorymapped, Files, Mutex; because, for reasons, I'm working in .NET 2.0, and those are not available there; And Mutex doesn't transfer data; And I like my hard disk nice, clean, un-busy and in pristine condition.
Again, Reminder: The goal is to communicate DATA of ANY TYPE and ANY SIZE (I can accept some limits), BETWEEN multiple INSTANCES of the same PROGRAM, or possibly other PROGRAMS, that is an .EXE in its own ApplicationDomain and etc.
Forgot to mention, this has to be in .NET 2.0, and all I need is a POINTER of some kind that points to the SAME DATA between multiple applications.
I'm guessing you'd either need to OpenHandle on the source process and ReadProcessMemory from there (since the memory address you're broadcasting is local to the application), or use memory-mapped files or shared memory space. Either way you are digging into Win32 P/Invoke land as neither is available fully managed on .NET 2.0.
Edit: It appears you edited your question to remove these as viable candidates. You're asking for methods of IPC while excluding all methods of IPC (without a reason).
Wow! Why you don't use WCF to comunicate between process via IPC?
http://tech.pro/tutorial/855/wcf-tutorial-basic-interprocess-communication
http://dotnet-experience.blogspot.com.es/2012/02/inter-process-duplex-communication-with.html

Preveting computer from going to sleep with program C# [duplicate]

I have to stop windows from going into sleep when my program is running.
And I don't only want to prevent the sleep-timer, I also want to cancel the sleep-event if I press the sleep-button or in any other way actively tell the computer to sleep. Therefore SetThreadExecutionState is not enough.
Or...I don't actually have to prevent the sleep completely, only delay it 5-10sec to allow my program to finish a task.
(I know that this is bad program behavior but it's only for personal use.)
After considering vim's answer
"Using PowerCreateRequest, PowerSetRequest, and PowerClearRequest
functions is the preferred method."
with the linked AvailabilityRequests.docx on msdn which is exhausting to get into it (too much to read), I have searched the web for a concrete example in c# that is based on the PowerCreateRequest and found http://go4answers.webhost4life.com/Example/problem-monitor-wakeup-service-windows7-12092.aspx [EDIT 2016 - isn't available anymore]
Copied and adapted it to my needs (PInvoke of CloseHandle copied from msdn):
using System.Runtime.InteropServices;
#region prevent screensaver, display dimming and automatically sleeping
POWER_REQUEST_CONTEXT _PowerRequestContext;
IntPtr _PowerRequest; //HANDLE
// Availability Request Functions
[DllImport("kernel32.dll")]
static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT Context);
[DllImport("kernel32.dll")]
static extern bool PowerSetRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);
[DllImport("kernel32.dll")]
static extern bool PowerClearRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
internal static extern int CloseHandle(IntPtr hObject);
// Availablity Request Enumerations and Constants
enum PowerRequestType
{
PowerRequestDisplayRequired = 0,
PowerRequestSystemRequired,
PowerRequestAwayModeRequired,
PowerRequestMaximum
}
const int POWER_REQUEST_CONTEXT_VERSION = 0;
const int POWER_REQUEST_CONTEXT_SIMPLE_STRING = 0x1;
const int POWER_REQUEST_CONTEXT_DETAILED_STRING = 0x2;
// Availablity Request Structures
// Note: Windows defines the POWER_REQUEST_CONTEXT structure with an
// internal union of SimpleReasonString and Detailed information.
// To avoid runtime interop issues, this version of
// POWER_REQUEST_CONTEXT only supports SimpleReasonString.
// To use the detailed information,
// define the PowerCreateRequest function with the first
// parameter of type POWER_REQUEST_CONTEXT_DETAILED.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct POWER_REQUEST_CONTEXT
{
public UInt32 Version;
public UInt32 Flags;
[MarshalAs(UnmanagedType.LPWStr)]
public string
SimpleReasonString;
}
[StructLayout(LayoutKind.Sequential)]
public struct PowerRequestContextDetailedInformation
{
public IntPtr LocalizedReasonModule;
public UInt32 LocalizedReasonId;
public UInt32 ReasonStringCount;
[MarshalAs(UnmanagedType.LPWStr)]
public string[] ReasonStrings;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct POWER_REQUEST_CONTEXT_DETAILED
{
public UInt32 Version;
public UInt32 Flags;
public PowerRequestContextDetailedInformation DetailedInformation;
}
#endregion
/// <summary>
/// Prevent screensaver, display dimming and power saving. This function wraps PInvokes on Win32 API.
/// </summary>
/// <param name="enableConstantDisplayAndPower">True to get a constant display and power - False to clear the settings</param>
private void EnableConstantDisplayAndPower(bool enableConstantDisplayAndPower)
{
if (enableConstantDisplayAndPower)
{
// Set up the diagnostic string
_PowerRequestContext.Version = POWER_REQUEST_CONTEXT_VERSION;
_PowerRequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
_PowerRequestContext.SimpleReasonString = "Continuous measurement"; // your reason for changing the power settings;
// Create the request, get a handle
_PowerRequest = PowerCreateRequest(ref _PowerRequestContext);
// Set the request
PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);
}
else
{
// Clear the request
PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);
CloseHandle(_PowerRequest);
}
}
I had a problem like this with a hardware device connected via usb. XP /Vista would sleep/hibernate right in the middle of ... Great you say, when it resumes it can just continue. If the hardware is still connected!!!
Users have the habit of pulling cables out whenever they feel like it.
You need to handle XP and Vista
Under XP trap the WM_POWERBROADCAST and look for the PBT_APMQUERYSUSPEND wparam.
// See if bit 1 is set, this means that you can send a deny while we are busy
if (message.LParam & 0x1)
{
// send the deny message
return BROADCAST_QUERY_DENY;
} // if
else
{
return TRUE;
} // else
Under Vista use SetThreadExecutionState like this
// try this for vista, it will fail on XP
if (SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED) == NULL)
{
// try XP variant as well just to make sure
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
} // if
and when you app has finished set it back to normal
// set state back to normal
SetThreadExecutionState(ES_CONTINUOUS);
Using PowerCreateRequest, PowerSetRequest, and PowerClearRequest functions is the preferred method. Details and sample code (C/C#) are inside http://msdn.microsoft.com/en-us/library/windows/hardware/gg463205.aspx
set wsc = CreateObject("WScript.Shell")
Do
WScript.Sleep (60*1000)
wsc.SendKeys ("{SCROLLLOCK 2}")
Loop
-put the above code in notepad and save the file as .vbs and double click the file
The same technique applies as for preventing the screensaver should be used. See Programmatically prevent Windows screensaver from starting.
Note that some security settings can override this (forcing computers to lock after a certain time is one).
If you need a display that should work until your application is running then try to set "ES_DISPLAY_REQUIRED" instead of away mode:
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
Once you are done with your application make sure to clear all other flags.
SetThreadExecutionState(ES_CONTINUOUS);
How about waking it back up if it goes to sleep?
http://www.enterprisenetworksandservers.com/monthly/art.php?1049
Below is my attempt using the modern power availability request API (supersedes SetThreadExecutionState), as suggested by vim.
I'm using a nice P/Invoke NuGet I came across, Vanara.PInvoke.Kernel32:
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
// create request object
using var request = PowerCreateRequest(new REASON_CONTEXT("App FOO is working"));
if (request.IsInvalid)
{
throw new InvalidOperationException(
$"Could not create power availability request: {Win32Error.GetLastError()}");
}
// send request
if (!PowerSetRequest(request, POWER_REQUEST_TYPE.PowerRequestSystemRequired))
{
throw new InvalidOperationException(
$"Could not send power availability request: {Win32Error.GetLastError()}");
}
// do stuff that required the machine to be up
Console.WriteLine("Doing stuff...");
await Task.Delay(5000);
// clear request
if (!PowerClearRequest(request, POWER_REQUEST_TYPE.PowerRequestSystemRequired))
{
Console.WriteLine(
"WARNING: Could not clear power availability request: {0}",
Win32Error.GetLastError());
}
You can see your request in action by issuing powercfg /requests from an admin terminal.

I/O exception error when using serialport.open()

FINAL UPDATE
It was our firmware the whole time. Embarrassing to a degree, but I'm happy we can move forward and I can put learning Java off for another day. My answer is below.
UPDATE
So I have more or less given up on this. I think it is a bug that goes down to the API, but I have neither the time, resources nor skill-set to get to the bottom of it. I think there exists some hardware to whom Windows just gives the middle finger. I have downloaded Eclipse, switched to Java and will try to see if that works. If not, you'll see me back here. However, I would absolutely love to solve this and so if anyone has the time or inclination to dig deep into this one, I'd love to see what you come up with. Obviously I will be checking back here from time to time. Please make sure you '#' me in your comments so I am alerted.
ORIGINAL POST
I know there are a few other people dealing with this issue, but I was hoping someone could help me. I am trying to connect to a COM port, but I am getting an I/O exception when I try to use the serialport.Open() command:
System.IO.IOException: The parameter is incorrect.
at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
at System.IO.Ports.InternalResources.WinIOError()
at System.IO.Ports.SerialStream.InitializeDCB(Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Boolean discardNull)
at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
at System.IO.Ports.SerialPort.Open()
at *programtitlehere.cs*:line 90
I am using a Stellaris LM4F232 to emulate a COM port. I can open, access and I get good results using Termite (a terminal program), but whenever I try with Visual Studio it won't even connect, and I get this error. Now I don't even really know what this error means and despite trying to read elsewhere, I still feel lost.
Can anyone explain to me what is happening here and maybe I can begin to try to figure this out? I can include more code, but to be honest there isn't much there; all the properties of the serial port device are as normal, and it is only happening with this device (I can use an MSP430 no problem with the same details).
My code is shown below for people who would like to see it (note this is just a 'sandbox', not the actual program, but the symptoms are identical):
try
{
serialPort1.PortName = "COM5";
serialPort1.Open();
if (serialPort1.IsOpen == true)
{
textBox1.Text = "CONNECTED";
}
else
{
textBox1.Text = "NOT CONNECTED";
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.ToString(), "ERROR");
}
and the other settings are done with the property manager (the only difference is baud is set to 230400; all others are on their default).
I can open up COM4 with this (an MSP430) which for all intents and purposes is an identical device. I can open COM5 with Termite, so I know the connection is good). And no, I am not trying to open them at the same time. If you need more information let me know and I can post more.
EDIT: I'm on day three of trying to figure this out and still no luck. I don't really understand why I can access this COM port through a terminal program and not my own when, as near as I can see, there is absolutely no difference. Is there a program that can 'examine' a COM port to see the properties of it (besides Windows manager I mean)? I'm getting pretty frustrated and am sort of at a stand still in my project until I figure this out...
EDIT2: I've found an apparent workaround, but I've yet to get it to work here. Now I get a few different I/O errors, but at least it is motion (not sure if it is progress). I've also learned that this is a .NET bug, which has existed since 2.0. I'd still love any help, but if I figure it out I will report back. Zach's code (the workaround linked above) is shown below:
using System;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace SerialPortTester
{
public class SerialPortFixer : IDisposable
{
public static void Execute(string portName)
{
using (new SerialPortFixer(portName))
{
}
}
#region IDisposable Members
public void Dispose()
{
if (m_Handle != null)
{
m_Handle.Close();
m_Handle = null;
}
}
#endregion
#region Implementation
private const int DcbFlagAbortOnError = 14;
private const int CommStateRetries = 10;
private SafeFileHandle m_Handle;
private SerialPortFixer(string portName)
{
const int dwFlagsAndAttributes = 0x40000000;
const int dwAccess = unchecked((int) 0xC0000000);
if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
SafeFileHandle hFile = CreateFile(#"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
IntPtr.Zero);
if (hFile.IsInvalid)
{
WinIoError();
}
try
{
int fileType = GetFileType(hFile);
if ((fileType != 2) && (fileType != 0))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
m_Handle = hFile;
InitializeDcb();
}
catch
{
hFile.Close();
m_Handle = null;
throw;
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, IntPtr arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
IntPtr securityAttrs, int dwCreationDisposition,
int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetFileType(SafeFileHandle hFile);
private void InitializeDcb()
{
Dcb dcb = new Dcb();
GetCommStateNative(ref dcb);
dcb.Flags &= ~(1u << DcbFlagAbortOnError);
SetCommStateNative(ref dcb);
}
private static string GetMessage(int errorCode)
{
StringBuilder lpBuffer = new StringBuilder(0x200);
if (
FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
IntPtr.Zero) != 0)
{
return lpBuffer.ToString();
}
return "Unknown Error";
}
private static int MakeHrFromErrorCode(int errorCode)
{
return (int) (0x80070000 | (uint) errorCode);
}
private static void WinIoError()
{
int errorCode = Marshal.GetLastWin32Error();
throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
}
private void GetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (GetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
private void SetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (SetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
#region Nested type: COMSTAT
[StructLayout(LayoutKind.Sequential)]
private struct Comstat
{
public readonly uint Flags;
public readonly uint cbInQue;
public readonly uint cbOutQue;
}
#endregion
#region Nested type: DCB
[StructLayout(LayoutKind.Sequential)]
private struct Dcb
{
public readonly uint DCBlength;
public readonly uint BaudRate;
public uint Flags;
public readonly ushort wReserved;
public readonly ushort XonLim;
public readonly ushort XoffLim;
public readonly byte ByteSize;
public readonly byte Parity;
public readonly byte StopBits;
public readonly byte XonChar;
public readonly byte XoffChar;
public readonly byte ErrorChar;
public readonly byte EofChar;
public readonly byte EvtChar;
public readonly ushort wReserved1;
}
#endregion
#endregion
}
internal class Program
{
private static void Main(string[] args)
{
SerialPortFixer.Execute("COM1");
using (SerialPort port = new SerialPort("COM1"))
{
port.Write("test");
}
}
}
}
EDIT3: Day 6: I'm still plugging away at this. My water rations are low, but still I struggle on. I feel help must surely be on the horizon. Whoever finds this journal bring my remains back to Canada and find Nicole. Tell her I love her.
But seriously, I have no idea what is causing this problem. I'm wondering if it is purely on the embedded side; maybe because it is USB On-The-Go (OTG), or because the device is capable of being a host also. Has anyone run into that problem? It doesn't explain why I can use Termite (a terminal program, for those viewers just joining us) though. I have been trying to find an open source terminal program that a) works and b) see a). As per usual, I will report back if I discover the issue here as I have now found countless forums where it sounds people have had this issue dating back to 2006.
EDIT4: So as per the advice given, I downloaded a port monitoring software application (I got Eltima Serial Port Monitor), and it does look like a baud issue:
But strangely no matter what baud I set, it still fails. And also can someone explain what the up/down thing means? I tried googling it, but the keywords are too general. As usual, I will keep reporting back any changes.
Also, for the record, I can connect using Eltima at a baud of 115200 (same as Termite). Unfortunately this does not work in Visual Studio.
EDIT5: Our plot takes a surprise twist. I was monitoring what happens when Termite connects to the COM port in question and BLAM! Termite throws the exact same error as my program, but it ignores it. Genius, right? Sloppy, but it works. Now I need to learn how to ignore IOExceptions. I'll report back when I get it figured out.
EDIT6: So as it turns out it is a baud rate issue, but it goes deeper. I have been using Eltima Serial Port Monitoring software, and it is very intuitive and easy to use. I would recommend it. After some research I have learned that you cannot ignore this exception and still connect to the serial port using .NET's library.
So I have to go deeper into the Win32 API and write my own. I have found a few pages that touch on this, but to be honest I have never done anything like this before, so it may be a while before I report back, but I will definitely figure this out and get back to everyone. There are way too many who suffer from this problem.
I have found quite a few forums and websites where I can see the exact same symptoms, but nobody has really done much besides say 'Yeah, .NET sucks'. I plan on writing a full static library class and then publish either on my website, here and wherever else I can. Hopefully .NET will take notice (this bug has existed since 2.0).
This comes from the serial port driver; it is unhappy about one of the settings. With baudrate being a good candidate, drivers tend to allow only up to 115200. Albeit that this should not be a restriction when this is a dedicated CAN bus product.
The best way to tackle this is by using Sysinternals' Portmon utility; you can see what is being sent to the driver. Observe it for Terminate first; that's your known-to-work baseline. Then tinker with SerialPort properties until the initialization commands, as you see them in PortMon, sent by your program matches Termite's. Just the values, not the order. If that doesn't pan out either then take it to the parking lot and back over it with your car several times and buy another brand.
Update: it certainly looks like a baudrate problem. That's an issue in .NET; it is not going to ignore the driver's error return code like your terminal emulator programs do. The actual value should not matter since you are talking to an emulated serial port. There is however a possible issue with the CAN bus speed; rates are variable and it isn't clear to me how they are negotiated. This tended to be done with DIP switches in the olden days, and it may well be that the driver wants you to specify the speed through the baudrate setting. There ought to be something about it on the box or in the manual. Typical speeds are 40, 250 or 500 kbit/s. The manufacturer certainly would know; give them a call.
I faced a similar problem as reported in this thread, but I managed to solve the problem!
I am using STM32F2xx for the VCP!
And indeed it was my firmware problem. I forgot to include serial port settings in my USB callback!
The process of connecting a serial port from PC and firmware:
When a PC opens a serial port communication, the PC will send some command into the "configuration endpoint"
In the firmware, it would have a callback and the firmware will provide all the USB information (they call it a USB descriptor)
USB information is the configuration of each endpoint, (for example, latency, data size transmission, and type of USB - high speed or low speed)
Once the firmware has completed sending all the information, the PC will acknowledge and USB communication is successfully opened
Then, the PC will send a command to get the serial port settings from the firmware
Serial port settings are baudrate, data parity, and bit length.
In firmware, it should reply the serial port settings back to PC (my mistake occurs here; I didn’t not send any serial port settings back to the PC)
If successful, PC will start the serial port communication!
If failed, PC will give an open serial port error (but, do note that this error sometimes is bypassed)
In STM32 firmware code:
static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
switch (cmd) {
case CDC_GET_LINE_CODING:
{
// I was missing this part
uint32_t baudrate = 9600;
pbuf[0] = (uint8_t)(baudrate);
pbuf[1] = (uint8_t)(baudrate >> 8);
pbuf[2] = (uint8_t)(baudrate >> 16);
pbuf[3] = (uint8_t)(baudrate >> 24);
pbuf[4] = 0;
pbuf[5] = 0;
pbuf[6] = 8;
break;
}:
....
I ran into the same situation. I am trying to connect serial communication to my 3G USB Dongle (Huawei E303F) at /dev/ttyUSB0. I use Mono in Raspbian (Raspberry Pi 2). On my development PC and macOS, my program runs fine. But when I deploy it into Raspbian, I got the IOException Broken Pipe error on Serial.Open().
It took me three days of debugging, and I tried all possible solutions. Finally I found that I have to set...
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
Before calling .Open().
And so our thrilling tale comes to a close. It was firmware the whole time (i.e. the code on the embedded device). We changed up a few functions and essentially poked around, chopped, added and altogether cleaned up the code and voila, the code is working. This pic sums it up pretty well. Curse you firmware!!
However, the bug described in my (lengthy) question still persists for many people and I know there are lots of people out there who still have it. All I can say is good luck and quadruple check your firmware (apparently triple checking it isn't enough these days).
I had the same problem and setting the baud rate to 1 fixed it!

Webbrowser control not working perfectly with proxies rotation

I am using many ipz and use them one after another some repeat after some time some with in seconds using this code:
string key = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
RegistryKey RegKey = Registry.CurrentUser.OpenSubKey(key, true);
RegKey.SetValue("ProxyServer", proxy);
RegKey.SetValue("ProxyEnable", 1);
webBrowser1.Navigate(customLinks[0].ToString());
The issue is its not always successful as i noticed many time.Suppose an ip is blocked so it takes the next one but i still see the block on the next one ,and even the next one.
So assuming its not taking proxy so fast etc?Maybe it needs to be refreshed.Kindly let me know how to implement this
Thank you
I got help from googling a lot , but do not remember the exact link:
Here is the code, i call the refresh function and pass proxy and it works 100 % everytime , anytime.
public struct Struct_INTERNET_PROXY_INFO
{
public int dwAccessType;
public IntPtr proxy;
public IntPtr proxyBypass;
};
[DllImport("wininet.dll", SetLastError = true)]
private static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int lpdwBufferLength);
private void RefreshIESettings(string strProxy)
{
const int INTERNET_OPTION_PROXY = 38;
const int INTERNET_OPEN_TYPE_PROXY = 3;
Struct_INTERNET_PROXY_INFO struct_IPI;
// Filling in structure
struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
struct_IPI.proxy = Marshal.StringToHGlobalAnsi(strProxy);
struct_IPI.proxyBypass = Marshal.StringToHGlobalAnsi("local");
// Allocating memory
IntPtr intptrStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI));
// Converting structure to IntPtr
Marshal.StructureToPtr(struct_IPI, intptrStruct, true);
bool iReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY, intptrStruct, Marshal.SizeOf(struct_IPI));
}
Sounds like you need to set a single proxy in the browser, and implement that proxy yourself, such that it rotates requests to your proxy list.

C++ DLL function does not seem to work in C#

I have developed a small program using C# and bird.dll, but the birdRS232WakeUp() function seem not to be working.
When I call the birdRS232WakeUp() function in C++ the program will stop for a while (8-10 seconds). It looks like it is beginning to do the process connecting with the hardware (Flock of bird).
But in C#, it does not stop when calling birdRS232WakeUp(). How do I fix this problem?
The C# code is like the following.
[DllImport(#"Bird.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool birdRS232WakeUp(int nGroupID, Boolean bStandAlone, int nNumDevices,
ref ushort[] pwComport, uint dwBaudRate,
uint dwReadTimeout, uint dwWriteTimeout);
ushort[] COM_port = new ushort[]{0,16,0,0,0};
if ((!birdRS232WakeUp(GROUP_ID, false, DEVCOUNT, ref COM_port, BAUD_RATE, READ_TIMEOUT, WRITE_TIMEOUT)))
{
LWakeUpStatus.Text = "Failde to wake up FOB";
}
And the C++ code is looking like the following.
WORD COM_port[5] = {0,15,0,0,0}
if ((!birdRS232WakeUp(GROUP_ID,
FALSE, // Not stand-alone
DEVCOUNT, // Number of Devices
COM_port, // COM Port
BAUD_RATE, // BAUD
READ_TIMEOUT,WRITE_TIMEOUT, // Reponses timeouts
GMS_GROUP_MODE_ALWAYS)))
{
printf("Can't Wake Up Flock!\n");
Sleep(3000);
exit(-1);}
C++ header file for this function:
birdRS232WakeUp(int nGroupID, BOOL bStandAlone, int nNumDevices,
WORD *pwComport, DWORD dwBaudRate, DWORD dwReadTimeout,
DWORD dwWriteTimeout, int nGroupMode = GMS_GROUP_MODE_ALWAYS);
And the manual states that "pwComport" points to an array of words, each of which is the number of the COM port attached to one of the birds (for example, COM1 = 1, COM2 = 2, etc.)
Update 1:
I have taken a suggestion from elder_george, but the problem still exist. I had to change the C# code to the following.
public static extern bool birdRS232WakeUp(int nGroupID, Boolean bStandAlone, int nNumDevices,
ushort[] pwComport, uint dwBaudRate, uint dwReadTimeout,
uint dwWriteTimeout,int nGroupMode);
if ((!birdRS232WakeUp(GROUP_ID, false, DEVCOUNT, COM_port, BAUD_RATE, READ_TIMEOUT, WRITE_TIMEOUT,2)))
{
LWakeUpStatus.Text = "Failde to wake up FOB";
}
BTW, the int nGroupMode is equal to 2, based on the enum type below .
enum GroupModeSettings
{
// GMS_DEFAULT, // Driver will determine whether or not to use RS232 group mode.
GMS_GROUP_MODE_NEVER, // RS232 group mode will never be used
GMS_GROUP_MODE_ALWAYS, // RS232 group mode will always be used
NUM_GROUP_MODE_SETTINGS
};
Not sure if these points will solve your problem, but:
1) pwComport should be declared as ushort[] pwComport, not ref ushort[] pwComport
2) you need to pass nGroupMode parameter from C#. You can set it to default value if you use C#4, but don't ignore it at all.

Categories