September 5th, 2008

Hey, Scripting Guy! How Can I Tell When I Last Logged On?

Hey, Scripting Guy! Question

Hey, Scripting Guy! I came into work this morning and my computer was running, and it was logged in. Of course I have a locking screen saver, and the screen was locked, but I am positive that I logged out and shut down my computer last night before I went home. Now I am wondering if someone logged into my computer. I know about the security logs and all that stuff, but…okay, here is the question: in other operating systems I have used, they tell me when I last logged on. If they can do that, surely Windows can do that as well, right?

– TW

SpacerHey, Scripting Guy! Answer

Hi TW,

So you cannot remember if you shut your computer down last night or not, and you are worried. Sometimes I cannot remember if I shut mine down last night or not. My first thought as I was reading your letter was, “Hey, we can query the security log and look for things such as failed logon attempts, or look in the system log for system restarts.” But you said you simply want to know when was the last time you logged on to the computer.

The easiest way to do this is to create a script that writes the current time to the registry, and then place that script in the Startup group of your profile. Each time you log on to the computer, the script will query the time from the registry and display this value to you. It will then update the time value that is stored in the registry with the current time from your computer. Obviously this is not a security solution, but it does answer your question, and can perhaps help you with remembering…uh, what was I talking about?

Oh, yes. There are two parts to our answer: the first part is the script itself and the second is the shortcut to the PowerShell script that we place in the Startup group of your profile. First the script:

$command = “LastLogon”
$scriptKey = “hkcu:\software\scripting\$command”

if(test-path -path $scriptKey) { $newdte = (get-date).tostring() $dte = (get-itemproperty -path $scriptKey -name date).date set-ItemProperty -path $scriptKey -name date -value $newdte | out-null ” Your $command was $dte ” } else { “You have no record of $command.” $dte = (get-date).tostring() new-item -path $scriptKey -force | out-null new-itemproperty -path $scriptKey -name date -value $dte | out-null }

We begin the script by creating a couple of variables. The first variable is the $command variable in which we store the string representing the command action we are documenting. Why did I do this? Well, a fundamental Scripting Guy principle is what I call the “Environmental approach to scripting.” Environmental? you ask. Sure. Reduce, recycle, and reuse. Reduce the amount of code you write by recycling scripts you have previously written, and reuse functions and subroutines you have squirreled away in other scripts. So as I write this script, I am thinking you may want to use this script to document when other commands may have been run as well. All you would need to do is change the value of the $command variable. The second variable we create points to the place in the registry where we will store this information. We choose the HKEY_CURRENT_USER\Software hive, and we are creating the scripting key for our use. These two commands are seen here:

$command = “LastLogon”
$scriptKey = “hkcu:\software\scripting\$command”

When you log on to the computer and the script runs, it checks to see if the registry key exists by using the Test-Path cmdlet. If the key exists, we use the Get-Date cmdlet and convert it to a string by using the tostring method. We then store the string in a variable named $newdte. Now that we have the current time, we use the Get-ItemProperty cmdlet to read the date value from the registry and store it in a variable named $dte. We then write the date string held in $newdte to the registry using Set-ItemProperty and display the message telling you when your last logon was. This message is seen here:

First run graphic

 

The code that performs the registry check, updates the registry, and displays the logon message is seen here:

if(test-path -path $scriptKey)
 {
  $newdte = (get-date).tostring()
  $dte = (get-itemproperty -path $scriptKey -name date).date
  set-ItemProperty -path $scriptKey  -name date -value $newdte  | out-null
   ”
     Your  $command was $dte 
   ”
 }

There is another scenario: This is the first time you run the script. In this case, there will be no registry key, so there will be no value to display. We need to store the current date time, create the registry key, and display a notification message. The first thing we will do is store the current date and time. To do this, we will essentially use the same line of code we used earlier. We use the Get-Date cmdlet and turn it into a string. This is seen here:

$dte = (get-date).tostring()

Next we need to create the registry key and update it with the time value. When the registry key is created, it will look similar to the registry settings seen here:

Registry graphic

 

To create the registry key and set its value, we need to first create the registry key, and then create the property associated with the key. To create the registry key we use the New-Item cmdlet and specify the path to the registry key. Next, we use the New-ItemProperty cmdlet to create the date property. These two lines of code are seen here:

  new-item -path $scriptKey  -force | out-null
  new-itemproperty -path $scriptKey -name date -value $dte | out-null

Because we need to let the user know that no value was stored in the registry, we print out a string message seen here:

“You have no record of $command.”

When this command runs, the screen displays the friendly message seen here:

Second run graphic

 

Putting the code together, this section of the code is seen here:

else
 {
  “You have no record of $command.”
  $dte = (get-date).tostring()
  new-item -path $scriptKey  -force | out-null
  new-itemproperty -path $scriptKey -name date -value $dte | out-null
 }

The trick to making all this work was the shortcut we created to run the script. The easiest way to create the shortcut is to go to theStartup folder in your profile, right-click the folder, and click New Shortcut. Specify the path to the script, and click OK until the shortcut is created. You now have a shortcut to the script. The problem is that the default file association for a PowerShell script is Notepad. Therefore, when you log in, the script will be displayed in Notepad. Not exactly what you had in mind.

To change this behavior we need to specify that we want to execute the script in PowerShell. To do this, open the Properties of the shortcut, go to the Shortcut tab and edit the target by typing PowerShell.exe -noexit -noprofile in front of the path to your script. This will cause PowerShell to launch the script, leave the PowerShell prompt open, and not use your profile. If you wish to have your profile, you can delete the -noprofile command. If you can read really really fast, you could leave the -noexit switch off as well; just don’t blink when the script runs. This figure below displays the trick for making the shortcut launch your PowerShell script:

First run graphic

 

Well, TW, I hope this script helps you to remember whether you logged off or not before you left for home. Now I know how I’m going to remember my wedding anniversary…

Ed Wilson and Craig Liebendorfer, Scripting Guys

Author

0 comments

Discussion are closed.