Введите имя пользователя в процесс CMD - PullRequest
1 голос
/ 09 марта 2011

В моем приложении Winform я выполняю exe-файл, используя cmd Process. В exe-файле необходимо ввести имя пользователя и пароль в строке «Введите имя пользователя» и «Введите пароль». Я не могу ввести имя пользователя и пароль, каким-то образом процесс завершается только и не работает только. Я также добавил проверку ThreadState и WaitReason, но в процессе нет потоков. Мне тоже нужен выход. Если я печатаю вывод перед процессом ввода, то он не доходит до ввода, а если я помещаю ввод перед выводом, то и ввод не принимается или что-то в этом роде. Просто получайте выходные данные одинаково все время. Вот код:

        public bool StartOpenVPN()
    {
        bool installed = false;
        ProcessStartInfo processInfo = null;
        Process process = null;
        try
        {
            string command = "files\\openvpn --config files\\client.ovpn";
            Console.WriteLine("Command = " + command);

            processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardInput = true;
            processInfo.RedirectStandardOutput = true;
            Console.WriteLine("Opening cmd");

            process = new Process();
            process.StartInfo = processInfo;
            process.Start();

            StreamWriter sw = process.StandardInput;
            sw.WriteLine("foo");
            sw.WriteLine("*baa");
            sw.Flush();
            sw.Close();

            process.BeginOutputReadLine();
            process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);

            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Installing Tap Adapter : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }
        finally
        {
            processInfo = null;
            if (process != null)
            {
                process.Close();
                process = null;
            }
        }
        return installed;
    }

    private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        string d = e.Data;

        if (!string.IsNullOrEmpty(d))
        {
            Console.WriteLine("Line = " + d);
        }
    }

Единственный вывод, который я получаю:

Line = Wed Mar 09 12:33:00 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] built on Feb 17 2010
Line = Wed Mar 09 12:33:00 2011 ERROR: could not read Auth username from stdin
Line = Wed Mar 09 12:33:00 2011 Exiting

Почему он не принимает ввод или даже показывает строку «Введите имя пользователя» в выводе? Я не могу понять, где я иду не так, но кажется, что где-то идет не так. Пожалуйста, помогите мне с этой проблемой, я застрял плохо и перепробовал много раз и вещей, и провел много времени после этого.

Любая помощь высоко ценится.

Спасибо

@ Fun Mun: вот обновленный код. Это просто идет к process_Exited при получении любого потока ввода / вывода:

        private void initProcess()
    {
        processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
        processInfo.UseShellExecute = false;
        processInfo.RedirectStandardInput = true;
        processInfo.RedirectStandardOutput = true;
        processInfo.WindowStyle = ProcessWindowStyle.Normal;

        process = new Process();
        process.StartInfo = processInfo;
        process.Exited += new EventHandler(process_Exited);
        return;
    }

    void process_Exited(object sender, EventArgs e)
    {
        Console.WriteLine("Into process_Exited....");
        processInfo = null;
        if (process != null)
        {
            sw = null;
            process.Close();
            process = null;
        }
    }

    public bool StartOpenVPN()
    {
        bool installed = false;
        try
        {
            Console.WriteLine("Command = " + command);

            Console.WriteLine("Opening cmd");

            initProcess();
            process.Start();

            sw = process.StandardInput;
            Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString()); // RETURS FALSE BUT GOES TO process_Exited & for next line results is NullPointerException
            sw.WriteLine("foo");
            sw.WriteLine("*baa");
             //sw.Flush();
            //sw.Close();

            //process.BeginOutputReadLine();
            //process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
             while (process.HasExited == false)
             {
                 string d = process.StandardOutput.ReadLine();
                 Console.WriteLine("Line = " + d);
             }

            process.WaitForExit();
            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Opening : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }

        return installed;
    }

До процесса. BeginOutputReadLine (); Обработчик & output не был удален, он продолжал ждать (может быть для входа) как зависший. В тот момент, когда эти 2 выходные строки удалены и добавлен цикл while, процесс просто получает выход при любом вызове потока, т.е. process.StandardOutput; ИЛИ StandardInput, в зависимости от того, что идет дальше, и генерирует исключение NullPointerException. Я сделал какую-либо ошибку в коде, как вы указали?


@ Fun Mum: Даже после использования и обновления вашей отредактированной версии кода, я получаю то же самое. Я обновил ваш код, немного изменил его, увидев, что после вывода 1-й строки openvpn запрашивает имя пользователя и затем passowrd, тогда их нет. Я получаю правильные результаты консоли, но результаты не так, как ожидалось. Вот код:

        public bool StartOpenVPN()
    {
        bool installed = false;
        int lineNo = 0;
        try
        {
            Console.WriteLine("Command = " + command + "\nOpening cmd");

            initProcess();
            process.Start();

            sw = process.StandardInput;
            Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString());
            //sw.WriteLine("123b5df33f");
            //sw.WriteLine("*3FgYxyt");
            //Console.WriteLine("Has Exited after writing data = " + process.HasExited.ToString());

             while (process.HasExited == false)
             {
                 string d = process.StandardOutput.ReadLine();
                 Console.WriteLine("Line = " + d);
                 lineNo++;
                 if (lineNo == 1)
                 {
                     Console.WriteLine("Writing Details");
                     sw.WriteLine("foo");
                     sw.Flush();
                     Console.WriteLine("Wrote Username");
                     sw.WriteLine("*baa");
                     sw.Flush();
                     Console.WriteLine("Wrote Password");
                 }
             }

             process.Close();
             process = null;
            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Installing Tap Adapter : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }

        return installed;
    }

