Powershell script to read column from CSV file, excluding one or more values

This script will read the input CSV file, and look for a column name as entered in either the -Column or -Alias parameters. If column is found, the script will read all the values in that column, exclude any values passed in the -ExcludeValue parameter, and return all remaining values.

Read-CSV -FileName ‘.\MigrationData-1.csv’ -Column ‘user’ -Verbose
This example reads and returns all values in column ‘user’


$UserList = Read-CSV -FileName ‘.\MigrationData-1.csv’ -Column ‘user’ -ExcludeValue ‘none’,’N/a’ -Verbose
This example reads and returns all values in column ‘user’, excluding the values ‘none and ‘n/a’ (not case sensitive), and stores the read user names in the $UserList variable


$UserList = Read-CSV -FileName ‘.\MigrationData-1.csv’ -Column ‘samAccountName’ -Alias ‘user’,’users’,’username’ -ExcludeValue ‘none’,’N/a’ -Verbose
This example reads the input CSV file, looks for a column named ‘samAccountName’,’user’,’users’,or ‘username’, and returns all values in the found column if any, excluding the values ‘none and ‘n/a’ (not case sensitive), and stores the read user names in the $UserList variable.


Powershell script to validate if a folder exists, creates it if not, creates subfolders if needed

This function will  validate that a folder exists, and creates the folder if missing.

If the -NoCreate switch is used the function will not create a missing folder

The function will create missing subfolders as well

The parameter -FolderName can be local like ‘c:\folder 1\folder 2’ or UNC path like ‘\\server\share\folder 1\folder 2’

The -NoCreate switch insructs the function to NOT create the folder if missing

The function returns a TRUE/FALSE value. The function returns TRUE if:

  • The folder exists
  • The folder did not exist but was created by the function

The function will return FALSE if:

  • The folder doesn’t exist and the -NoCreate switch is used
  • The folder doesn’t exist and the function failed to create it

The function will create the folder tree if it does not exist. For example, if c:\sandbox has no subfolders and we run the cmdlet:

Validate-Folder f1\22\33\44\55\66\77\88 -Verbose

It will create the folders:

  • c:\sandbox\f1 and
  • c:\sandbox\f1\22 and
  • c:\sandbox\f1\22\33 and
  • c:\sandbox\f1\22\33\44 and
  • c:\sandbox\f1\22\33\44\55 and
  • c:\sandbox\f1\22\33\44\55\66 and
  • c:\sandbox\f1\22\33\44\55\66\77 and
  • c:\sandbox\f1\22\33\44\55\66\77\88



Validate-Folder -FolderName c:\folder1
This example checks if folder c:\folder1 exists, creates it if not,
returns TRUE if exists or created, returns FALSE if failed to create missing folder

Validate-Folder -FolderName ‘c:\folder 2’ -NoCreate
This example checks if ‘c:\folder 2’ exists, return TRUE if it does, FALSE if it doesn’t

if (Validate-Folder ‘c:\folder 1\sub 2’) { ‘hi’ | Out-File ‘c:\folder 1\sub 2\file.txt’ }
This example checks if folder ‘c:\folder 1\sub 2’ exists,
creates it if it doesn’t,
creates file ‘c:\folder 1\sub 2\file.txt’, and
writes ‘hi’ to it

@(‘c:\folder1′,’\\server\share\folder 4’) | % { Validate-Folder $_ -Verbose }
This example validates if the folders in the input array exist, creates them if they don’t


Powershell script to provide a PS Credential object, saving password securely

Have you ever been in the situation where you need to execute a cmdlet like

Disable-ADAccount -Identity ‘Someone’ -Server ‘MyDomainController’ 

To disable a user account, but it fails because your account does not have permission to disable users?

You can use another account that have permissions to disable users by using the -Credential parameter of the Disable-ADAccount cmdlet as in

