≡ Menu

In this post, you will see various options for extracting folder name from given file or directory path. This is generally useful in many ways as you work more with file and folders.

Let us proceed to see how we can achieve this. For example you have a absolute path c:\temp\abc\myproj1\newdata.txt file and you want to get the parent directory of the newdata.txt from the path string that is given to you. This operation might look simple if you just have one path and what you do if you have to do this for some 10,000 files paths? Obviously a programmatic approach is destination.

My favorite approach is using [System.IO.Path] Class.

[System.IO.Path]::GetDirectoryName("c:\temp\abc\myproj1\newdata.txt")

The GetDirectoryName method takes a path as input and returns the directory name. Alternative to this is using split-path cmdlet that comes with PowerShell. Using this cmdlet is much better than GetDirectoryName method because this cmdlet provides several other features.

What they are?

Like the GetDirectoryName method, it also returns the parent directory

Split-Path "c:\temp\abc\myproj1\newdata.txt"

It verifies if the path exists or not when -Resolve parameter is specified

Split-Path "c:\temp\abc\myproj1\newdata.txt" -Resolve

It can be used to get the file name from path instead of parent directory.

Split-Path "c:\temp\abc\myproj1\newdata.txt" -Leaf

Hope this tip helps you

{ 0 comments }

While connecting Windows Server 2012(or R2) using RDP you might notice error which says “An authentication error occurred. The Local Security Authority cannot be contacted”. In this post we will see how to get rid of this error and have some PowerShell solution so that you can deploy this across to your servers.

Basically this problem happens when RDP configuration on Windows Server 2012 enforces you to use Network Level Authentication(NLA) to connect using RDP client. It is a security feature introduced starting from Windows Vista/Windows Server 2008. You can read more about NLA at https://technet.microsoft.com/en-us/magazine/hh750380.aspx.

While NLA increases security and performance of the server, it prevents clients which doesn’t support NLA or the ones in broken state from connecting via RDP. If you decided to disable NLA, then follow below steps.

On the server where you want to disable NLA to allow RDP connections.

  • Go to Start -> Run -> type “sysdm.cpl” and Press Enter
  • It opens System Properties. Now go to Remote tab
  • Uncheck Allow Connections only from computers running Remote Desktop with Network Level Authentication (recommended) checkbox.
  • Click on Apply and try to RDP again to the server.

It should work without issues this time. Below screenshot shows the option that I am explaining in above steps.

Now you know how to address this error on single server. But how to do it on multiple server or you want to make it part of your build process? There is a way using PowerShell.

The Win32_TSGeneralSetting WMI class in Root\CIMv2\TerminalServices namespace provides a method called SetUserAuthenticationRequired() to enable or disable above check box.

To disable NLA:

$TSObj = Get-WMIObject -Class Win32_TSGeneralSetting -Namespace Root\CIMV2\TerminalServices            
$TSObj.SetUserAuthenticationRequired(0)

RDP-NLA-Disable

To enable NLA:

$TSObj = Get-WMIObject -Class Win32_TSGeneralSetting -Namespace Root\CIMV2\TerminalServices            
$TSObj.SetUserAuthenticationRequired(1)

Above commands enables or disables NLA for RDP on local computer. If you want to perform these actions on remote computer, just use -ComputerName parameter with Get-WMIObject cmdlet.

Like the way we can enable/disable NLA, we can also check what is the current state of it. There is a Property called UserAuthenticationRequried which stores 0 or 1 that indicates it is disabled or enabled respectively.

$TSObj = Get-WMIObject -Class Win32_TSGeneralSetting -Namespace Root\CIMV2\TerminalServices            
$TSObj.UserAuthenticationRequired

Hope this helps.

{ 0 comments }

PowerShell: How to get DNS client Cache

Tip: How to get(or read) DNS client cache using PowerShell.

