[C#] Process.StartAndWait wacht niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Topicstarter
Ik heb een klein(?) probleempje. Ik ben niet zo gedreven in C#, dus ik loop vrij snel vast op iets dat niet lijkt te werken, maar een methode als StartAndWait lijkt me wel heel erg evident. Toch werkt ie niet.
Stukje code...
C#:
1
2
3
4
5
6
Process p = new Process();
p.StartInfo.FileName = "mstsc.exe";
p.StartInfo.Arguments = "servertje.rdp"
p.Start();
p.WaitForExit();
p.Close();

Ik start dus een RDP-sessie op en wil wachten tot die afgelopen is. Echter, nog voordat de client ook maar connected is, skipt m'n progsel al over WaitForExit heen. Welk gedeelte aan "wait" betekent iets anders dan wachten?? Die p.Close() doet ook niets, de client gaat gewoon door met connecten.

Met het batch-commando "start /wait ..." werkt het evenmin, tenminste dan werkt het soms. Het lijkt erop waarvandaan de batch wordt opgestart ofzo. Heel raar. Maar in mijn geval start ik em op vanuit een command prompt en vanuit de debugger van VS2010. Maakt niet uit natuurlijk.
Met notepad.exe werkt het overigens perfect :?

Geen idee of het uitmaakt, maar ik draai Windows 7 x64, en start VS2010 als administrator (anders werkt TFS niet |:(). Ik ben zelf niet als een administrator ingelogd.

Weet iemand wat er aan de hand is? Of beter nog, hoe ik het kan fixen? Ik maak vast een of andere rare fout...

日本!🎌


Acties:
  • 0 Henk 'm!

  • mOrPhie
  • Registratie: September 2000
  • Laatst online: 15:41

mOrPhie

❤️❤️❤️❤️🤍

Mijn gok zou zijn dat mstsc z'n proces sluit en een nieuw proces opent om een connectie te maken.
Wellicht dat het helpt een bat-file te maken en deze te runnen met een proces. Het proces is dan de bat-file. :)

Een experimentele community-site: https://technobabblenerdtalk.nl/. DM voor invite code.


Acties:
  • 0 Henk 'm!

  • Grompie
  • Registratie: Maart 2010
  • Laatst online: 15-04-2024
Plaats de p.WaitForExit in een while loop eens waarin je wacht.

C#:
1
2
3
4
5
6
7
8
9
Process p = new Process();
p.StartInfo.FileName = "mstsc.exe";
p.StartInfo.Arguments = "servertje.rdp"
p.Start();
while (p.WaitForExit())
{
Thread.sleep(100); // weet niet zeker of dit zelfs nodig is.
}
p.Close();

Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

mOrPhie schreef op vrijdag 15 april 2011 @ 10:45:
Mijn gok zou zijn dat mstsc z'n proces sluit en een nieuw proces opent om een connectie te maken.
Wellicht dat het helpt een bat-file te maken en deze te runnen met een proces. Het proces is dan de bat-file. :)
Dat neem ik ook aan, WaitForExit werkt gewoon goed.

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • DRaakje
  • Registratie: Februari 2000
  • Niet online
C#:
1
2
3
4
5
6
7
 myProcess.StartInfo.RedirectStandardOutput = true;
            myProcess.StartInfo.RedirectStandardInput = true;
            myProcess.StartInfo.RedirectStandardError = true;
            myProcess.StartInfo.CreateNoWindow = true;
            myProcess.Start();
            string Standardoutput = myProcess.StandardOutput.ReadToEnd();
            string ErrorOutputoutput = myProcess.StandardError.ReadToEnd();


Ik heb wel wat dingen die ik mbv Perl opstart en dan wacht zowiezo tot het klaar is. Kan me voorstellen dat het anders werkt met non commandline dingen. Maar ik zou eens kijken of je niet ergens een error krijgt. Probeer gewoon alleen eens met notepad opstarten, en anders kan je altijd nog kijken welke processen actief zijn en daar op wachten. Maar volgens mij moet het wel gewoon kunnen.

[ Voor 11% gewijzigd door DRaakje op 15-04-2011 10:56 ]


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Topicstarter
@Grompie
Dat blijft in een oneindige loop hangen. Tenminste als ik aan WaitForExit een timeout toevoeg, want anders compileert het niet :)

@DRaakje
Dat heeft vrij weinig zin, denk ik, gezien notepad.exe geen commandline I/O gebruikt. En runtime errors krijg ik uiteraard ook niet, anders was me dat wel opgevallen...

