|
Hi,
I am trying to get a date in the format dd/MM/yyyy HH:mm:ss from a datetime.addseconds operation but everything that is returned (unless I tickcount - which tells me the elapsed time) is wrong, i.e. 1601,1,1,0,0,0.
While I 'understand' why I get that response I don't know how to fix it.
Code:
long st = procs.StartTime.ToFileTime();
DateTime stDt = new DateTime(1601, 1, 1, 0, 0, 0).AddSeconds(st);
If I do this
string stime = String.Empty;
stime += (Environment.TickCount / 86400000).ToString() + "d";
stime += (Environment.TickCount / 3600000 % 24) + "h";
stime += (Environment.TickCount / 120000 % 60) + "m";
stime += (Environment.TickCount / 1000 % 60) + "s";
I get 7d10h17m44s.
How do I get the difference between datetime.now and that process startdate expressed in the desired format or how do I convert 7d10h17m44s into a usable format so that I can deduct it from datetime.now?
Thanks for your time.
|
|
|
|
|
CCodeNewbie wrote: how do I convert 7d10h17m44s into a usable format so that I can deduct it from datetime.now?
DateTime result = DateTime.Now - new TimeSpan (7, 10, 17, 44); /ravi
|
|
|
|
|
1.
I fail to understand how your code matches your problem description. What has ToFileTime to do with it?
2.
DateTime is the fundamental CLR type dealing with dates and times, and it holds most everything you'll ever need. What you should do is:
- convert your dates and times to DateTime values (if they start out differently);
- then operate on those DateTimes;
- and finally convert them to something else, if that is what you need.
So DON'T start with ToFileTime(), if at all you should do that at the end and only then.
3.
Your second snippet is very bad; it is calling Environment.TickCount four times, and each of them may well return a different value!
4.
How about this:
DateTime dt1=DateTime.Now;
DateTime dt2=dt1.AddSeconds(10000);
TimeSpan span=dt2-dt1;
string text1=span.Days+"d "+span.Hours+"h "+span.Minutes+"m "+span.Seconds+"s";
string text2=span.ToString();
And obviously you should consider creating a little static method that turns a TimeSpan in the exact format you want everywhere.
|
|
|
|
|
Hi Luc,
Thanks for your reply but I just can't seem to find the error.
long dt1 = DateTime.Now.Ticks;
long dt2 = procs.StartTime.Ticks;
long dt3 = new DateTime(1601, 1, 1, 0, 0, 0).AddTicks(dt2).Ticks;
long ts = (dt1 - dt3) / 10000000;
DateTime ST = new DateTime(ts);
result - System.ArgumentOutOfRangeException: Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
Parameter name: ticks
long dt1 = DateTime.Now.Ticks;
long dt2 = procs.StartTime.Ticks;
long st = (dt1 - dt2)/10000000;
DateTime ST = new DateTime(st);
result - Arithmetic overflow error converting expression to data type datetime,
DateTime dt1 = DateTime.Now;
DateTime dt2 = procs.StartTime;
DateTime dt3 = new DateTime(1601, 1, 1, 0, 0, 0);
DateTime st = dt3.AddSeconds(dt2);
DateTime result = new DateTime(dt1.Subtract(st));
result - none
DateTime dt1 = DateTime.Now;
DateTime dt2 = procs.StartTime;
TimeSpan ts = dt1.Subtract(dt2);
DateTime result = DateTime.Now.Subtract(ts);
result - 01/01/1601 00:00:00
What am I missing?
|
|
|
|
|
CCodeNewbie wrote: What am I missing?
A clear description of what it is you want. Scrap all the code, write a text describing your goal first.
Then read my previous reply once more.
|
|
|
|
|
I would like to get the date & time that the process started.
The process start date/time is in nano seconds (Ticks) whose value is the difference between now and 01/01/1601 00:00:00 + the start date/time.
Thus, startdate/time = a
01/01/1601 00:00:00 = b
now = c
startdate/time = c - a + b
what is the syntax?
|
|
|
|
|
Wouldn't it be far easier to get that from the Process.StartTime property for the process in question?
Documentation can be found here[^].
|
|
|
|
|
Hi Dave,
The "System" process isn't enumerable as part of Process.GetProcesses. It has to be isolated.
I can get all the processes quite easily except for "Idle" - not enumerable & "System" - independently enumerable.
Thanks for your answer though.
|
|
|
|
|
CCodeNewbie wrote: I would like to get the date & time that the process started.
Err....
DateTime startTime = DateTime.Now;
|
|
|
|
|
Hi jschell,
Not sure that you mean.
The process started ~8 days ago but when I can't get that value from process.starttime because it is a tickcount.
Using a tickcount method I get many different answers, none of which are correct (when they don't error that is.
Using a timespan I get 150191.15:00:50.2796717 which is roughly 411 years ago. This means (to me) that the starttime is "stuck" at 1601,1,1,0,0,0.
It looks like the starttime is not directly enumerable as a datetime and has to be deduced.
Thanks for your reply.
|
|
|
|
|
CCodeNewbie wrote: Not sure that you mean.
When your application starts you collect that value.
You use it, not update it, after that.
|
|
|
|
|
Oh my.
1.
CCodeNewbie wrote: is in nano seconds (Ticks) no, ticks is not the same as nanoseconds.
2. forget about 1601, there were no computers back then. Use DateTime exclusively, without worrying about its origin. Just add ticks, seconds, or whatever it is you have.
3. from another of your posts, I get it your description is still no good, as you want to know when the idle process got launched, which amounts to when the system got booted. There is this[^] to handle that, mind you, they unfortunately have chosen a very confusing property name.
|
|
|
|
|
You shouldn't normally be messing around with ticks but since you already have that format:
final DateTime epochStart = new DateTime(1600, 01, 01, 0, 0, 0);
DateTime startTime = new DateTime(ticks - epochStart.Ticks);
And make sure that 'ticks' actually means the same thing. DateTime[^] thinks it means 100ns.
|
|
|
|
|
Hi Bob,
Thanks for your reply but I think you may have lost me a bit as I am not sure which of the examples you reply refers to.
I am also not familiar with "final" as VS2005 won't recognise the "DateTime" portion of "final DateTime epochStart"
Do you mean I should do something like:
long dt1 = DateTime.Now.Ticks;
long dt2 = procs.StartTime.Ticks;
long ticks = dt1 - dt2;
DateTime epochStart = new DateTime(1600, 01, 01, 0, 0, 0);
DateTime startTime = new DateTime(ticks - epochStart.Ticks);
Sorry if it's a stupid question but I have been around-and-around this problem so many times that I have lost a grip on it and was about to exclude the starttime value from the code altogether.
|
|
|
|
|
Uh sorry, I've been writing Java, try 'readonly' (probably 'static readonly'). epochStart can be a psuedo-constant at the class level as it will never change.
I don't understand why you keep trying to bring Now into the equation. The start time is defined by the epoch start and its tick count, nothing to do with the present.
If you have procs.StartTime then, well, I don't understand the problem any more because that is what you are trying to find, right? Just use that DateTime directly ...
|
|
|
|
|
Thanks for your patience Bob,
Not sure why I included the Now operation in my post to you, sorry.
OK, so I tried this
long dt2 = procs.StartTime.Ticks;
DateTime epochStart = new DateTime(1600, 01, 01, 0, 0, 0);
DateTime startTime = new DateTime(dt2 - epochStart.Ticks);
and got
02/01/0002 00:00:00
if I go
DateTime startTime = new DateTime(dt2 + epochStart.Ticks);
I get 01/01/3200 00:00:00.
Interestingly (?) though, if I do this
long st = procs.StartTime.ToFileTime();
depite Luc's instructions, I get 504911232000000000. Dividing that by DateTime Ticks (10000000) I get 504911232 which is 31/12/1985 21:07:12 according to http://www.epochconverter.com/[^]
I think I need to pursue the method described in my reply to Alan's post.
|
|
|
|
|
What is procs.StartTime? Is it this property[^]? That's already a DateTime.
Edit: just seen Alan's post, apparently this property gives you a nonsense value (which you could have checked with the debugger).
|
|
|
|
|
full(ish) code, I am inserting the data int a SQL db thus the "inprocs" stuff...
Process[] processlist = Process.GetProcesses();
foreach (Process procs in processlist)
{
if (procs.ProcessName == "System")
{
insprocs.Parameters.Add("@PStart", SqlDbType.NVarChar, 30).Value = startTime.ToString();
}
}
I am currently ToString-ing it for testing but that may/may not remain the case.
If you try to GetProcesses without separating out the "System" (and "Idle")process,even though it is a DateTime, you get the error "System.ComponentModel.Win32Exception: Unable to enumerate the process modules", probably because of the "System" process's starttime properties.
So I am running GetProcesses 3 times-
1) if ((procs.ProcessName != "Idle") && (procs.ProcessName != "System")) // get everything
2) if (procs.ProcessName == "System") // get everything except "MainModule.FileName" (unenumerable for the System process)
3) if (procs.ProcessName == "Idle") // get only ProcessID, ProcessName (I think I can get RAM in use but I am not sure yet)
Depending on how you manipulate the starttime value, you get different values.
|
|
|
|
|
Process.StartTime is a DateTime. 'Manipulating' it means converting it into some other form that will give you a wrong answer. Now, according to Alan, on the System process this will give you a nonsense answer. That just means that Windows will not give you a sensible answer for that process (presumably because it's not a real process and various things in Windows internals are faking it). If you don't want that nonsense answer in your DB, then you need to use one of the other approaches to calculate a different value.
|
|
|
|
|
Yup, that's pretty much where I am at the moment too, at least until I can figure out the relationship between a known bootup time and the long st = procs.StartTime.ToFileTime().
I have gone back to this, but am struggling to work out how to make "stime" available;
long st = procs.StartTime.ToFileTime();
DateTime stDt = new DateTime(1601, 1, 1, 0, 0, 0).AddSeconds(st);
string stime = String.Empty;
stime += (Environment.TickCount / 86400000).ToString() + ",";
stime += Convert.ToInt32(Environment.TickCount / 3600000 % 24) + ",";
stime += Convert.ToInt32(Environment.TickCount / 120000 % 60) + ",";
stime += (Environment.TickCount / 1000 % 60);
DateTime result = DateTime.Now - new TimeSpan(stime);
currently erroring with "System.FormatException: Input string was not in a correct format."
|
|
|
|
|
Hi Bob,
Other approach used..[^]... can't figure out why I get 2 different results though...
Thanks for all your time today
|
|
|
|
|
Hi Luc,
Tried you code like so
DateTime dt1 = DateTime.Now;
TimeSpan span = dt1 - procs.StartTime;
string text1 = span.Days + "d " + span.Hours + "h " + span.Minutes + "m " + span.Seconds + "s";
string text2 = span.ToString();
result - 150191d 18h 18m 21s
How am I supposed to translate that in to 10/03/2012 09:15:22 (which is the approximate process start time)?
|
|
|
|
|
My bad, I meant to say Ticks are 100 nanosecond units.
TickCount becomes inaccurate (without conditional calculation) if the system is up for more than 24,9 days
To get system uptime I used this
DateTime Utime = new DateTime(1970, 1, 1).AddSeconds(t);
string uptime = String.Empty;
uptime += (Environment.TickCount / 86400000).ToString() + "d";
uptime += (Environment.TickCount / 3600000 % 24) + "h";
uptime += (Environment.TickCount / 120000 % 60) + "m";
uptime += (Environment.TickCount / 1000 % 60) + "s";
|
|
|
|
|
This bit of code will give you the system uptime regardless of how long the system has been running:
TimeSpan uptime = TimeSpan.Zero;
using (var ut = new PerformanceCounter("System", "System Up Time")) {
ut.NextValue();
uptime = TimeSpan.FromSeconds (ut.NextValue());
} /ravi
|
|
|
|
|
The Windows "System" process has a StartTime value of 01/01/1601 00:00:00. It is what it is and there is nothing you can do to transform the value into the actual start time of the process.
You have to accept that Windows is not giving you the start time and assume that 01/01/1601 means "not available". If you want to assign a hypothetical start time corresponding to computer's boot time then do so, but be clear in your own mind that the calculation you do to get that has nothing to do with January 1, 1601.
Alan.
modified 19-Mar-12 9:10am.
|
|
|
|
|