Disable-ADAccount -Identity ‘Someone’ -Server ‘MyDomainController’ -Credential (Get-Credential)

The Get-Credential cmdlet prompts for a user name and password, which is fine if ypu need to run it once or a few times. However, we often come across situation where we need to use several credentials to automate tasks in Active Directory, Exchange, SharePoint,… You will rarely have a single account that has permission to do all these tasks, or across multiple directories. In an automation script, the Get-SBCredntial function can make this easy.

Here’s an example:

$SourceADCred = Get-SBCredential 'domain1\MyADAdmin'
$TargetADCred = Get-SBCredential 'domain2\MyADAdmin'
$ExCred = Get-SBCredential 'domain1\MyExchangeAdmin'
Disable-ADAccount -Identity 'Someone' -Server 'MyDomainController1' -Credential $SourceADCred
Disable-ADAccount -Identity 'Sometwo' -Server 'MyDomainController2' -Credential $TargetADCred
Get-Mailbox -Identity '' -Credential $ExCred




Powershell script to list StorSimple network interface information including MAC addresses

In many cases we can obtain the IP address of a network interface via one command but get the MAC address from another command. StorSimple 8k series which runs a core version of server 2012 R2 (as of 20 June 2016) is no exception. In this case we can get the IP address information of the device network interfaces via the Get-HCSNetInterface cmdlet. However, to identify MAC addresses we need to use the Get-NetAdapter cmdlet. This Powershell script merges the information from both cmdlets presenting a PS Object collection, each of which has the following properties:

  • InterfaceName
  • IPv4Address
  • IPv4Netmask
  • IPv4Gateway
  • MACAddress
  • IsEnabled
  • IsCloudEnabled
  • IsiSCSIEnabled

Script output may look like:


For more information about connecting to StorSimple via PowerShell see this post.


Powershell script to migrate FSRM Quota settings

When migrating file servers, you may need to migrate FSRM based Quota settings.


There can be hundreds of these settings based on FSRM Quota templates. This Powershell script migrates FSRM Quota settings from remote server to local computer, including Quota Templates, Admin Options, and Quotas applied to folders.


Sample script output:


As usual, script output is displayed at the console and saved to a log file for future reference.

After running the script the FSRM Quota Templates and FSRM Quotas (applied to folders) can be viewed in the File Server Resource Manager (Server 2012)


Powershell script to backup all user databases on current SQL server

This script will backup all user databases on the current SQL server. The Input region accepts values for 2 variables:

$Destination ==>This is the folder where backup files will be stored
$Retension ==> Number of days to keep backup files. Backup files older than this will be deleted. If you don’t want any files deleted, make this number high like 99999

The script creates a folder for each database under the $Destination folder. Backup file name contains the database name and date/time of backup. For example, for database ‘INM’, backup file would be ‘H:\SQL-Backup\INM\INM-20160605_081237AM.bak’
Script returns an object collection. Each object has the following properties:

  • ServerName
  • DatabaseName
  • RecoveryModel
  • BackupDateTime(yyyyMMdd_hhmmsstt)
  • BackupDuration(hh:mm:ss)
  • BackupFileSize(MB)
  • BackupFileSize

Sample script output:


Also see script to list SQL Recovery Model of all databases on current server, script to modify and list SQL Recovery Model of all databases, and this related post.

Presenting StorSimple iSCSI volumes to a failover cluster

In a typical implementation, StorSimple iSCSI volumes (LUNs) are presented to a file server, which in turn presents SMB shares to clients. Although the StorSimple iSCSI SAN features redundant hardware, and is implemented using redundant networking paths on both the Internet facing side and the iSCSI side, the file server in this example constitutes a single point of failure. One solution here is to present the iSCSI volume to all nodes in a failover cluster. This post will go over the steps to present a StorSimple iSCSI volumes to a failover cluster as opposed to a single file server.

Create volume container, volume, unmask to all cluster nodes

