NET VIEW behaves differently when used with Process.Start() - c#

I use net.exe in my program to view all computers in a workgroup.
The code is as follows:
var net = new Process();
net.StartInfo.FileName = "net.exe";
net.StartInfo.CreateNoWindow = true;
net.StartInfo.Arguments = #"VIEW /DOMAIN:my-workgroup";
net.StartInfo.RedirectStandardOutput = true;
net.StartInfo.UseShellExecute = false;
net.StartInfo.RedirectStandardError = true;
net.Start();
The command works fine when I execute in a shell, but when I use the shown code, the command returns the device is not connected.
I also tried running the program as administrator, that makes no difference.
The domain name specified is actually a workgroup.
For net.exe running in the shell specifying a workgroup works fine.
Furthermore the code also works when I try a net view for a different domain. So there must be some difference in the environment when I run the command from the shell or with Process.Start().
What would be the reasons for the command to behave differently in the shell and with Process.Start()?

I don't know if it will solve what you're looking for, but this works for me;
You need to hook into the capture the output to bring it to the console
class Program
{
static void Main(string[] args)
{
var net = new Process()
{
StartInfo = new ProcessStartInfo("net.exe", #"view /domain:domain")
{
RedirectStandardOutput = true,
UseShellExecute = false,
},
};
net.OutputDataReceived += WriteToConsole;
net.ErrorDataReceived += WriteToConsole;
net.Start();
net.BeginOutputReadLine();
net.WaitForExit();
Console.ReadLine();
}
private static void WriteToConsole(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}
}

Related

Running VM tests with GitLab Pipelines

I have a problem with running in VM tests using Gitlab Pipeline (Windows Server 2019).
I want to specify that when I run manually in a VM, everything works perfectly.
When I run in the GitLab Pipeline, methods like opening applications (Process.Start ("src")), closing applications from code do not work.
Code of methods for deleting processes and opening processes:
public static void KillProc(string processName)
{
Process[] processes= Process.GetProcessesByName(processName);
foreach (Process process in processes)
{
process.Kill();
process.WaitForExit();
process.Dispose();
}
}
public static void StartProcess(string appName, string path, string argument ="")
{
var task = new Process
{
UseShellExecute = true;
FileName = appName;
Arguments = argument;
CreateNoWindow = false
WorkingDirectory = path + "/" + appName;
}
task.Start();
}
What do you recommend me to do? I would need to be able to use at least the process opening functions, I want to mention that if I want to open the same application twice with StartProcess, only one application with GitLab Pipeline opens

Execute commands from command prompt in c# web application

I have a C# web application in which I want to execute Unix commands one by one. I want the command prompt window to appear and then after each command execution , move to the next command and then exit the window. I have tried the below, but the command prompt window does not appear and the commands are not getting executed after each wait
public void connecterOne()
{
try
{
using (Process p = new Process())
{
// set start info
p.StartInfo = new ProcessStartInfo("cmd.exe")
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
WorkingDirectory = #"c:\"
};
// event handlers for output & error
p.OutputDataReceived += p_OutputDataReceived;
p.ErrorDataReceived += p_ErrorDataReceived;
// start process
p.Start();
// send command to its input
p.StandardInput.Write("ftp server" + p.StandardInput.NewLine);
p.StandardInput.Write("username" + p.StandardInput.NewLine);
p.StandardInput.Write("pwd" + p.StandardInput.NewLine);
string output = p.StandardOutput.ReadToEnd();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
static void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Process p = sender as Process;
if (p == null)
return;
Console.WriteLine(e.Data);
}
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Process p = sender as Process;
if (p == null)
return;
Console.WriteLine(e.Data);
}
How to execute commands one by one and have the command prompt window open which shows the commands being executed. I am not getting any errors, but there is no output seen.
This is a security issue A web application has no access to user pc command prompt ,
A web application deployed on IIS on web server not on user pc.
If you run a process it will execute on that server but you need to allow server to execute these commands.But I think it is bad practice.
To execute a command on a remote Linux based machine, you need to connect first with ssh. For C#, you can use the SSH.NET
Also, this article might help you.

C# Get standard input/output/error of running, NOT child process

My question is pretty simple: how do I get the standard output/input/error of a process I did not start? Let's say I have some program (that is not mine) XYZ that runs all day and prints things to stdout. I want to be able to start my C# application and start reading XYZ's output. Then close my C# application and restart it 2 hours later and continue reading the output (not necessarily where I left off but that would be a plus).
I know this can be achieved if XYZ is a child process of mine with
serverProcess = Process.Start(new ProcessStartInfo()
{
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
WorkingDirectory = WorkingDir,
Arguments = Args,
FileName = "XYZ",
UseShellExecute = false
});
serverProcess.OutputDataReceived += serverProcess_OutputDataReceived;
serverProcess.ErrorDataReceived += serverProcess_OutputDataReceived;
serverProcess.BeginOutputReadLine();
serverProcess.BeginErrorReadLine();
But this is not the case since XYZ is is completely independent of my application, and needs to keep running regardless of what I do to it.
It is worth noting that (if it helps) I can start XYZ myself (with those redirection parameters). It's just that my lifecycle needs to be completely independent of XYZ, and I need to be able to "reattach" after I relaunch.
I have seen some suggestions using Get/SetStdHandle but most of them claimed to not work, and I din't quite understand how to apply them anyways.
Thanks for any advice!
It is worth noting that (if it helps) I can start XYZ myself (with those redirection parameters). It's just that my lifecycle needs to be completely independent of XYZ, and I need to be able to "reattach" after I relaunch.
Here is a simple implementation of what I suggested in the comments (publishing data through an intermediary process).
basicaly the sample is composed of 3 main parts
1. Sample XYZ Process
which in our case, is a simple console application that spits a Hello from XYZ message every second.
class Program
{
static void Main(string[] args)
{
var count = 0;
while (true)
{
Console.WriteLine("Hello from XYZ "+count);
count++;
Thread.Sleep(1000);
}
}
}
2. Intermediary Process
which should start XYZ and redirect its output to itself and then publish it through. for publishing part we use ZeroMQ library here that can be obtained easily from nuget.
class Program
{
private static Socket _pub;
static void Main(string[] args)
{
using (var context = new Context())
{
_pub = context.Socket(SocketType.PUB);
_pub.Bind("tcp://*:2550");
StartXyz();
Console.WriteLine("Press any key to close middle process...");
Console.ReadKey();
}
}
private static void StartXyz()
{
var serverProcess = Process.Start(new ProcessStartInfo
{
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory,
Arguments = string.Empty,
FileName = "XYZ.exe",
UseShellExecute = false
});
serverProcess.OutputDataReceived += serverProcess_OutputDataReceived;
serverProcess.ErrorDataReceived += serverProcess_OutputDataReceived;
serverProcess.BeginOutputReadLine();
serverProcess.BeginErrorReadLine();
}
private static void serverProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
_pub.Send(e.Data, Encoding.UTF8);
Console.WriteLine(e.Data + " pushed.");
}
}
3. Consumer Process
and finally we have our process, which consumes redirected data from XYZ.
class Program
{
static void Main(string[] args)
{
using (var context = new Context())
{
var sub = context.Socket(SocketType.SUB);
sub.Connect("tcp://localhost:2550");
sub.Subscribe(string.Empty, Encoding.UTF8);
while (true)
{
var data = sub.Recv(Encoding.UTF8);
Console.WriteLine(data);
}
}
}
}

