All instances Pipe Are busy - c# NamedPipeServerStream - c#

im trying to use pipe via .net v4.0 on winforms application background
heres my code -->
public void main()
{
using (NamedPipeServerStream pipeserver = new NamedPipeServerStream("colors", PipeDirection.Out,4))
{
pipeserver.WaitForConnection();
try
{
using (StreamReader sr = new StreamReader(pipeserver))
{
string data = sr.ReadLine();
ConvertToGuiColor(data);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
trying to understand why Exception "All instances Pipe Are busy"
thought maybe because
pipeserver.WaitForConnection();
,but the Exception is throwing in this :
"using (NamedPipeServerStream pipeserver = new NamedPipeServerStream("colors", PipeDirection.Out,4))"
command
ty for helpers
sKY Walker

Related

How to fix "access the file because it is being used by another process"

I'm using Microsoft Visual Studio Professional 2022 (64-bit) - Current
Version 17.3.1 to build a Console App with .NET Core 6.
The App appends text to a .csv file, and it runs fine.
When I start the App twice (giving different data input) I get:
"access the file because it is being used by another process"
The function that appends to the .csv files is:
public static readonly object myAppendLock = new();
public static void AppendToRocket(string outputFilePath, string data) {
lock (myAppendLock) {
try {
using StreamWriter w = File.AppendText(outputFilePath);
w.Write(data + "\n");
w.Flush();
w.Close();
w.Dispose();
} catch (Exception ex) {
Log.WriteLog("AppendToRocket.txt", $"Error: {ex.Message}");
}
}
}
Please help me to understand why I'm getting the "access" error.
Charles
I want to thank C Helling. FileShare was the answer. Here is my working solution:
public static void AppendToRocket(string outputFilePath, string data) {
try {
using FileStream fs = new(outputFilePath,
FileMode.Append,
FileAccess.Write,
FileShare.ReadWrite);
using var writer = new StreamWriter(fs);
using var syncWriter = TextWriter.Synchronized(writer);
syncWriter.WriteLine(data);
} catch (Exception ex) {
Log.WriteLog("AppendToRocket.txt", $"Error: {ex.Message}");
}
}
Charles

How to strip ANSI escape codes from AIX topas command result in C#

I'm trying to capture AIX real-time information like CPU, memory, IO load with a C# console application because I would like to show that information in a third part custom dashboard.
After running the command topas, I need to capture periodically the whole following text:
I tried to capture it with the following code that I have found out in some forum:
using Renci.SshNet;
using System;
using System.IO;
using System.Threading;
namespace SSH_check_commands
{
public class MyAsyncInfo
{
public MyAsyncInfo(Byte[] array, ShellStream stream)
{
ByteArray = array;
Stream = stream;
}
public Byte[] ByteArray { get; set; }
public ShellStream Stream { get; set; }
}
class Program
{
private static ShellStream stream;
private static SshClient client;
private static byte[] _data = new byte[2048];
static void Main(string[] args)
{
client = new SshClient("host", "user", "password");
client.Connect();
stream = client.CreateShellStream(#"xterm", 80, 24, 800, 600, 1024);
stream.DataReceived += StartAsyncRead;
stream.Write("bash\n");
Thread.Sleep(5000);
stream.Write("topas -i 10\n");
Console.ReadLine();
}
private static void StartAsyncRead(object sender, EventArgs e)
{
try
{
stream.BeginRead(_data, 0, _data.Length, OnReadCompletion, new MyAsyncInfo(_data, stream));
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
private static void OnReadCompletion(IAsyncResult ar)
{
try
{
var mai = (MyAsyncInfo)ar.AsyncState;
int datalen = mai.Stream.EndRead(ar);
string line = client.ConnectionInfo.Encoding.GetString(mai.ByteArray, 0, datalen);
Console.Write(line);
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
public static string SendCommand(string cmd, ShellStream sh)
{
StreamReader reader = null;
try
{
reader = new StreamReader(sh);
StreamWriter writer = new StreamWriter(sh);
writer.AutoFlush = true;
writer.WriteLine(cmd);
while (sh.Length == 0)
{
Thread.Sleep(1000);
}
}
catch (Exception ex)
{
Console.WriteLine("exception: " + ex.ToString());
}
return reader.ReadToEnd();
}
}
}
But I can't parse the result because it's not structured:
Could you please help me?
Workaround:
I have changed the approach to the problem.
I could not catch whole text with ssh streaming because I receive only changed chars.
Hence periodically I run the following ssh command to save nmon content in a file (called hostname_YYMMDD_H24_mm.nmon):
nmon -f -c 1
After with the cat command I can read the file, extract the content, transform it and load it in my dashboard.
The results are structured. Those are ANSI escape codes. You can parse those, the same way your SSH terminal client parses those to display the nice output.
But that's a huge task. See SSH.NET based colored terminal emulator.
Though I'd say that trying to parse an output of a command that is intended for a human use is a bad idea, in the first place. For sure there's another way to retrieve the same information in a format that's easier to parse. But that's a question for another site (for example Super User).
If you just want to strip the ANSI escape codes, you can use a regular expression, as shown in How to remove ^[, and all of the escape sequences in a file using linux shell scripting:
s = new Regex(#"\x1B\[[^#-~]*[#-~]").Replace(s, "");

Why Does Threading Break Named Pipes During Inter-Processing Communications?

I am trying to write a sample C# program for named pipe streaming. I create two executable files, one for server and another for client. Please check my code below. These two applications sometimes work correctly and sometimes client application closes without any reason or exception, resulting Pipe is broken exception in server application. I think, in this situation, these processes are not synchronized, specially when I put some delays in their code such as debug mode delays. Why is client process being suddenly closed when server is still waiting for PipeDrain (pipeServer.WaitForPipeDrain())?
I appreciate your help.
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.Threading;
namespace NamedPipeServer
{
class NamedPipeServerClass
{
static void Main(string[] args)
{
NamedPipeServerStream pipeServer = new NamedPipeServerStream("namedPipe", PipeDirection.InOut, 4);
StreamReader SR = new StreamReader(pipeServer);
StreamWriter SW = new StreamWriter(pipeServer);
pipeServer.WaitForConnection();
string temp;
try
{
SW.WriteLine("Waiting");
SW.Flush();
pipeServer.WaitForPipeDrain();
temp = SR.ReadLine();
Console.WriteLine(temp + '\n');
SW.WriteLine("Hello");
SW.Flush();
pipeServer.WaitForPipeDrain();
temp = SR.ReadLine();
Console.WriteLine(temp + '\n');
SW.WriteLine("How are you?");
SW.Flush();
pipeServer.WaitForPipeDrain();
temp = SR.ReadLine();
Console.WriteLine(temp + '\n');
SW.WriteLine("GoodBye");
SW.Flush();
pipeServer.WaitForPipeDrain();
temp = SR.ReadLine();
Console.WriteLine(temp + '\n');
}
catch (Exception ex)
{
throw ex;
}
finally
{
pipeServer.WaitForPipeDrain();
if (pipeServer.IsConnected)
{
pipeServer.Disconnect();
}
}
Console.WriteLine("Server: Press any key to exit...");
Console.ReadLine();
}
}
}
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.Threading;
namespace NamedPipeClient
{
class NamedPipeClientClass
{
static NamedPipeClientStream pipeClient;
static StreamReader SR;
static StreamWriter SW;
static Thread Conversation = new Thread(new ThreadStart(Con_function));
static bool HandShake_Ok = false;
static void Main(string[] args)
{
pipeClient = new NamedPipeClientStream(".", "namedPipe", PipeDirection.InOut, PipeOptions.None);
if (pipeClient.IsConnected != true)
{
pipeClient.Connect();
}
SR = new StreamReader(pipeClient);
SW = new StreamWriter(pipeClient);
Conversation.Name = "ConversationThread";
Conversation.IsBackground = true;
Conversation.Start();
}
static void Con_function()
{
string temp;
while (true)
{
try
{
temp = SR.ReadLine();
}
catch (Exception ex)
{
throw ex;
}
if (temp == "Waiting")
{
HandShake_Ok = true;
try
{
SW.WriteLine("Welcome");
SW.Flush();
}
catch (Exception ex)
{
throw ex;
}
}
else if (HandShake_Ok && temp == "Hello")
{
try
{
SW.WriteLine("Hi");
SW.Flush();
}
catch (Exception ex)
{
throw ex;
}
}
else if (HandShake_Ok && temp == "How are you?")
{
try
{
SW.WriteLine("I am fine");
SW.Flush();
}
catch (Exception ex)
{
throw ex;
}
}
else if (HandShake_Ok && temp == "GoodBye")
{
try
{
HandShake_Ok = false;
SW.WriteLine("Good bye :)");
SW.Flush();
}
catch (Exception ex)
{
throw ex;
}
}
}
}
}
}
Update: In the client the writings and readings into pipe are done in a thread, called Conversation. If I remove this thread and bring all writings and readings into Main function, the problem will be resolved. Why does thread have such an effect on inter-process pipeline communications?
I believe what you are experiencing here is since Conversation.IsBackground = true; the client application will NOT wait for the Conversation thread to complete before exiting
Try:
Conversation.Name = "ConversationThread";
Conversation.IsBackground = true;
Conversation.Start();
Conversation.Join();
The Conversation.Join(); blocks the calling thread from executing until the thread object terminates
See Thread.Join Method & Thread.IsBackground Property on MSDN

C# SVN Pre Commit Hook, SharpSvn error

I have a C# console application that I use as an SVN Pre Commit Hook. The console app is started perfectly. However, as soon as I try to do a Write using SharpSvn, I get this error:
Commit failed (details follow):
Commit blocked by pre-commit hook (exit code -1066598274) with output:
Unhandled Exception: System.Runtime.InteropServices.SEHException: External
component has thrown an exception.
at svn_client_cat2(svn_stream_t* , SByte* , svn_opt_revision_t* ,
svn_opt_revision_t* , svn_client_ctx_t* , apr_pool_t* )
at SharpSvn.SvnClient.Write(SvnTarget target, Stream output, SvnWriteArgs args)
at SharpSvn.SvnClient.Write(SvnTarget target, Stream output)
at SvnPreCommitHook.Program.Main(String[] args)
I have tried to do the svn.Write command from my own machine, pointing to svn://svn-server instead of localhost - and that works fine. I guess it is something on the server. TortoiseSVN is installed, although I don't see any context menus...
My code looks like this:
private static EventLog _serviceEventLog;
static void Main(string[] args)
{
_serviceEventLog = new EventLog();
if (!System.Diagnostics.EventLog.SourceExists("Svn Hooks"))
{
System.Diagnostics.EventLog.CreateEventSource("Svn Hooks", "Svn Hooks");
}
_serviceEventLog.Source = "Svn Hooks";
_serviceEventLog.Log = "Svn Hooks";
SvnHookArguments ha;
if (!SvnHookArguments.ParseHookArguments(args, SvnHookType.PreCommit, false, out ha))
{
/*Console.Error.WriteLine("Invalid arguments");
Environment.Exit(1);*/
}
using (SvnLookClient cl = new SvnLookClient())
{
SvnChangeInfoEventArgs ci;
cl.GetChangeInfo(ha.LookOrigin, out ci);
if (!ci.LogMessage.Equals("Svn Hook Test"))
{
AllowCommit();
return;
}
var checkoutDir = #"C:\SvnTemp\" + DateTime.Now.Ticks.ToString();
foreach (SvnChangeItem i in ci.ChangedPaths)
{
var checkoutFilepath = checkoutDir + "\\" + Path.GetFileName(i.Path);
if (!Directory.Exists(checkoutDir))
{
Directory.CreateDirectory(checkoutDir);
}
using (SvnClient svn = new SvnClient())
{
using (StreamWriter sw = new StreamWriter(checkoutFilepath))
{
svn.Write(SvnTarget.FromString("svn://localhost/" + i.RepositoryPath), sw.BaseStream);
}
}
var fileContents = File.ReadAllText(checkoutFilepath);
if (fileContents.Contains("Martin Normark"))
{
RemoveTempDirectory(checkoutDir);
PreventCommit("Name is not allowed!");
}
}
RemoveTempDirectory(checkoutDir);
}
AllowCommit();
}
Maybe one of the following:
64bit vs 32 bit
vcredist missing on the server
Maybe you should first catch the thrown exception by using the HandleProcessCorruptedStateExceptionsAttribute:
[HandleProcessCorruptedStateExceptions]
static void Main() // main entry point
{
try
{
}
catch (Exception ex)
{
// Handle Exception here ...
}
}

C# Keeping Pipes Open

I've Got two Programs (Server / Client)
I'm trying to setup IPC for them (They both run on the same box)
Using System.IO.Pipes & Net 3.5
When I call ComOpen, it opens the Pipe correctly, sends the Process ID to the server, but then the Pipe closes and I get an error when it tries to send "Second Write Test"
So Question is.
How do I keep the Pipe open for the Life of the Program?
(I use the Process ID on the server to close everything down if the Client crashes)
private static StreamWriter MyWriter;
private static StreamReader MyReader;
private static NamedPipeClientStream IPCPipe = new NamedPipeClientStream(".", "MyPipe", PipeDirection.InOut);
public static bool MyWrite(string DataOut)
{
bool ValidPipeOut = false;
if(ValidComPort)
try
{
// Send Data
using (QstWriter = new StreamWriter(IPCPipe))
{
QstWriter.AutoFlush = true;
QstWriter.WriteLine(QstDataOut);
QstWriter.Close();
QstWriter.Dispose();
}
ValidPipeOut = true;
}
catch
{
ValidPipeOut = false;
}
return ValidPipeOut;
}
public static bool ComOpen()
{
ValidComPort = true;
try { IPCPipe.Connect(1000); }
catch (Exception ex)
{
string Erroris;
Erroris = ex.Message;
if (Erroris == "Already in a connected state.")
{
// We're Already Connected, Ignore this error.
ValidComPort = true;
}
else
{
ValidComPort = false;
MessageBox.Show(Erroris);
}
}
if (ValidComPort)
{
string ClientProcessID = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
MyReader = new StreamReader(IPCPipe);
ValidComPort = MyWrite(ClientProcessID);
ValidComPort = MyWrite("Second Write Test");
}
return ValidComPort;
}
The problem is the following line:
using (QstWriter = new StreamWriter(IPCPipe))
At the end of the using statement, the StreamWriter will be disposed and that will in turn dispose the IPCPipe. You are also explicitly calling Dispose and Close on QstWriter, which will close the pipe too.
To fix this, remove the using statement and the calls to Dispose and Close on QstWriter. And assign+initialize QstWriter only once.

Categories