@mOrPhie, Phyxion
Nee dat werkt ook niet, volgens Process Explorer is het proces wat opgestart wordt, ook precies het proces dat ik opstart. Wel heb ik ermee ontdekt dat de PID anders is. Dat kan komen doordat mijn progsel als x86 opgestart wordt, terwijl mstsc x64 is. Dat verklaart alleen nog niet waarom notepad wel goed gaat. Maar een andere PID is natuurlijk funest...

Het leuke is trouwens, in Windows XP (32-bits) werkt het helemaal feilloos, ook met die nieuwste RDP-client.

日本!🎌


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

_Thanatos_ schreef op vrijdag 15 april 2011 @ 11:29:
@mOrPhie, Phyxion
Nee dat werkt ook niet, volgens Process Explorer is het proces wat opgestart wordt, ook precies het proces dat ik opstart. Wel heb ik ermee ontdekt dat de PID anders is. Dat kan komen doordat mijn progsel als x86 opgestart wordt, terwijl mstsc x64 is. Dat verklaart alleen nog niet waarom notepad wel goed gaat. Maar een andere PID is natuurlijk funest...
Een andere PID is een ander proces, punt uit. Jij wacht op het oude proces terwijl je het nieuwe wil monitoren.

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Apart dat de Remote Desktop-namespace uitblinkt door afwezigheid in het .NET-framework.

Deze is wel ranzig, trouwens, maar werkt wel :P

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "mstsc.exe";
            p.StartInfo.Arguments = "servertje.rdp";
            Boolean running = p.Start();

            while (running)
            {
                running = false;
                foreach (System.Diagnostics.Process clsProcess in System.Diagnostics.Process.GetProcesses())
                {

                    if (clsProcess.ProcessName.Contains("mstsc"))
                        running = true;
                }
            }


Ranzig omdat er best nog wel eens een proces kan draaien wat mstsc heet. :)

[ Voor 83% gewijzigd door CodeCaster op 15-04-2011 22:11 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Topicstarter
@H!GHGuY
Dat is op zich een correcte uitleg van het probleem... Maar ik zoek eigenlijk een oplossing ;)

@CodeCaster
Haha, ja dat werkt nog ook. Briljant, maar inderdaad wel ranzig... Het komt geregeld voor dat ik twee sessies opentrap, en dat valt dit mechanisme ook om.

Als er een nieuw proces gestart wordt, zou ik eigenlijk te weten moeten komen door welke PID een proces geinitiëerd is. Dan zou ik die kunnen opvissen en daarop kunnen monitoren... Maar geen idee of zulke informatie beschikbaar is.

EDIT
Ha! Ik heb em, denk ik. Inderdaad met P/Invoke kun je uiteindelijk achter het parent proces van een proces komen, dus op die manier kun je alle children van een proces opvissen. En omdat het met P/Invoke werkt, werkt het met ID's en handles, ipv met objecten, dus de parent ID is nog steeds te vinden, ook al bestaat dat proces niet meer. Fancy :)

Stukje code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Process p = new Process();
p.StartInfo.FileName = filename;
p.StartInfo.Arguments = string.Join(" ", processArgs);
p.Start();
int pid = p.Id;
Console.WriteLine("Waiting for {0} to exit...", p.Id);
List<Process> children = new List<Process>();

p.WaitForExit();
foreach (System.Diagnostics.Process clsProcess in System.Diagnostics.Process.GetProcesses()) {
    try {
        if (!clsProcess.HasExited && clsProcess.GetParentProcess() == pid) {
            children.Add(clsProcess);
        }
    }
    catch { }
}

foreach (Process child in children) {
    Console.WriteLine("Waiting for {0} to exit...", child.Id);
    child.WaitForExit();
}


En dit hoort er ook bij:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[StructLayout(LayoutKind.Sequential)]
public struct ParentProcessUtilities {
    internal IntPtr Reserved1;
    internal IntPtr PebBaseAddress;
    internal IntPtr Reserved2_0;
    internal IntPtr Reserved2_1;
    internal IntPtr UniqueProcessId;
    internal IntPtr InheritedFromUniqueProcessId;

    [DllImport("ntdll.dll")]
    private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);

    public static int GetParentProcess(IntPtr handle) {
        ParentProcessUtilities pbi = new ParentProcessUtilities();
        int returnLength;
        int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
        if (status != 0)
            throw new Win32Exception(status);

        try {
            return pbi.InheritedFromUniqueProcessId.ToInt32();
        }
        catch (ArgumentException) {
            // not found
            return 0;
        }
    }
}

