Archive for August, 2014

Find-Text Powershell function to find text in files, folders, subfolders


This function will search for the input text in the files under the input folders and their subfolders. It can bedownloaded from the Microsoft Script Center Repository.

It can search for more than one text pattern – separated by commas. For example:

Find-Text -TextPattern numlock,Cheese
This example will seach for the text patterns ‘numlock’ and ‘cheese’ in all files under the current folder and its subfolders.
If it does not find any matches it will display a message like:
Find-text10b
Search patterns are not case sensitive. So searching on “numlock” will return results including “numlock” and “NumLokc”
You can limit the search to certain file types by using the -FilePattern parameter. For example:
Find-text -TextPattern numlock,boutros -FolderName \\MyServer\install\scripts -FilePattern *.txt,*.csv,*.ps1
This example will search for “numlock” and “boutros” in files with the text patterns *.txt,*.csv,*.ps1 under the folder \\MyServer\install\scripts and its subfolders

Function will display a progress bar indicating text patterns it’s searching for, file it’s currently searching in, and file number out of total number of files. Function returns a PS object with 2 properties: String, and File. String is the text pattern found, and File is the full path where the text pattern was found:

Find-text7

Function output can be displayed to the screen as in:

$Found = Find-text "numlock","boutros" "\\xHost15\install\scripts",".\test"  
if ($Found) { $Found | Out-GridView }
Output will look like:
Find-text8
Function output can be exported to CSV for viewing/processing in MS Excel for example:
$Found = Find-text "numlock","boutros" "\\xHost15\install\scripts",".\test"  
if ($Found) { $Found | Export-CSV ".\Found.csv" -NoTypeInformation }
Output will look like:
Find-text9
Advertisements

Powershell Function to get Hyper-V host networking configuration


This function generates a txt report on one or more Hyper-V hosts’ networking configuration. It’s a useful tool when troubleshooting issues that relate to VM live-migration, VM replication and similar issues. It can be downloaded from the Microsoft Script Center Repository.

To get help for the function type in:

help Get-HVNetworking -full

You will see output similar to:

 .Synopsis 
  Function to get Hyper-V host networking configuration 
  
 .Description 
  Function generates report in txt format 
  The function will skip computers that don't have Hyper-V role installed 
 
 .Parameter ComputerName 
  Name(s) of the Hyper-V host(s) to report on 
  
 .Parameter ReportFile 
  File name to save the resulting report to.  
  Example: "c:\reports\Hyper-V_Networking.txt" 
  If absent, the resulting report is saved to a text file in the current folder. 
 
 .Example 
  Get-HVNetworking -ComputerName "Host1" 
  This example reports on the Hyper-V host "Host1" 
 
 .Example 
  Get-HVNetworking "Host1","Host2","Host3" -Verbose 
  This example reports on the Hyper-V hosts "Host1","Host2","Host3" 
  and displays results to the screen as well. 
 
 .Example 
  Get-ADComputer -Filter * | Select name | foreach-Object { Get-HVNetworking $_.name ".\Domain-HVNetworkingReport.txt" -Verbose } 
  This example goes through all computers in the domain  
  and reports on the ones that have Hyper-V role installled  
  and saves all gathered data into a single report 
 
 .Link 
  http://superwidgets.wordpress.com/category/powershell/ 
  
 .Notes 
  Function by Sam Boutros 
  v1.0 - 08/29/2014 
  Possible future updates: 
    Select specific properties of interest instead of returning all properties 
    Return selected properties as a PSObject  
 

Using Powershell to report on files containing PII (Personally Identifiable Information)


26 August 2016:

This updated script also outputs the files found as a PS object that can be exported to CSV.

For example:

$PiiFiles = get-pii -FileType 'txt' 

Searches files with txt extension in the current folder and its subfolders, outputs the findings in HTML report and saves the file list in the $PiiFiles variable. That can be exported to CSV as in:

$PiiFiles | Export-Csv .\piilist1.csv -NoTypeInformation

Management of PII (Personally Identifiable Information) has always been a source of concern. PII includes information such as social security numbers and credit card numbers. Companies may have policies to regulate how they’re handled, and perhaps require encrypting the files where they’re stored. IT may be asked to audit or report on any files containing PII. This script does just that. The script is implemented as a function the SBTools module available on the Microsoft Script Center Repository.

