Add to Technorati Favorites
Welcome to ThePowerShellGuy.com Sign in | Join | Help

Hey, PowerShell Guy ! How Can I Get the Uptime of a Service?

And another Hey, Scripting Guy ! translation to powerShell How Can I Get the Uptime of a Service?

The PowerShell translation :

$s = gwmi win32_service -filter "name = 'spooler'" 
"{0}" -f ((get-date) - ([wmi]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDate)) 

 I do output the Uptime in default formatting as I find this more clear, so it looks like this :

 

PoSH> $s = gwmi win32_service -filter "name = 'spooler'"                                                                
PoSH> "{0}" -f ((get-date) - ([wmi]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").Cr
eationDate))                                                                                                            
1.22:57:49.1208030                                                                                                      
PoSH>                                                   

 

You see that again this is very simple in PowerShell, just 2 lines,

Only that second line might look a bit cryptic at first look as a lot of processing happens in this single line, but as you break it apart you will see it's not as difficult as it looks, and easy to create using the "Admin Development Method" and REPL (Read, Evaluate, Print, loop)

 so let's work out how I came to this

 Lets start with the first line :

PoSH> gwmi win32_service -filter "name = 'spooler'"                                                                     
                                                                                                                        
                                                                                                                        
ExitCode  : 0                                                                                                           
Name      : Spooler                                                                                                     
ProcessId : 1536                                                                                                        
StartMode : Auto                                                                                                        
State     : Running                                                                                                     
Status    : OK                                                                                                          
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH>                                                  

 but as you could see in the original Article the Win32_Service does not provide to uptime

Now, ideally, we’d be done at this point: we’d simply report back the date and time that the service started. That would be nice, but, for better or worse, the Win32_Service class doesn’t include a property that tells us when the service started. So does that mean that all is lost? Yes, yes it does.

Ha-ha; sometimes we crack ourselves up. No, in the wonderful world of scripting nothing is ever lost. While it’s true that the Win32_Service class doesn’t have a property that tells us when a service was started, it does have a property that tells us the process ID (PID) of the process in which the service is running. Is that useful? You bet it: we can take that PID and use it to retrieve process information from the Win32_Process class. Is that useful? Of course it is: after all, the Win32_Process class just happens to have a property (CreationDate) that tells us when the process started.

So next we need to get the ProcessID and use that to construct a new get-WmiObject command to get back the Process, so I save the result in the variable $s, and go on :

