Not too long ago, I wrote an MCPMag Tip Sheet column on using the pipeline in PowerShell. I showed how you could get the start time of a specified service:
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
$svcname=Read-Host "Enter a service name" ; get-process | where {$_.id -eq (get-wmiobject win32_service | where {$_.name -eq $svcname}).ProcessID} | select -property StartTime
We can take this a step further and calculate the Uptime. Let's look at a quick one-line example using a process:
(get-date).Subtract((Get-Process firefox).starttime)
This expression subtracts the start time property of the Firefox process from the current date and time. When executed, you should get output like this:
Days : 1
Hours : 4
Minutes : 20
Seconds : 29
Milliseconds : 506
Ticks : 1020295067859
TotalDays : 1.18089706928125
TotalHours : 28.34152966275
TotalMinutes : 1700.491779765
TotalSeconds : 102029.5067859
TotalMilliseconds : 102029506.7859
If I wanted nicer output from my one-liner I can clean it up like this:
$u=(get-date).Subtract((Get-Process firefox).starttime);Write-Host $u.Days day $u.hours hours $u.minutes minutes and $u.seconds seconds
This is one single line expression.
Since all services are associated with a process, we can find the uptime of the process and thus the service. Except for some shared services that use svchost, this should be pretty accurate. I've split this back up into separate expressions to make it easier to follow:
$svcname=Read-Host "Enter a service name"
$p=Get-Process | where {$_.id -eq (Get-WmiObject win32_service | where {$_.name -eq $svcname}).ProcessID} | select -property StartTime
write-host $svcname service
$u=(get-date).Subtract($p.StartTime)
Write-Host $u.Days day $u.hours hours $u.minutes minutes and $u.seconds seconds
Not too shabby. The process is a little tedious because I have to query each service via WMI to get it's associated process. To wrap this up, let's go whole hog and report on the uptime for each running service. You'll really need to put this in a script.
Function Get-ProcessUptime {
param([string]$svcname)
$p=Get-Process | where {$_.id -eq (Get-WmiObject win32_service | where {$_.name -eq $svcname}).ProcessID} | select -property StartTime
$u=(get-date).Subtract($p.StartTime)
Write-Host $svcname service `t $u.Days day $u.hours hours $u.minutes minutes and $u.seconds seconds
}
foreach ($svc in (get-service | where {$_.status -eq "running"})) {Get-ProcessUptime $svc.name}
I've put the uptime code in a function that takes a service name as a parameter. I then get a list of running services and pass each one to the function. There's probably a more efficient way to do this, but it doesn't jump out at me right now.
Bonus:
Get uptime for all processes:
foreach ($proc in (Get-Process | where {$_.name -ne "Idle" -AND $_.name -ne "System"})) {
$u=(get-date).Subtract($proc.starttime);
Write-Host $proc.name `t $u.Days day $u.hours hours $u.minutes minutes and $u.seconds seconds
}
Are you aware of any way to do this remotely? The starttime doesn’t seem to be available from Win32_process through WMI.
As you are aware Get-Process only works locally. You could get the same result but you’d need to use Get-WMIObject and the Win32_Process class. There is CreationDate property you could use, although you’d need to convert it to a usable date format. I don’t have anything handy in Powershell to show you. But you might take a look at my Mr. Roboto column from August 2007 (http://redmondmag.com/columns/article.asp?EditorialsID=1860)
I wrote an HTA that reports on processes for any given computer including how long the process has been running. It’s VBScript but it might get you on the right track until I can put something together for PowerShell.