Get-PII function uses EnahncedHTML2 functions by Don Jones who graciously agreed to have them included in SBTools module.

NIST provides examples of PII such as:

  • Name, such as full name, maiden name, mother‘s maiden name, or alias
  • Personal identification number, such as social security number (SSN), passport number, driver‘s license number, taxpayer identification number, patient identification number, and financial accountor credit card number
  • Address information, such as street address or email address
  • Asset information, such as Internet Protocol (IP) or Media Access Control (MAC) address or other host-specific persistent static identifier that consistently links to a particular person or small, well defined group of people
  • Telephone numbers, including mobile, business, and personal numbers
  • Personal characteristics, including photographic image (especially of face or other distinguishing characteristic), x-rays, fingerprints, or other biometric image or template data (e.g., retina scan, voice signature, facial geometry)
  • Information identifying personally owned property, such as vehicle registration number or title number and related information
  • Information about an individual that is linked or linkable to one of the above (e.g., date of birth, place of birth, race, religion, weight, activities, geographical indicators, employment information, medical information, education information, financial information).

This script searches and reports only on social security numbers and credit card numbers. It can be modified to detect additional PII patterns. Feel free to post a comment if you’d like to see more patterns added..

To search on a set of folders and report on files containing PII use a command like:

Get-PII “txt”,”csv”,”doc?” “D:\Sandbox”,”\\Server1\Install\Script?”

This searches the folder d:\sandbox and \\Server1\Install\script? for files with extensions txt, csv, and doc?, and compiles an HTML report of any files including PII.

The command output looks like:

PII1

The HTML report looks like:

PII2

The sample file looks like:

PII3


Working with Powershell Arrays


In Powershell, arrays are one of the most useful data types. In a script they can be used to store and handle all sorts of data.

To declare an array:

$a = @()
# This declares an empty array

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = 1..4
# Creates new array ‘a’, and assigns the numbers 1 through 4 to its first 4 elements
$a

arr02

We can also explicitly declare the variable type as in:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
[array]$a = “fun”
$a.GetType() # This is an array, as opposed to:
Remove-Variable a # Make sure we’re starting fresh
$a = “fun”
$a.GetType() # This is a string

arr12

Why does that matter? Although Powershell does a pretty amazing job at picking a data type for you when you don’t explicitly declare a data type, sometimes you need to make sure you got the variable data type you want. For example:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = “fun”
$a += “sun”
$a

arr13

This may not be what we wanted, as now the 2 values are concatenated together into a single string.

This is more like it:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
[array]$a = “fun”
$a += “sun”
$a

arr14

Array elements can be addressed by their index number between [] brackets. Index numbers start with zero. Array property ‘count’ tells us how many elements are in an array.

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = 1..4
$a[1] # This is second element of the array, shows value of ‘2’
$a.count # This shows how many elements in the array => 4

arr04

We can also refer to several array elements by separating their index numbers with commas, like this:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = “Black”,”Blue”,”Cyan”,”DarkBlue”,”DarkCyan”,”DarkGray”,”DarkGreen”,”DarkMagenta”,”DarkRed”,”DarkYellow”,”Gray”,”Green”,”Magenta”,”Red”,”White”,”Yellow”
$a[2,7] # This selects the 2nd and 7th elements of the array – remember first element is number zero

arr09

Array elements can be of different data types:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = 1,2,3,4,”cheese”,(Get-Date)
for ($i=0; $i -lt $a.Count; $i++) { $a[$i].GetType() }

arr05

To add an element to an array, we can use:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = 1,2,3,4,”cheese”,(Get-Date)
$a += 7
$a += “Monday”
$a

arr06

Removing an array element is not straight forward. Although the array object has add() and remove() methods they do not work:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = 1..4
$a.Add(5)
$a.Remove(2)

arr07

This is due to the fact that Array implements the IsFixedSize property because it is required by the System.Collections.IList interface.

So, how can we remove an element from an array?

We simply create a new array excluding the element we want to remove, as in:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = 1..4
$a = $a -ne 2 # Creates new array based on the old ‘a’ array excluding the element whose value is ‘2’
$a

arr08