You know that DNS client caches the results it received from DNS server for the amount of allowed as per the values in DNS Zone. Client refers to this cache first before making a call to DNS server for resolving any record. Sometime this cache goes stale and we need to clear it to get fresh results. If you want to see what is there in local DNS client cache you can run IPCONFIG /displayDNS. This gives the details in plain text.

You can use below PowerShell cmdlet which is part of DNSClient in Windows 8 & Windows server 2012 and above operating systems to read what is there in the cache and the result is in object format which is easy to parse.

Get-DNSClientCache

You can look for cache details of a particular domain by passing it to -Entry parameter.

Get-DnsClientCache -Entry techibee.com

Get-DNSClientCache

Use Get-Help cmdlet to know more about it.

Get-Help Get-DnsClientCache -Detailed

Hope this helps..

{ 0 comments }

This post will discuss about querying DNS Server (Microsoft or Non-Microsoft) using PowerShell for different types of records like A, PTR, MX, NS, and resource records.

Nslookup.exe is a great utility for querying DNS servers. You can connect to server and query records types that you need. Its very useful utility but only problem is it is not flexible to use inside your scripts/automations. If this utility is used inside script, you to parse the text output to extract the details you need. Ideally anything that returns results in object format is very good in programming.

Are you looking for a script to resolve host name to IP and IP to host name using PowerShell, then check this post.

Alternative to nslookup in windows world is querying DNS server using WMI. There are WMI Classes available to query DNS server for various record types. Try below command to get a list of WMI classes that helps you to query and manage DNS running on a Windows Server.

Get-WmiObject -Namespace root\MicrosoftDNS -List

The downside with approach is, it works only for querying windows based DNS servers and this approach absolutely not valid for non Microsoft DNS server like bind. You can read about using these WMI classes using PowerShell at this Hey Scripting Guy post.

This problem is addressed in much better way in Windows 8/Windows Server 2012 with the introduction of Resolve-DNSName cmdlet. Using this cmdlet you can query any kind of DNS server(Microsoft or non-MS) for any record type without requiring any extra privileges and utilities. This cmdlet returns results in object format which is easy to consume within the script.

This cmdlet is part of DNSClient module in Windows 8/Windows Server 2012 or above Operating Systems. You cannot use this module on Windows 7 or any other previous operating systems.

resolve-dnsname-intro

Now let us look at some examples to understand how to query DNS server using this.

We can query A record techibee.com using below command. This queries the DNS servers that are listed in your network connection configuration. You can get DNS Server IP details of a computer using the script provided in this post.

Resolve-DnsName -Name techibee.com -Type A

resolve-dnsname-queryASimilarly you can query Name server rescords(NS) of a Domain by passing NS as value to -Type Parameter. This lists all name servers that are hosting the Domain name you are querying. Below examples shows how to query NS records of Google.com

Resolve-DnsName -Name google.com -Type NS -DnsOnly

resolve-dnsname-queryNS

We can target these queries against any DNS server in your network. For example, we can query Google name servers directly for a record or internal DNS server for records. Below command shows how to query a DNS server directly instead of relying on what is configured in local computer network configuration.

Resolve-DnsName -Name techibee.com -Type A -Server 202.156.1.16

resolve-dnsname-queryA2

In above example, 202.156.1.16 is the IP of Google DNS server. You can try giving your internal DNS server name/IP or any external DNS name. It works same way as NSLookup does.

Similarly you can query MX records of a domain using below command.

Resolve-DnsName -Name techibee.com -Type MX -Server 202.156.1.16

resolve-dnsname-queryMX

You might be wondering what all types of records you can query using this cmdlet. Below is the list of records that this cmdlet supports.

If you have any questions about using this cmdlet, please write it in comments section.

Source : TechNet

Record Name
A_AAAA
A
AAAA
NS
MX
MD
MF
CNAME
SOA
MB
MG
MR
NULL
WKS
PTR
HINFO
MINFO
TXT
RP
AFSDB
X25
ISDN
RT
SRV
DNAME
OPT
DS
RRSIG
NSEC
DNSKEY
DHCID
NSEC3
NSEC3PARAM
ANY
ALL