C# input/output with another console application

I'm trying to build a c# program that will pass string to an existing console application and will get back string after it is done processing.
Here is how I would want it to work:
public void InitializeUtil(List<object> items)
{
Process DataValidationUtilitty = new Process();
DataValidationUtilitty.StartInfo.FileName = Configuration.DVUTIL;
DataValidationUtilitty.StartInfo.CreateNoWindow = false;
DataValidationUtilitty.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
DataValidationUtilitty.StartInfo.RedirectStandardInput = true;
DataValidationUtilitty.StartInfo.RedirectStandardOutput = true;
DataValidationUtilitty.StartInfo.RedirectStandardError = true;
DataValidationUtilitty.StartInfo.UseShellExecute = false;
DataValidationUtilitty.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
DataValidationUtilitty.ErrorDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
DataValidationUtilitty.Start();
DataValidationUtilitty.BeginOutputReadLine();
DataValidationUtilitty.StandardInput.WriteLine(items[0].ToString());
}
public void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine.Data.ToString());
}
// And I call
Program ThisProgram = new Program();
ThisProgram.InitializeUtil(items);
For some obvious reasons this does not work and I don't know why.
Here is a working example:
I have here executable with DLL that it needs
I have an input string in document.json file
I have a .bat file that will run this executable
Run the program and pass document.json as input string
Pause execution to see the results
Get back correct string
What am I missing here, what don't I understand about this process? I was assured from dvutils.exe developers that program does std input,output,error.