This also works for data types other than integer and string:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$Date = Get-Date
$a = 1,2,3,4,”cheese”,$Date
$a = $a -ne $Date
$a

arr10

We can remove elements from an array based on their index number as well:

if ($a) { Remove-Variable a } # Make sure we’re starting fresh
$a = “Black”,”Blue”,”Cyan”,”DarkBlue”,”DarkCyan”,”DarkGray”,”DarkGreen”,”DarkMagenta”,”DarkRed”,”DarkYellow”,”Gray”,”Green”,”Magenta”,”Red”,”White”,”Yellow”
$a = $a[0..3 + 5..$a.Count] # Removes the element with index #4 (DarkCyan) in the array
$a

arr11


New ‘Import-SessionCommands’ function added to SBTools module


SBTools module can be downloaded from the Microsoft Script Center Repository.

To install it, extract the .rar file, and run install-SBTools.ps1 in the folder where you extracted the .rar file.

The Import-SessionCommands function will import modules from other computers and export them locally if the -Keep switch us selected.

NAME
Import-SessionCommands

SYNOPSIS
Function to import commands from another computer

SYNTAX
Import-SessionCommands [-ModuleName] <String[]> [-ComputerName] <String> [[-Keep]] [-WhatIf] [-Confirm] [<CommonParameters>]

DESCRIPTION
Function will import commands from remote computer from the module(s) listed.

PARAMETERS
-ModuleName <String[]>
Name(s) of the module(s) that we want to import their commands into the current
PS console.
Note that session commands will not be available in other PS instances.

Required? true
Position? 1
Default value
Accept pipeline input? true (ByPropertyName)
Accept wildcard characters? false

-ComputerName <String>
Computer name that has the module(s) that we need to import their commands.

Required? true
Position? 2
Default value
Accept pipeline input? true (ByPropertyName)
Accept wildcard characters? false

-Keep [<SwitchParameter>]
This is a switch. When selected, the function will export the imported module(s)
locally under “C:\Program Files\WindowsPowerShell\Modules” if it’s in the PSModulePath,
otherwise, it will export it to the default path “$home\Documents\WindowsPowerShell\Modules”
– Note 1: Exported modules and their commands can be used directly from any PS instance
after a module has been exported with the -keep switch
– Note 2: Even though a module has been exported locally, everytime you try to use one of
its commands, PS will start an implicit remoting session to the server where the
module was imported from.

Required? false
Position? 3
Default value False
Accept pipeline input? false
Accept wildcard characters? false

