ShowWindow User32 не работает, как ожидалось - PullRequest
1 голос
/ 14 января 2009

Я использую метод ShowWindow от User32, чтобы скрыть окно (cmd.exe) от пользователя (главным образом, чтобы они не закрывали его). Когда пользователь открывает форму, процесс запускается и скрывается, затем, когда форма закрывается, процесс уничтожается. Однако, когда форма открывается снова, она не скрывает окно (а иногда и не в первый раз). Может ли кто-нибудь помочь мне с этим?

    [DllImport("User32")]
    private static extern int ShowWindow(int hwnd, int nCmdShow);   //this will allow me to hide a window

    public ConsoleForm(Process p) {
        this.p = p;
        p.Start();
        ShowWindow((int)p.MainWindowHandle, 0);   //0 means to hide the window. See User32.ShowWindow documentation SW_HIDE

        this.inStream = p.StandardInput;
        this.outStream = p.StandardOutput;
        this.errorStream = p.StandardError;

        InitializeComponent();

        wr = new watcherReader(watchProc);
        wr.BeginInvoke(this.outStream, this.txtOut, null, null);
        wr.BeginInvoke(this.errorStream, this.txtOut2, null, null);
    }

    private delegate void watcherReader(StreamReader sr, RichTextBox rtb);
    private void watchProc(StreamReader sr, RichTextBox rtb) {
        string line = sr.ReadLine();
        while (line != null && !stop && !p.WaitForExit(0)) {
            //Console.WriteLine(line);
            line = stripColors(line);
            rtb.Text += line + "\n";

            line = sr.ReadLine();
        }
    }

    public void start(string[] folders, string serverPath) {

        this.inStream.WriteLine("chdir C:\\cygwin\\bin");
        //this.inStream.WriteLine("bash --login -i");
        this.inStream.WriteLine("");
    }

    private void ConsoleForm_FormClosed(object sender, FormClosedEventArgs e) {
        this.stop = true;
        try {
            this.p.Kill();
            this.p.CloseMainWindow();
        } catch (InvalidOperationException) {
            return;
        }
    }

Ответы [ 2 ]

4 голосов
/ 14 января 2009

Это было бы НАМНОГО проще:

public ConsoleForm(Process p) {
        this.p = p;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        p.StartInfo.CreateNoWindow = true;
        p.Start();

        this.inStream = p.StandardInput;
        this.outStream = p.StandardOutput;
        this.errorStream = p.StandardError;

        InitializeComponent();

        wr = new watcherReader(watchProc);
        wr.BeginInvoke(this.outStream, this.txtOut, null, null);
        wr.BeginInvoke(this.errorStream, this.txtOut2, null, null);
    }
0 голосов
/ 14 января 2009

Вы проверили, является ли p.MainWindowHandle допустимым дескриптором? Это должно быть ненулевым, по крайней мере. Попробуйте позвонить IsWindow для подтверждения.

MSDN предлагает позвонить WaitForInputIdle перед проверкой MainWindowHandle; возможно, вы обращаетесь к свойству до того, как новый процесс создаст свое окно. Тем не менее, свойство в любом случае является ненадежным, потому что процессы не имеют понятия «главного» окна. Все окна обрабатываются одинаково. Инфраструктура .Net просто определяет первое окно как главное, но самому процессу не нужно так думать.

Кроме того, рассматривали ли вы просто сначала скрыть процесс, вместо того, чтобы запустить его, а затем скрыть за фактом? Установите свойства процесса StartInfo , как показывает Scotty2012 .

...