public static class ProcessExtension {
    public static int GetParentProcess(this Process p) {
        return ParentProcessUtilities.GetParentProcess(p.Handle);
    }
}


M'n implementatie is niet erg netjes met die catchall, maar anders krijg je exceptions met "access denied" meldingen voor processen waar je als gebruiker niet aan mag zitten (bijv system services, en processen van andere users). Maar Hij wacht nu dus eerst op het parent proces, en zodra hij doorheeft dat er children zijn aangemaakt, wacht ie daar ook op.

Ik zou het dus kunnen uitwerken tot een mooie extension method, maar voor nu is het probleem verholpen. Bedankt voor het meedenken iig :)

[ Voor 101% gewijzigd door _Thanatos_ op 18-04-2011 13:16 ]

日本!🎌


Acties:
  • 0 Henk 'm!

  • GateKeaper
  • Registratie: April 2004
  • Laatst online: 05-08 21:46

GateKeaper

#1 Procastinator

Als je toch op de ranzige tour gaat, met de code van CodeCaster vindt je alle processen. Sla de processen op in een list voordat je een nieuwe instantie start, start je instantie, en verzamel de processen nog een keer.

Het pid dat je niet zag in je eerste list en wel in je tweede list is je pid dat je in de gaten moet houden.

Er is een file wachter service binnen het .net framework. Is er niet zoiets als een process watcher ?

*edit, ff voor je rond gekeken. Het lijkt mij dat je wel iets aan de WMI service "Win32_ProcessStartTrace" moet hebben.

linkje met voorbeeld in vb: http://www.vbdotnetforums...starttrace.html#post20792

[ Voor 22% gewijzigd door GateKeaper op 18-04-2011 12:13 ]


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Topicstarter
@GateKeaper
In mijn oplossing(-achtige) doe ik wachten tot het parent proces klaar is, en ga daarná pas zoeken naar children. Op dat moment kunnen er niet nog meer children aangemaakt worden (door die parent), dus tot op één niveau diep aan proces-children, zou dit moeten werken.

日本!🎌


Acties:
  • 0 Henk 'm!

  • GateKeaper
  • Registratie: April 2004
  • Laatst online: 05-08 21:46

GateKeaper

#1 Procastinator

_Thanatos_ schreef op maandag 18 april 2011 @ 12:13:
@GateKeaper
In mijn oplossing(-achtige) doe ik wachten tot het parent proces klaar is, en ga daarná pas zoeken naar children. Op dat moment kunnen er niet nog meer children aangemaakt worden (door die parent), dus tot op één niveau diep aan proces-children, zou dit moeten werken.
Ja.... maar.... die stond er toen nog niet :p

Acties:
  • 0 Henk 'm!

  • Rutix
  • Registratie: Augustus 2009
  • Laatst online: 05-09-2024
GateKeaper schreef op maandag 18 april 2011 @ 12:07:
Als je toch op de ranzige tour gaat, met de code van CodeCaster vindt je alle processen. Sla de processen op in een list voordat je een nieuwe instantie start, start je instantie, en verzamel de processen nog een keer.

Het pid dat je niet zag in je eerste list en wel in je tweede list is je pid dat je in de gaten moet houden.
Dat is inderdaad wel heel ranzig :P want is niks dat garandeert dat in die tijd dat je de vergelijking doet geen ander proces is opgestart ;).

Nothing to see here!


Acties:
  • 0 Henk 'm!

  • GateKeaper
  • Registratie: April 2004
  • Laatst online: 05-08 21:46

GateKeaper

#1 Procastinator

Rutix schreef op dinsdag 19 april 2011 @ 09:34:
[...]


Dat is inderdaad wel heel ranzig :P want is niks dat garandeert dat in die tijd dat je de vergelijking doet geen ander proces is opgestart ;).
Klopt, maar aangezien je zelf het start-remote-desktop-knopje in drukt, is het redelijk veilig. Maar inderdaad, niet minder ranzig O-)

ps. Wel op naam filteren hé :P Niet alle processen opslaan in je list.

[ Voor 9% gewijzigd door GateKeaper op 19-04-2011 11:25 ]


Acties:
  • 0 Henk 'm!

  • _Thanatos_
  • Registratie: Januari 2001
  • Laatst online: 05-09 14:39

_Thanatos_

Ja, en kaal

Topicstarter
GateKeaper schreef op dinsdag 19 april 2011 @ 11:24:
ps. Wel op naam filteren hé :P Niet alle processen opslaan in je list.
pps. Ik denk dat mijn oplossing dan nog steeds minder vies is... wel rare catches en P/Invoke, maar toch :)

日本!🎌

Pagina: 1