Sunday, March 7, 2010

Last Logon User and Time

Need to find out who the last person to log into a computer was and what time they did? Here you go!

CODE

$data = @()

$NetLogs = Get-WmiObject Win32_NetworkLoginProfile

foreach ($NetLog in $NetLogs) {
    if ($NetLog.LastLogon -match "(\d{14})") {
        $row = "" | Select Name,LogonTime
        $row.Name = $NetLog.Name
        $row.LogonTime=[datetime]::ParseExact($matches[0], "yyyyMMddHHmmss", $null)
        $data += $row
    }
}

$data | Sort LogonTime -Descending | Select -First
 code: copy : expand : collapse
EXPLANATION
The WMI class Win32_NetworkLoginProfile contains logon information for every valid session since the machine was booted. It does have limits, but this statement is generally true. We'll grab all instances of this and parse through one at a time.

Not all logons have a valid time stamp. Only interactive logons via the console or RDP do. So, we must filter them out. That's where we use if ($NetLog.LastLogon -match "(\d{14})"). This looks for a match of 14 decimals. (\d = decimals, {14} = 14 characters). Because the timestamp is not in a standard format we cannot use PowerShell's Get-Date, we must utilize .Net's [datetime] to parse it. DateTime's ParseExact is in the format (InputString,Format,IFormatProvider). Here we have $matches[0] as the input string (created by PoSh when using the -matches comparison). Please see http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo.aspx for the DateTimeFormat information. Since we're not using any other custom Format interface the 3rd input is $null)

Once all the data is gathered and filtered out we only want to show the most recent logon time. To do this we sort by LogonTime in a Descending order and only Select the -First.

Done!

Monday, March 1, 2010

Importing a TSV

I have been playing around a bit today with .tsv files (Tab Seperated).  Most of the time this would simply be a matter of using import-csv filename.csv.  Well, what happens when the header row has spaces or special characters, or you have no header row?  Create one.

CODE

$data = @()
$list = gc file.tsv

foreach ($line in $list) {
    $row = "" | Select One,Two,Three,Four,Five
    $row.One = ($line.Split("`t"))[0]
    $row.Two = ($line.Split("`t"))[1]
    $row.Three = ($line.Split("`t"))[2]
    $row.Four = ($line.Split("`t"))[3]
    $row.Five = ($line.Split("`t"))[4]
    $data += $row
}
 code: copy : expand : collapse
EXPLANATION
I have used $row = "" | Select One,Two,Three,Four,Five to create headers called One,Two..., but these can be renamed to anything a bit more meaning full. Remember, no space or special characters. That was the original point of this. Once the header is created then we simply use the .Split() method to create an array of strings from each line. Simple enough!

Thursday, January 7, 2010

Custom aliases

If there is one thing missing from PowerShell it is definately aliases.  The 100+ provided in 2.0 just aren't enough.  Graciously, the folks at MS understand our pain, and have given us the ability to create custom aliases in PoSh 2.0.

ONELINER

Set-Alias se Set-ExecutionPolicy
 code: copy : expand : collapse

EXPLANATION
This creates a new alias named "se" for the CmdLet Set-ExecutionPolicy.  Very simple.  Now, substitute any alias name you would like for any CmdLet (or even scriptlet, executable,...)

NOTE
This is great, but it does not stay.  Once your session is closed, the alias goes away.  So how do we keep it constant?  Add it to your profile.

Tuesday, January 5, 2010

Determining OS Bit-Level

With x64 computing quickly overtaking 32-bit environments a vast need has been created to know what bit-level on which a given OS is running.  Welcome back PowerShell and WMI

ONELINER

(gwmi win32_computersystem).SystemType
 code: copy : expand : collapse

EXPLANATION
Opening the Win32_ComputerSystem class gives us very useful information such as the mfg model, computer name, domain,...the list goes on.  What we are looking for is the OS architecture (bit-level).  We're able to retrieve this throught the SystemType property.  On a x64 OS it will return "x64-based PC", and "X86-based PC" for a 32-bit OS.

Friday, December 11, 2009

HashtoArray

A few days ago powershell.com's blogger David Fargo put out a great little trick to change a hash table into a psobject (http://app.en25.com/e/es.aspx?s=1403&e=242&elq=82fe96d591f745bc820e8359018e3ffe). That was a great start, but really did not seem to usefull without a few more tweaks. Why? Because it was still just a single object from which you would get the same information.  Example:

$hash.Firstname = "Tobias"
$object.Firstname = "Tobias"

Now, we can add this new object into an array and create useful mergers of data to create full tables.

CODE

$array = @()

$hash = @{}
$hash.Firstname = "Tobias"
$hash.Lastname = "Weltner"
$hash.Age = 99
$object = New-Object PSObject -Property $hash
$array += $object

$hash = @{}
$hash.Firstname = "Adrian"
$hash.Lastname = "Caliente"
$hash.Age = 47
$object = New-Object PSObject -Property $hash
$array += $object

$array)}

 code: copy : expand : collapse

Thursday, December 3, 2009

Mapping a network drive on a remote computer

As many blogs have stated there is a a quick way to map network drives within PowerShell; create a Wscript.Network object and use the MapNetworkDrive method.  Example:
(New-Object -Com WScript.Network).MapNetworkDrive("u:",\\computer\share)

Now, that is great to run localy, but New-Object does not connect to a remote computer.  So, with PoSh 2.0 and Remoting, we now can create remote sessions and run the command as though it was local to the remote computer.

CODE

$session = new-pssession -ComputerName computer1
invoke-command -session $session -scriptblock {(New-Object -Com WScript.Network).MapNetworkDrive("u:",\\computer\share)}

 code: copy : expand : collapse

EXPLANATION
When this is run a new session will open on the remote computer and keep it open as a local object to be called later.  invoke-command will use this session and run the scriptblock necessary to map the network drive

Wednesday, December 2, 2009

GetMotherboardModel


ONELINER

gwmi win32_computersystem | select Manufacturer,Model | fl "
 code: copy : expand : collapse

EXPLANATION
Using WMI (of course) we can pull a great amount of information about the physical computer equipment. Items such as amount of memory, computer name... many others. We're interested in getting the motherboard model and manufacturer. Lets gather all information, and only display these two items using select. For a full list of what is available, try this: gwmi win32_computersystem | select *

ALIASES
GWMI = Get-WMIObject