Hope this helps….

{ 0 comments }

This post helps you to understand how to get Windows 10 upgrade notification on Windows 8 or Windows 7 computers.

As you might already aware, Microsoft announced free upgrade to Windows 10 for customers who are already running windows 8 or windows 7. There are some pre-requisites which your computer should meet in order to get this free upgrade. Let us take a look at them and also understand how to register for the free upgrade if your computer OS meeting the pre-requisites.

You should be running with one of the blow operating systems in order to get free Windows 10 upgrade.

  • Windows 8.1
  • Windows 7 SP1

Have you noticed the above properly? Yes, you should have Windows 8.1(not Windows 8) to get free upgrade. If your computer is running windows 8, you can upgrade it to windows 8.1 without any additional cost. There are many articles in web which can help you for this upgrade. Take a look at http://windows.microsoft.com/en-sg/windows-8/update-from-windows-8-tutorial link which covers most of the information.

Similarly you should have SP1 installed if your Computer is running Windows 7.

Once you meet the above pre-requisites, your computer is ready for registering to free Windows 10 upgrade. If you Windows update is running on your computer and it has internet connectivity, by this time you might have already noticed below type of icon in your system tray.

upgradelogoIn case you are not seeing something similar to this, then you must ensure your system is up to date with Windows Updates. Your computer must have Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update: April 2014 (KB2919355) update installed which is pre-requisite for actual update that installs the icon in System tray. If this is already available, then look for Update enables additional capabilities for Windows Update notifications in Windows 8.1 and Windows 7 SP1 (KB3035583)which installs this system tray icon which helps in registering for free Windows 10.

Once you start noticing above icon in System tray, registering for the Windows 10 is straight forward. Just click on the icon in System tray and it opens up below window.

Register-windows10

Click on Reserve your free upgrade to complete the registration.

When I clicked on it, it didn’t give me any confirmation about the registration. So, I right clicked on upgrade icon in system tray and went to Check Your Upgrade Status and it gave me below window which confirmed my upgrade registration.

Confirm-Windows10-registration

Optionally you can enter your email address here and click on Send confirmation you have a email confirmation sent about Free Windows 10 Upgrade.

As you can read from the upgrade registration window, the upgrade will be made available from July 29th onwards through Windows update. Make sure you have sufficient bandwidth to download the update. It is expected to around 3GB.

I will make a followup post after July 29th once my computer is upgraded. If you have any questions about how this upgrade, please feel free to write in comments section. I will get back when I get chance.

 

{ 0 comments }

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.

sampleoutput

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 {            
[CmdletBinding()]            
Param(            
    [parameter(mandatory=$true)]            
    [string]$File1,            
    [parameter(mandatory=$true)]            
    [string]$File2            
)            
    $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.

mergecsv

Output shows the name of the output file.

{ 1 comment }

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.

pselevation1

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            
$h.UI.RawUI

pselevation2

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 {            
[CmdletBinding()]            
param(            
)            
 [Security.Principal.WindowsPrincipal] $Identity = [Security.Principal.WindowsIdentity]::GetCurrent()            
 $Identity.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)            
}            

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.

[CmdletBinding()]            
Param(            
)            
            
function Test-IsElevated {            
[CmdletBinding()]            
param(            
)            
 [Security.Principal.WindowsPrincipal] $Identity = [Security.Principal.WindowsIdentity]::GetCurrent()            
 $Identity.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)            
}            
            
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.

{ 0 comments }

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.

Networkteaming

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.

new-team

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.

nic-teamingstatus

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.

{ 0 comments }

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

Get-networkadapter

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

disable-netadapter

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.

{ 0 comments }

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.

Hyper-V-Failed-Add-Disk

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.

Remove-sparseflag

Hope this helps.

 

{ 0 comments }