Thursday, 19 July 2012

LttP: Powershell Games 2012 - Beginner Event 10

Here goes my entry for Beginner Event 10:

for($i=0;$i -lt 3; $i++){(Get-Counter -ListSet Processor).Paths | Get-Counter | Out-File (Join-Path ([Environment]::GetFolderPath("mydocuments")) $env:COMPUTERNAME"_ProcessorCounters.txt") -Append;Start-Sleep 5}

I went for the "one-liner" option basically just to help me get into the habit of cleaning my own code up a bit.

This one was quite fun really, it took me a few tries with Out-File to realised I needed the "-Append", as I'm used to using Add-Content instead.

Also, the construction of the path threw me for a minute, until I remembered about "Join-Path".

Time to read what the Expert has to say :)

UPDATE:

The results are right, but the method is a bit...wonky.

Firstly, I could've just used the "-SampleInterval" and "-MaxSamples" switches with the "Get-Counter" cmdlet, instead of doing a For loop with a "Start-Sleep".

Secondly, "[Environment]::GetFolderPath("mydocuments")" isn't strictly native Powershell, it pulls in the .NET framework.  I was going to go with the way the Expert did, but I let my self-doubt creap in when I read the Scripting Wife's comments.

Unfortunately I was late to the party (LttP) so I won't ever really know how I would've been scored for real, but I've learned quite a bit and had some fun with it.

I'm really looking forward to the games next year, and then I'll see how I do for real!

LttP: Powershell Games 2012 - Beginner Event 9

Here's my entry for Beginner Event 9:

Get-EventLog -LogName Application -EntryType "Information" -InstanceId 10001 -Source "Microsoft-Windows-Winsrv" | Format-Table -Property "TimeGenerated","ReplacementStrings" -AutoSize

I'm pretty confident that I'm there, as it's as filtered as possible without restricting to a given application that causes the error.

I did have to follow the tip in the comments about how to create the item in the log and admittenly I was pretty frustrated with this one up to that point.  Then using the "Details" part of the Event Viewer GUI helped me find the "proper" source name.

Anyway, time to see the expert commentary.

LttP: Powershell Games 2012 - Beginner Event 8

Beginner Event 8 has me a bit worried, as I think it's a bit easy.  That normally means I've missed something big and, normally, painfully obvious...

As far as I can tell the design points boil down to this:
  • Write the output to the host
  • Check if the machine is a laptop or desktop based on hardware
  • Only run it on the local computer
  • If it needs admin rights, check that it's running as admin
  • Use a simple function that returns a Boolean value
This means that the whole "inventory of machine on the network" part is a red-herring, and that what I should end up with is something fairly simple.

Here's my thought process on how I tackled those design points:
  • Build up my "message" and use Write-Host to output it at the end
  • Check for a battery using WMI (there is probably a WMI class for that...)
  • Local computer only...no problem
  • Get-WMIObject doesn't need admin rights...so I'm good here so far
  • I'll use a function to work out if the machine has a battery, then use an If statement to amend the message accordingly
Turns out I was right about WMI and there is a Win32_PortableBattery class.  When I run it on my desktop I get nothing, and an error is thrown when trying to run the following:

Get-WMIObject Win32_PortableBattery | Get-Member

That looks good to me, because my desktop doesn't have a portable battery. 

I checked Get-WMIObject Win32_PortableBattery on a laptop and it returned results so, armed with that confidence I charged off and wrote the following to become my "entry":

Function Is-Laptop
{
 If(Get-WMIObject Win32_PortableBattery)
 {
  Return $true
 }
 else
 {
  Return $false
 }
}

$comupterType="desktop"

If(Is-Laptop)
{
 $comupterType="laptop"
}

$Message=$Env:COMPUTERNAME
$Message+=" is a "
$Message+=$comupterType

write-host $Message

Time to read the expert commentary.

UPDATE:

I'm not sure how I would've scored as I used a different WMI class than the expert, and therefore a slightly different approach for figuring out if a machine was a desktop or laptop.

In my entry I basically said that if the machine has a portable battery then it's a laptop; which isn't strictly true because of tablets and slates (although not all that common); but I considered it a reasonable assumption.

LttP: Powershell Games 2012 - Beginner Event 7

Beginner Event 7 had me delving into the "new" logging system and scratching my head with regards to what a "hidden log" might be.

I've taken it to mean a Debug / Analytic log, and as such my "entry" follows:

Get-WinEvent -ListLog * -Force -EA 0 | Where-Object {($_.IsEnabled -eq $true) -and ($_.RecordCount)} | Sort-Object RecordCount -Descending | Format-Table -Property "LogName","RecordCount" -AutoSize -Wrap

Time to check the expert blog...

UPDATE:

It would appear I didn't need the "-Force" according to the expert, and also I could loose the "-eq $true" from my Where-Object clause (as IsEnabled is already a boolean.)

Wednesday, 18 July 2012

LttP: Powershell Games 2012 - Beginner Event 6

Well, Beginner Event 6 looks quite familiar.  I've had to do exactly this before, albeit with a different output.  Anyway my "entry":

[datetime]$LastBootTime = (Get-WmiObject Win32_OperatingSystem).ConvertToDateTime((Get-WmiObject Win32_OperatingSystem).LastBootUpTime)
$UpTime = New-TimeSpan -Start $LastBootTime -End (Get-Date)

$Message="The computer "
$Message+=$env:COMPUTERNAME
$Message+=" has been up for "
$Message+=$UpTime.Days
$Message+=" days "
$Message+=$UpTime.Hours
$Message+=" hours "
$Message+=$UpTime.Minutes
$Message+=" minutes, "
$Message+=$UpTime.Seconds
$Message+=" seconds as of "
$Message+=(Get-Date).ToString()