PoSH> $s = gwmi win32_service -filter "name = 'spooler'"                                                                
PoSH> $s.ProcessId                                                                                                      
1536                                                                                                                    
PoSH> gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'"                                                        
                                                                                                                        
                                                                                                                        
ProcessName                : spoolsv.exe                                                                                
Handles                    : 333                                                                                        
VM                         : 88211456                                                                                   
WS                         : 6844416                                                                                    
Path                       :                                                                                            
__GENUS                    : 2                                                                                          
__CLASS                    : Win32_Process                                                                              
__SUPERCLASS               : CIM_Process                                                                                
__DYNASTY                  : CIM_ManagedSystemElement                                                                   
__RELPATH                  : Win32_Process.Handle="1536"                                                                
__PROPERTY_COUNT           : 45                                                                                         
__DERIVATION               : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemElement}                                
__SERVER                   : MowVista                                                                                 
__NAMESPACE                : root\cimv2                                                                                 
__PATH                     : \\MowVista\root\cimv2:Win32_Process.Handle="1536"                                        
Caption                    : spoolsv.exe                                                                                
CommandLine                :                                                                                            
CreationClassName          : Win32_Process                                                                              
CreationDate               : 20070227192629.875000+060                                                                  
CSCreationClassName        : Win32_ComputerSystem                                                                       
CSName                     : MowVista                                                                                
Description                : spoolsv.exe                                                                                
ExecutablePath             :                                                                                            
ExecutionState             :                                                                                            
Handle                     : 1536                                                                                       
HandleCount                : 333                                                                                        
InstallDate                :                                                                                            
KernelModeTime             : 6406250                                                                                    
MaximumWorkingSetSize      :                                                                                            
MinimumWorkingSetSize      :                                                                                            
Name                       : spoolsv.exe                                                                                
OSCreationClassName        : Win32_OperatingSystem                                                                      
OSName                     : Microsoftr Windows VistaT Ultimate |C:\Windows|\Device\Harddisk0\Partition2                
OtherOperationCount        : 3473                                                                                       
OtherTransferCount         : 14668                                                                                      
PageFaults                 : 8591                                                                                       
PageFileUsage              : 5562368                                                                                    
ParentProcessId            : 588                                                                                        
PeakPageFileUsage          : 5750784                                                                                    
PeakVirtualSize            : 90451968                                                                                   
PeakWorkingSetSize         : 9691136                                                                                    
Priority                   : 8                                                                                          
PrivatePageCount           : 5562368                                                                                    
ProcessId                  : 1536                                                                                       
QuotaNonPagedPoolUsage     : 10672                                                                                      
QuotaPagedPoolUsage        : 141784                                                                                     
QuotaPeakNonPagedPoolUsage : 13104                                                                                      
QuotaPeakPagedPoolUsage    : 145104                                                                                     
ReadOperationCount         : 26                                                                                         
ReadTransferCount          : 2637                                                                                       
SessionId                  : 0                                                                                          
Status                     :                                                                                            
TerminationDate            :                                                                                            
ThreadCount                : 18                                                                                         
UserModeTime               : 4062500                                                                                    
VirtualSize                : 88211456                                                                                   
WindowsVersion             : 6.0.6000                                                                                   
WorkingSetSize             : 6844416                                                                                    
WriteOperationCount        : 457                                                                                        
WriteTransferCount         : 379016                                                                                     
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH>                                                  

 You can see that this is about the same as the first line, only now I use the Win32_Prosess class and the ProcessId I did find in my first Command, I use the $() construct (that will execute the command inside the parenthesis and will add it to the string, like it is a variable that get's substituted)  here to merge this with the rest of the filter string.

 Now I only need the CreationDate, so I will only select that, this time I do not use a variable, but just used the UP key to get the former command and place it in Parenthesis, this tells PowerShell to first execute the code and then I can get the Property from the result without using a variable to store the output first.

PoSH> (gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDate                                         
20070227192629.875000+060                                                                                               
PoSH>                                                 

 Ok, so far so good, but as this date is in WMI format so not really usefull, next task is to translate this to a normal date.

In the VbScript example the string is parsed and a date is constucted from that, in PowerShell we can also do that but there is a much simpler way, every WMI Object has some Standard ScriptMethods in PowerShell we can use for this : 

PoSH> $s | gm -MemberType ScriptMethod                                                                                  
                                                                                                                        
                                                                                                                        
   TypeName: System.Management.ManagementObject#root\cimv2\Win32_Service                                                
                                                                                                                        
Name                MemberType   Definition                                                                             
----                ----------   ----------                                                                             
ConvertFromDateTime ScriptMethod System.Object ConvertFromDateTime();                                                   
ConvertToDateTime   ScriptMethod System.Object ConvertToDateTime();                                                     
Delete              ScriptMethod System.Object Delete();                                                                
GetType             ScriptMethod System.Object GetType();                                                               
Put                 ScriptMethod System.Object Put();                                                                   
                                                                                                                        
                                                                                                                        
PoSH> $s.ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDate)                   
                                                                                                                        
Tuesday, February 27, 2007 7:26:29 PM                                                                                   
                                                                                                                        
                                                                                                                        
PoSH> ([WMI]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDate)            
                                                                                                                        
Tuesday, February 27, 2007 7:26:29 PM                                                                                   
                                                                                                                        
                                                                                                                        
PoSH>                                                  

 You see that you can use the $s variable holding the Win32_Service for this, but as I find that a bit confusing (as  ConvertToDateTime is not a Method of the Win32_Service WMI class but a Common helper Method) , so I normaly create an "Empty" WMI class for this ([WMI]'').

Now we have the Start time of the service as a DateTime object so it is readable and easy to work with. 

 to get the uptime we only need to get the current time with Get-Date and substract the startTime we have collected now

PoSH> get-date                                                                                                          
                                                                                                                        
Thursday, March 01, 2007 7:23:21 PM                                                                                     
                                                                                                                        
                                                                                                                        
PoSH> get-date - ([WMI]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDate) 
Get-Date : A parameter cannot be found that matches parameter name '-'.                                                 
At line:1 char:9                                                                                                        
+ get-date  <<<< - ([WMI]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDat 
e)                                                                                                                      
PoSH> (get-date) - ([WMI]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDate
)                                                                                                                       
                                                                                                                        
                                                                                                                        
Days              : 1                                                                                                   
Hours             : 23                                                                                                  
Minutes           : 57                                                                                                  
Seconds           : 25                                                                                                  
Milliseconds      : 189                                                                                                 
Ticks             : 1726451897715                                                                                       
TotalDays         : 1.99820821494792                                                                                    
TotalHours        : 47.95699715875                                                                                      
TotalMinutes      : 2877.419829525                                                                                      
TotalSeconds      : 172645.1897715                                                                                      
TotalMilliseconds : 172645189.7715                                                                                      
                                                                                                                        
                                                                                                                        
                                                                                                                        
PoSH>                                                  

 you can see we need to use parentheses again to first execute the get-date Cmdlet and get a [dateTime] object and then we can substract the StartTime, otherwise the parser will think the - indicates a parameter to get-date.

We are almost ready but this is a bit to much information so let's format it a bit, as said I liked the default formatting better so I just used that but I will show first how you could use and format that also (for readability I used an extra helper variable first, as the scriptline was constructed by using the UP arrow and append extra code to the line, test it and then add the next step, while making the script, I did just add () again and did put "{}" -f in front (REPL) :

 

PoSH> ((get-date) - ([WMI]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").CreationDat
e)).TotalMinutes                                                                                                        
2886.58836705                                                                                                           
PoSH> $timeSpan = (get-date) - ([WMI]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").
CreationDate)                                                                                                           
PoSH> $timeSpan.TotalMinutes                                                                                            
2887.024227825                                                                                                          
PoSH> [int]$timeSpan.TotalMinutes                                                                                       
2887                                                                                                                    
PoSH> "{0}" -f $timeSpan.TotalMinutes                                                                                   
2887.024227825                                                                                                          
PoSH> "{0:n0}" -f $timeSpan.TotalMinutes                                                                                
2,887                                                                                                                   
PoSH> "{0}" -f $timeSpan                                                                                                
2.00:07:01.4536695                                                                                                      
PoSH> "{0}" -f ((get-date) - ([wmi]'').ConvertToDateTime((gwmi Win32_Process -filter "ProcessID = '$($s.ProcessId)'").Cr
eationDate))                                                                                                            
2.00:09:28.1483820                                                                                                      
PoSH>                                                  

 

 you can see that you can just cast the Minutes to an Int to round it

but you can also use the Format String ( -f ) operator for this, also note that I did not use $() here as I did with the ProcessID before but -f.

Using -f is much easier here because I already have quotes in my command allready , so embedding in a string another time would give a lot of Escaping problems, this can be solved by using a variable to store result first, but using -f for this is much easier as the escaping problems are not there and I can keep on using REPL and just use the UP arrow and put some code in front.

I hope this post will show how to use the Admin Development method in PowerShell to tackle this kind of tasks, and how the Interactive use of the PowerShell console, and using the command history for REPL supports this.

As I use this kind of oneliners a lot, and you can find a lot of PowerShell  oneLinerson the internet .

I hope this also shows, that if you find a onliner like this and do not understand the workings of it, how  you can can break it apart in pieces and analyze and/or try them part by part, what makes it easier to follow and that way helps understanding the complete script.

Enjoy,

Greetings /\/\o\/\/

Published Thursday, March 01, 2007 1:06 PM by admin

Comments

# re: Hey, PowerShell Guy ! How Can I Get the Uptime of a Service?

Using get-process allows an even shorter solution. The second line would be:

"{0}" -f ((get-date) - (gps -id $s.processid).Starttime)

Thursday, March 01, 2007 5:09 PM by Martin

# re: Hey, PowerShell Guy ! How Can I Get the Uptime of a Service?

@ Martin,

thanks,

yep that even a better solution, missed that

Greetings /\/\o\/\/

Friday, March 02, 2007 2:41 AM by MoW

# re: Hey, PowerShell Guy ! How Can I Get the Uptime of a Service?

Just wanted to say these are awesome! I don't really want to script in vbscript right now and would prefer to stick to Powershell, so your "translations" to PowerShell of the Scripting Guys' stuff is awesome and much appreciated!

Friday, March 02, 2007 2:12 PM by LonerVamp
Anonymous comments are disabled