문제

System.Diagnostics.Process는 StandardInput이라는 스트림 라이터를 노출 시키는데, 이는 내가 아는 한 문자 만 허용합니다.

그러나 키 스트로크도 보내야하며 일부 키 스트로크는 문자에 잘 매핑되지 않습니다.

어떻게해야합니까?

도움이 되었습니까?

해결책

입력 스트림과 제어 신호를 혼합하고 있습니다. 콘솔 프로세스에는 이미 알고 있듯이 StandardInput로 제어 할 수있는 기본 입력 스트림이 있습니다. 그러나 Ctrl-C와 Ctrl-Break 은이 스트림을 통해 프로세스로 전송되는 문자가 아니라 대신 대신입니다. 제어 신호 프로세스가 등록 된 신호 핸들러를 사용하여 수신한다는 것은 Ctrl+C 및 Ctrl+브레이크 신호:

기본적으로 콘솔 창에 키보드 초점이있는 경우 Ctrl+C 또는 Ctrl+Break는 키보드 입력이 아닌 신호 (Sigint 또는 Sigbreak)로 처리됩니다.

사용할 수있는 프로세스에 가짜 신호를 보내려면 GenerateConsoleCtrlEvent 그리고 둘 중 하나를 보내십시오 CTRL_C_EVENT 또는 CTRL_BREAK_EVENT. 이 API에는 .NET 동등성이 없으므로 Pinvoke가 필요합니다.

.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+브레이크 신호를 프로세스로 보냅니다 (특히 프로세스가 명령 줄 프로그램/배치 파일 인 경우). 여기에 관한 기사가 있습니다 CodeProject 이것이 정확히 수행하고 sendkeys를 반영합니다 ... 나는 아직도 이것에 몇 가지 코드를 붙여 넣지 않았다 ....

#2 편집 : 사실 나는 매우 놀랐습니다 ...이 코드가 표시 될 때 (개념 증명) ... 사용 중입니다.

  • inputSimulator (앞에서 언급 한 바와 같이)
  • 양식이로드 될 때 버튼으로 구성된 Windows 양식은 자동으로 클래스를 실행합니다. 버튼을 클릭하면 숨겨진 프로세스에 CTRL 브레이크를 게시합니다.
  • 출력 스트림은 실제로 리디렉션되며 숨겨진 창입니다.
  • 이상한 점은 출력이 캡처되고 있지만 디버그 창의 결과를 실시간으로 표시하지는 않습니다. 즉, 프로세스가 종료 될 때까지 버퍼링됩니다. 전체 출력이 표시됩니다 ...
  • 나는 약간 속임수를 썼다 FindWindow API Call은 창의 제목이 어쨌든 전경으로 가져올 수 있다는 것을 알았 기 때문에 입력 시스트 로크를 사용하여 키 스트로크를 보내거나 전통적인 평원 오래된 구식을 사용합니다. SendKeys 기능 ... 내가 가진 이유 Thread.Sleep '활성 전경 창의 키보드 대기열에 밀어 넣기 위해 키 스트로크가 전송되도록하는 것입니다.
  • 나는 'netstat -e 5'명령을 사용하여 영원히 루프를 사용하여 'Ctrl+C'가 수신 될 때까지 5 초마다 결과를 새로 고쳐서 무한 루프를 깨뜨 렸습니다.
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);
         }
     }
}

Nitpicky는 제쳐두고, 나는 그것을 알고 있습니다 netStat '배경 작업자'스레드를 실행 중이며 메인 GUI 스레드에서 'PostCtrlc'메소드를 직접 호출했습니다. 그것을 실로 만들기 위해, 그것은 제쳐두고 ... 그것은 실제로 작동합니다.

이 훌륭한 도구를 보셨습니까? 오토이트. 이것은 스크립팅 도구입니다. 백 스페이스를 보내려면 사용할 것입니다 Send("{BACKSPACE}")

이 도구는 훌륭한 도구이며 많은 수동 클릭을 자동화/두 번 클릭하는 데 도움이 될 수 있습니다.

이것이 귀하의 질문과 관련이 있습니까?

Keys를 보낼 수있는 Windows Forms Window가있는 경우 sendkeys 적절한 솔루션 일 수 있습니다.

백 스페이스 및 Ctrl+C를 누르려면

SendKeys.Send("{BACKSPACE}^C");
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top