none
Externe Anwendungen verbergen RRS feed

  • Frage

  • Tag zusammen,

    ich versuche eine externe Anwendung zu starten, dies allerdings verborgen so, dass sie in der Taskleiste nicht angezeigt wird und auch kein Fenster sichtbar ist.

    Zum starten benutze ich die ProcessStartInfo Klasse, da lässt sich der WindowStyle zwar auf Hidden stellen und CreateNoWindow auf false allerdings funktioniert das nur bei Konsolenanwendungen.

    Ich hab dazu zwar gefzunden, dass man die Funktion ShowWindow aus der user32.dll benutzen soll nur irgendwie werden die Fenster trotz des Aufrufs immer noch angezeigt.

    Hier noch der Code den ich momentan verwende:

    ProcessStartInfo oPInfo = new ProcessStartInfo();
    oPInfo.FileName = m_sAppPath;
    oPInfo.CreateNoWindow = m_bHideWindows;
    
    if (m_bHideWindows)
    {
        oPInfo.WindowStyle = ProcessWindowStyle.Hidden;
        oPInfo.UseShellExecute = false;
    }
    
    Process oP = new Process();
    oP.StartInfo = oPInfo;
    oP.Start();
    
    if (m_bHideWindows)
    {
        Win32.ShowWindow(oP.Handle, WindowState.Hide);
    }

    Dabei ist Win32 eine selbst erstellte Kasse die nur die Win API Funktionen einbindet.

     

    public enum WindowState
    {
        Hide = 0,
        Normal = 1,
        Minimized = 2,
        Maximized = 3,
        NoActive = 4,
        Restore = 9,
        Default = 10,
    }
    
    public static class Win32
    {
        [DllImport("User32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, WindowState nCmdShow);
    }
    Schonmal Danke für Hilfe im Voraus

    User XXX

     

     


    • Bearbeitet User XXX Donnerstag, 3. November 2011 18:30
    Donnerstag, 3. November 2011 18:28

Antworten

  • Hallo User XXX,

    Du hast uns noch nicht gesagt, wozu das Ganze letztendlich gut sein soll. Das wäre aber für die Beantwortung der Frage schon wichtig, denn abhängig von deinen Zielen könnten wir den einen oder anderen Vorschlag machen.

    Im einfachsten Fall könntest Du den WindowStyle auf Hidden setzen:

    Process.Start(new ProcessStartInfo { FileName = "notepad.exe", WindowStyle = ProcessWindowStyle.Hidden });
    

    Versuchst Du das nun mit winword.exe, wirst Du jedoch merken, dass verschiedene andere Fenster (Splash, Toolbox etc.) dennoch sichtbar werden, was auch nahe legt, dass der Ansatz über FindWindow/ShowWindow unzureichend ist (Edit: die Office-Anwendungen unterstützen Automation und stellen insofern einen speziellen Fall dar, da sie bereits über das eigene Objektmodell die Möglichkeit anbieten, die Sichtbarkeit der Anwendung zu beeinflussen [Application.Visible=false]).

    Eine fortgeschrittene Technik zum Schluß: Du könntest - entspr. Rechte immer vorausgesetzt - den Prozess in einer ganz anderen Windows Station erstellen. Versteckter geht's nicht. Dazu müßtest Du auf die Windows API zurückgreifen und die Funktion CreateProcessWithLogonW() aufrufen, die u.a. einen Parameter vom Typ STARTUPINFO akzeptiert, über den Du die Sichtbarkeit des Fensters festlegen kannst.

    Ich kann mir einige Szenarien vorstellen, wo man Fenster verbergen möchte, um sie erst zu einem späteren Zeitpunkt wieder sichtbar zu machen, aber grundsätzlich sind Fenster natürlich da um sichtbar zu sein, und da sie Teil der Interaktion mit dem Benutzer sind, mußt Du dir absolut sicher sein, dass während ihrer unsichtbaren Phase nichts passiert, was den Benutzer zur Interaktion auffordert. Erscheint auch nur eine einfache MessageBox, kann dies freilich deine ganze Anwendung blockieren.

    ProcessWindowStyle-Enumeration:
    http://msdn.microsoft.com/de-de/library/system.diagnostics.processwindowstyle.aspx 

    pinvoke.net - CreateProcessWithLogonW:
    http://pinvoke.net/default.aspx/advapi32/CreateProcessWithLogonW.html

    ShowWindow function:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx

    STARTUPINFO structure:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx

    Gruß
    Marcel


    Samstag, 5. November 2011 08:17
    Moderator
  • Hallo User XXX,

    >  Marcel schrieb: Du hast uns noch nicht gesagt, wozu das Ganze letztendlich gut sein soll.
    >  User XXX schrieb: [?]

    > User XXX schrieb: Mach ich irgendwas falsch oder sollte das funktionieren?

    Ich hatte die Dokumentation von STARTUPINFO einfach verlinkt, ich hätte vielleicht noch etwas dazu schreiben sollen: Solange man nicht STARTUPINFO.dwFlags auf STARTF_USESHOWWINDOW setzt und dadurch mitteilt, dass man STARTUPINFO.wShowWindow verwenden möchte, wird wShowWindow einfach ignoriert.

    Setze also dwFlags auf 1 und alles ist gut:

    startInfo.dwFlags = 0x00000001;
    

    Warum Du LogonFlags.LOGON_NETCREDENTIALS_ONLY verwendest, erschließt sich mir nicht ganz, aber ich kenne auch nicht dein Szenario.

    Gruß
    Marcel


    Samstag, 5. November 2011 20:28
    Moderator

Alle Antworten

  • Hallo User XXX,

    Du hast uns noch nicht gesagt, wozu das Ganze letztendlich gut sein soll. Das wäre aber für die Beantwortung der Frage schon wichtig, denn abhängig von deinen Zielen könnten wir den einen oder anderen Vorschlag machen.

    Im einfachsten Fall könntest Du den WindowStyle auf Hidden setzen:

    Process.Start(new ProcessStartInfo { FileName = "notepad.exe", WindowStyle = ProcessWindowStyle.Hidden });
    

    Versuchst Du das nun mit winword.exe, wirst Du jedoch merken, dass verschiedene andere Fenster (Splash, Toolbox etc.) dennoch sichtbar werden, was auch nahe legt, dass der Ansatz über FindWindow/ShowWindow unzureichend ist (Edit: die Office-Anwendungen unterstützen Automation und stellen insofern einen speziellen Fall dar, da sie bereits über das eigene Objektmodell die Möglichkeit anbieten, die Sichtbarkeit der Anwendung zu beeinflussen [Application.Visible=false]).

    Eine fortgeschrittene Technik zum Schluß: Du könntest - entspr. Rechte immer vorausgesetzt - den Prozess in einer ganz anderen Windows Station erstellen. Versteckter geht's nicht. Dazu müßtest Du auf die Windows API zurückgreifen und die Funktion CreateProcessWithLogonW() aufrufen, die u.a. einen Parameter vom Typ STARTUPINFO akzeptiert, über den Du die Sichtbarkeit des Fensters festlegen kannst.

    Ich kann mir einige Szenarien vorstellen, wo man Fenster verbergen möchte, um sie erst zu einem späteren Zeitpunkt wieder sichtbar zu machen, aber grundsätzlich sind Fenster natürlich da um sichtbar zu sein, und da sie Teil der Interaktion mit dem Benutzer sind, mußt Du dir absolut sicher sein, dass während ihrer unsichtbaren Phase nichts passiert, was den Benutzer zur Interaktion auffordert. Erscheint auch nur eine einfache MessageBox, kann dies freilich deine ganze Anwendung blockieren.

    ProcessWindowStyle-Enumeration:
    http://msdn.microsoft.com/de-de/library/system.diagnostics.processwindowstyle.aspx 

    pinvoke.net - CreateProcessWithLogonW:
    http://pinvoke.net/default.aspx/advapi32/CreateProcessWithLogonW.html

    ShowWindow function:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx

    STARTUPINFO structure:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx

    Gruß
    Marcel


    Samstag, 5. November 2011 08:17
    Moderator
  • Hallo Marcel,

     

    mit ShowWindow und ProcessWindowStyle habe ich es ja bereits versucht (siehe oben).

    Aber auch CreateProcessWithLogonW funktioniert bei mir nicht. Auch wenn ich es so einstelle, dass eigentlich kein Fenster angezeigt werden sollte öffnet sich ein Fenster, hier mein Code:

    ProcessInformation processInfo = new ProcessInformation();
    StartupInfo startInfo = new StartupInfo();
    startInfo.dwFlags &= 0x00000001; // UseShowWindow
    startInfo.wShowWindow = 0;         // HideWindow
    startInfo.cb = Marshal.SizeOf(startInfo);
    
    CreateProcessWithLogonW(
                        strName, 
                        strDomain, 
                        strPassword,
                        0x00000002, // Notwendig um vom aktuellen User zu starten
                        strCommand,
                        strCommand, 
                        0, 
                        IntPtr.Zero, 
                        null, 
                        ref startInfo, 
                        out processInfo
                    );
    

    Mach ich irgendwas falsch oder sollte das funktionieren?

    User XXX

     

    Samstag, 5. November 2011 19:21
  • Hallo User XXX,

    >  Marcel schrieb: Du hast uns noch nicht gesagt, wozu das Ganze letztendlich gut sein soll.
    >  User XXX schrieb: [?]

    > User XXX schrieb: Mach ich irgendwas falsch oder sollte das funktionieren?

    Ich hatte die Dokumentation von STARTUPINFO einfach verlinkt, ich hätte vielleicht noch etwas dazu schreiben sollen: Solange man nicht STARTUPINFO.dwFlags auf STARTF_USESHOWWINDOW setzt und dadurch mitteilt, dass man STARTUPINFO.wShowWindow verwenden möchte, wird wShowWindow einfach ignoriert.

    Setze also dwFlags auf 1 und alles ist gut:

    startInfo.dwFlags = 0x00000001;
    

    Warum Du LogonFlags.LOGON_NETCREDENTIALS_ONLY verwendest, erschließt sich mir nicht ganz, aber ich kenne auch nicht dein Szenario.

    Gruß
    Marcel


    Samstag, 5. November 2011 20:28
    Moderator
  • Sorry, hatte ich überlesen.

    Das Programm lässt den User festlegen ob er ein Programm "unsichtbar" starten möchte. Mein Programm legt sich dann bei den Icons rechts in der Taskleiste ab. Die Funktion ist für Anwendungen gedacht die sowieso nur "im Hintergrund" mitlaufen ohne irgendeine Interaktion mit dem Benutzer zu benötigen.

    Dementsprechend wird die Anwendung gestartet wenn meine startet aber erst wenn mein Programm beendet wird auch beendet.

    Danke, das hat funktioniert, ich hatte

    startInfo.dwFalgs &= 0x00000001;

    verwendet, fubnktioniert aber nur bei nur =

    LogonFlags.LOGON_NETCREDENTIALS_ONLY verwende ich, weil der aktuell angemeldete Benutzer (bei meiner Recherche bin ich auch darauf gestoßen, dass es auch am Admin Account liegen könnte) sonst nicht angemeldet wird und der Aufruf fehlschlägt.

     

    Nochmal Danke für deine Hilfe,

    Gruß

    User XXX


    • Bearbeitet User XXX Samstag, 5. November 2011 21:15
    Samstag, 5. November 2011 21:08
  • Hallo User XXX,

    > Danke, das hat funktioniert ... Nochmals Danke für deine Hilfe.

    Gerne. Ich freue mich immer, wenn hier interessante Fragestellungen gepostet werden.

    Gruß
    Marcel

    Samstag, 5. November 2011 21:20
    Moderator