[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

C#  ProcessStart - How to automatically press the Y key

Posted on 2011-05-07
21
Medium Priority
?
4,919 Views
Last Modified: 2012-05-11
Hi.. I'm using ProcessStart to automatically run an external process. I need to press the Y key after about a second to continue the process.  The process runs in DOS and I need to 'Accept' a message.  How can I press the Y key automatically here is my existing code.  thanks

  ProcessStartInfo _psi = new ProcessStartInfo("pgp.exe");
                _psi.WorkingDirectory = "C:\";
                _psi.RedirectStandardInput = true;
                _psi.RedirectStandardOutput = true;
                _psi.RedirectStandardError = true;

                _psi.CreateNoWindow = false;

                 _psi.Arguments = " -e  test.txt  public.asc  myEmail +force  ";

                 System.Diagnostics.Process proc = System.Diagnostics.Process.Start(_psi);

                 System.IO.StreamReader output = proc.StandardOutput;

             
                 // Attach the in for writing
                 System.IO.StreamWriter sIn = proc.StandardInput;

       
                 // Write each line of the batch file to standard input
                 while (output.Peek() != -1)
                 {
                               /// Need to press the enter key after the message in dos window

                     sIn.WriteLine(output.ReadLine());
                 }
0
Comment
Question by:JElster
  • 8
  • 8
  • 2
  • +2
21 Comments
 
LVL 11

Expert Comment

by:saragani
ID: 35712601
You can try using this:

http://inputsimulator.codeplex.com/

0
 
LVL 14

Expert Comment

by:systan
ID: 35712669
How about;
SendKeys.Send("{Y}");
0
 
LVL 18

Expert Comment

by:dj_alik
ID: 35712709
SendKeys only work with windows applications
You  redirected stdin so your can write strings to a stream and the console
will read it from std in like normal

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:JElster
ID: 35713034
What?
0
 
LVL 18

Expert Comment

by:dj_alik
ID: 35713065
something like this:

sIn.WriteLine("Y");
sIn.Flush();      

Open in new window

0
 
LVL 11

Expert Comment

by:saragani
ID: 35713177
If SendKeys.Send("{Y}") doesn't help you then try the InputSimulator.
The InputSimulator should also solve your problem.
0
 
LVL 33

Accepted Solution

by:
Todd Gerbert earned 2000 total points
ID: 35713594
You can redirect the StandardInput and StandardOutput of a child process, so that instead of getting it's input from the keyboard the process will get it's input from whatever you write to it's StandardInput (which is a StreamWriter); and instead of showing it's output on the screen it sends it's output to Process.StandardOutput, which you can read from.

This is preferred because instead of just guessing at how long to wait you can read what the program's outputting, so you can wait until you see the confirmation prompt before sending input - and will let you detect error conditions (e.g. if the child process outputs "File Not Found" you can read that and know what happened instead of just blindly sending input).

using System;
using System.Diagnostics;
using System.Text;

class Program
{
	static void Main(string[] args)
	{
		Process proc = new Process();
		// Run the command "del c:\temp" in a DOS window
		// This will show a confirmation prompt requiring 
		// us to send a "Y" to continue
		proc.StartInfo.FileName = "cmd.exe";
		proc.StartInfo.Arguments = @"/c del c:\temp\*";

		// Redirect standard input & output for the process
		// Instead of showing output on the screen and
		// taking input from the keyboard, we can read
		// the output from the process's proc.StandardOutput
		// and send input to proc.StandardInput, which
		// are System.IO.StreamWriter/StreamReader objects
		proc.StartInfo.RedirectStandardInput = true;
		proc.StartInfo.RedirectStandardOutput = true;

		// UseShellExecute must be false to redirect input/output
		proc.StartInfo.UseShellExecute = false;

		// Start the process
		proc.Start();

		// Use a StringBuilder to hold the program's output
		StringBuilder procOutput = new StringBuilder();

		// Read the process's output until we see the
		// "Are you sure?" prompt and then send a "Y"
		while (!proc.StandardOutput.EndOfStream)
		{
			// Read up to 1024 characters into the char[] array "buffer"
			char[] buffer = new char[1024];
			proc.StandardOutput.Read(buffer, 0, buffer.Length);

			// Append the chars we just read to the procOutput StringBuilder
			procOutput.Append(buffer);

			// Check if procOutput ends with "Are you sure (Y/N)?"
			if (procOutput.ToString().Contains("Are you sure (Y/N)?"))
			{
				// If so send "Y" and exit this loop
				proc.StandardInput.WriteLine("Y");
				break;
			}
		}

		// Now that we've sent the confirmation "Y" wait for the process to exit
		proc.WaitForExit();

		Console.WriteLine("The process finished with ExitCode: {0}", proc.ExitCode);
		Console.Write("Press any key to exit...");
		Console.ReadKey();
	}
}

Open in new window

0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35713599
You can also redirect StandardInput and not StandardOutput, wait for a second, and then write a "Y" to StandardInput - this is much simpler but has the downside that you might send the "Y" too early, and won't be able to know if something went wrong.

using System;
using System.Diagnostics;
using System.Text;
using System.Threading;

class Program
{
	static void Main(string[] args)
	{
		Process proc = new Process();
		// Run the command "del c:\temp" in a DOS window
		// This will show a confirmation prompt requiring 
		// us to send a "Y" to continue
		proc.StartInfo.FileName = "cmd.exe";
		proc.StartInfo.Arguments = @"/c del c:\temp\*";

		// Redirect standard input
		proc.StartInfo.RedirectStandardInput = true;

		// UseShellExecute must be false to redirect input
		proc.StartInfo.UseShellExecute = false;

		// Start the process
		proc.Start();

		// Wait a second
		Thread.Sleep(1000);

		// Write a "Y" to the process's input
		proc.StandardInput.WriteLine("Y");

		// Now that we've sent the confirmation "Y" wait for the process to exit
		proc.WaitForExit();

		Console.WriteLine("The process finished with ExitCode: {0}", proc.ExitCode);
		Console.Write("Press any key to exit...");
		Console.ReadKey();
	}
}

Open in new window

0
 
LVL 1

Author Comment

by:JElster
ID: 35716628
It appears I have to press ENTER after the Y.
How can I press ENTER.
thx again
0
 
LVL 1

Author Comment

by:JElster
ID: 35716665
The following does not help

  proc.StandardInput.WriteLine("Y");
                         proc.StandardInput.WriteLine();
                         proc.StandardInput.Flush();


Still requires a manual enter

????????
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35717054
Post your code.
0
 
LVL 1

Author Comment

by:JElster
ID: 35717112
 ProcessStartInfo _psi = new ProcessStartInfo("pgp.exe");
                _psi.WorkingDirectory = ConfigurationSettings.AppSettings["UpLoadLocation"];
                _psi.UseShellExecute = false;
                _psi.RedirectStandardInput = true;
                _psi.RedirectStandardOutput = true;
                _psi.RedirectStandardError = true;

                _psi.CreateNoWindow = false;

                 _psi.Arguments = " -e " + _zipFile + "  MYKEY.asc  MYEMAIL   +force  ";

                 System.Diagnostics.Process proc = System.Diagnostics.Process.Start(_psi);

                 StringBuilder procOutput = new StringBuilder();

                 // Read the process's output until we see the
                 // "Are you sure?" prompt and then send a "Y"
                 while (!proc.StandardOutput.EndOfStream)
                 {
                     // Read up to 1024 characters into the char[] array "buffer"
                     char[] buffer = new char[1024];
                     proc.StandardOutput.Read(buffer, 0, buffer.Length);

                     // Append the chars we just read to the procOutput StringBuilder
                     procOutput.Append(buffer);

                     // Check if procOutput ends with "Are you sure (Y/N)?"
                     if (procOutput.ToString().Contains("(y/N)?"))
                     {
                         // If so send "Y" and exit this loop
                         proc.StandardInput.WriteLine("Y");
                         proc.StandardInput.WriteLine();
                         proc.StandardInput.Flush();
                         break;
                     }
                 }

                 // Now that we've sent the confirmation "Y" wait for the process to exit
                 proc.WaitForExit();
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35720288
Does pgp.exe not have a command line to suppress confirmation prompts?  There should be a BATCHMODE option, intended specifically for this purpose...
0
 
LVL 1

Author Comment

by:JElster
ID: 35720354
I think it does... checking now.......
thx!
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35720408
Maybe --force?
0
 
LVL 1

Author Comment

by:JElster
ID: 35720452
I'm doing a force and batchmode... get a Encryption error.......  

Says it skipping the Y/N but get an encryption error...
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35720491
I'm not particularly familiar with PGP - are you sure the rest of the command line is correct? Are you testing it in a cmd window by hand before trying to run it in your C# code?
0
 
LVL 1

Author Comment

by:JElster
ID: 35720516
Yes.. that's exactly what I've been doing
thx
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35720916
Well, if that switch doesn't work out for you I've updated the code slightly to be more accurate:

ProcessStartInfo _psi = new ProcessStartInfo("pgp.exe");
_psi.WorkingDirectory = ConfigurationSettings.AppSettings["UpLoadLocation"];
_psi.UseShellExecute = false;
_psi.RedirectStandardInput = true;
_psi.RedirectStandardOutput = true;
_psi.RedirectStandardError = true;

_psi.CreateNoWindow = false;

_psi.Arguments = " -e " + _zipFile + "  MYKEY.asc  MYEMAIL   +force  ";

System.Diagnostics.Process proc = System.Diagnostics.Process.Start(_psi);

StringBuilder procOutput = new StringBuilder();

// Read the process's output until we see the
// "Are you sure?" prompt and then send a "Y"
while (!proc.StandardOutput.EndOfStream)
{
	// Read up to 1024 characters into the char[] array "buffer"
	char[] buffer = new char[1024];
	// Store the number of characters actually read
	// (since it will undoubtedly be less than 1024)
	int charsRead = proc.StandardOutput.Read(buffer, 0, buffer.Length);

	// Append the chars we just read to the procOutput StringBuilder
	// Use "charsRead" to only append the part of the buffer[] array
	// that was filled, otherwise we'd end up appending a couple
	// characters that Read() filled followed by a bunch of nulls
	procOutput.Append(buffer, 0, charsRead);

	// Check if procOutput ends with "Are you sure (Y/N)?"
	if (procOutput.ToString().Contains("(y/N)?")) // Make sure this is actually "(y/N)?" and not "(y/N) ?"
	{
		// If so send "Y" and exit this loop
		proc.StandardInput.WriteLine("Y");
		proc.StandardInput.WriteLine();
		proc.StandardInput.Flush();
		break;
	}
}

// Now that we've sent the confirmation "Y" wait for the process to exit
proc.WaitForExit(); 

Open in new window


Making that batch mode work is your best bet, though.
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 35720925
...You can also omit lnes 37 & 38 in that example (the WriteLine method automatically appends a CRLF).
0
 
LVL 1

Author Comment

by:JElster
ID: 35720944
I think the issue is that I'm using an old PGP exe and the batchmode sucks...
Will try with a new PGP exe.. thanks for you help
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question