Вопрос

System.diagnostics.Process обнаруживает стригритера с именем StandardInput, который, насколько я знаю, принимает только символы.

Но мне также нужно отправить клавишные, а некоторые нажатия на несколько наметок не сопоставляются с символами.

Что я должен делать?

Это было полезно?

Решение

Вы смешиваете входные потоки с контрольными сигналами. Консольный процесс имеет поток ввода по умолчанию, который вы можете управлять со стандартным INTINPUT, как вы уже знаете. Но Ctrl-C и Ctrl-Break не являются символами, отправляемыми в процесс через этот поток, а вместо этого они вместо этого контрольные сигналы что процесс получает с использованием зарегистрированных обработчиков сигнала, см. CTRL+C и CTRL+Break Signals:

По умолчанию, когда окно консоли имеет фокус клавиатуры, CTRL+C или CTRL+Break рассматривается как сигнал (Sigint или SigBreak), а не как вход клавиатуры.

Чтобы отправить фальшивые сигналы в процесс, который вы можете использовать GenerateConsoleCtrlEvent и отправить тоже CTRL_C_EVENT или же CTRL_BREAK_EVENT. Анкет Этот API не имеет эквивалента .NET, поэтому вы должны его писать.

Чтобы использовать его из .net, вам просто нужно включить определение функции:

const int CTRL_C_EVENT = 0;
const int CTRL_BREAK_EVENT = 1;

[DllImport("kernel32.dll")]
static extern bool GenerateConsoleCtrlEvent(
    uint dwCtrlEvent,
    uint dwProcessGroupId);

Другие советы

Здесь найден симулятор ввода Кодеплекс что может сделать только работу для вас. Я работаю над образцом кода и в ближайшее время отправлюсь сюда, имейте в виду, что симулятор ввода похож на то, что было найдено в ссылке, поставляемой Remus ...

Редактировать: Я обнаружил, что есть ограничение с этим, вы определенно можете сойти с рук с типичными System.Windows.Forms.SendKeys.Send Метод, он работает эффективно! , но процесс должен иметь

  • Нет перенаправления потоков
  • Не может быть скрытое окно (именно здесь оно потерпит неудачу, так как ручка окна нигде не видно, ни в том же духе довести его на передний план, чтобы сделать его активным!)
  • Окно, показывающее процесс, чтобы это было эффективным!

В вашем случае это вопрос поиска окна, установить его активным через Pinvoke 'SetForegroundWindow' и отправьте последовательности ^{BREAK} который посылает сигнал CTRL+Break в процесс, который работает очень хорошо (особенно, если процесс является программой командной строки/файла партии). Вот статья о Кодепроект Это делает это точно и отражает Sendkeys ... Мне еще предстоит вставить в это какой -то код, чтобы продемонстрировать ...

РЕДАКТИРОВАТЬ № 2: На самом деле я очень удивлен ... Как покажет этот код (доказательство концепции) ... он использует:

  • Inputsimulator (как упоминалось ранее)
  • Форма Windows, которая состоит из кнопки, когда форма загружается, она автоматически запускает класс. Нажав кнопку, она публикует CTRL-перерыв в скрытый процесс
  • Выходной поток действительно перенаправляется и является скрытым окном.
  • Странная вещь-это то, что вывод захватывается, но не показывает результаты в окне отладки, в режиме реального времени он буферируется (я думаю), пока процесс не завершится, весь вывод показан ...
  • Я немного обманул на FindWindow Вызов API, потому что я знал, что название окна было и было каким -то образом, способным вывести его на передний план и использовать входнойсимулятор для отправки на него клавиш SendKeys функция ... причина, по которой у меня была Thread.Sleep для обеспечения того, чтобы нажатые клавишные были отправлены для того, чтобы «толкнуть в очередь клавиатуры« окно активного переднего плана », что, несмотря на это, скрыто»
  • Я использовал команду «NetStat -e 5», чтобы навсегда зацикливаться, обновляя результаты каждые 5 секунд, пока она не получит «Ctrl+C», чтобы сломать бесконечный цикл.
public partial class Form1 : Form
{
    private TestNetStat netStat = new TestNetStat();
    public Form1()
    {
       InitializeComponent();
       using (BackgroundWorker bgWorker = new BackgroundWorker())
       {
           bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
           bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
           bgWorker.RunWorkerAsync();
       }
    }

    void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       System.Diagnostics.Debug.WriteLine("BGWORKER ENDED!");
    }

    private void  bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
       netStat.Run();
    } 
    void btnPost_Click(object sender, EventArgs e)
    {
       netStat.PostCtrlC();
       System.Diagnostics.Debug.WriteLine(string.Format("[{0}] - {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), this.netStat.OutputData.Replace(Environment.NewLine, "")));
    }
}

public class TestNetStat
{
    private StringBuilder sbRedirectedOutput = new StringBuilder();
    //
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32")]
    public static extern int SetForegroundWindow(IntPtr hwnd);
    public string OutputData
    {
       get { return this.sbRedirectedOutput.ToString(); }
    }
    public void PostCtrlC()
    {
       IntPtr ptr = FindWindow(null, @"C:\Windows\System32\netstat.exe");
       if (ptr != null)
       {
          SetForegroundWindow(ptr);
          Thread.Sleep(1000);
          WindowsInput.InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.CANCEL);
          // SendKeys.Send("^{BREAK}");
          Thread.Sleep(1000);
        }
    }
    public void Run()
    {
        System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo();
        ps.FileName = "netstat";
        ps.ErrorDialog = false;
        ps.Arguments = "-e 5";
        ps.CreateNoWindow = true;
        ps.UseShellExecute = false;
        ps.RedirectStandardOutput = true;
        ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
        {
           proc.StartInfo = ps;
           proc.EnableRaisingEvents = true;
           proc.Exited += new EventHandler(proc_Exited);
           proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived);
           proc.Start();
           proc.BeginOutputReadLine();
           proc.WaitForExit();
        }
     }

     void proc_Exited(object sender, EventArgs e)
     {
        System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended");
     }

     void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
     {
         if (e.Data != null)
         {
            this.sbRedirectedOutput.Append(e.Data + Environment.NewLine);
            System.Diagnostics.Debug.WriteLine("proc_OutputDataReceived: Data: " + e.Data);
         }
     }
}

Придирки в стороне, я знаю, что netStat Запускается из потока «Фонообрабатывателя», и я напрямую призвал метод «postctrlc» из основного потока графического интерфейса ... это педантично в качестве кода подтверждения концепции, но он показывает, что он должен реализовать «isynchronizeinvoke» Чтобы сделать это безопасным, это в стороне ... это действительно работает.

Вы видели этот замечательный инструмент - Авто. Анкет Это инструмент сценариев. Чтобы отправить обратное пространство, которое вы бы использовали Send("{BACKSPACE}")

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

Это имеет отношение к вашему вопросу?

Если у вас есть окно Windows Forms, в которое вы можете отправить клавиши, тогда Sendkeys может быть подходящим решением.

Для нажатия Backspace и Ctrl+C, это должно быть

SendKeys.Send("{BACKSPACE}^C");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top