It is currently March 29th, 2024, 9:49 am

Help with getting uptime for selected Process

Get help with creating, editing & fixing problems with skins
robin_3010
Posts: 2
Joined: December 7th, 2016, 9:19 pm

Help with getting uptime for selected Process

Post by robin_3010 »

Hi, I'm trying to get process uptime with Perfmon, but all I get is strange mix of windows timestamp and process uptime in seconds, which also doesn't updating at all even with with DynamicVariables=1.

Code: Select all

[mUptime]
Measure=Plugin
Plugin=PerfMon
PerfMonObject=Process
PerfMonCounter=Elapsed Time
PerfMonInstance=Rainmeter
PerfMonDifference=0
DynamicVariables=1
and I get measure value something like this 131400521842129056.
Is it possible to get that type of info from perfmon correctly? Get it at least in seconds would be enough for me.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with getting uptime for selected Process

Post by jsmorley »

This is actually moderately complicated, but certainly possible.

What Perfmon returns is a Windows FILETIME number, which is defined as the number of 100-nanosecond increments since January 1, 1601. While the Perfmon interface / UI shows the number of "elapsed seconds", that is not what it returns to functions that ask for the underlying raw numbers like the Perfmon plugin for Rainmeter does. It's not really tracking "uptime", but just tracks when the application was started. The Perfmon.exe interface figures out the "elapsed seconds" from the raw data , and that is what you want to do.

So what you get is a number like 131402166815389584. What we want to do is convert that to a date/time that we can subtract from the current date/time to get the difference.

To do that, we will use the TimeStamp option on a Time measure to get the time represented by that number. HOWEVER, the TimeStamp option is measured in "seconds", while the FILETIME structure is in 100-nanoseconds. To fix that we divide the number returned by 10000000.

https://docs.rainmeter.net/manual/measures/time/
https://docs.rainmeter.net/manual/measures/time/#TimeStamp

Code: Select all

[mUptime]
Measure=Plugin
Plugin=PerfMon
PerfMonObject=Process
PerfMonCounter=Elapsed Time
PerfMonInstance=Rainmeter
PerfMonDifference=0
UpdateDivider=-1

[MeasureUptimeStamp]
Measure=Time
Format=%A, %B %#d, %Y at %I:%M:%S %p
TimeStamp=([mUptime:] / 10000000)
DynamicVariables=1
UpdateDivider=-1
That will return a string representing that date / time in the format Thursday, May 25, 2017 at 08:11:21 PM and a :TimeStamp number that is the number of seconds from January 1, 1601 that Rainmeter was started on. Note that the timestamp value is expressed in GMT, not local time.

Then we just need the current time IN GMT, (ignoring Daylight Saving Time) and then subtract them.

Code: Select all

[MeasureCurrentTimeGMT]
Measure=Time
Format=%A, %B %#d, %Y at %I:%M:%S %p
TimeZone=0
DaylightSavingTime=0

[MeasureDiff]
Measure=Calc
Formula=[MeasureCurrentTimeGMT:TimeStamp] - [MeasureUptimeStamp:TimeStamp]
DynamicVariables=1
That [MeasureDiff] measure will be the number of seconds difference from when Rainmeter was started until now.


Extra Credit:

If you want to format those seconds into something more useful, i recommend a pretty simple Lua script. to do it first create a Script measure somewhere in the skin:

Code: Select all

[MeasureConvertSeconds]
Measure=Script
ScriptFile=#CURRENTPATH#FormatSeconds.lua
UpdateDivider=-1
Then create a FormatSeconds.lua text file in the same folder as the skin, and in it put:

Code: Select all

function ParseSeconds(inputSeconds,meterName)

	local days, hours, minutes, seconds = FormatSeconds(tonumber(inputSeconds))

	SKIN:Bang('!SetOption', meterName, 'Text', 'Rainmeter Uptime: '..days..' days '..hours..' hours '..minutes..' minutes '..seconds..' seconds')
	SKIN:Bang('!UpdateMeter', '*')
	SKIN:Bang('!Redraw')
	
end

function FormatSeconds(secondsArg)

	local days = math.floor(secondsArg / 86400)
	local hours = math.floor((secondsArg - days * 86400) / 3600)
	local minutes = math.floor((secondsArg - days * 86400 - hours * 3600) / 60)
	local seconds = math.floor(secondsArg - days * 86400 - hours * 3600 - minutes * 60)
	
	return days, hours, minutes, seconds
	
end
Last, on the [MeasureDiff] measure, add an OnUpdateAction that executes the function in the script:

Code: Select all

[MeasureDiff]
Measure=Calc
Formula=[MeasureCurrentTimeGMT:TimeStamp] - [MeasureUptimeStamp:TimeStamp]
DynamicVariables=1
OnUpdateAction=[!CommandMeasure MeasureConvertSeconds "ParseSeconds([MeasureDiff:],'MeterUptime')"]
My final example skin will look like:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[MeasureConvertSeconds]
Measure=Script
ScriptFile=#CURRENTPATH#FormatSeconds.lua
UpdateDivider=-1

[mUptime]
Measure=Plugin
Plugin=PerfMon
PerfMonObject=Process
PerfMonCounter=Elapsed Time
PerfMonInstance=Rainmeter
PerfMonDifference=0
UpdateDivider=-1

[MeasureUptimeStamp]
Measure=Time
Format=%A, %B %#d, %Y at %I:%M:%S %p
TimeStamp=([mUptime:] / 10000000)
DynamicVariables=1
UpdateDivider=-1

[MeasureCurrentTimeGMT]
Measure=Time
Format=%A, %B %#d, %Y at %I:%M:%S %p
TimeZone=0
DaylightSavingsTime=0

[MeasureDiff]
Measure=Calc
Formula=[MeasureCurrentTimeGMT:TimeStamp] - [MeasureUptimeStamp:TimeStamp]
DynamicVariables=1
OnUpdateAction=[!CommandMeasure MeasureConvertSeconds "ParseSeconds([MeasureDiff:],'MeterUptime')"]

[MeterExplain]
Meter=String
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
DynamicVariables=1
Text=Number seconds from January 1, 1601 to when Rainmeter was started: [MeasureUptimeStamp:TimeStamp]#CRLF#Date format of that value in GMT time: [MeasureUptimeStamp]#CRLF##CRLF#Date format of the current GMT time: [MeasureCurrentTimeGMT]#CRLF##CRLF#Difference in seconds: [MeasureDiff:]

[MeterUptime]
Meter=String
Y=10R
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
DynamicVariables=1
And will display:
1.png
You do not have the required permissions to view the files attached to this post.
robin_3010
Posts: 2
Joined: December 7th, 2016, 9:19 pm

Re: Help with getting uptime for selected Process

Post by robin_3010 »

Thank you kindly, jsmorley!
I somehow missed that fact that filetime number format is in 100-nanoseconds. Also, thanks for greatly explaining the logic of this perfmon counter, I would spend more time to figure it out on my own.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with getting uptime for selected Process

Post by jsmorley »

Glad to help.