As usual, keep one volume per volume container to be able to restore one volume at a time. Give the volume a name, size, type: tiered. Finally unmask it to all nodes in the failover cluster:


Format the volume:

In Failover Cluster Manager identify the owner node of the ‘File Server for general use‘ role:


In Disk Management of the owner node identified above, you should see the new LUN:


Right click on Disk20 in the example above, click Online. Right click again and click Initialize Disk. Choose GPT partition. It’s recommended to use GPT partition instead of MBR partition for several reasons such as maximum volume size limitation.

Right click on the available space to the right of Disk20 and create Simple Volume. It’s recommended to use Basic Disks and Simple Volumes with StorSimple volumes.

Format with NTFS, 64 KB allocation unit size, use the same volume label as the volume name used in StorSimple Azure Management Interface, and Quick format. Microsoft recommends NTFS as the file system to use with StorSimple volumes. 64KB allocation units provide better optimization as the device internal deduplication and compression algorithms use 64KB blocks for tiered volumes. Using the same volume label is important since currently (1 June 2016) StorSimple does not provide a LUN ID that can be used to correlate a LUN created on StorSimple to one appearing on a host. Quick formatting is important since these are thin provisioned volumes.

For existing volumes, Windows GUI does not provide a way of identifying the volume allocation unit size. However, we can look it up via Powershell as in:

