PowerShell for Windows Admins


February 8, 2010  2:10 PM

Defragmenting a volume

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

We have seen how to analyse a volume to see if it needs a defrag.  This is how we do it.  Modern windows systems will do a certain amount of defrag work automatically but sometimes we need to help them out.

 

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
function Start-Defrag {
[CmdletBinding(SupportsShouldProcess=$true)]
param ([string]$computer=".",
       [string]$drive
)
    if ($drive -notlike "?:"){ 
    Throw "Drive should be submitted as letter and colon e.g. C:"}
   
    $filt = "Name=’" + $drive + "\\’"
    $vol = Get-WmiObject -Class Win32_Volume -Filter $filt `
    -ComputerName $computer
   
    $res = $vol.Defrag($false)
   
    if ($res.ReturnValue -eq 0) {
        Write-Host "Defrag succeeded"
        $res.DefragAnalysis | 
        Format-List AverageFileSize, AverageFragmentsPerFile, 
        AverageFreeSpacePerExtent, ClusterSize,
        ExcessFolderFragments, FilePercentFragmentation, 
        FragmentedFolders, FreeSpace, FreeSpacePercent, 
        FreeSpacePercentFragmentation, 
        LargestFreeSpaceExtent, MFTPercentInUse, 
        MFTRecordCount, PageFileSize, TotalExcessFragments, 
        TotalFiles, TotalFolders, TotalFragmentedFiles, 
        TotalFreeSpaceExtents, TotalMFTFragments, 
        TotalMFTSize, TotalPageFileFragments, 
        TotalPercentFragmentation, TotalUnmovableFiles, 
        UsedSpace, VolumeName, VolumeSize 
    }
    else {Write-Host "Defrag failed Result code: " $res.ReturnValue}
}

 

Our function has a computer name and drive as parameters. We check the drive is in the right format and reject if it isn’t.

From that its just a case of getting a WMI object for the volume and calling the defrag method.  The $false parameter means don’t automatically fix problems – we want to deal with those ourselves.

If the return value is 0 – we have a winner and our defrag succeeded. Time to see the results other wise we dump out the return code so we can find out what went wrong

Technorati Tags: ,,,

February 7, 2010  4:55 AM

PowerShell, WMI and WQL

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Don’t forget the PowerShell UG Live Meeting on Tuesday 9 February at 7:30 GMT . Details can be found here

http://msmvps.com/blogs/richardsiddaway/archive/2010/01/24/ug-meeting-9-february.aspx

Technorati Tags: ,,


February 6, 2010  1:22 PM

Defrag Analysis Part 2

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Last time we saw how to check whether a single volume needs a defrag run.  Usually our servers have a number of volumes – ideally we want to check all of them together

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
function Test-Defrag {
[CmdletBinding(SupportsShouldProcess=$true)]
param ([string]$computer=".")
    "`n $computer" 
    Get-WmiObject -Class Win32_Volume -ComputerName $computer | 
      where {$_.Name -like "?:\"} | 
      foreach {
       $_.Name
       $dfa = $_.DefragAnalysis()
     
       if ($dfa.DefragRecommended){
            $dfa.DefragAnalysis | Format-List AverageFileSize, 
            AverageFragmentsPerFile, AverageFreeSpacePerExtent, 
            ClusterSize,ExcessFolderFragments, FilePercentFragmentation, 
            FragmentedFolders, FreeSpace, FreeSpacePercent, 
            FreeSpacePercentFragmentation, LargestFreeSpaceExtent, 
            MFTPercentInUse, MFTRecordCount, PageFileSize, 
            TotalExcessFragments, TotalFiles, TotalFolders, 
            TotalFragmentedFiles, TotalFreeSpaceExtents, 
            TotalMFTFragments, TotalMFTSize, TotalPageFileFragments, 
            TotalPercentFragmentation, TotalUnmovableFiles, 
            UsedSpace, VolumeName, VolumeSize 
       }
       else {Write-Host "`t Drive does not need defrag at this time"}

    }
}

We has a function that we can give a computer name to as a parameter.  This then gets the volume information using the Win32_Volume class. We only accept volumes with names like c:\ and pass the results into a foreach.

Because we already have an object representing the volume we can use the DefragAnalysis method directly. If it indicates a defrag is necessary we dump out the results.

We could have continued with the Invoke-WmiMethod route we used previously but it would have been a bit complicated to code – lets keep it simple.

Technorati Tags: ,,


February 5, 2010  3:25 PM

Defrag Analysis

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

One nasty fact of life we have to deal with as admins is disk fragmentation. We can discover how fragmented our disks are by Opening the Start Menu – Admin tools – Computer Management – Disk Management – pick a volume – click analyse.  My fingers ache from all this clicking.

Our alternative is to use WMI.

The Win32_Volume class has a method called DefragAnalysis that allows us to this analysis – remember we can work on remote machines as well.

We can call it like this

Invoke-WmiMethod -Path ((Get-WmiObject -Class Win32_Volume -Filter "Name=’C:\\’").__PATH)        -Name DefragAnalysis

which produces results like this. WMI needs to use \\ to represent the single \ in the volume name.

__GENUS           : 2
__CLASS           : __PARAMETERS
__SUPERCLASS      :
__DYNASTY         : __PARAMETERS
__RELPATH         :
__PROPERTY_COUNT  : 3
__DERIVATION      : {}
__SERVER          :
__NAMESPACE       :
__PATH            :
DefragAnalysis    : System.Management.ManagementBaseObject
DefragRecommended : False
ReturnValue       : 0

OK so we don’t need to defrag BUT we can’t see the results of the analysis – hmm not good.  OK lets try plan B.

$dfa = Invoke-WmiMethod -Path ((Get-WmiObject -Class Win32_Volume -Filter "Name=’C:\\’").__PATH) -Name DefragAnalysis

PS> $dfa

Gives us this

__GENUS           : 2
__CLASS           : __PARAMETERS
__SUPERCLASS      :
__DYNASTY         : __PARAMETERS
__RELPATH         :
__PROPERTY_COUNT  : 3
__DERIVATION      : {}
__SERVER          :
__NAMESPACE       :
__PATH            :
DefragAnalysis    : System.Management.ManagementBaseObject
DefragRecommended : False
ReturnValue       : 0

but if we then wave our magic wands and do this

PS> $dfa.DefragAnalysis

__GENUS                       : 1
__CLASS                       : Win32_DefragAnalysis
__SUPERCLASS                  :
__DYNASTY                     : Win32_DefragAnalysis
__RELPATH                     : Win32_DefragAnalysis
__PROPERTY_COUNT              : 27
__DERIVATION                  : {}
__SERVER                      : RSLAPTOP01
__NAMESPACE                   : ROOT\CIMV2
__PATH                        : \\RSLAPTOP01\ROOT\CIMV2:Win32_DefragAnalysis
AverageFileSize               : 53
AverageFragmentsPerFile       : 1.02
AverageFreeSpacePerExtent     : 11710464
ClusterSize                   : 4096
ExcessFolderFragments         : 58
FilePercentFragmentation      : 0
FragmentedFolders             : 23
FreeSpace                     : 114998321152
FreeSpacePercent              : 66
FreeSpacePercentFragmentation : 35
LargestFreeSpaceExtent        : 74555568128
MFTPercentInUse               : 100
MFTRecordCount                : 208383
PageFileSize                  : 0
TotalExcessFragments          : 5742
TotalFiles                    : 203253
TotalFolders                  : 16620
TotalFragmentedFiles          : 2988
TotalFreeSpaceExtents         : 9802
TotalMFTFragments             : 2
TotalMFTSize                  : 213385216
TotalPageFileFragments        : 0
TotalPercentFragmentation     : 0
TotalUnmovableFiles           : 197
UsedSpace                     : 56800366592
VolumeName                    :
VolumeSize                    : 171798687744

Which is good but we can improve the display a bit

$dfa.DefragAnalysis | Format-List AverageFileSize, AverageFragmentsPerFile, AverageFreeSpacePerExtent, ClusterSize,ExcessFolderFragments, FilePercentFragmentation, FragmentedFolders, FreeSpace, FreeSpacePercent, FreeSpacePercentFragmentation, LargestFreeSpaceExtent, MFTPercentInUse, MFTRecordCount, PageFileSize, TotalExcessFragments, TotalFiles, TotalFolders, TotalFragmentedFiles, TotalFreeSpaceExtents, TotalMFTFragments, TotalMFTSize, TotalPageFileFragments, TotalPercentFragmentation, TotalUnmovableFiles, UsedSpace, VolumeName, VolumeSize

Will give a good display.  If required we could use the calculated fields we have seen previously to perform even more more formatting

On Windows Vista\Windows 2008 and above we have to run PowerShell with elevated privileges for this to work. We will get a return code of 11 if running PowerShell without these privileges.

 

Technorati Tags: ,,,


February 3, 2010  4:40 PM

Disk Methods Part 2

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

We recently saw how to use the Chkdsk method of the Win32_Logicaldisk class.  A quicker way to do this is to use Invoke-WmiMethod which was introduced with PowerShell 2.  This uses the path to the WMI object we are interested in – this is held in the __PATH property.  That is two underscores.  We can find the path like this

PS>  Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=’G:’" | select __PATH

__PATH
——
\\RSLAPTOP01\root\cimv2:Win32_LogicalDisk.DeviceID="G:"

We just need the value of the path which we can get like this

PS> $path = ( Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=’G:’" ).__PATH

and then we invoke the method

PS> Invoke-WmiMethod -Path $path -Name Chkdsk

Alternatively we can do it in one line like this

PS> Invoke-WmiMethod -Path $(( Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=’G:’" ).__PATH) -Name Chkdsk

Technorati Tags: ,,


February 1, 2010  1:35 PM

PowerGUI 2.0

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

We have had a quick look at discovering the WMI classes available on our systems using get-wmiobject.

Another way is to use PowerGUI. This is a free tool that gives you a graphical way to present information from PowerShell scripts. You can use it to store and run your favourites scripts. There are a number of default scripts that come with it and a lot more to down load for free from www.powergui.org

From our view point one of the big pluses is that it comes with a built in browser for WMI.  There is also a very good script editor.

 

Give it a try – I’ve been using it for a few years and find it a very useful tool


January 25, 2010  1:17 PM

Correct version of PowerShell

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

It seems that versions of the PowerShell v2 CTP are still being used and problems are being reported because the incorrect version of PowerShell is being used.

Tobias has a great post explaining which version you should be using and providing tools to check your PowerShell installation.

http://powershell.com/cs/blogs/tobias/archive/2010/01/24/are-you-using-the-correct-powershell-version.aspx

 

Technorati Tags: ,


January 24, 2010  3:39 PM

Remember Tuesday

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Tuesday 26 January 7:30 GMT

PowerShell User group meeting on Windows 2008 R2 AD cmdlets

Details from

http://msmvps.com/blogs/richardsiddaway/archive/2010/01/06/uk-user-group-meeting-jan-2010.aspx

Technorati Tags: ,


January 23, 2010  6:54 AM

Disk Methods Part 1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

We have seen how to pull information about our disks – what about working with them. As a quick recap on the objects that PowerShell deals with – properties give us the information and methods enable us to do stuff. So what stuff can we do?

We can find out from the documentation or we can use

Get-WmiObject -Class Win32_LogicalDisk | Get-Member -MemberType method

Name
—-
Chkdsk
Reset
SetPowerState

Get-WmiObject -Class Win32_DiskPartition | Get-Member -MemberType method

Name
—-
Reset
SetPowerState

Get-WmiObject -Class Win32_DiskDrive | Get-Member -MemberType method

Name
—-
Reset
SetPowerState

 

For conciseness I’ve only shown the Name of the method.

In reality the Reset and SetPowerState methods are not available because they are derived from the CIM* parent class. We’ll leave that for another day.

Chkdsk on the Logical Disk sounds familiar – lets have a look at that one

$disk = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceId=’G:’"

$disk.ChkDsk($false, $true, $true, $false, $false, $false)

The meaning of the parameters is as follows:
 
FixErrors – Indicates what should be done to errors found on the disk. If true, then errors are fixed. The default is false.

VigorousIndexCheck – If true, a vigorous check of index entries should be performed. The default is true.

SkipFolderCycle – If true, the folder cycle checking should be skipped. The default is true.

ForceDismount – If true, the drive should be forced to dismount before checking. The default is false.

RecoverBadSectors -If true, the bad sectors should be located and the readable information should be recovered from these sectors. The default is false.

OKToRunAtBootUp – If true, the chkdsk operation should be performed at next boot up time, in case the operation could not be performed because the disk is locked at time this method is called. The default is false.

Now we have seen how to run this manually we need to turn it into a script.


January 19, 2010  2:26 PM

Mapping Physical Drives to Logical Drives Part 3

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

Following on from last time we will extend our script to pull the information for logical drives.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
Get-WmiObject -Class Win32_DiskDrive | foreach {
    "`n {0} {1}" -f $($_.Name), $($_.Model)

    $query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=’" `
     + $_.DeviceID + "’} WHERE ResultClass=Win32_DiskPartition"
    
    Get-WmiObject -Query $query | foreach {
        ""
        "Name : {0}" -f $_.Name
        "Description : {0}" -f $_.Description
        "PrimaryPartition : {0}" -f $_.PrimaryPartition
   
        $query2 = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=’" `
        + $_.DeviceID + "’} WHERE ResultClass=Win32_LogicalDisk"
           
        Get-WmiObject -Query $query2 | Format-List Name,
        @{Name="Disk Size (GB)"; Expression={"{0:F3}" -f $($_.Size/1GB)}},
        @{Name="Free Space (GB)"; Expression={"{0:F3}" -f $($_.FreeSpace/1GB)}}
   
    }
}

When we get the data for the partitions (line 7) we now put that into a foreach loop. The name, description and if its a primary partition are dumped. I’m using a string to write it because we will get a formatting error if we try to use format-list with two different objects in the same script.

A query to get the associators of the partition (as long as its a logical drive) is created and run. The results from that are displayed using the calculated fields we have seen earlier.

That concludes our look at getting information about disks. Next we’ll look at the methods these WMI classes make available – in other words what can we do with them

Technorati Tags: ,,


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: