views:

571

answers:

3

Is there a way to get the date/time that a service last started in C#. I'm using this code now to check the status of services:

ServiceController sc = new ServiceController(serviceName);
// check sc.status for "Running" etc... with a Switch statement...

Can I do it with this object? Or need WMI?

(Reason: I'm writing a little BizTalk Monitor, and a common problem is that people often forget to restart the BizTalk Service (host instances) after doing a deploy. I want to show the time it last was started.)

Thanks,

Neal Walters

+1  A: 

Considering this information isn't visible in the Services Manager, it probably can't be found through the ServiceController class (and I didn't see anything in there either).

That being said, try looking at the Event Log. An event is generated automatically when a service is started and stopped.

Jon Seigel
-1 he wants to do it in C#
0A0D
@Roboto: http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx
Jon Seigel
@Jon: This info would be good in the answer. Telling him to look at the Event Log does not imply to use System.Diagnostics.EventLog... a better answer would even be to include a code sample
0A0D
@Roboto: I assumed since he is familiar with the ServiceController class, he would also know about the EventLog class. I will edit my answer, though.
Jon Seigel
Stopping a service terminates the Service process. Starting it runs it again...
Charles Bretana
@ Charles Bretana: If it is not one of the svchost.exe processes that run multiple services. But I am not familiar with BizTalk.
Uros Calakovic
+3  A: 

In a C# app, write

 using System.Diagnostics;
 private static DateTime GetStartTime(string processName)
 {
    Process[] processes = 
        Process.GetProcessesByName(processName);
    if (processes.Length == 0) 
       throw new ApplicationException(string.Format(
          "Process {0} is not running.", processName));
    // -----------------------------
    DateTime retVal = DateTime.Now;
    foreach(Process p in processes)
       if (p.StartTime < retVal) 
          retVal = p.StartTime;

    return retVal ;
 }

if processname is not running, this throws an exception, modify to implement whatever alternative behavior you want. Also, if multiple instances of this process are running, this returns when the earliest was started...

Charles Bretana
This would only work if the service is currently running.
Jon Seigel
Yes, fixed that
Charles Bretana
It still doesn't answer the question, which is what I was getting at. He asked to find out "when the service was last started." Using this method, you can only find the time when the service is currently running.
Jon Seigel
Oh, Sorry, What do you think happens when you "Stop" a service?? The process is terminated. This returns the DateTime when the process was last run, which, for a service, is when it was last started.
Charles Bretana
@Charles: I think what he means is that if the service is not started, then the exception is thrown. I just tried it here on the Windows Telnet Service and the exception was thrown. If the service is stopped or disabled, this does not work
0A0D
@Roboto: But OPs reason for doing this is to restart the BizTalk Service after doing a deploy, so if the service is not started than that is probably fine too - just start the service.
Uros Calakovic
@Uros: Gotcha, but he wants the time it was /last/ started. Starting it again, won't get you this.. I don't know why he needs it but this only works if it is started
0A0D
@Roboto: I suspect that he compares the service start time and the application deployment time and decides whether to restart the service or not based on the result.
Uros Calakovic
ahhh, If the OP needs to know for a non-running service, when it was last started, then he needs to look in event log. ... Although if service is not running, I'm not sure why the last start time would be helpful.
Charles Bretana
Very cool. It took s a few tries and debugger to figure out that the process name was 'BTSNTSvc' and not 'BTSNTSvc.exe' and not 'BTSNTSvc.exe *32' etc... BizTalk needs to be re-started to grab changed code in the GAC. Sometimes, even after 5 years, I still forget to do this. The deployment process is not fully automated, and varies from company to company (and even on my dev machine). This routine is also useful if they are running multiple Host-Instances (BT processes), I might display all their start-times.
NealWalters
Also - please note - this code uses ProcessName, not ServiceName (but that's fine with me).
NealWalters
Probably works for the OP but FWIW, this works only if the service runs in its own process. My 2-cents.
Serge - appTranslator
For what it's worth, I just learned that if you create a 64-bit Host Instance, it has a separate process name and a separate config file. (Just learned that SQL adapter doesn't run under 64-bit host).
NealWalters
Code uses processName cause it will work for any process, not just a service host
Charles Bretana
@Serge. If we're talking about NT or Windows Services, they always run in their own process space, no? Can you run one in a separate Host Process ? If you can, then I'd venture to say that the "service" you are talking about isn;t really a service in that sense, i.e, it probably does not derive from the .Net class System.ServiceProcess.ServiceBase,
Charles Bretana
For the process name, I can just choose any process in the Task Manager?
yeeen
+2  A: 

This should do the proper lookup for you. Modify as necessary!

public List<Hashtable> GetEventEntryByEvent(
            ref string logName, ref string machineName, 
            ref string source)
        {
            try
            {
                //Create our list
                List<Hashtable> events = new List<Hashtable>();

                //Connect to the EventLog of the specified machine
                EventLog log = new EventLog(logName, machineName);

                //Now we want to loop through each entry
                foreach (EventLogEntry entry in log.Entries)
                {
                    //If we run across one with the right entry source
                    //  we create a new Hashtable
                    //  then we add the Message,Source, and TimeWritten values
                    //  from that entry
                    if (entry.Source == source)
                    {
                        Hashtable entryInfo = new Hashtable();

                        entryInfo.Add("Message", entry.Message);
                        entryInfo.Add("InstanceId", entry.InstanceId);
                        entryInfo.Add("Source", entry.Source);
                        entryInfo.Add("TimeWritten", entry.TimeWritten);
                        // You can also replace TimeWritten with TimeGenerated
                        //Add this new Hashtable to our list
                        events.Add(entryInfo);

                        entryInfo = null;
                    }
                }
                //Return the results
                return events;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return null;
            }
        }
0A0D