Jan 232013
 

Checking System Uptime

In a previous tip we explained how you read date and time information from WMI and convert it into a regular date and time information. With this technique, you can then manipulate and calculate with the regular date and time functions. So, this piece of code returns the days a given system is running since the last reboot was done:

$os=Get-WmiObject-ClassWin32_OperatingSystem

$boottime=
[
System.Management.ManagementDateTimeConverter]::
ToDateTime($os.LastBootupTime)

$timedifference=New-TimeSpan-Start$boottime

$days=$timedifference.TotalDays

‘Your system is running for {0:0.0} days.’-f$days

from PowerShell

Jul 312012
 

Find WMI Classes with PowerShell

Get-WmiObject is a great cmdlet that returns all instances of a WMI class:

PS> Get-WmiObject-ClassWin32_LogicalDisk

All you need to know is the name of the appropriate WMI class that represents what you are looking for. Fortunately, Get-WmiObject has a built-in class browser. Simply add the switch parameter -List, and now you can use wildcards:

PS> Get-WmiObject-ClassWin32_*Disk*-List

Next, use the first call again and replace the class name with the class you want to try. Note that not all of the class names provide useful information. If the command does not return anything, then that’s OK: it tells you that there is no instance for the class you specified.

Jul 092012
 

Making netstat.exe Object-Oriented with PowerShell

Netstat.exe is a useful tool, like many other console-based applications. Take a look how relatively easy it is for PowerShell to take the text-based output and convert it into real objects:

netstat-an|

    ForEach-Object {

       $i=$_|Select-Object-PropertyProtocol , Source , Destination , Mode

       $null, $i.Protocol, $i.Source, $i.Destination, $i.Mode=

                ($_-split‘\s{2,}’)

       if ($i.Protocol.length-eq 3) { $i }

    }

Since the result is converted to objects, you can now easily use other PowerShell cmdlets to sort or filter the results. This slight variation would i.e. show all listening connections:

netstat-an|

    ForEach-Object {

       $i=$_|Select-Object-PropertyProtocol , Source , Destination , Mode

       $null, $i.Protocol, $i.Source, $i.Destination, $i.Mode=

                ($_-split‘\s{2,}’)

       if ($i.Protocol.length-eq 3) { $i }

    } |

    Where-Object { $_.Mode-eq‘LISTENING’ }

Like always with console applications, the data may be localized and different on different UI cultures.

Jul 032012
 

Stopping Services Remotely with PowerShell

Stop-Service cannot stop services remotely. One easy way of doing so is Set-Service:

Set-Service-NameSpooler-Status“Stopped”-ComputerNametargetcomputer

However, unlike Stop-Service, Set-Service has no -Force parameter, so you cannot stop services if they, for example, have running dependent services.

If your infrastructure supports PowerShell Remoting, you could use Invoke-Command instead:

Invoke-Command { Stop-Service-NameSpooler-Force } -ComputerNametargetcomputer

Jun 272012
 

Finding Files Owned by a User with Powershell

Here’s a simple filter that will show only those files and folders that a specific user is owner of:

filter Get-Owner ($Account=“$env:UserDomain\$env:USerName”) {

    if ((Get-ACL$_.Fullname).Owner-like$Account) {

        $_

    }
}

It is very easy to use. By default, it checks for files and folders owned by you:

PS> Dir$home|Get-Owner

You can specify a specific user name (including domain part) or use wildcards as well:

PS> Dir$home|Get-Owner*system*

Jun 212012
 

Check PowerShell Speed

To find out how much time a particular PowerShell cmdlet or command takes, here’s a handy little stopwatch that you can use:

functionTest {

  $codetext=$Args-join‘ ‘

  $codetext=$ExecutionContext.InvokeCommand.ExpandString($codetext)

 

  $code= [ScriptBlock]::Create($codetext)

 

  $timespan=Measure-Command$code

  “Your code took {0:0.000} seconds to run”-f$timespan.TotalSeconds

}

Now, to find out the performance of a particular command, try this:

PS> testGet-Service

Yourcodetook 0,004 secondstorun


PS
> testGet-WmiObjectWin32_Service

Yourcodetook 0,445 secondstorun

This can be especially useful if you have two cmdlets or parameters that apparently do the same. Performance difference can be tremendous, though:

PS> testdir$home-Include*.ps1-Recurse

Yourcodetook 5,741 secondstorun

PS> testdir$home-Filter*.ps1-Recurse
Yourcodetook 0,894 secondstorun

To test drive more complex commands, make sure you place them in quotes.

Jun 122012
 

Delete Files older than a certain number of days with PowerShell

$date = get-date ; get-childitem | foreach {IF ($_.lastwritetime -lt $date.adddays(-30)) {Remove-Item $_.Name -WhatIf}}

 