Вывод:

Command = files\openvpn --config files\client.ovpn

Открытие cmd Вышел после SW = False Line = Fri Mar 11 18:10:06 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] построен 17 февраля 2010 Написание подробностей // ПОСЛЕ 1-Й СТРОКИ ПИСЬМЕННО Написал имя пользователя Написал пароль Строка = пт 11 марта 18:10:06 2011 ОШИБКА: не удалось прочитать имя пользователя Auth из stdin Line = Fri Mar 11 18:10:06 2011 Выход Линия = Готовый cmd

Не удалось разобрать, если приложение не может правильно генерировать ввод в stdin или openvpn не может его принять. Я также попробовал sw.WriteLine ("foo" + ConsoleKey.Enter); это также дало те же результаты. Интересно и пытался увидеть окно cmd во время выполнения / отладки, чтобы узнать точные результаты, но также не смог увидеть это.

Если мы обычно запускаем openvpn через командную строку, мы получаем:

D:\>files\\openvpn --config files\\client.ovpn

Пт. 11 марта 18:03:48 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] bui 17 февраля 2010 г. Введите имя пользователя:

Действительно озадачен этим.

Ответы [ 3 ]

1 голос
/ 09 марта 2011

Вы фактически закрываете свой процесс в блоке finally.Попробуйте добавить process.WaitForExit(); перед Console.WriteLine("Finished cmd");

В качестве альтернативы, вы можете заменить process.BeginOutputReadLine(); на:

while (!process.HasExited)
{
    string d = process.StandardOutput.ReadLine();
    Console.WriteLine("Line = {0}", d);
}

Еще лучше подойти, чтобы сделать process переменной-членом, а нелокальная переменная.Просто переместите код в блоке finally в обработчик выхода из процесса:

void process_Exited(object sender, EventArgs e)
{
    // Code from finally here
}

Но вы должны не забыть добавить обработчик выхода:

process.Exited += new EventHandler(process_Exited);

В другой заметке, закрыввходной поток может вызвать некоторые проблемы.Попробуйте удалить следующие 2 строки, чтобы увидеть, что происходит

sw.Flush();
sw.Close();

Ниже приведена отредактированная версия вашего кода:

private void initProcess()
{
    processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
    processInfo.UseShellExecute = false;
    processInfo.RedirectStandardInput = true;
    processInfo.RedirectStandardOutput = true;
    processInfo.WindowStyle = ProcessWindowStyle.Normal;

    process = new Process();
    process.StartInfo = processInfo;
    //process.Exited += new EventHandler(process_Exited); // Actually no longer required, since HasExited will test for it
    // return; // return not required
}

// No longer need Exited, since HasExited checks for it
/*
void process_Exited(object sender, EventArgs e)
{
    Console.WriteLine("Into process_Exited....");
    processInfo = null;
    if (process != null)
    {
        sw = null;
        // Do not close here. Closing here will prevent "process.WaitForExit()" and "process.HasExited" from working
        //process.Close();
        //process = null;
    }
}
*/

public bool StartOpenVPN()
{
    bool installed = false;
    try
    {
        Console.WriteLine("Command = " + command);

        Console.WriteLine("Opening cmd");

        initProcess();
        process.Start();

        sw = process.StandardInput;
        Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString()); // RETURS FALSE BUT GOES TO process_Exited & for next line results is NullPointerException
        sw.WriteLine("foo");
        sw.WriteLine("*baa");
         //sw.Flush();
        //sw.Close();

        //process.BeginOutputReadLine();
        //process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
         while (process.HasExited == false)
         {
             string d = process.StandardOutput.ReadLine();
             Console.WriteLine("Line = " + d);
         }

        // process.WaitForExit(); // Not required, since HasExited already check whether process has exited
        // Added here from Exited, so that it only close after exit
        process.Close();
        process = null;
        Console.WriteLine("Finished cmd");
    }
    catch (Exception e)
    {
        Console.WriteLine("Errror Opening : " + e.Message);
        Console.WriteLine(e.StackTrace);
    }

    return installed;
}
0 голосов
/ 08 апреля 2011

Этот запрос был для меня неразрешимым, так как openvpn не поддерживал прием stdin из приложения.

Спасибо всем за помощь, идеи и предложения.

Спасибо.

0 голосов
/ 09 марта 2011

Вместо того, чтобы пытаться передать имя пользователя и пароль через командную строку, используйте переключатель OpenVPN --auth-user-pass [file], где [file] - все две строки:

user secretPassword

Я никогда не пробовал, но это то, о чем говорят документы.

То есть, вы открываете линию примерно так:

string command = "files\\openvpn --config files\\client.ovpn --auth-user-pass files\\TEMP-AUTH";

Просто не забудьтеудалите TEMP-AUTH, как только закончите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...