Sending commands to cmd prompt in C#

For one of my implementations I am working on a tool that is supposed to send/retrieve commands/results to/from the cmd window. Everything works fine but the Use case below fails to do anything. It seems as if my application is waiting for something (instead of displaying the result)
From my tool I navigate to the python folder . From the python folder I try to launch python.exe but at this point, my editor does not do anything. it simply keeps on waiting.
For your kind consideration I am also linking the video here. It would be easier for you guys to understand what I am trying to say.
View the Video here (on youtube)
I am also attaching the code that I currently have.
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
string argument = null;
if (!string.IsNullOrEmpty(startingDirectory) && System.IO.Directory.Exists(startingDirectory))
{
argument += #"cd\";
}
else
{
argument += "\"";
}
info.Arguments = argument;
info.CreateNoWindow = true;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
this.shellProcess = System.Diagnostics.Process.Start(info);
this.shellProcess.EnableRaisingEvents = true;
//this.InputStream.AutoFlush = true;
this.shellProcess.Exited += new EventHandler(ProcessExited);
this.ErrorBeginRead();
this.OutputBeginRead();
private void OutputBeginRead()
{
this.shellProcess.StandardOutput.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, new AsyncCallback(this.OnOutputInput), this.shellProcess);
}
private void ErrorBeginRead()
{
this.shellProcess.StandardError.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, new AsyncCallback(this.OnErrorInput), this.shellProcess);
}
Thank you !
EDIT:
Launching python is just an example. I need to use the same method for other normal cmd line commands as well.It would be nice, if somebody can point what i am doing wrong with the code that I have or what I must do , in order to achieve the intended functionality.
EDIT 2 : The normal cmd commands are working perfectly. The command line tools like python,perl are not working .
Edit 3 : So I managed to do move a wee bit forward following Jamie's suggestions. The ui is not "hanging" anymore. but when i access the python interpreter , the interpreter's output is still not visible in my tool. Any suggestions why that might be happening ?
You cannot send commands to a shell this way. The string in info.Arguments is the arguments provided to the program on the command line. If you want the cmd.exe shell to execute a series of command and then quit you will have to provide the /c argument. If you have multiple commands that you want it to perform you will either have to put the commands in a batch file and execute that or enclose them in quotes and separate them with &&, i.e. info.Arguments = #"/c ""cd \ && dir""";. Your other issue with never returning is that cmd.exe opens in interactive mode by default when it is executed without any, or proper, arguments. The /c option tells cmd.exe to execute the relevant commands and then quit.
Additionally, interpreters like python and perl sometimes have weird behaviors when launched directly from ProcessStartInfo. If info.Arguments = #"""MyPerlProgram.pl"""; with perl.exe doesn't work, you may find it necessary to launch them inside cmd.exe to get normal behavior out of them, i.e. info.Arguments = #"/c ""perl.exe ""MyPerlProgram.pl""""";.
See Cmd and ProcessStartInfo.Arguments Property.
To answer your Edit 3 problem, you're probably not correctly hooking into the outputs. Instead of trying to hook the StreamReader's BaseStream, hook the OutputDataReceived event with this.shellProcess.OutputDataReceived += ProcessOutputHandler; before you call Start where ProcessOutputHandler has a signature like public static void ProcessOutputHandler(object sendingProcess, DataReceivedEventArgs outLine). Immediately after calling Start, call this.shellProcess.BeginOutputReadLine();. The process is similar for the error ouput as well. See Process.BeginOutputReadLine Method and Process.BeginErrorReadLine Method for more details.
If you still have a problem, what do you get if you just try process.StartInfo.Arguments = #"/c ""python.exe -c ""import sys; print 'Test.';""""";?
Also, the code below demonstrates most of the necessary concepts for shell communication:
public static void Main()
{
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.WorkingDirectory = #"C:\";
process.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "cmd.exe");
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardInput = true;
// Runs the specified command and exits the shell immediately.
//process.StartInfo.Arguments = #"/c ""dir""";
process.OutputDataReceived += ProcessOutputDataHandler;
process.ErrorDataReceived += ProcessErrorDataHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
// Send a directory command and an exit command to the shell
process.StandardInput.WriteLine("dir");
process.StandardInput.WriteLine("exit");
process.WaitForExit();
}
}
public static void ProcessOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine.Data);
}
public static void ProcessErrorDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine.Data);
}
You may have threading issues causing your problems. I've done some further work with this and was able to get a textbox on a form to update with the following code:
using System;
using System.Diagnostics;
using System.IO;
using System.Timers;
namespace DummyFormsApplication
{
class ProcessLauncher : IDisposable
{
private Form1 form;
private Process process;
private bool running;
public bool InteractiveMode
{
get;
private set;
}
public ProcessLauncher(Form1 form)
{
this.form = form;
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.WorkingDirectory = #"C:\";
process.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "cmd.exe");
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardInput = true;
process.OutputDataReceived +=new DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
process.Exited += new EventHandler(process_Exited);
}
public void Start()
{
if (running == false)
{
running = true;
InteractiveMode = true;
// Runs the specified command and exits the shell immediately upon completion.
process.StartInfo.Arguments = #"/c ""C:\python27\python.exe -i""";
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
}
public void Start(string scriptFileName)
{
if (running == false)
{
running = true;
InteractiveMode = false;
// Runs the specified command and exits the shell immediately upon completion.
process.StartInfo.Arguments = string.Format(#"/c ""C:\python27\python.exe ""{0}""""", scriptFileName);
}
}
public void Abort()
{
process.Kill();
}
public void SendInput(string input)
{
process.StandardInput.Write(input);
process.StandardInput.Flush();
}
private void process_OutputDataReceived(object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine.Data != null)
{
form.Invoke(form.appendConsoleTextDelegate, new object[] { outLine.Data });
}
}
private void process_ErrorDataReceived(object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine.Data != null)
{
form.Invoke(form.appendConsoleTextDelegate, new object[] { outLine.Data });
}
}
private void process_Exited(object sender, EventArgs e)
{
running = false;
}
public void Dispose()
{
if (process != null)
{
process.Dispose();
}
}
}
}
I created a form and added a textbox and the following code in the form:
public delegate void AppendConsoleText(string text);
public AppendConsoleText appendConsoleTextDelegate;
private void Form1_Load(object sender, EventArgs e)
{
appendConsoleTextDelegate = new AppendConsoleText(textBox1_AppendConsoleText);
using (ProcessLauncher launcher = new ProcessLauncher(this))
{
launcher.Start();
launcher.SendInput("import sys;\n");
launcher.SendInput("print \"Test.\";\n");
launcher.SendInput("exit()\n");
}
}
private void textBox1_AppendConsoleText(string text)
{
textBox1.AppendText(string.Format("{0}\r\n", text));
}
One thing to note is that if the Form1_Load event doesn't complete, Invoke will hang until it does. If you have long-running code in an event you'll either need to invoke asynchronously using BeginInvoke, or periodically call DoEvents in your long-running code.
EDIT
Per your comment, I've modified the code to work with interactive submissions. There is, however, a problem. The python prompt (>>>) is provided on the StandardError output and it does not echo the StandardInput. It also does not terminate the line. This makes detecting a prompt difficult and causes some out of order output of the prompt characters due to the process_ErrorDataReceived not firing until either the process ends or a line end is seen.
There's not enough code in your question to figure out exactly what your application is hanging on. There are some things in your code which look odd. For example, why are you starting your own error and output read loops instead of using the ones built into the Process class? Like this:
var shellProcess = System.Diagnostics.Process.Start(info);
shellProcess.EnableRaisingEvents = true;
shellProcess.Exited += ProcessExited;
shellProcess.OutputDataReceived += ShellProcess_OutputDataReceived;
shellProcess.ErrorDataReceived += ShellProcess_ErrorDataReceived;
shellProcess.BeginOutputReadLine();
shellProcess.BeginErrorReadLine();
void ShellProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
// Do Something
}
void ShellProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
// Do Something
}
Since your error and output async events are not firing, it leads me to believe that there might be a lifetime issue with the shellProcess. If you post more of your code, we can give better guidance.
I can't see all your code, but you can easily use Steam objects to write/send commands to the CMD Window created by you. e.g.:
StreamWriter inputStream = shellProcess.StandardInput;
//send command to cmd prompt and wait for command to execute with thread sleep
inputStream.WriteLine("echo "CMD just received input");
inputStream.Flush();
In the above example for instance, Command prompt will receive the echo command just like it was entered in the window. To show the output you will have to create StreamReader object and assign it to the process's StandardOutput.

Categories