CSharpFeeds - All your C# feeds in one place.

Sponsors

Friday, October 27, 2006

Process and ServiceProcess Caching [Robert Villahermosa]

by BCLTeam via BCL Team Blog on 10/27/2006 1:36:00 AM

I’ve seen several questions over the last month or two about refreshing the status of certain properties on the Process and ServiceProcess classes.  I’d like to take this opportunity to take a look at an example from both these classes and see how we can resolve these issues.

Issue One: Process.MainWindowHandle resturns 0, even though a window is created

A user found that even though they waited for the UI Window of their application to be displayed, they were getting a MainWindowHandle of 0.  User code may look something like this:

    Process myProc = new Process();
    myProc.StartInfo.FileName = "notepad.exe";
    myProc.Start();
    IntPtr myWinHandle = myProc.MainWindowHandle;
    System.Threading.Thread.Sleep(5000);
    Console.WriteLine(myWinHandle);

After this executes, myWinHandle has a value of 0, even though the sleep should be sufficient for the Window to pop up.  The first proposed solution I saw was to do the following:

    Process myProc = new Process();
    myProc.StartInfo.FileName = "notepad.exe";
    myProc.Start();
    System.Threading.Thread.Sleep(5000);
    IntPtr myWinHandle = myProc.MainWindowHandle;
    Console.WriteLine(myWinHandle);

Better, but we still have the problem with the Sleep – we don’t know if the window is up or not when the thread awakes.  It is important to realize that the Process class actually takes a snapshot of Process state and caches it, and does not continually update the state information.  That is why there is a Refresh() method on this class, this should be called if you want updated Process state information.  Also, a better way to determine if the Window has come up is to use the WaitForInputIdle() method.   The fixed code looks something like this:

    Process myProc = new Process();
    myProc.StartInfo.FileName = "notepad.exe";
    myProc.Start();
    myProc.WaitForInputIdle(5000);  //at this point we know the window is up
                                    //we could handle the time-out based on
                                    //the return value of WaitForInputIdle
                                    //it’s omitted for clarity
    myProc.Refresh();
    IntPtr myWinHandle = myProc.MainWindowHandle;
    Console.WriteLine(myWinHandle);

Issue 2: Changing the ServiceName property does not refresh DependentServices/ServicesDependedOn

This customer found that changing the service name didn’t update the DependentServices or ServicesDepended on.  A code snippet for the repro looked something like:

    ServiceController sc = new ServiceController("workstation");
    Console.WriteLine("Workstation dependent services:");
    foreach (ServiceController dependency in sc.DependentServices)
        Console.WriteLine(dependency.ServiceName);

    Console.WriteLine();

    sc.ServiceName = "alerter";
    Console.WriteLine("Alerter dependent services:");
    foreach (ServiceController dependency in sc.DependentServices)
        Console.WriteLine(dependency.ServiceName);

This would output:

    Workstation dependent services:
    RpcLocator
    Netlogon
    Messenger
    Browser
    Alerter

    Alerter dependent services:
    RpcLocator
    Netlogon
    Messenger
    Browser
    Alerter

Like Process, ServiceProcess caches this information so Refresh() needs to be called.  In the documentation, we say that calling Refresh() sets the DependentServices and ServicesDependedOn properties to null.  Technically, this is true as in our internal implementation this is indeed what happens.  However, the next time the getter for either of these properties is called, a null check is performed and if either are null we will update them to their current values.  We’ve updated the documentation for the next release to make this clearer.  The fix is one line adding the call to Refresh():

    ServiceController sc = new ServiceController("workstation");
    Console.WriteLine("Workstation dependent services:");
    foreach (ServiceController dependency in sc.DependentServices)
        Console.WriteLine(dependency.ServiceName);

    Console.WriteLine();

    sc.ServiceName = "alerter";
    sc.Refresh();
    Console.WriteLine("Alerter dependent services:");
    foreach (ServiceController dependency in sc.DependentServices)
        Console.WriteLine(dependency.ServiceName);
email it!bookmark it!digg it!

Original Post: Process and ServiceProcess Caching [Robert Villahermosa]

Subscribe

New Feed

Product Spotlight

Recently Updated Sources

Legal Note

The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.

Advertise with us