Write-Host $Message

LttP: Powershell Games 2012 - Beginner Event 5

Beginner Event 5 was a nice challenge as I've not yet had the need/desire to use Powershell to query the Event logs.

Anyway, my "before I read what the expert says" entry is as follows:

Get-EventLog "Application" -ComputerName localhost -EntryType error | Group-Object -Property "Source" | Sort-Object -Property "Count" -Descending | Format-Table -Property "Count","Name" -AutoSize

Then I could quite simply just add the following to the end to write the output to a file:
 | Out-File  

LttP: Powershell Games 2012 - Begineer Event 4

This one was quite interesting, and after reading the Scripting Wife's comments I was determined that I too would  create a one-liner.

Beginner Event 4:

 ForEach($item in (Compare-Object (Get-Childitem "C:\1") (Get-Childitem "C:\2"))){$item.InputObject}

Although normally I would prefer to break it out a bit more to something like this (although it does exactly the same thing):

$Differences=(Compare-Object (Get-Childitem "C:\1") (Get-Childitem "C:\2"))

ForEach($item in $Differences)

{

 $item.InputObject

}

UPDATE:

I probably would've lost a point or two, as there is an even easier way to do that using the "-PassThru" option...

Compare-Object (Get-Childitem "C:\1") (Get-Childitem "C:\2") -Property Name -PassThru

LttP: Powershell Games 2012 - Beginner Event 3

Again, here's my entry for the Beginner Event 3 before I read the expert commentary.

<#
 .Synopsis
 2012SG_BE3 is the entry for the 2012 Powershell Scripting Games Beginner Event 3
 
 When run it will create a text file listing the running Process Name and ID.
 
 .Description
 2012SG_BE3 will create a text file listing the name and ID of all the running Process on the specified computer.
 
 If run multiple times results will be appended to the end of the file.
 
 .Example 2012SG_BE3.ps1 -ResultsRoot "D:\ScriptingGames" -ComputerName "HomeLaptop"
 
 Will store the name and ID's of the running processes on the computer named HomeLaptop in "D:\ScriptingGames\2012SG\event3\process3.txt"
 
 .Example 2012SG_BE3.ps1
 
 Will store the name and ID's of the running processes on the localhost in "C:\2012SG\event3\process3.txt"
 
 .Parameter ResultsRoot
 The -ResultsRoot parameter is used to change the Root folder of the Results.  
 If left blank the System Drive (as defined in the Environment Variables) will be used.
 
 If the trailing "\" is missing it will be added by default.
 
 .Parameter ComputerName
 The -ComputerName parameter is used to define the computer to collect the running Processes from.  
 If left blank "localhost" will be used.
    
 .Notes
    NAME: 2012SG_BE3
 AUTHOR: Owen Ballentine
 LASTEDIT: 04/27/2011 12:11:58
 
 .Link 
 http://sid351.blogspot.co.uk/
#>
Param([string]$ResultsRoot,[string]$ComputerName)
$FileLocation=""
If($ResultsRoot)
{
 $FileLocation=$ResultsRoot
 If($ResultsRoot.Substring($ResultsRoot.Length-1) -ne "\")
 {
  $FileLocation+="\"
 }
}
else
{
 $FileLocation=$env:SystemDrive
 $FileLocation+="\"
}
If(!$ComputerName)
{
 $ComputerName="localhost"
}
$FileLocation+="\2012SG\event3\"
Function Check-Path
{
param($Location, $TypeOfPath)
 If(!(Test-Path $Location))
 {
  New-Item -Path $Location -ItemType $TypeOfPath
 }
}
Check-Path $FileLocation "directory"
$FileLocation += "process3.txt"
Add-Content $FileLocation (Get-Process -ComputerName $ComputerName | Format-Table -Property "ProcessName","ID" -AutoSize | Out-String) 
I've made a mental note to look for a way to make PS scripts look nicer in the blog. Done...a bit. :)

UPDATE:

Looking at the expert commentary, I would've lost a point or two for not putting any error handling in the Check-Path function.  The expert setup error handling and then went one step further to default to the current users "My Documents".  Also, I needlessly added the "ComputerName" element.

At least I didn't fall for the hardcoded "C:\" trap that was set :)

LttP: Powershell Games 2012 - Beginner Event 2

Before I go reading the expert comentary I'll post my "entry"; then update if I'm wrong.

Beginner Event 2:

Get-Service -ComputerName localhost | Where-Object {$_.Status -eq "Running"}
UPDATE:

It looks like I fell into a well placed trap, that I'm sure others did during the games as well.

After reading the expert commentary I've learned my lesson and will be using Get-Member as well as Get-Help in future!

My reviewed entry would be:
Get-Service -ComputerName localhost | Where-Object {$_.CanStop}
The output looks similar, but there is a big difference between something that is Running, and something that "can stop" as the requirements state.

Oh well, I got this one wrong but at least I learned somethings!

Late to the Party - Powershell Games 2012 - Beginner Event 1

Well,  I had some downtime at work today which led me to spend some time brushing up on my scripting skills.

On my adventures across the web trying to find some "Powershell Challenges" I found the "Powershell Games 2012".  Like the title says, I'm late to this party; they kicked off and finshed back in April. 

Still, late is better than never, so I'm going to tackle the challenges and document my progress here :)

Beginner Event 1:

Here's my "entry":

Get-Process | Sort-Object -Property "WS" -Descending | select -First 10
The output looks like this: