C # -C Межпроцессное взаимодействие - PullRequest
2 голосов
/ 01 марта 2011

Хорошо, у меня есть программа, написанная на c #, которая запускает процесс, выполняющий другую программу, написанную на C. Теперь я уже разработал перенаправление stdout из программы C и поднял его на стороне C #, и это прекрасно работает Но мне нужен способ, чтобы программа на C # сказала программе на C завершиться. Сначала я подумал, что, поскольку программа на C изначально контролировалась посредством тестирования kbhit из conio.h, я мог просто перенаправить stdin и выполнить потоковую запись чего-либо, и это обнаружило бы нажатие клавиши, но это не сработало (я предполагаю, что kbhit не поддается перенаправлению), поэтому я искал вокруг, и многие люди продолжали предлагать PeekConsoleInput (), потому что я пишу эту программу исключительно для Windows (на самом деле для конкретной машины). Поэтому я изменил программу на c, чтобы использовать PeekConsoleInput вместо kbhit и перенаправить стандартный ввод, и он все еще не обнаружил ничего, что я ему отправил. Например, в C ...

#include <stdio.h>
#include <windows.h>
int main() {
    BOOL peeked = 0;
    HANDLE input_handle = GetStdHandle(STD_INPUT_HANDLE);
    DWORD events = 0;      // how many events took place
    INPUT_RECORD input_record;  // a record of input events
    DWORD input_size = 1;    // how many characters to read
    printf("Hello World\n");
    fflush(stdout);
    while (1) {
        FlushConsoleInputBuffer(input_handle);
        peeked = PeekConsoleInput(input_handle, &input_record, input_size, &events);
        if (peeked && events>0) {
            break;
        }
    }
    printf("Hit Detected\n");
    return 0;
}

и фрагмент кода C # ...

ProcessStartInfo info = new ProcessStartInfo("CTest.exe");
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardInput = true;
pro = new Process();
pro.StartInfo = info;


pro.Start();
StreamWriter sw = pro.StandardInput;
sw.AutoFlush = true;
pro.BeginOutputReadLine();
pro.OutputDataReceived += new DataReceivedEventHandler(pro_OutputDataReceived);
sw.WriteLine("Q");

Программа на C выполняется сама по себе, но когда она запускается программой на C #, она никогда не достигает «Обнаружено попадание». Я также задержал s.WriteLine ("Q") на несколько секунд, чтобы посмотреть, не была ли это проблема синхронизации, и она все еще не работала.

В идеале я хотел, чтобы программа C могла запускаться сама по себе или запускаться программой C #, но даже если вы не можете запустить программу C самостоятельно, это было бы не так плохо.

Одна вещь, которую я попробовал, это сработало: программа C # просто записывала файл, а программа C просто опрашивала fopen до тех пор, пока она успешно не открывала его, но одна из основных целей этой программы C - писать в данные на диск очень быстрые, и я беспокоюсь, что опрос диска может замедлить его работу.

Еще одна вещь, которая вроде как работала, это просто закрытие процесса. Но это грязно, потому что программе на C нужно очистить некоторые вещи перед закрытием (если только нет способа заставить программу на C выполнить некоторый код, прежде чем она закроется, но я не уверен, что вы можете это сделать).

Другими способами сделать это были бы сокеты, каналы и т. Д., Но кажется, что для однобитового сигнала требуется много работы. Кроме того, все примеры, которые я мог найти о том, как это сделать, казалось, все, как заставить две программы на C # общаться или как заставить общаться две программы на C, никогда не две разные программы на двух разных языках.

Итак, во-первых, есть ли способ заставить работать перенаправление stdin? и если нет, то как проще всего сообщить процессу C, что ему нужно выйти?

Ответы [ 3 ]

1 голос
/ 14 июля 2011

Я столкнулся с той же проблемой и смог заставить ее работать, используя SendKeys . Просто добавьте ссылку на System.Windows.Forms, если у вас есть приложение WPF.

Для процессов StartInfo Я использовал:

newProcess.StartInfo.UserShellExecute = false; 
newProcess.StartInfo.CreateNoWindow = false;
newProcess.StartInfo.RedirectStandardInput = false;
newProcess.StartInfo.RedirectStandardOutput = true; 
newProcess.StartInfo.RedirectStatndardError = true; 
newProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
newProcess.OutputDataReceived += new DataReceivedHandler(gotData);

Причиной установки CreatNoWindow в false является то, что вы можете найти окно в Spy ++. ProcessWindowStyle.Hidden скрывает окно после его кратковременного всплытия.

RedirectStatndardInput должно быть ложным, потому что мы используем SendKeys для имитации ввода с клавиатуры в скрытое окно.

Использование SendKeys.waitSend("command{ENTER}"); Мне удалось отправить команду консольному приложению, которое использует _kbhit() и getc() для ввода.

0 голосов
/ 22 декабря 2012

Вы можете использовать объект Process для уничтожения порожденного процесса: (при условии, что программа C имеет обработчик для очистки после получения сигнала «CloseMainWindow ()»)

/// <summary>
/// Close the shelled process, if there is any
/// </summary>
/// <param name="reason">why closing?</param>
public static void shellTerminate(string reason)
{
    Process p = shelledProcess;

    try
    {
        if (p == null)
        {
            o3(reason + ". No shelled process.");
        }
        else if (p.HasExited)
        {
            o3(reason + ". Process has exited already.");
        }
        else
        {
            //Process is still running.
            //Test to see if the process is hung up.
            if (p.Responding)
            {
                //Process was responding; close the main window.
                o3(reason + ". Process is being closed gracefully.");
                if (p.CloseMainWindow())
                {
                    //Process was not responding; force the process to close.
                    o3(reason + ". Process is being killed.");
                    p.Kill();
                    p.Close();
                    p = null;
                }
            }

            if (p != null)
            {
                //Process was not responding; force the process to close.
                o3(reason + ". Process is being killed.");
                p.Kill();
            }

            p.Close();
        }

        if (shellOut != null)
        {
            shellOut.Close();
            shellOut = null;
        }

        shelledProcess = null;
    }
    catch (Exception ex)
    {
        o("Exception in shellTerminate: " + ex.Message);
    }
}
0 голосов
/ 01 марта 2011

Вы пытались выяснить, насколько программа C работает быстрее при записи файлов?

Существуют и другие способы (в Windows) межпроцессного взаимодействия.

  1. Именованные каналы (аналогично TCP)
  2. Файлы с отображением в памяти (может быть хорошим вариантом здесь - похоже на ваш другой эксперимент, который работал)
  3. TCP / IP (как вы предложили).

Что касается TCP / IP, он не ограничен работой со сборкой программного обеспечения с использованием того же языка и инструмента. Ваша C-программа будет TCP-сервером, а C # -программа будет TCP-клиентом. Если вы знаете, как это сделать на одном из языков, вы получите ответ.

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