@('c:','d:','y:') | % {
 $Query = "SELECT BlockSize FROM Win32_Volume WHERE DriveLetter='$_'"
 $BlockSize = (Get-WmiObject -Query $Query).BlockSize/1KB
 Write-Host "Allocation unit size on Drive $_ is $BlockSize KB" -Fore Green

Replace the drive letters in line 1 with the ones you wish to lookup.

Summary of volume creation steps/best practices:

  • GPT partition
  • Basic Disk (not dynamic)
  • Simple volume (not striped, mirrored, …)
  • NTFS file system
  • 64 KB allocation unit (not the default 4 KB)
  • Same volume label as the one in StorSimple
  • Quick Format

Add the disk to the cluster:

Back in Failover Cluster Manager, under Storage, right click on Disks, and click Add Disk


Pick Disk20 in this example


Right click on the new cluster disk, and select Properties


Change the default name ‘Cluster Disk 3’ to the same volume label and name used in StorSimple


Assign Cluster Disk to File Server Role

In Failover Cluster Manager, under Storage/Disks, right click on TestSales-Vol in this example, and select Assign to Another Role under More Actions


Select the File Server for General Use role – we happen to have one role in this cluster:


Create clustered file shares

As an example, I created 2 folders in the TestSales-Vol volume:


In Failover Cluster Manager, under Roles, right click on the File Server for General Use role, and select Add File Share


Select SMB Quick in the New Share Wizard


Click Type a custom path and type in or Browse to the folder on the new volume to be shared


Change the share name or accept the default (folder name). In this example, I added a dollar sign $ to make this a hidden share


It’s important to NOT Allow caching of share for StorSimple volumes. Access based enumeration is my personal recommendation


Finally adjust NTFS permissions as needed or accept the defaults:


Click Create to continue


Repeat the above steps for the TestSales2 folder/share in this example


Migrating WordPress web site to Azure

From the IT prospective a WordPress web site requires:

  • A web server like Microsoft IIS or Apache
  • PHP
  • mySQL database

Migrating a WordPress website includes copying all its files/folder structure, and its mySQL database, and changing the wp-config.php file to point to the new mySQL database. These tasks could be complicated for a large site and may require specific skills related to web site configuration and mySQL database administration. This post goes over a very simple way to migrate a WordPress web site to Azure, using the Duplicator WordPress plugin.

Executive Summary

  • Add Duplicator WordPress Plugin
  • Create New Package
  • Create new Azure WebApp
  • Add mySQL database
  • Upload the Duplicator package to the new Azure WebApp
  • Run the Duplicator Package Installer

Add Duplicator WordPress Plugin

If you don’t have it already, add the WordPress Duplicator Plugin. On the Plugins page click Add New


Search for Duplicator, click Install Now


Create New Package

Click on Duplicator link on the left, then click Create New


Accept the defaults and click Next to scan your WordPress site


Duplicator scans your current WordPress site


and displays the result like:


In this example, I have a couple of warnings about large site size, and some large files. I check the box and click Build.


Duplicator builds the package:


The package consists of an Installer (installer.php file) and Archive (.zip file). I download both to my desktop. The zip file contains all the WordPress site files and folder structure + a scripted copy of the associated mySQL database

Create new Azure WebApp

In the Azure Portal, click New/Web+Mobile/Web App


In the Web App blade I type in the new Web App name ‘MyWebApp407’ which must be unique under I pick the Azure subscription from the Subscription drop down menu. I choose to create a new Resource Group. I give it a name; ‘MyWebApp-RG’. I click the arrow to create a new Service Plan


In the App Service Plan blade (middle) I click Create New,  type in MyWebApp-SP as the name, select East-US and accept the default Pricing teir of S1 Standard.

Finally, I click OK and Create

In a few minutes Azure complete MyWebApp deployment


Add mySQL database

I browse under Resource Groups/MyWebApp-RG, and click Add


I search for mySQL, and select MySQL Database by ClearDB


and click Create


I give it a name ‘MyWebAppDB’ (avoid using other than alphanumeric characters in DB name), pick East US for the location, click the arrow and OK to accept the terms, and finally click Create


Click Refresh and note the new blank mySQL database:


Upload the Duplicator package to the new Azure WebApp

If you browse to the new web site now you may see a temporary page like:


First zip the 2 files downloaded from the Duplicator Package above into 1 file:


Next browse to the KUDU page

Click CMD under the Debug Console menu


Browse to d:\site\wwwroot


Drag the zip file from prior steps and drag it on the right side as shown below:


Azure will upload


and unzip the file


Run the Duplicator Package Installer

Browse to the installer.php file as in

You will see a page similar to


Back in the Azure Portal, click MyWebAppDB/Properties


Note the Database Name, Hostname, username, and password


Back in the installer.php screen, enter the required information as shown below:


Click ‘Connect and Remove All Data’, click ‘Test Connection’, check the box to acknowledge the notices, and click ‘Run Deployment’

Click OK to continue..


The installer extracts the Duplicator Package zip file restoring the file system and rebuilds the mySQL database from the script contained in the zip file


Accept the defaults and click Run Update


The Installer makes the selected changes to the WebApp config files


Follow the installer instructions to do final testing:


Step number 2 above is actually important. Clicking on the link next to ‘2.’ above will take you to the site admin login page:


Use the same credentials from the original site.

Adjust your permalinks setting as it is on the original site.:


As a last step, once the site users have tested that everything looks OK, add a custom domain to the site and switch the domain DNS records to point to your new Azure site.







Powershell script to Auto-Expand StorSimple volume based on amount of free space

StorSimple Hybrid Cloud Storage array is an on-premise iSCSI SAN that extends seamlessly to the cloud. iSCSI volumes provisioned from a StorSimple device can be expanded but cannot be shrunk. So, a typical recommendation here is to start a volume small and grow it as needed. Growing a volume is a process that does not require down time. This script grows a StorSimple volume automatically based on set conditions of volume free space and a not-to-exceed value.

The input region of this script is the one that should be edited by the script user:


Similar to the script that monitors StorSimple Backups, the values for SubscriptionName, SubscriptionID, and StorSimpleManagerName variables can be found in the classic Azure Management Interface under your StorSimple Manager node Dashboard and Device pages:


and the RegistrationKey:


and the SSDeviceName (StorSimple Device Name)


The value for the SSVolumeName (StorSimple volume name) variable can be found under the device\volume container:


Notify variable can be either $true or $false. This instructs the script whether or not to send email notification when an expansion is triggered,

Similarly, Expand variable can be either $true or $false. This instructs the script whether or not to expand the volume when an expansion is triggered, When set to $false (and Notify is set to $true) and an expansion is triggered, the script will send an email notification that an expansion is triggered but will not do the actual expansion.

ExpandThresholdGB and ExpandThresholdPercent variables are used by the script to identify the amount of free space on the volume below which a volume expansion is triggered. Only one of these variables is needed. If both are provided the script will use the larger value.

  • Example 1: If the volume size is 100 GB, and the ExpandThresholdGB is set to 10 (GB) and the ExpandThresholdPercent is set to 15 (%), the script will trigger a volume expansion if the amount of free space is at or below 15 GB
  • Example 2: If the volume size is 100 GB, and the ExpandThresholdGB is set to 10 (GB) and the ExpandThresholdPercent is set to 5 (%), the script will trigger a volume expansion if the amount of free space is at or below 10 GB

Similarly, the ExpandAmountGB and ExpandAmountPercent variables instruct the script on how much to expand the volume once expansion is triggered. Only one of these variables is needed. If both are provided the script will use the larger value.

  • Example 1: If the volume size is 100 GB, and the ExpandAmountGB is set to 10 (GB) and the ExpandAmountPercent is set to 15 (%), the script will expand the volume by 15 GB once expansion is triggered.
  • Example 2: If the volume size is 100 GB, and the ExpandAmountGB is set to 10 (GB) and the ExpandAmountPercent is set to 5 (%), the script will expand the volume by 10 GB once expansion is triggered.

The value assigned to the variable NotToExceedGB is used by the script as volume maximum size that the script must not exceed. For example, if the prior 4 variables instruct the script to expand a 900 GB volume by an additional 200 GB and the NotToExceedGB variable is set to 1024 (1 TB), the script will expand the volume by 124 GB only to reach the NotToExceedGB amount but to not to exceed it.

DiskNumber and DriveLetter are values that the script user should obtain from the server’s Disk Management screen of the file server using this iSCSI volume:


As of the time of writing this post and script (1 April 2016), there’s no way to correlate a volume on a file server to a volume on a StorSimple device. For example, if you create 3 volumes of the same size on a StorSimple device and call them data1, data2, and data3, and present them to the same file server and format them with the same file system and block size, and use volume labels data1, data2, data3, there’s no way to tell if data1 on the StorSimple device is the volume labeled data1 on the file server. This is why it’s recommended to provision and format StorSimple volumes one at a time and use the same volume label when formatting the volume as the volume name on StorSimple. Long story short, it’s the user’s responsiblity to:

  1. Make sure the DrviveLetter and DiskNumber correspond to the SSVolumeName, and
  2. Update the DrviveLetter and DiskNumber values if they change on the file server due to adding or removing volumes.

One last point here; if this iSCSI volume is presented to a Windows Failover cluster, this script must be run on the owner node.

LogFile is the path to where the script will log its actions – each log line will be time stamped. This could be on a network share.

EmailSender is the name and email address you wish to have the email notification appear to come from. For example: StorSimple Volume Size Monitor <>

$EmailRecipients = @(
‘Sam Boutros <>’
‘Your Name <>’

is an array that takes one or more email addresses in the format shown above.

SMTPServer is your SMTP relay server. You need to make necessary configuration/white-listing changes to allow your SMTP server to accept and relay SMTP email from the server running the script.

Sample script output:


another example:


and example of email notification:


Possible future enhancements to this script include:

  1. Rewrite the script as a function so that it can handle several volumes
  2. Rewrite the script to use Powershell remoting, so that it does not have to run on the file server.
  3. Add functionality to detect if the target file server is a member of a failover cluster, and to automatically target the owner node.




Get every new post delivered to your Inbox.

Join 35 other followers