≡ Menu

Recently a friend asked me a question. He has two text files with names in it. He want to have names from first text file copied to first column in CSV and contents of second text file copied to second column in CSV. This post talks about how to achieve this using PowerShell.

Below screenshot shows how the text file contents looks like and how the output CSV file will be.


First read the contents of text files into variables.

$firstnames = Get-Content C:\temp\firstnames.txt            
$Lastnames = Get-Content C:\temp\lastnames.txt            

Find out which text file has more no. of lines/entries in it. This number tells us how many no. of times we need to loop through to process all items in the text files.

$maxcount = 0            
if($firstnames.count -gt $Lastnames.Count) {            
    $maxcount = $firstnames.count            
} else {            
    $maxcount = $lastnames.Count            

Now loop through the contents and save the details to CSV file.

$outputfilename = "c:\temp\namesoutput.csv"            
Add-Content -Path $outputfilename -Value "FirstName,LastName"            
for($i=0;$i -lt $maxcount; $i++) {            
    $value = "{0},{1}" -f $firstnames[$i],$lastnames[$i]            
    Add-Content -Path $outputfilename -Value $value            

The output file, c:\temp\namesoutput.csv contains the desired output.

Below is a small function that combines all above code pieces and makes the usage generic. You can change the name of output file as you need and names of the CSV columns. I kept them as Column1Name & Column2Name.

function Merge-TextFilesToCSV {            
    $outputfilename = "c:\temp\megedoutput.csv"            
    $File1Contents = Get-Content $File1            
    $File2Contents = Get-Content $File2            
    $maxcount = 0            
    if($File1Contents.count -gt $File2Contents.Count) {            
        $maxcount = $File1Contents.count            
    } else {            
        $maxcount = $File2Contents.Count            
    Add-Content -Path $outputfilename -Value "Column1Name,Column2Name"            
    for($i=0;$i -lt $maxcount; $i++) {            
        $value = "{0},{1}" -f $File1Contents[$i],$File2Contents[$i]            
        Add-Content -Path $outputfilename -Value $value            
    Write-Host "Output available at $outputfilename"            

Copy past the above function into PowerShell window and run it as shown below.


Output shows the name of the output file.


Sometimes you get a requirement to start the PowerShell script from an elevated prompt and you don’t want to continue executing the script if the PowerShell window is not in elevated mode. You can easily recognize a PowerShell window is in elevated mode or not just by looking at the title of the Window. You will notice Administrator: prefixed with shell title when it is launched in elevated mode. See below screen for example.


But how to verify this in programmatic way so that we can incorporate the logic within the script to continue only if the shell is in elevated mode?

One approach is, we can verify the WindowTitle of the Shell prompt and check if it has the string Administrator: in it. Below is small piece of code that can help you check the window title.

$h = Get-Host            


But problem with it this approach is, the window title is just a string and can be easily overwritten. When someone makes their custom window title, you might ending up thinking that PS window as normal though it is actually elevated prompt.

So, we need much better solution here using which we can detect the elevation of the Shell. Below is a small PowerShell function which returns true or false based on the elevation status of the shell from where you are running it. This function can be easily added to your PowerShell scripts and can be called when you want to verify the elevation status.

function Test-IsElevated {            
 [Security.Principal.WindowsPrincipal] $Identity = [Security.Principal.WindowsIdentity]::GetCurrent()            

Below is a test script which uses this function and verifies if the script is launched from elevated shell or not.

Code: Test-Elevation.ps1.

function Test-IsElevated {            
 [Security.Principal.WindowsPrincipal] $Identity = [Security.Principal.WindowsIdentity]::GetCurrent()            
Write-Host "This script tests if current PowerShell session is in elevated mode or not"            
if(Test-IsElevated) {            
 Write-Host "Current PowerShell session is in elevated mode"            
} else {            
 Write-Host "Current PowerShell session is NOT in elevated mode"            

Hope you will find this useful.


NIC Teaming(LBFO) Guide for Windows Server 2012 R2

Microsoft introduced built-in teaming capabilities in Operating System starting from Windows Server 2012. Using these Network Adapters can be teamed without using any vendor/third party utilities. This Microsoft given teaming facility provides load balancing as well as Fail Over capabilities. Hence it is referred as LBFO in many places while describing the feature.

Configuring Teaming using UI method:

You can start the teaming utility on a Windows Server 2012 by using LBFOadmin.exe utility. You can launch it by typing “lbfoadmin.exe” from Start->Run or from command prompt on Windows Server 2012 or above. Using this utility you can manage teaming abilities of local as well as remote computer.

Look at the below screenshot which shows the teaming configuration of my local host. Teaming of remote servers can also be managed by using this wizard.


You can add more servers by using the Add Servers option in TASKS section under SERVERS.

Creating a new teaming is as simple as selecting the Network connections from “Adapters and Interfaces” section(Hold Ctrl key to select multiple NICs), right click, select Add To New Team as shown in the below picture.


It pop-up an wizard where you need to enter Team name and chose some more teaming parameters like team mode, active/passive adapters, VLAN Configuratin, etc and click OK to complete the teaming.

New-team-detailsThere are different teaming modes and load balancing algorithms available which you can select as per your needs. The details of each of these modes and algorithms can be found from TechNet or you can refer to one of below NIC Teaming Deployment and Management documents from Microsoft.

Windows Server 2012 : http://www.microsoft.com/en-us/download/details.aspx?id=30160

Windows Server 2012 R2 : http://www.microsoft.com/en-us/download/details.aspx?id=40319

After selecting the required options, Click OK to complete the teaming. Review the TEAMS section in LBFOAdmin.exe utility to review the status of teaming.


Since I have used a VM to demonstrate the teaming ability and both of the network connections are connected to Internal Network, teaming is showing as Fault. Otherwise, It should show online to indicate that it is successful.

Configuring Teaming Using PowerShell:

We have seen how to configure teaming using UI method. But this method is not efficient if you want to incorporate the teaming task into build routines or you want to perform on multiple computers. Windows Server 2012 introduced a new module called NetLBFO which can be used to manage the teaming from PowerShell.

You can get the list of cmdlets in this module by using below command.

PS C:\temp> Get-Command -Module NetLBFO

CommandType     Name                                               ModuleName
———–     —-                                               ———-
Function        Add-NetLbfoTeamMember                              NetLBFO
Function        Add-NetLbfoTeamNic                                 NetLBFO
Function        Get-NetLbfoTeam                                    NetLBFO
Function        Get-NetLbfoTeamMember                              NetLBFO
Function        Get-NetLbfoTeamNic                                 NetLBFO
Function        New-NetLbfoTeam                                    NetLBFO
Function        Remove-NetLbfoTeam                                 NetLBFO
Function        Remove-NetLbfoTeamMember                           NetLBFO
Function        Remove-NetLbfoTeamNic                              NetLBFO
Function        Rename-NetLbfoTeam                                 NetLBFO
Function        Set-NetLbfoTeam                                    NetLBFO
Function        Set-NetLbfoTeamMember                              NetLBFO
Function        Set-NetLbfoTeamNic                                 NetLBFO

PS C:\temp>

As you can see there are cmdlets available for performing various tasks related to teaming. Now let us use New-NetLbfoTeam cmdlet to create the teaming similar way we have done using the UI.

New-NetLbfoTeam -Name TIBDC2-Team1 -TeamMembers Ethernet2, Ethernet3 -Confirm:$false

That’s it. The result will show the status of teaming. Looking very simple right? That is the reason I like PowerShell. Once the teaming is available you can use Set-Netlbfo* cmdlets to change the teaming configuration, Get-NetLbfo* cmdlets to read the teaming info. The Add-Netlbfo* and Remove-Netlbfo* cmdlets are used for adding and teaming members, nics, and to remove the team itself.

Refer to this TechNet article(http://technet.microsoft.com/en-us/library/jj130849.aspx) to know more about each of these cmdlets and how they can help automate you tasks.

Hope this helps and happy learning.


In one of my previous posts, I shared the PowerShell code that helps in enabling or disabling a network connection easily in any operating System. Starting with Windows Server 2012 this has become very easy that you don’t need any additional code to perform this. Windows Server 2012/Windows 8 and above has a bunch of cmdlets that can work with network connections to enable or disable them.

A new module called NetAdapter is introduced to work with network connections. It has total of 64 cmdlets that can be used to perform operations against network connections in Windows Server 2012/Windows 8 or above. In future post, you will see more content about usage of the cmdlets in these modules. In today’s post we will how to enable or disable network connections locally as well as remote.

Get-NetAdapter cmdlet helps in listing the current network connections.

Get-NetAdapter -CimSession TIBDC2


It lists the network adapters and their status on TIBDC2 server. As you can see in the output, there is one network adapter which is in disabled state. If you want to enable that adapter you can use Enable-NetAdapter as shown below.

Enable-NetAdapter -CimSession TIBDC2 -Name Ethernet2

This command will return nothing when completed successfully. You can use -Passthru parameter if you want to see what is the status of the network connection after running the enable command.

Enable-NetAdapter -CimSession TIBDC2 -Name Ethernet2 -PassThru

Disabling a network connection is similar to enable operation. Instead of Enable-NetAdapter, we need to use Disable-NetAdapter cmdlet. The parameters that you need to supply to this cmdlet are same as what you have provided for Enable-Netadapter cmdlet.

Now let us look at below sample command that disables the Ethernet2 adapter that we just enabled.

Disable-NetAdapter -CimSession TIBDC2 -Name Ethernet2


This command will prompt you for a confirmation to disable the connection. You can suppress this by specifying -Confirm:$false to the cmdlet.

Disable-NetAdapter -CimSession TIBDC2 -Name Ethernet2 -Confirm:$false

You can use these sample commands and disable/enable network connections. Hope article helps.


After downloading a VHD from Microsoft site and trying to import in Hyper-V environment you may observe this error. This can happen in Windows Server 2012 or above.


Looking the error message, you may feel that this VHD doesn’t support the Hyper-V version I am running. But wait!!!. I have downloaded a Windows Server 2012 R2 evaluation VHD from Microsoft and it is not working on a Hyper-V which is running on Windows Server 2012. I don’t think Microsoft will do such silly things. After debugging for sometime, I recollected a article that wrote some days back. It is about sparse flag for the files downloaded from Microsoft website.

You can read the complete article at http://techibee.com/powershell/powershell-script-to-query-folder-size/1060

So, I quickly verified and noticed that the VHD I downloaded has this sparse file set. So, removing it should solve the problem.

I made use of the Remove-SparseFlag PowerShell function which I wrote in aforementioned article and  removed the flag. After that the VM started fine.


Hope this helps.



PowerShell: Get Windows System Info in Object format

I came across a tip in twitter from Jeffry Snover that helps in converting the System Information from Windows System information into PowerShell object. This conversion helps in easily accessing the information just by accessing the Property values.

Look at below example for better understanding.

$Obj = systeminfo /FO CSV | ConvertFrom-CSV            
$Obj.'System Boot Time'            
$Obj.'System Type'            

The first line queries the System information from local computer and stores the value in $Obj after converting the output from CSV to Object format. Once the results are available in $Obj you can review the properties of this object and query the data you want. All you see in $Obj is same as what you see when systeminfo command is ran. It’s just that formatting the output and storing in object structure for better processing.


Here is the original tweet I am referring to.

Hope this tiny tip helps.

{ 1 comment }

Add Computers to WSUS Group Using PowerShell

WSUS is still a good choice for Windows Administrators to deploy patches. This article will demonstrate how to add a Computer account to WSUS Group using PowerShell.

This activity will look cumbersome and time consuming when you want to add large no. of computers to a WSUS Group. The manual procedure involves, searching each computer and right click on it, change group membership and then select the group name that you want to move.

I faced similar situation and wanted to automate it though it is a one time task for me. A quick search in Google led me to basics of managing WSUS using PowerShell written by Boe Prox. I make up a quick script based on this article and able to move computers to new group in no time.

First we need to establish connection to WSUS.

#Connect to WSUS server            
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer("localhost",$False)

Once the connection established, we should get a reference to Computer Group to which you want to add computers. The $GroupObj will hold the result.

#Get reference to WSUS Group to which you want to add computer account            
$GroupObj = $wsus.GetComputerTargetGroups() | ? {$_.Name -eq "MyNewGroup"}

Similarly we need to get reference to Computer object that we want to add. The SearchComputerTargets() method allows us to search for computer accounts matching a given name. Note that this method will always return a array even though the search returns a single computer object. That is the reason I have used a for loop to add all results from search operation. If you don’t want to perform add operations if the search results are more than one, then just perform a check on the $CompObj array to see how many items it is containing. If the count is 1, then search operation resulted in finding one computer. Based on this value you can process further.

#Search for the computer account that you want to add            
$CompObj = $wsus.SearchComputerTargets("Server01")            
#Add computer to the WSUS Group            
foreach($Comp in $COmpObj) {            

You won’t see a error message at the end of addition if successful.

Windows 8.1 and Windows Server 2012 R2 has a built PowerShell module for managing WSUS which you may want to take a look.


Cheat Sheet for Process Management is a small handy guide for any process related operations using PowerShell. It covers most common and basic things related to windows processes that any Windows Admin want to perform on a day to day basis. If you are in the process of learning PowerShell, I prefer you keep a print of it at desk as a quick reference. These are simple one liners which are targeted perform more common tasks.

The current version of this cheat sheet covers following basic tasks. If you have any suggestion to include new items, please drop me a note(see about section in my blog).

  • Get all processes and list name, PID, exe path
  • Check if a process is running by Name
  • Check if a process is running(by PID)
  • Kill a process by name
  • Kill a process by pid
  • Query full path of a process executable
  • Get process id of a process
  • Get owner(user name) of a process
  • Get Creation time of a process
  • Start a new process(locally)
  • Start a new process(locally) and get pid of it
  • Start a new process(remotely)

Do you like this idea of preparing Cheat Sheet for frequently used PowerShell commands?? Provide your feed back in comments sections. That helps me to prepare future guides in the same line.


{ 1 comment }

Remove empty items from array in PowerShell

Often we get this situation where in you read the contents of a file for servers list or some other content and end up with blank/empty items in the array because of empty lines in the files. This is often seen when doing split operation on array and because of string format you will end up with empty items in array.

The below example will give you understanding of what I am saying. Scenario#1 shows how blank entries will get added to array when you read the file contents using Get-Content cmdlets and Scenario#2 shows how you will end up with blank/empty entries when you split a string using Split() method. These are two most common cases where you will end up with empty items in resultant array.


Now let us go ahead and see how to get rid of them.

Addressing scenario#1:

It can be addressed by using simple technique where you will check each item in array and verify if it is empty or not. Need even shorter solution? Try the below.

$content = Get-Content c:\temp\servers.txt            
Write-Host "Array size before removing empty lines : $($content.Count)"            
$content = $content | ? {$_}            
Write-Host "Array size AFTER removing empty lines : $($content.Count)"


I am not aware of any other better approaches, please feel free to share if you have better technique.

Addressing scenario#2:

Scenario#2 can also be addressed in same way as scenario#1 but I don’t want to do it since there is better approach. Let me be a good programmer.

$string = "try;splitting;;me;;by semi;;coluns;;to see what ;; happens;ok?"            


As you can see split() method can take a optional parameter called splitoptions where we can specify it to remove empty entries.

As you can see in output, empty lines are removed now.


In my previous post, we explored the way to identify list of group policies linked to a particular Active Directory OU. While it serves the purpose, there are few details missing there like whether GPO is enabled, enforced, what is the order of the GPO, etc.

Articles related to working with Group Policies using PowerShell

  1. Find Group Policies Objects in Domain using PowerShell
  2. Find Group Policies linked to Active Directory OU Using PowerShell

The applicability of Group Policy object on an Active Directory OU completely replies on status of Group Policy link on that OU. If the status of Group Policy link is in enabled state, then policy will get applied. If the status is disabled, policy is not applicable for members inside that OU. Below screen shot shows the link enable status of a Group Policy on LAB OU from GPMC editor.


When the GPO link is disabled, it appears like below in GPMC editor.


Similarly enforced option has its significance to decide policy applicability.

So let us see how we can identify the link status, enforcement status and order of a Group Policy object on a OU using PowerShell since this these plays vital role in deciding the GPO applicability to objects inside that OU>

In my previous post, I used a property called LinkedGroupPolicyObjects to retrieve list of linked Group Policies on OU. There is another property called gPLink which gives more details about the policy that is linked. The values inside gPlink property talks about list of policies, their order, link enable status, enforce status. The format of gplink property looks like below.

[<GPO DN_1>;<GPLinkOptions_1>][<GPO DN_2>;<GPLinkOptions_2>]… [<GPODN_n>;<GPLinkOptions_n>]

Where GPO DN is the distinguished name of the GPO and GPLinkOptions represent the GPO enabled and enforcement status. Also first DN in the string has high precedence order while the last one has low precedence order. You can find more details about this structure at http://msdn.microsoft.com/en-us/library/cc232505.aspx

The below script take a OU name, searches active directory for OUs having that name, queries the group policies linked to that OU, identifies link status, enforcement status, order details and returns the information in Object format.


$OUs = @(Get-ADOrganizationalUnit -Filter * -Properties gPlink | ? {$_.Name -eq "$OUName"})            
#Return if no OUs found with given name            
if(!$OU) { Write-Warning "No such OU found"; return }            
foreach($OU in $OUs) {            
 $OUName = $OU.Name            
 $OUDN = $OU.DistinguishedName            
 #Hackey way to get LDAP strings. Regex might be best option here            
 $OUGPLinks = $OU.gPlink.split("][")            
 #Get rid of all empty entries the array            
 $OUGPLinks =  @($OUGPLinks | ? {$_})            
 $order = $OUGPLinks.count;            
 foreach($GpLink in $OUGPLinks) {            
   $GpName = [adsi]$GPlink.split(";")[0] | select -ExpandProperty displayName            
   $GpStatus = $GPlink.split(";")[1]            
   $EnableStatus = $EnforceStatus = 0            
   switch($GPStatus) {            
    "1" {$EnableStatus = $false; $EnforceStatus = $false}            
    "2" {$EnableStatus = $true; $EnforceStatus = $true}            
    "3" {$EnableStatus = $false; $EnforceStatus = $true}            
    "0" {$EnableStatus = $true; $EnforceStatus = $false}            
   $OutputObj = New-Object -TypeName PSobject            
   $OutputObj | Add-Member -MemberType NoteProperty -Name OUName -Value $OUName            
   $OutputObj | Add-Member -MemberType NoteProperty -Name OUDN -Value $OUDN            
   $OutputObj | Add-Member -MemberType NoteProperty -Name GPName -Value $GPName            
   $OutputObj | Add-Member -MemberType NoteProperty -Name IsLinked -Value $EnableStatus            
   $OutputObj | Add-Member -MemberType NoteProperty -Name IsEnforced -Value $EnforceStatus            
   $OutputObj | Add-Member -MemberType NoteProperty -Name GPOrder -Value $Order            


Group Policy link status

The output is easy to understand. It mentions about OU name, its DN, policy name, link status, enforcement status, and order of the GPO that you see in GPMC console.

gpo status in gpmc

Hope this helps.. stay tuned for more articles in future.

This script is also available at technet library (http://gallery.technet.microsoft.com/Get-GPO-link-status-a6e5fe7e)