ShowWindow от User32 работает не так, как ожидалось

Я использую метод 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;
        }
    }

person Malfist    schedule 14.01.2009    source источник


Ответы (2)


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

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);
    }
person scottm    schedule 14.01.2009

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

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

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

person Rob Kennedy    schedule 14.01.2009