this is perhaps an easier script, includes sub folders, only files with .log extension and older than 30 days. The -WhatIf describes what would happen if you executed the command without actually executing the command.

 

$date = get-date ; get-childitem -recurse -include *.log | Where-Object {$_.lastwritetime -lt $date.adddays(-30)} | Remove-Item -WhatIf

 

Jun 082012
 

Hiding Drive Letters with PowerShell

Sometimes you may want to hide drive letters in Windows Explorer from users. There’s a Registry key that can do this for you. It takes a bit mask where each drive has a bit. When the bit is set, the drive is hidden. Fortunately, in a previous tip you learned how to turn drive letters into bit masks, so here’s the function:

functionHide-Drive {
param($DriveLetter)

$key= @{
Path=HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
Name=‘NoDrives’
}

if ($DriveLetter-eq$null) {
Remove-ItemProperty @key
}
else {
$mask= 0
$DriveLetter|
ForEach-Object { $_.toUpper()[0] }
|
Sort-Object|
ForEach-Object { $mask+= [Math]::Pow(2,(([Byte]$_) 65)) }

Set-ItemProperty @key-Value$mask-typeDWORD
}

}

For example, to hide drives A, B, E, and Z, you would use it like this:

PS> Hide-DriveA,B,E,Z

To display all drives, omit arguments:

PS> Hide-Drive

Note that you need to have administrative privileges to change policies, and that policies may be overridden by group policy settings set up by your corporate IT.

For the changes to take effect, you need to log off and on again or kill your explorer.exe and restart it.

Jun 062012
 

Checking Size of Downloads-Folder with Powershell

Whenever you download something with IE, by default the files get stored in your personal download folder. Often, over time a lot of garbage can accumulate. This line tells you just how much data you store in this folder:

 

$folder=$env:userprofile\Downloads
Get-ChildItem
-Path$folder-Recurse-Force-ea 0 |
Measure-Object-PropertyLength-Sum|
ForEach-Object {
$sum=$_.Sum/ 1MB
“Your Downloads folder
wastes {0:#,##0.0} MB storage”
-f$sum

}

You may be surprised just how much stuff has been collected there.

Jun 052012
 

Copying Files in the Background with PowerShell

In a previous tip we showed how you can use the BITS service to copy files. The main advantage of BITS is that it can copy things silently in the background, and it is resilient to interruptions such as reboots. After a reboot, BITS will continue the copy process, so this can be a good starting point to create a robust backup mechanism.

Import-ModuleBitsTransfer

# adjust source and
destination to your needs:
$Source
=“$env:userprofile\downloads\*.exe”
$Destination
=“C:\BackupFolder\”

if ( (Test-Path$Destination) -eq$false)
{
 $null=New-Item-Path$Destination-ItemTypeDirectory
}

$params= @{
Source=$Source
Destination=$Destination
Description=“Backup”
DisplayName=“Backup”
Asynchronous=$true
}

Start-BitsTransfer @params

This script would copy all downloaded EXE files to a backup location. Since the backup is running in the background, you get back immediately a response like this:

 

JobId                                       DisplayName                      TransferType                     JobState                         OwnerAccount
—–                                       ———–                      ————                     ——–                         ————
0488f61c-ab39-4661-81ce-b8f8a3… Backup                             Download                          Transferring                    TobiasAir1\Tobias 

To check progress, you can check progress using Get-BITSTransfer. You can call this cmdlet anytime, even next week after a couple of restarts. It may look like this:

 

PS> Get-BitsTransfer

JobId                                           DisplayName                   TransferType                     JobState                         OwnerAccount
—–                                           ———–                   ————                     ——–                         ————
287ed32a-ec3a-4e13-b88d-9f288f…    Upload TUDI
Data             Upload                             Transferred                     TobiasAir1\Tobias
546c7a07-315b-4900-b1de-134aaa…    Upload TUDI
Data             Upload                             Transferred                     TobiasAir1\Tobias
0488f61c-ab39-4661-81ce-b8f8a3…    Backup                          Download                           Transferring                   TobiasAir1\Tobias

You may see other BITS operations in this list as well since Windows is using the BITS service, too, to receive updates and upload data.

To actually complete the backup once it is done, you need to call Complete-BITSTransfer:

 

Import-ModuleBITSTransfer

Get-BitsTransfer
|
Where-Object { $_.DisplayName-eq‘Backup’ } |
ForEach-Object {
   $_|Select-Object-Property*

if ($_.JobState-eq‘Transferring’) {
$transferred=$_.FilesTransferred
$total=$_.FilesTotal
$text=‘{0}
of {1} files transferred. Try again later.’
-f
$transferred
, $total
Write-Warning$text
}
else {
$done=$_.TransferCompletionTime
Complete-BitsTransfer$_
Write-Warning“Backup
process done at $done”

}

  }