-WhatIf [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

-Confirm [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

NOTES
Function by Sam Boutros
Requires PS 3.0
v1.0 – 08/17/2014
Although we need to eventually run:
Remove-PSSession -Session $Session
We cannot do that in the function as we’ll lose the imported session commands
Two things to consider:
1. The session will be automatically removed when the PS console is closed
2. If in the parent script that’s using this function a blanket Remove-PSSession
command is run, like:
Get-PSSession | Remove-PSSession
We’ll lose this session and its commands, which could cripple the parent script

————————– EXAMPLE 1 ————————–

C:\PS>Import-SessionCommands -ModuleName ActiveDirectory -ComputerName DC01

This example imports all the commands from the ActiveDirectory module from the DC01 server
So, in this PS console instance we can use AD commands like Get-ADComputer without the need
to install AD features, tools, or PS modules on this computer!

————————– EXAMPLE 2 ————————–

C:\PS>Import-SessionCommands SQLPS,Storage V-2012R2-SQL1 -Verbose

This example imports all the commands from the PSSQL and Storage modules from the MySQLServer
server into the current PS instance

————————– EXAMPLE 3 ————————–

C:\PS>Import-SessionCommands WebAdministration,BestPractices,MMAgent CM01 -keep

This example imports all the commands from the WebAdministration, BestPractices, and MMAgent
modules from the CM01 server into the current PS instance, and exports them locally.

RELATED LINKS
https://superwidgets.wordpress.com/category/powershell/


New ‘Get-FilesContainingText’ function added to SBTools module


SBTools module can be downloaded from the Microsoft Script Center Repository.

To install it, extract the .rar file, and run install-SBTools.ps1 in the folder where you extracted the .rar file.

The Get-FilesContainingText function will search one or more folders and their subfolders for a text pattern and return a list of files containing that pattern.

NAME
Get-FilesContainingText

SYNOPSIS
Function to get a list of iles containg certain text in a given set of
folders and their subfolders

SYNTAX
Get-FilesContainingText [-SearchString] <String> [[-FolderName] <String[]>] [-WhatIf] [-Confirm] [<CommonParameters>]

DESCRIPTION
Function returns a list of file names, each containing the search text

PARAMETERS
-SearchString <String>
The text string to search for

Required? true
Position? 1
Default value
Accept pipeline input? true (ByValue, ByPropertyName)
Accept wildcard characters? false

-FolderName <String[]>
Name of the folder(s) to search in.
Function searches in each folder and its subfolders

Required? false
Position? 2
Default value .\
Accept pipeline input? true (ByPropertyName)
Accept wildcard characters? false

-WhatIf [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

-Confirm [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

NOTES

Function by Sam Boutros
v1.0 – 08/16/2014

————————– EXAMPLE 1 ————————–

C:\PS>Get-FilesContainingText “import”

This example lists all the files in the current folder and
its subfolders that contain the string “import”

————————– EXAMPLE 2 ————————–

C:\PS>Get-FilesContainingText -SearchString “cheese” -FolderName “d:\Sandbox”,”\\MyServer1\install” -Verbose

This example lists all the files in the folders”d:\Sandbox” and
“\\MyServer1\install” and their subfolders that contain the string “cheese”

RELATED LINKS
https://superwidgets.wordpress.com/category/powershell/



New ‘Get-SBIPInfo’ function added to SBTools module retrieves computer IPv4 and IPv6 information


SBTools module can be downloaded from the Microsoft Script Center Repository.

To install it, extract the .rar file, and run install-SBTools.ps1 in the folder where you extracted the .rar file.

The Get-SBIPInfo function will retrieve computer IP information for one or more computers.

Sample output:

get-sbipinfo1

NAME
Get-SBIPInfo

SYNOPSIS
Function to get computer IP information.

SYNTAX
Get-SBIPInfo [[-ComputerName] <String[]>] [-WhatIf] [-Confirm] [<CommonParameters>]

DESCRIPTION
Function to get computer IP information.
Function returns an object that has the following properties:
ComputerName, AdapterDescription, IPAddress, IPVersion, SubnetMask, CIDR, MAC, DefaultGateway, DNSServer

PARAMETERS
-ComputerName <String[]>
Name(s) of the computer(s) to be used to get their IP information.

Required? false
Position? 1
Default value $env:COMPUTERNAME
Accept pipeline input? true (ByValue, ByPropertyName)
Accept wildcard characters? false

-WhatIf [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

-Confirm [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

INPUTS
System.String[]

OUTPUTS
System.Object

NOTES
Function by Sam Boutros
V 1.0
08/12/2014

————————– EXAMPLE 1 ————————–

C:\PS>Get-SBIPInfo

This example retuns the current computer IP information

————————– EXAMPLE 2 ————————–

C:\PS>Get-SBIPInfo xhost11 | Out-GridView

This example displays IP information of computer xHost11

————————– EXAMPLE 3 ————————–

C:\PS>Get-Content .\computers.txt | Get-SBIPInfo

This example returns IP information of every computer listed in the computers.txt file

————————– EXAMPLE 4 ————————–

C:\PS>Get-SBIPInfo | Where-Object { $_.IPversion -eq 4 } | Select-Object { $_.IPAddress }

This example lists the IPv4 address(es) of the local computer


New ‘ Test-SBVHDIntegrity’ function added to SBTools module tests VM VHD(x) files’ integrity


SBTools module can be downloaded from the Microsoft Script Center Repository.

To install it, extract the .rar file, and run install-SBTools.ps1 in the folder where you extracted the .rar file.

The Test-SBVHDIntegrity function will test the drive files of a Hyper-V virtual machine and verify the specified file exists and that there are no problems with it.

This is a function by Jeff Hicks originally published here, modified by Sam Boutros 08/09/2014, added functionality to work on VMs from other than localhost.

NAME
Test-SBVHDIntegrity

SYNOPSIS
Test VHD files for integrity

SYNTAX
Test-SBVHDIntegrity [-VM] <Object[]> [-WhatIf] [-Confirm] [<CommonParameters>]

DESCRIPTION
Test the drive files for a Hyper-V virtual machine and verify the specified
file exists and that there are no problems with it.

PARAMETERS
-VM <Object[]>
VM object. Function will check integrity of input VM disk files.

Required? true
Position? 1
Default value
Accept pipeline input? true (ByValue, ByPropertyName)
Accept wildcard characters? false

-WhatIf [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

-Confirm [<SwitchParameter>]

Required? false
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false

<CommonParameters>
This cmdlet supports the common parameters: Verbose, Debug,
ErrorAction, ErrorVariable, WarningAction, WarningVariable,
OutBuffer, PipelineVariable, and OutVariable. For more information, see
about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

————————– EXAMPLE 1 ————————–

C:\PS>Get-VM | Test-SBVHDIntegrity | Out-Gridview

————————– EXAMPLE 2 ————————–

C:\PS>Get-VM -ComputerName xHost11,xHost12 | Test-SBVHDIntegrity | Out-Gridview

This example displays disk integrity results for each VM on the Hyper-V hosts xHost11 and xHost12

————————– EXAMPLE 3 ————————–

C:\PS>Get-VM -ComputerName (Get-Content .\computers.txt) | Test-SBVHDIntegrity | Out-Gridview

This example displays disk integrity results for each VM on the Hyper-V hosts listed n the .\computers.txt file

————————– EXAMPLE 4 ————————–

C:\PS>Get-VM | Test-SBVHDIntegrity | where {(-NOT $_.TestPath) -OR (-NOT $_.TestVHD)}

This examples displays disks that fail either the TestPath or TestVHD checks


Getting information from web pages via Powershell


PS1In many cases, the information we need is available on one or many web pages, but we need to process the same information repeatedly. To automate such a repeated task via Powershell we need to read and parse HTML data. For example, a question was recently posted on the Microsoft 2010 Sharepoint forum:

I love how SharePoint 2010 has the page: http://Server:880/_admin/PatchStatus.aspx. However, looking at this page each server has about 100 patches.  Scrolling through this list is difficult to see if one of the servers is missing a patch or has patches that other servers do not. Is there a way to export the information on the PatchStatus.aspx page in Central Admin to an excel spreadsheet?

For the purpose of this exercise, let’s say we want to get the titles of the posts in this URL https://superwidgets.wordpress.com/category/sql

First, let’s read in the HTML code of this page:

HTML2

Now, let’s pipe that to Get-Member to see what kind of object we got and its available methods and properties:

HTML3

After exploring different properties of the $HTML object we have, and with some background HTML knowledge, you can tell that the information we’re looking for is in the HTML Body.

Using the same technique above, we can explore further properties of the HTML object like “ParsedHTML”

$HTML.ParsedHtml | Get-Member

This shows that it’s a HTMLDocumentClass object with tons of events, methods, and properties:

HTML7

Partial list of HTMLDocumentClass object events, methods, and properties

What’s useful to us here is the following 3 methods:

getElementById
getElementsByName
getElementsByTagName

Now that we know how to extract the information we need from a web page, let’s look at the specifics of the web page at hand https://superwidgets.wordpress.com/category/sql. Open it in IE for example, hit F12 to open the DOM explorer at the bottom, expand the HTML tags, and move the mouse over the tags one by one. Notice that the top IE pane changes the background color of the element you’re moving the mouse on. This gives us a visual indication of which element in the HTML code represents which text or area of an HTML page.

HTML6

You can see the article titles we’re interested in are the ones that start with

<h2 class =”entry-title”>

We can now write the following few lines of Powershell script code to complete the task:

HTML8

# Script to display post titles in the SQL Categroy of Superwidgets blog
# Sam Boutros – 08/10/2014
$URI = “https://superwidgets.wordpress.com/category/sql/
$HTML = Invoke-WebRequest -Uri $URI
($HTML.ParsedHtml.getElementsByTagName(‘h2’) | Where{ $_.className -eq ‘entry-title’ } ).innerText

In line 5 we pick HTML elements by the “H2” tag, filter on ClassName = “entry-title” and select innertext property.

Output looks like this:

HTML9

which is the exactly the article titles we set out to get.

This information can be further processed, logged, stored, or repackaged in other HTML, CSV or other reports..