2

I'm trying to do this:

        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;

        p.StartInfo = info;
        p.Start();

        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine("git config --global user.name \"My Name\"");
                sw.WriteLine("git config --global user.email \"my email\"");
                sw.WriteLine("call start-ssh-agent");
                sw.WriteLine("ssh-add c:\\temp\\ServerPull.ppk");
                System.Threading.Thread.Sleep(10000);
                sw.WriteLine(Environment.NewLine);
                sw.WriteLine("git clone git@github.com:myrepo");
            }
        }

        Console.WriteLine("Done");
    }

Problem is that the "ssh-add" command wants a passphrase entering, and I can't make C# enter it. Any other commands after the Thread.Sleep go into the buffer until I actually enter something on the CMD box myself.

Console.Writeline() outputs into that same box, but it doesn't actually get "entered"

Edit: For clarity, I'm not looking to do a Console.ReadLine() or actually get input from a user. The commands are how I need them, but I need to automatically send a string to another application (ssh-add) that is asking for a passphrase. Writing the passphrase through sw.WriteLine does not work as the console wont execute any code if it's waiting for input.

EDIT: In writing my first edit, I had a eureka moment on some code suggestions from the comments. Ended up with this now:

    const int VK_RETURN = 0x0D;
    const int WM_KEYDOWN = 0x100;

    static void Main(string[] args)
    {
        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;

        p.StartInfo = info;
        p.Start();

        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine("git config --global user.name \"my name\"");
                sw.WriteLine("git config --global user.email \"my email\"");
                sw.WriteLine("call start-ssh-agent");

                var enterThread = new Thread(
                    new ThreadStart(
                        () =>
                        {
                            Thread.Sleep(10000);
                            var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
                            PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
                        }
                        ));

                enterThread.Start();
                sw.WriteLine("ssh-add c:\\temp\\ServerPull.ppk");
                sw.WriteLine("git clone myrepo");
                sw.WriteLine("ping 127.0.0.1");
            }
        }

        Console.WriteLine("Done");
    }

    [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
    private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

which sends the enter key after a delay. I should be able to modify this from there to send in whatever I need.

Craig
  • 474
  • 7
  • 21

3 Answers3

1

I think you can use args[] of the main method. See the sample below.

public class CommandLine

{

public static void Main(string[] args)

{

Process p = new Process();
    ProcessStartInfo info = new ProcessStartInfo();
    info.FileName = "cmd.exe";
    info.RedirectStandardInput = true;
    info.UseShellExecute = false;

    p.StartInfo = info;
    p.Start();

    using (StreamWriter sw = p.StandardInput)
    {
        if (sw.BaseStream.CanWrite)
        {
            sw.WriteLine(string.Format("git config --global user.name {0}",args[0]));
            sw.WriteLine(string.Format("git config --global user.email {0}",args[1]));
            sw.WriteLine("call start-ssh-agent");
            sw.WriteLine(string.Format("ssh-add {0}",args[2]));  
            System.Threading.Thread.Sleep(10000);
            sw.WriteLine(Environment.NewLine);
            sw.WriteLine("git clone git@github.com:myrepo");
        }
    }

    Console.WriteLine("Done");
}}

Execute your exe and in command line use arguments:

x:\> yourapp.exe user2645643 xyx@yourdomain.com c:\temp\ServerPull.ppk

Update

Then its quite simple. Use var inp = Console.ReadLine() and place you input variable wherever you want.

  • 1
    The problem isn't getting arguments in, it's that the ssh-add wants input from something like Console.ReadLine(). As in, it sits there waiting for me to press Enter, so I need to press enter somehow. The actual commands going to CMD are fine. – Craig Jan 08 '14 at 10:52
1

This works fine for Keying in Command Prompt

        foreach (var v in message)
        {
            PostMessage(cmdProcess.MainWindowHandle, WM_CHAR, (IntPtr)v, IntPtr.Zero);
        }

        PostMessage(cmdProcess.MainWindowHandle, WmKeyUp, (IntPtr)Keys.Enter, IntPtr.Zero);
Malathy S
  • 11
  • 1
0

I think you can do this ,..

https://stackoverflow.com/a/9634490/3156689

This link Explains howto send return key to Console .. It is better than simulating keypresses or closing stdin stream

Community
  • 1
  • 1
spetzz
  • 679
  • 8
  • 19
  • Getting the same behavior. Using the same code and tried setting var hWnd = p.MainWindowHandle; – Craig Jan 08 '14 at 10:50
  • Figured it out based on this in the end. Updated the question with relevant changes. – Craig Jan 08 '14 at 11:06