In Windows PowerShell: Extracting Strings Using Regular Expressions, I introduced the Windows PowerShell and discussed the concept of regular expressions, giving an example of how to build a Windows PowerShell script to extract strings from a file using a given regular expression. In this two part series, I will discuss a number of PowerShell scripts to assist with some of the fundamental administration and troubleshooting tasks. We will touch on the Microsoft Troubleshooting Packs, discuss a script for checking file and folder permissions, a script for monitoring storage space, as well as one for determining if a host is alive and notifying a given user.

Microsoft Troubleshooting Packs

I thought it would be worth starting off by mentioning the Microsoft Troubleshooting Packs that are bundled with Windows 7, Windows Server 2008 and above. The Microsoft Troubleshooting Packs are a series of detection, resolution and verification PowerShell scripts that you can use to diagnose different aspects of your servers, clients or network. Different packages are available to troubleshoot printers, networks, performance, power, Windows Update, etc.

To see which components are available for troubleshooting, simply run the dir command against the directory that holds the scripts. You will get a list like the one shown in the image below:

dir C:\Windows\diagnostics\system

To run a Troubleshooting Pack, you will first need to import the modules associated with the pack by running the following command from the Windows PowerShell command window:

Import-Module TroubleshootingPack

You then specify the Get-TroubleshootingPack cmdlet along with the desired pack location and pipe it to the Invoke-TroubleshootingPack cmdlet as follows:

Get-TroubleshootingPack <TroubleshootingPackLocation> | Invoke-TroubleshootingPack

The image below shows the options available when the Network Troubleshooting Pack is invoked:

It is likely that you will want to run these scripts on a remote machine (e.g. a Windows 7 client). To do so, you will first need to connect to the remote machine from PowerShell using the “Enter-PSSession” cmdlet, as shown below:

Enter-PSSession -ComputerName remotehost -Credential domain\adminaccount

Replace ‘remotehost’ with the name or IP address of the remote machine and ‘domain\adminaccount’ with an admin level account on the domain. A dialog box will appear asking you to enter the password for the ‘domain\adminaccount’, following which you will have initiated a remote management session within PowerShell to execute commands on the remote machine.

Note: Ensure that the Windows Remote Management service is running and that you have configured the remote machine to allow Remote Management connections (using the winrm quickconfig command).

Checking ACL Permissions on Files and Folders

Whether for troubleshooting or simply for verification purposes, you will often find the need to check ACL permissions on files or folders. In larger environments where permissions are granted on files and folders on a regular basis, a permissions review may take place every quarter for example, and having an ACL report to compare with would come in handy.

To construct this script, you need the following main elements:

1) The path to check permissions on

2) The output path to create the report file

3) An Array to store each enumerated path

4) A ForEach loop to perform an operation on each object in the Array

5) The Get-Acl cmdlet.

The first part of the script asks the user for the path to check permissions on, as well as the path for the output file, and stores the results in a variable called $Path and $OutFilePath respectively. The Get-Date cmdlet is used twice; once to hold the current date and time in the $ReportDate variable and another to store the current date and time in a custom format within the $FileTS variable (which is used to create a timestamp for the output filename). The $ReportUser variable holds the name of the currently logged on user in the domain\username format.

An if statement is used to check if the path stored in the $OutFilePath variable exists. If it doesn’t exist, it will be created automatically using the New-Item (abbreviated to ni) cmdlet. The filename of the report is then appended to the output path and stored in the $FullOutFile variable.

Various variables, such as $RptNameInfo, $DateInfo and $PathInfo, are used to add the main pieces of information to the report. The $NumFolders and $NumFiles variables store the count of folders and files respectively, and uses the Get-ChildItem (or gci for short) cmdlet to pull back all the files and folders that fall under the location stored in $Path.

An Array is then created to store each of the enumerated file and folder paths and a ForEach loop handles the processing of the data within the Array. For each object in the Array, the path is converted from the PowerShell path to a standard system path. The size of each folder and file is obtained using the Measure-Object cmdlet and stored in a variable called $PathSizeCount. $PathSizeCountKB and $PathSizeCountMB store the size in KB and MB respectively. The path and size information for each folder or file is then added to the report.

Finally, the Get-Acl cmdlet is run against all the enumerated paths within $PSPath and formatted using the format-list (or fl for short) command. All this is added to the file specified in the $FullOutFile variable.

Script:

# set variables

$Path = Read-Host “Enter path to check permissions on”

$OutFilePath = Read-Host “Enter path to store output file”

$ReportDate = Get-Date -format F

$ReportUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name

$FileTS = Get-Date -format “yyyy.M.dd.hh.mm.ss”

$ReportFileTS = $FileTS.replace(‘.’,”)

# check if path to output file exists, if not create it

if(!(Test-Path -Path $OutFilePath))

{

    ni -Path $OutFilePath –ItemType Directory -Force

}

# construct full path to output file

$FullOutFile = “$outfilepath\ACLCheckReport.$reportfilets.txt”

# add main report info

$RptNameInfo = “==============================`r`n    ACL Permissions Report    `r`n==============================”

$RptNameInfo | ft | Out-File $FullOutFile

$DateInfo = “Created on: $reportdate `r`nCreated by: $reportuser`r`n`==============================`r`n”

$DateInfo | ft | Out-File -append $FullOutFile

$NumFolders = (gci $Path -recurse | where {$_.PsIsContainer}).Count

$NumFiles = (gci $Path -recurse | where {$_.GetType() -match “fileInfo”} | measure-object).Count

$PathInfo = “Listing permissions for: $path ( Folders: $numfolders | Files: $numfiles )`r`n”

$PathInfo | ft | Out-File -append $FullOutFile

# fill array with folders and files

[Array] $Objects = gci -path $Path -force -recurse

# fill array with folders only

#[Array] $Objects = gci -path $path -force -recurse | Where {$_.PSIsContainer}

# process data in array

ForEach ($Object in [Array] $Objects)

{

# convert pspath to full system path

$PSPath = (Convert-Path $Object.PSPath)

# get the size of each folder/file

$PathSizeCount = (gci $PSPath -recurse | Measure-Object -property length -sum).Sum

$PathSizeCountKB = “{0:N2}” -f ($PathSizeCount / 1KB)

$PathSizeCountMB = “{0:N2}” -f ($PathSizeCount / 1MB)

# add path and size info for each folder/file to the report

$PathSizeInfo = (“Path: $PSPath `r`nSize (KBytes): $PathSizeCountKB | Size (MBytes): $PathSizeCountMB”)

$PathSizeInfo | ft | Out-File -append $FullOutFile

# run the get-acl command using the list of enumerated paths and format accordingly

Get-Acl -path $PSPath | fl -property Owner,AccessToString | Out-File -append $FullOutFile

}

Uncomment the following code within the script to change it so that only folders and sub-folders are enumerated as part of the permissions list:

#[Array] $folders = gci -path $path -force -recurse | Where {$_.PSIsContainer}

Then, add a comment tag to the following code within the script to disable files from being enumerated as part of the permissions list:

[Array] $objects = gci -path $path -force –recurse

The following shows a sample ACL Permissions Report.

Note: The format of the report can be modified by changing the “ft” and “fl” portions of the script accordingly.

In Part 2, we will look at two more scripts, one to check if a host is alive and trigger a notification event, and another to check for storage space and take action accordingly if a certain threshold is reached.

 

Like our posts? Subscribe to our RSS feed or email feed (on the right hand side) now, and be the first to get them!