Thursday, 25 June 2015

Powershell: Find AD users with Change Password at Next Logon

We can get the list of AD users who should change their password at the next logon using Active Directory powershell cmdlet Get-ADUser. In this article, I am going to write Powershell script to list of AD users who have the setting "Change Password At the Next Logon" enabled and export AD users to CSV file.

use the following command to import Active Directory cmdlets.
Import-Module ActiveDirectory
List AD users with change password at the next logon:
Get-ADUser -LDAPFilter "(pwdLastSet=0)" | Select SamAccountName,distinguishedName

Export AD Users with with Change Password at Next Logon to CSV using Powershell

We can export powershell output into CSV file using Export-CSV cmdlet. The following command export selected properties of all the AD users with change password at next the logon to CSV file.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter "(pwdLastSet=0)" | Select SamAccountName,distinguishedName |
Export-CSV "C:\\ChangePasswordAtNextLogon.csv" -NoTypeInformation -Encoding UTF8

Powershell: Get AD users with Password Never Expires

We can get the list of AD users whose password never expire using Active Directory Powershell cmdlet Search-ADAccount with the parameter PasswordNeverExpires. In this article, I am going to write Powershell script to get the list of AD users whose password never expire and export AD users with password never expires to CSV file.

Run the following command to import Active Directory cmdlets.
Import-Module ActiveDirectory
Powershell command to list password never expire ad users:
Search-ADAccount –PasswordNeverExpires | Select Name, DistinguishedName

Find Password Never Expire AD Users from specific OU:

We can set target OU scope by using the parameter SearchBase in Search-ADAccount cmdlet. The following command select and list all the AD users whose password never expires from the Organization Unit 'TestOU'.
Import-Module ActiveDirectory
Search-ADAccount  -SearchBase "OU=TestOU,DC=TestDomain,DC=Com" –PasswordNeverExpires |
Select -Property Name,DistinguishedName

Export Password Never Expire AD Users to CSV using Powershell

We can export powershell output into CSV file using Export-CSV cmdlet. The following command export selected properties of all the password never expire AD users to CSV file.
Import-Module ActiveDirectory
Search-ADAccount –PasswordNeverExpires | Select -Property Name,DistinguishedName |
Export-CSV "C:\\PasswordNeverExpireADUsers.csv" -NoTypeInformation -Encoding UTF8

CSV output of Password Never Expire AD users report:

Powershell script to find AD users whose password never expires

Wednesday, 24 June 2015

Powershell : Resolve Hostname from IP address and vice versa

In this article, I am going to write powershell script to find machinename from IP address and get IP address from computer name. We can resolve hostname from IP address and vice versa by using .NET class System.Net.Dns.

Find machine name from IP address:

$ipAddress= "192.168.1.54"
[System.Net.Dns]::GetHostByAddress($ipAddress).Hostname

Resolve Hostname to IP Address:

$machineName= "DC1"
$hostEntry= [System.Net.Dns]::GetHostByName($machineName)
$hostEntry.AddressList[0].IPAddressToString

Resolve Hostname for set of IP addresses from text file:

Use the below powershell script to find machine name for multiple IP addresses. First create the text file ip-addresses.txt which includes one IP address in each line. You will get the machinename list in the txt file machinenames.txt.
Get-Content C:\ip-addresses.txt | ForEach-Object{
$hostname = ([System.Net.Dns]::GetHostByAddress($_)).Hostname
if($? -eq $True) {
  $_ +": "+ $hostname >> "C:\machinenames.txt"
}
else {
   $_ +": Cannot resolve hostname" >> "C:\machinenames.txt"
}}

Find Computer name for set of IP addresses from CSV:

Use the below powershell script to get hostname for multiple IP addresses from csv file. First create the csv file ip-addresses.csv which includes the column IPAddress in the csv file. You will get the hostname and IP address list in the csv file machinenames.csv.
Import-Csv C:\ip-Addresses.csv | ForEach-Object{
$hostname = ([System.Net.Dns]::GetHostByAddress($_.IPAddress)).Hostname
if($? -eq $False){
$hostname="Cannot resolve hostname"
}
New-Object -TypeName PSObject -Property @{
      IPAddress = $_.IPAddress
      HostName = $hostname
}} | Export-Csv C:\machinenames.csv -NoTypeInformation -Encoding UTF8

Friday, 19 June 2015

Export AD Group Members to CSV using Powershell

We can export AD groups and its members using the Active Directory Powershell cmdlets Get-ADGroup and Get-ADGroupMember.

Use the following command to enable Active Directory cmdlets.
Import-Module ActiveDirectory

Get specified AD Group members:

Use the below Powershell command to get the list of members of specified AD Group.
Get-ADGroupMember -Identity "Domain Admins" | Select Name, SamAccountName

Export AD Groups and Members to CSV:

The following PowerShell script gets a list of all AD groups and its members. The Get-ADGroup cmdlet gets all the AD Groups and the list of group values passed into ForEach-Object to get members of every AD Group. Finally it exports both groups and members as semi-colon(;) separated values to CSV file using Export-CSV cmdlet.
$Groups = Get-ADGroup -Filter "*"
$Groups | ForEach-Object {
$group = $_.Name
$members = ''
Get-ADGroupMember $group | ForEach-Object {
        If($members) {
              $members=$members + ";" + $_.Name
           } Else {
              $members=$_.Name
           }
  }
New-Object -TypeName PSObject -Property @{
      GroupName = $group
      Members = $members
     }
} | Export-CSV "C:\\AD-Group-Members.csv" -NoTypeInformation -Encoding UTF8

Sample CSV output of Export AD Groups and Members:

Export AD Group Members to CSV using Powershell script

Get AD Group Members using Powershell

We can get the list of AD Group members using Active Directory Powershell cmdlet Get-ADGroupMember. In this article, I am going to write Powershell script to get list of AD Group members, export group members to CSV file and export AD groups and members to CSV file.

Run the following command to import Active Directory cmdlets.
Import-Module ActiveDirectory
Use the following Powershell command to get the list of specified AD Group members.
Get-ADGroupMember -Identity "Domain Admins" | Select Name, SamAccountName

Export AD Group Members to CSV:

The following Powershell script gets a list of members of specified AD group and exports member details to CSV file. Replace the group name "Domain Admins" with your own group name in the below script.
$GroupName = "Domain Admins"
Get-ADGroupMember -Identity $GroupName | Select Name, SamAccountName |
Export-CSV "C:\\ADGroupMembers.csv" -NoTypeInformation -Encoding UTF8

Export AD Groups and Members to CSV:

The following PowerShell script gets a list of all Active Directory groups and its members. The Get-ADGroup cmdlet gets all the AD Groups and passed into ForEach-Object to get members of every AD Group. Finally it exports both group and member details to CSV file.
$Groups = Get-ADGroup -Filter "*"
$Groups | ForEach-Object {
$group = $_.Name
$members = ''
Get-ADGroupMember $group | ForEach-Object {
        If($members) {
              $members=$members + ";" + $_.Name
           } Else {
              $members=$_.Name
           }
  }
New-Object -TypeName PSObject -Property @{
      GroupName = $group
      Members = $members
     }
} | Export-CSV "C:\\AD-Group-Members.csv" -NoTypeInformation -Encoding UTF8

CSV output AD Groups and Members:

Export AD Group Members to CSV using Powershell script


Thursday, 18 June 2015

Change Service Account Information using VBScript

We can easily manage Windows Service account through vbscript by using the WMI class Win32_Service. Use the below vbscript code to change windows service account

1. Copy the below vbscript code and paste it in notepad or a VBScript editor.
2. Change the value strService into your own windows service name which you want to change service account.
3. Replace your new user account and password in the variables strUser and strPwd.
3. If you want to modify a service account in Remote machine, set the Remote computer name in the variable strComputer instead of "." (local machine).
4. Save the file with a .vbs extension, for example: ChangeServiceAccount.vbs
5. Double-click the vbscript file (or Run this file from command window) to change the given windows service logon user account .
Option Explicit
Dim objWMIService, objService,errOut
Dim strService,strComputer,strUser,strPwd
strService="RemoteRegistry"
strUser= ".\Morgan"
strPwd = "Password"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
For Each objService In objWMIService.ExecQuery("Select * from Win32_Service Where Name = '"&strService&"'")
    errOut = objService.Change( , , , , , , strUser, strPwd)
  If(errOut=0) Then
     WScript.Echo strService & ": Service account changed successfully"
  Else
     WScript.Echo strService & ": Account change failed. Error code: "& errOut
  End If
Next
WScript.Quit
Use the following vbscript code if you want to change only password of the service account.
Option Explicit
Dim objWMIService, objService,errOut
Dim strService,strComputer,strPwd
strService="RemoteRegistry"
strPwd = "NewPassword"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
For Each objService In objWMIService.ExecQuery("Select * from Win32_Service Where Name = '"&strService&"'")
    errOut = objService.Change( , , , , , , , strPwd)
  If(errOut=0) Then
     WScript.Echo strService & ": Service account password changed successfully"
  Else
     WScript.Echo strService & ": Password change failed. Error code: "& errOut
  End If
Next
WScript.Quit

Change Service Account Password using VBScript

We can easily manage Windows Service through vbscript by using the WMI class Win32_Service. Use the below vbscript code to change service account password.

1. Copy the below vbscript code and paste it in notepad or a VBScript editor.
2. Change the value strService into your own windows service name which you want to reset password.
3. If you want to modify password of a service account in Remote machine, set the Remote computer name in the variable strComputer instead of "." (local machine).
4. Save the file with a .vbs extension, for example: ChangeServicePwd.vbs
5. Double-click the vbscript file (or Run this file from command window) to change the given windows service account password.
Option Explicit
Dim objWMIService, objService,errOut
Dim strService,strComputer
strService="RemoteRegistry"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
For Each objService In objWMIService.ExecQuery("Select * from Win32_Service Where Name = '"&strService&"'")
    errOut = objService.Change( , , , , , , , "password")
  If(errOut=0) Then
     WScript.Echo strService & ": Service account password changed successfully"
  Else
     WScript.Echo strService & ": Password change failed. Error code: "& errOut
  End If
Next
WScript.Quit

Wednesday, 17 June 2015

Powershell Error: Pipelines Cannot be Executed Concurrently

Problem:

Today I have received the Powershell error "Pipelines Cannot be Executed Concurrently" while running commands in Exchange Management Shell.
Pipeline not executed because a pipeline is already executing. Pipelines cannot be executed concurrently.
    + CategoryInfo          : OperationStopped: (Microsoft.Power...tHelperRunspace:ExecutionCmdletHelperRunspace) [],
   PSInvalidOperationException
    + FullyQualifiedErrorId : RemotePipelineExecutionFailed

Pipeline not executed because a pipeline is already executing. Pipelines cannot be executed concurrently.
    + CategoryInfo          : OperationStopped: (Microsoft.Power...tHelperRunspace:ExecutionCmdletHelperRunspace) [],
   PSInvalidOperationException
    + FullyQualifiedErrorId : RemotePipelineExecutionFailed
You can simply reproduce this error by running the following Exchange Powershell commands by two times.
Get-DistributionGroup | ForEach-Object {
$group = $_.Name
Get-DistributionGroupMember $_.Name | ForEach-Object {
      New-Object -TypeName PSObject -Property @{
       Group = $group
       Members = $_.Name
}}}

Fix/Solution: Pipelines Cannot be Executed Concurrently

In above Powershell, you can see that we are piping the output of Get-DistributionGroup to Foreach-Object and attempting to run the Get-DistributionGroupMember cmdlet.

The Get-DistributionGroupMember cmdlet is designed to accept pipeline input from Get-DistributionGroup, so there is no need to use Foreach-Object. You can just pipe Get-DistributionGroup to Get-DistributionGroupMember.
Get-DistributionGroup | Get-DistributionGroupMember
But the above command returns only members of all the Groups and doesn't return group name. Our need is to get both group names and members, so we supposed to use ForEach-Object. To fix this issue, we have to do it as two step process. First, we need to save the results of the Get-DistributionGroup cmdlet to a variable. Then we can pipe the variable to ForEach-Object.
$Groups = Get-DistributionGroup
$Groups | ForEach-Object {
$group = $_.Name
Get-DistributionGroupMember $_.Name | ForEach-Object {
      New-Object -TypeName PSObject -Property @{
       Group = $group
       Members = $_.Name
}}}

Export Distribution List Members to CSV using Powershell

We can get Distribution list members by using the Exchange cmdlet Get-DistributionGroupMember in Powershell and export Distribution list members to CSV file using Powershell cmdlet Export-CSV.

Get Distribution Group members:

Use the following Powershell command to list Distribution list members.
Get-DistributionGroupMember -Identity <Group-Name>

Export Members of a single Distribution Group to CSV:

The following Powershell script gets members of a given distribution group and exports output to CSV file. Replace the distribution group name "TestDG" with your own group name in the below script.
$DGName = "TestDG"
Get-DistributionGroupMember -Identity $DGName | Select Name, PrimarySMTPAddress |
Export-CSV "C:\\Distribution-List-Members.csv" -NoTypeInformation -Encoding UTF8

Export All Distribution Groups and Members to CSV:

We can list all the distribution groups using Exchange cmdlet Get-DistributionGroup and get its members by passing group name into Get-DistributionGroupMember cmdlet. The following Powershell script gets all the distribution groups and its members and exports group names and members to CSV file.
$Groups = Get-DistributionGroup
$Groups | ForEach-Object {
$group = $_.Name
$members = ''
Get-DistributionGroupMember $group | ForEach-Object {
        If($members) {
              $members=$members + ";" + $_.Name
           } Else {
              $members=$_.Name
           }
  }
New-Object -TypeName PSObject -Property @{
      GroupName = $group
      Members = $members
     }
} | Export-CSV "C:\\Distribution-Group-Members.csv" -NoTypeInformation -Encoding UTF8

Get Exchange Distribution List Members using Powershell

We can get and list Distribution group members using the Exchange Powershell cmdlet Get-DistributionGroupMember. In this article, I am going to write Powershell script to get distribution list members, export distribution list members to CSV file and export distribution groups and members to CSV file.

Get Distribution List members:

Run the following command to enable Exchange cmdlets if you are working with normal PowerShell console instead of Exchange Management Shell.
Add-PSSnapin *Exchange*
Use the following Powershell command to list Distribution group members.
Get-DistributionGroupMember -Identity <Group-Name>
By default this command returns only two properties (Name and RecipientType) of the Group members. You can select required values by using select command.
Get-DistributionGroupMember -Identity <Group-Name> | Select Name, RecipientType, PrimarySMTPAddress

Export Distribution List Members to CSV:

The following Powershell script gets a list of distribution group members and exports output to CSV file. Replace the distribution group name "TestDG" with your own group name in the below script.
$DGName = "TestDG"
Get-DistributionGroupMember -Identity $DGName | Select Name, PrimarySMTPAddress |
Export-CSV "C:\\Distribution-List-Members.csv" -NoTypeInformation -Encoding UTF8

Export Distribution Groups and Members to CSV:

The following PowerShell script gets a list of Distribution groups and its members and exports output to CSV file.
$Groups = Get-DistributionGroup
$Groups | ForEach-Object {
$group = $_.Name
$members = ''
Get-DistributionGroupMember $group | ForEach-Object {
        If($members) {
              $members=$members + ";" + $_.Name
           } Else {
              $members=$_.Name
           }
  }
New-Object -TypeName PSObject -Property @{
      GroupName = $group
      Members = $members
     }
} | Export-CSV "C:\\Distribution-Group-Members.csv" -NoTypeInformation -Encoding UTF8

Tuesday, 16 June 2015

How to apply desktop wallpaper using Group Policy

Setting the desktop wallpaper background to all users through GPO is a most common task for every Administrator to maintain common environment in all the AD user's computer. We can set desktop wallpaper background via Group Policy using following two methods.

Apply Desktop Wallpaper using GPO's Administrative Template Setting

This method is the easiest and most commonly used way to configure the desktop wallpaper using GPO.

Note: Users can't change their backgrounds once the background wallpaper is applied using this method.

Follow the steps to set desktop wallpaper using Administrative Template:

1. Open the Group Policy Management console by running the command gpmc.msc.

2. Expand the tree and right-click on the OU you want this policy to be applied to. Now, I am going to apply for users who are under the OU TestOU. so right-click on the OU TestOU, and click Create a GPO in this domain, and Link it here...
How to apply desktop wallpaper using Group Policy

3. Give the new policy name and click OK. I have given new policy name "Desktop Wallpaper Policy".

4. Now right-click on the newly created GPO Desktop Wallpaper Policy and click Edit...

How to apply desktop wallpaper via Group Policy

5. In the Group Policy Management Editor window, expand User Configuration and go to the node Desktop (User Configuration > Administrative Templates > Desktop > Desktop). In right hand side, select the setting Desktop Wallpaper and double-click it. 

How to apply desktop wallpaper via Group Policy

6. Enable the Desktop Wallpaper setting by selecting the option Enabled and set the explicit local path or a UNC to the image you want display as the desktop wallpaper. Finally click the Apply button to complete.

Deploy desktop wallpaper background via Group Policy

7.Now update the GPO by running the command gpupdate /force in Command Window.

8. That's all. Now we have successfully created GPO to apply desktop background wallpaper for the users who are under OU TestOU. Behind the scene, this policy update the registry value HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System\Wallpaper.

Deploy desktop wallpaper background using GPO

9. Now, you can see that desktop wallpaper by logging into any of the user's desktop who are under TestOU.

Note: This setting is not applied to domain users who log on to client computers that are running Windows 7 or Windows Server 2008 R2. You need to install the hotfix http://support.microsoft.com/kb/977944 to fix this issue.


Apply Desktop Wallpaper using GPO Preference Registry Setting

As I said in Method #1, the desktop background wallpaper is controlled by the registry setting KEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System\Wallpaper , we can also use Group Policy Preferences Registry setting to configure desktop wallpaper background through Group Policy.

Note: We can allow user to change their background using this method and also we can restrict users to change if needed.

Follow the below steps to deploy desktop wallpaper via Group Policy Preference Registry Extension:

- Repeat the steps 1-4 in Method #1 (Revert the old changes if you configured using Method #1).
5. In the Group Policy Management Editor window, expand User Configuration and go to the node Registry (User Configuration > Preferences > Windows Settings > Registry ).
6. Right-click on the node Registry and select New > Registry Item.

Configure desktop wallpaper background using GPO

7. Now depends on the need you can set registry key that you configure for this setting. You can either have this as a Restricted setting or Unrestricted setting that allows users to change their own background wallpaper. Click Apply button to complete the process.
Restricted: HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\Wallpaper
Unrestricted: HKCU\Control Panel\Desktop\Wallpaper

Configure desktop wallpaper background through GPO

8. Now update the GPO by running the command gpupdate /force.

9. That's all. Now we have successfully created GPO to apply desktop background wallpaper for the users who are under OU TestOU. You can see that desktop wallpaper by logging into any of the user's desktop who are under TestOU.

Enable Exchange Cmdlets in Powershell

We can run Exchange Management Powershell cmdlets using Exchange Management Shell to get exchange related details. However, If you are working with normal PowerShell console instead of Exchange Management Shell, you need to import Exchange snapins to enable and use Exchange Management cmdlets.

If you run the Exchange commands in Powershell (Ex: Get-Mailbox) without loading the Exchange Management cmdlets, you will get the following error:
The term 'Get-Mailbox' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
 spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:12
+ Get-Mailbox <<<<
    + CategoryInfo          : ObjectNotFound: (Get-Mailbox:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Run the following command to load Exchange Powershell cmdlets that supports Admin tasks.
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
-or- Run the following command if you want to enable all the Exchange related cmdlets.
Add-PSSnapin "Exchange*
Note: The Exchange Management Powershell cmdlets will be available only if the Exchange System Management Tools installed in your machine. Otherwise, you need to use Exchange Cmdlets through Remote Exchange Powershell. Read this article to Connect Remote Exchange PowerShell.

List Domain Controllers and IP Address using Powershell

We can list all the Active Directory Domain Controllers in current domain or forest using .NET classes System.Directoryservices.Activedirectory.Domain and System.Directoryservices.Activedirectory.Forest. We can resolve IP Address for every Domain Controller by using .NET class System.Net.Dns.

Note: This PowerShell script doesn't require to import Active Directory Module since it is using the methods from .NET Framework.

List all Domain Controllers and IP Address in Current Domain:

This following script returns all the Domain Controllers from current Domain and resolves IP address by DNS lookup. The results are output to the PowerShell console screen.
$domain = [System.Directoryservices.Activedirectory.Domain]::GetCurrentDomain()
$domain | ForEach-Object {$_.DomainControllers} | 
ForEach-Object {
  $hostEntry= [System.Net.Dns]::GetHostByName($_.Name)
New-Object -TypeName PSObject -Property @{
      Name = $_.Name
      IPAddress = $hostEntry.AddressList[0].IPAddressToString
    }
} | Select Name, IPAddress

Export List of Domain Controllers and IP Address to CSV:

We can export PowerShell output into CSV file using Export-CSV cmdlet. The following PowerShell script find all the Domain Controllers from current Domain and resolve IP address by DNS lookup and exports output to CSV file.
$domain = [System.Directoryservices.Activedirectory.Domain]::GetCurrentDomain()
$domain | ForEach-Object {$_.DomainControllers} | 
ForEach-Object {
  $hostEntry= [System.Net.Dns]::GetHostByName($_.Name)
  New-Object -TypeName PSObject -Property @{
      Name = $_.Name
      IPAddress = $hostEntry.AddressList[0].IPAddressToString
     }
} | Export-CSV "C:\\DomainControllers.csv" -NoTypeInformation -Encoding UTF8

Monday, 15 June 2015

Find AD Domain Controllers using Powershell

We can get the list of Active Directory Domain Controllers in current domain or forest using .NET classes System.Directoryservices.Activedirectory.Domain and System.Directoryservices.Activedirectory.Forest.

Note: This PowerShell script doesn't require to import Active Directory Module since it is using the methods from .NET Framework.

Find Domain Controllers from current Domain:

This script return all the Domain Controllers from current Domain
$domain = [System.Directoryservices.ActiveDirectory.Domain]::GetCurrentDomain()
$domain | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name} 

List Domain Controllers from current Forest:

This script return all the Domain Controllers from current Forest
$Forest = [System.Directoryservices.ActiveDirectory.Forest]::GetCurrentForest()  
$Forest.Domains | ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name} 

Find Domain Controllers from specific Domain:

Using below PowerShell script you can search specific domain and get all the available Domain Controllers.
$domainName ="TestDomain.Com"
$Forest = [System.Directoryservices.ActiveDirectory.Forest]::GetCurrentForest()
$Forest.Domains | Where-Object {$_.Name -eq $domainName} |  
ForEach-Object {$_.DomainControllers} | ForEach-Object {$_.Name}

Saturday, 13 June 2015

PowerShell - Get-Mailbox ResultSize

The Exchange PowerShell cmdlet Get-Mailbox is one of the most useful and powerful command to retrieve all the properties for all the Mailboxes from your Exchange Server 2010/2013.

If you have more than 1000 mailboxes and execute the command Get-Mailbox, you will get first 1000 Mailboxes and followed by the following warning message:
WARNING: By default only the first 1000 items are returned. To change the number of items returned, specify the parameter "-ResultSize". To return all items specify "-ResultSize Unlimited" (Note: Returning all items may take a very long time and consume a large amount of memory depending on the actual number of items). It is not recommended to store the results in a variable; instead pipe the results to another task or script to perform batch changes
As per the warning message, this command will only return the first 1000 Mailboxes. You can change this by adding -ResultSize Unlimited to get all the Mailbox details
Get-Mailbox -ResultSize Unlimited
If you want to get only first 100 Mailboxes, add the value 100 in ResultSize.
Get-Mailbox -ResultSize 100
You can also get only first 100 mailboxes with other method using Select-Object.
Get-Mailbox | Select-Object -First 100
In this way, you can also get second 100 mailboxes by adding -Skip parameter.
Get-Mailbox | Select-Object -Skip 100 -First 100 
The above command returns second 100 Mailbox details in between 101 to 200.

Control PowerShell ResultSize (First, Last and Between)

PowerShell script may returns 1000 of records for a single command, viewing large amount of records in a single page will be difficult, so we need to restrict size of PowerShell output to view results in a better way. Some of PowerShell cmdlets may internally give support to control ResultSize of Powershell output.

Let's consider the Exchange PowerShell cmdlet Get-MailBox. Using this cmdlet, we can control PowerShell output by using the parameter -ResultSize.
Get-Mailbox -ResultSize 250
We can get unlimited results by giving ResultSize input as "Unlimited".
Get-Mailbox -ResultSize Unlimited
If you are working with a PowerShell cmdlet which doesn't support the parameter -ResultSize to control PowerShell output, in this case, you can control the result size by using Select-Object method which is generic method for all the PowerShell cmdlets.

Select First 'N' Results:

The following PowerShell command lists first 10 results.
Get-Process | Select-Object -First 10

Select Last 'N' Results:

The following PowerShell command returns last 10 results.
Get-Process | Select-Object -Last 10

Select PowerShell Output Between Specific Range:

If you are working to display PowerShell result (page by page) using page size, you need to select results between specific range size. You can select PowerShell output between specific range size by using the parameters -Skip and -First in Select-Object method.
$a = Get-process 
$a | Select-Object -Skip 10 -First 10 
The above command returns 10 processes between the index 10 and 19. The -Skip parameter skips first 10 records and the -First parameter select next 10 records, finally it returns 10 results between the index 10 to 19.

Note: -Skip (do not select) the specified number of items. By default, the Skip parameter counts from the beginning of the array or list of objects, but if the command uses the Last parameter, it counts from the end of the list or array. Unlike the Index parameter, which starts counting from 0, the Skip parameter begins at 1.

PowerShell - List only Files or Folders by Recursively

We can retrieve only list of Files or Folders by Recursively using the Powershell cmdlet Get-ChildItem.

List Only Files:

Use the following script to get only list of Files from a Folder and its Sub Folder by using Recursive parameter.
Get-ChildItem -Recurse "C:\TestDir" | Where { ! $_.PSIsContainer } | Select Name,FullName,Length

List Only Folders:

Use the following PowerShell script to get only list of Folders from a Folder and its Sub Folder by using Recursive parameter.
Get-ChildItem -Recurse "C:\TestDir" | Where { $_.PSIsContainer } | Select Name,FullName

List Files and Exclude Some Files:

The following PowerShell script list all the files under the folder "C:\TestDir" but exclude the csv files.
Get-ChildItem -Recurse "C:\TestDir" -Exclude *.csv | Where {! $_.PSIsContainer } | Select Name,FullName

List Files and Exclude Files from a Folder:

The following powershell script list all the files under the folder "C:\TestDir" but exclude files from the Folder Test2.
Get-ChildItem -Recurse "C:\TestDir" |  Where-Object { $_.FullName -notmatch '\\Test2($|\\)' } | Where {! $_.PSIsContainer } | Select Name,FullName
The expression '\\Test2($|\\)' allow us to exclude the directory Test2 and its files.

Friday, 12 June 2015

Enable Remote Exchange PowerShell with Basic Authentication

In Exchange server, We can run Exchange Management Powershell cmdlets to get mailbox related details. In this article, I am going to explain how to connect Remote Exchange Powershell using Basic Authentication.

Before proceed, in your local machine, Windows Powershell needs to be enabled to run scripts. Run the following command in an elevated Windows Powershell window (Run as administrator) to configure Powershell to allow scripts to run.
Set-ExecutionPolicy RemoteSigned
The PowerShell Virtual directory has no authentication settings configured by default. Run the following command with Exchange Management Shell in Exchange Server to get list of enabled authentications for Exchange Powershell
Get-PowerShellVirtualDirectory |fl *auth*
You can see no authentications is enabled for PowerShell virtual directory by default.
Connect Remote Exchange PowerShell with Basic Authentication

Run the following command with Exchange Management Shell in Exchange Server to enable Basic Authentication and this will allow us to use an SSL connection (HTTPS) to connect Exchange Powershell from computer.
Get-PowershellVirtualDirectory | Set-PowerShellVirtualDirectory -BasicAuthentication $true
TCP port 443 traffic needs to be open between your local computer and the Exchange server to use Basic Authentication.

- Copy the below powershell script and paste in Notepad file.
- Replace the parameter <FQDN of Exchange Server> with your own Exchange server name.
- Run the script in powershell to get Mailbox features from Remote Exchange server using Basic Authentication.
$cred = Get-Credential
$pso = new-pssessionoption -skipcacheck -SkipCNCheck -SkipRevocationCheck
$Session= New-PSSession -Configuration Microsoft.Exchange -ConnectionUri https://<FQDN of Exchange Server>/PowerShell/ -Credential $cred -Authentication Basic -Sessionoption $pso
Import-PSSession $Session 
Get-CASMailBox

Thursday, 11 June 2015

Enable Remote Exchange Powershell

We can run Exchange Management Powershell cmdlets in Exchange server to get mailbox related details. However, if you want to read mailbox related details from remote computer, you need to setup some configuration to connect Exchange Management Powershell.

Follow the below steps to enable Remote Exchange Management Shell:

In your local machine, Windows PowerShell needs to be configured to run scripts. To enable Windows PowerShell to run signed scripts, run the following command in an elevated Windows PowerShell window (Run as administrator).
Set-ExecutionPolicy RemoteSigned
2. The account you use to connect to the Exchange server must be enabled for Remote Shell. Run the following command in your Exchange server to enable Remote Shell.
Set-User –Identity username -RemotePowerShellEnabled $True
3. TCP port 80 traffic needs to be open between your local computer and the Exchange server. It's probably open, but it’s something to consider if your organization has a restrictive Internet access policy.

Connect Remote Exchange PowerShell using Kerberos Authentication:

- Copy the below powershell script and paste in Notepad file.
- Replace the parameter <FQDN of Exchange Server> with your own Exchange server name.
- Run the script in powershell to get mailbox features from remote Exchange server using Kerberos Authentication.
$cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<FQDN of Exchange Server>/PowerShell/ -Credential $cred -Authentication Kerberos
Import-PSSession $Session 
Get-CASMailBox

Connect Remote Exchange PowerShell using Basic Authentication:

You can use Kerberos Authentication to connect Exchange 2010/2013 Management Shell if both the computers (local computer and exchange server) are on a same domain or in trusted domain network, but you need to use Basic Authentication if both the computers are not in the same domain or not a trusted domain network.

Run the following command with Exchange Management Shell window in Exchange server to enable Basic Authentication.
Get-PowershellVirtualdirectory | Set-PowerShellVirtualDirectory -BasicAuthentication $true
TCP port 443 traffic needs to be open between your local computer and the Exchange server to use Basic Authentication.

- Copy the below powershell script and paste in Notepad file.
- Replace the parameter <FQDN of Exchange Server> with your own Exchange server name.
- Run the script in powershell to get mailbox features from remote Exchange server using Basic Authentication.
$cred = Get-Credential
$pso = new-pssessionoption -skipcacheck -SkipCNCheck -SkipRevocationCheck
$Session= New-PSSession -Configuration Microsoft.Exchange -ConnectionUri https://<FQDN of Exchange Server>/PowerShell/ -Credential $cred -Authentication Basic -Sessionoption $pso
Import-PSSession $Session 
Get-CASMailBox

Wednesday, 10 June 2015

Remote Exchange Powershell - Value cannot be null. Parameter name: serverSettings

Problem:

I have tried to get mailbox user details in Exchange 2010 from remote computer through powershell script. To run Exchange management powershell cmdlets in remote machine, I have created new remote powershell session using Enter-PSSession and added PSSnapin Microsoft.Exchange.Management.PowerShell.E2010. Things are working fine until loading exchange management pssnapin, but I am getting the error "Value cannot be null. Parameter name: serverSettings" when executing the Exchange management cmdlet Get-Mailbox.

Powershell script:

$cred = Get-Credential
Enter-PSSession -ComputerName ExchSVR -Credential $cred
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
Get-Mailbox Morgan

Error:

PS C:\> $cred = Get-Credential
PS C:\> Enter-PSSession -ComputerName ExchSVR -Credential $cred
[ExchSVR]: PS C:\Users\Morgan\Documents> Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
[ExchSVR]: PS C:\Users\Morgan\Documents> Get-Mailbox Morgan
Value cannot be null.
Parameter name: serverSettings
    + CategoryInfo          :
    + FullyQualifiedErrorId : System.ArgumentNullException,Microsoft.Exchange.Management.RecipientTasks.GetMailbox

Solution:

I have concluded into following solution after I have analyzed some time. Use the following script to connect Exchange Management PowerShell when you are running Exchange management powershell commands from remote computer (i.e From other domain machine).
$cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<FQDN of Exchange Server>/PowerShell/ -Credential $cred -Authentication Kerberos
Import-PSSession $Session 
Get-Mailbox Morgan

Tuesday, 9 June 2015

Create a Folder If Not Exists in PowerShell

We can check if a folder exist or not by using the PowerShell cmdlet Test-Path and create a new folder using New-Item cmdlet.
The below powershell script will check whether the folder "Test" is already exists or not under the path C:\Share and it creates new folder if it not exists already.
$dir = "C:\Share\Test"
if(!(Test-Path -Path $dir )){
    New-Item -ItemType directory -Path $dir
    Write-Host "New folder created"
}
else
{
  Write-Host "Folder already exists"
}

Export Mailbox Size to CSV using Powershell Script

We can find the mailbox size of all users by using the exchange powershell cmdlet Get-MailboxStatistics. The Get-MailboxStatistics cmdlet is used to obtain information about a mailbox, such as the total size of the mailbox, the number of messages it contains, and the mailbox logon activity.

Before proceed, if you are working with normal PowerShell console instead of Exchange Management Shell, you need to run the following command to import exchange management powershell cmdlets.
Add-PSSnapin *Exchange*

Summary:

Get Mailbox Size for Single User:

The following command gets the mailbox size and total count of messages for the user 'Morgan'.
Get-MailboxStatistics -Identity 'Morgan' | Select DisplayName,ItemCount,TotalItemSize

Get Mailbox Size of all the users and sorted by size:

The following powershell script get a list of all the user's mailbox size and sorted by size in Descending order, so that you can easily find the users who are using high storage space in their mailbox.
Get-MailboxStatistics -Server 'ExchSVR1' | Where {$_.ObjectClass -eq “Mailbox”} | 
Sort-Object TotalItemSize -Descending |
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression={$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, 
LastLogonTime

Export Mailbox Size Report to CSV:

We can export powershell output into CSV file using Export-CSV cmdlet. The following powershell script export all the user's mailbox size, total messages and lastLogon time values into CSV file.
Get-MailboxStatistics -Server 'ExchSVR1' | Where {$_.ObjectClass -eq “Mailbox”} | 
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression={$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, LastLogonTime | 
Export-CSV "C:\\MailBoxSize-Report.csv" -NoTypeInformation -Encoding UTF8

CSV output of mailbox size report:

Exchange Powershell - Get Mailbox Size for All Users

Export mailbox size report with filter:

we can use the exchange powershell cmdlet Get-Mailbox to get specific set of mailbox enabled Active Directory users and pass user details to Get-MailboxStatistics cmdlet. You can apply filters in Get-Mailbox cmdlet to select users.
Get-Mailbox | Where {$_.DistinguishedName -like "*OU=TestOU,DC=TestDomain,DC=local*"} |
Get-MailboxStatistics | Where {$_.ObjectClass -eq “Mailbox”} | 
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression={$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, LastLogonTime| 
Export-CSV "C:\\MailBoxSize-Report.csv" -NoTypeInformation -Encoding UTF8

Monday, 8 June 2015

Create a File If Not Exists via PowerShell

We can check if a file exist or not by using the PowerShell cmdlet Test-Path and create new file using New-Item cmdlet.
The below powershell script will check whether the file sample.txt is already exists or not under the path C:\Share. It creates new file if it not exists already and add new text content by using Add-Content cmdlet if file already exists.
if (!(Test-Path "C:\Share\sample.txt"))
{
   New-Item -path C:\Share -name sample.txt -type "file" -value "my new text"
   Write-Host "Created new file and text content added"
}
else
{
  Add-Content -path C:\Share\sample.txt -value "new text content"
  Write-Host "File already exists and new text content added"
}

Check If Folder Exists or Not in PowerShell

We can check and test if a folder exist or not by using the PowerShell cmdlet Test-Path.
The below powershell script will check whether the folder "C:\Share" exists or not.
$dir = "C:\Share"
if (Test-Path $dir) 
{
  Write-Host "Folder Exists"
}
else
{
  Write-Host "Folder Not Exists"
}

Read or Import CSV File in PowerShell

We can read text from CSV file using powershell's Import-Csv cmdlet. The Import-Csv cmdlet provides a way to read in data from a comma-separated values file (CSV) and then display that data in tabular format within the Windows PowerShell console. Consider the following CSV file (AllUsers.CSV).
Name,Department,Title
Kevin,Research,Manager
Smith,"IT Security",Administrator
Kim,"IT Security",Administrator
Mike,Finance,Accountant
Use the following command to import csv file and display output in tabular format in powershell console:
Import-Csv C:\Scripts\AllUsers.csv
If you want to work with csv file inputs, you can read values as row by row by piping the imported data into ForEach function.
Import-Csv C:\Scripts\AllUsers.csv |
    ForEach-Object {
        $Name = $_.Name
        $Title = $_."Title"

       Write-Host "Name: " $Name "; Title:" $Title
    }
We can filter CSV input values, pipe the imported data to the Where-Object cmdlet to filter csv input.
Import-Csv C:\Scripts\AllUsers.csv |  Where-Object {$_.Title -eq "Administrator"} |
    ForEach-Object {
        $Name = $_.Name
        $Title = $_."Title"

       Write-Host "Name: " $Name "; Title:" $Title
    }

Friday, 5 June 2015

Get Mailbox Size for All Users using PowerShell

We can find the total used space of mailbox of all users by using the exchange powershell cmdlet Get-MailboxStatistics. The Get-MailboxStatistics cmdlet is used to obtain information about a mailbox, such as the total size of the mailbox, the number of messages it contains, and the mailbox logon activity.

Summary:

Get Mailbox Size for Single User:

Get-MailboxStatistics -Identity 'Kevin' | Select DisplayName,ItemCount,TotalItemSize
Note: If you are working with normal PowerShell console instead of Exchange Management Shell, you need to run the following command to import exchange management powershell cmdlets.
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010

Get Mailbox Size for All Users:

To get malibox size of all the users, you need to give exchange server name as input paramater instead of user identity .Use the below powershell script to get mailbox size of all the users.
Get-MailboxStatistics -Server 'ExchSVR1' | Where {$_.ObjectClass -eq “Mailbox”} | 
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression= {$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, LastLogonTime

Get a list of Mailboxes sorted by size:

The following powershell script get a list of mailboxes with sizes and sorted by size in Descending order, so that you can easily find the users who are using high storage space in their mailbox.
Get-MailboxStatistics -Server 'ExchSVR1' | Where {$_.ObjectClass -eq “Mailbox”} | 
Sort-Object TotalItemSize -Descending |
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression={$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, 
LastLogonTime

Export Mailbox Size Report to CSV:

We can export powershell output into CSV file using Export-CSV cmdlet. The following powershell script export all the user's mailbox size, total messages and lastLogon time values into CSV file.
Get-MailboxStatistics -Server 'ExchSVR1' | Where {$_.ObjectClass -eq “Mailbox”} | 
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression={$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, LastLogonTime | 
Export-CSV "C:\\MailBoxSize-Report.csv" -NoTypeInformation -Encoding UTF8

CSV output of mailbox size report:

Exchange Powershell - Get Mailbox Size for All Users

Get Mailbox Size of specific set of users:

You can use the exchange management powershell cmdlet Get-Mailbox to get specific set of mailbox enabled Active Directory users and pass user details to Get-MailboxStatistics cmdlet. You can apply filters in Get-Mailbox cmdlet to select users.
Get-Mailbox | Where {$_.DistinguishedName -like "*OU=TestOU,DC=TestDomain,DC=local*"} |
Get-MailboxStatistics | Where {$_.ObjectClass -eq “Mailbox”} | 
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression={$_.ItemCount}},
@{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}}, LastLogonTime

Thursday, 4 June 2015

Get and Set Execution Policy in PowerShell

The powershell cmdlet Get-ExecutionPolicy tells you which of the four execution policies is currently enabled. The Windows PowerShell execution policies include the following four policies:

Restricted - No scripts can be run. Windows PowerShell can be used only in interactive mode.
AllSigned - Only scripts signed by a trusted publisher can be run.
RemoteSigned - Downloaded scripts must be signed by a trusted publisher before they can be run.
Unrestricted - No restrictions; all Windows PowerShell scripts can be run.

To find the current execution policy run the below cmdlet: The default value is "Restricted."
Get-ExecutionPolicy
Use the below command to set new execution policy:
Set-ExecutionPolicy RemoteSigned -Force

How to check PowerShell Version

We can use $PSVersionTable.PSVersion to determine what version of PowerShell is installed on a computer. If the variable does not exist, it is safe to assume that the installed PowerShell version is 1.0.
$PSVersionTable.PSVersion
--------- Output -----------
Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1
Use the following command to check only Major version of PowerShell.
($PSVersionTable.PSVersion).Major
2

Wednesday, 3 June 2015

VBScript - Create File and Create Folder

In vbscript, we can create a new textfile and directory using FileSystemObject. The FileSystemObject contains the functions CreateFolder and CreateTextFile to create file and folder. The following vbscript create the folder "TestDir" under "C:\" and create the file "Sample.txt".
Option Explicit
Dim objFSO, objFSOText
Dim strDirectory, strFile
strDirectory = "C:\TestDir"
strFile = "\Sample.txt"

' Create the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")

' Create the folder "TestDir"
 objFSO.CreateFolder(strDirectory)

' Create the file "Sample.txt"
objFSO.CreateTextFile(strDirectory & strFile)
Wscript.Echo "File created: " & strDirectory & strFile
Wscript.Quit

VBScript - Create a File and Check if a File Already Exists

Before creating new file, we need to check whether the file is already exists or not. The following vbscript check the folder "TestDir" is already exists and create the folder if not exists, and it check the file "Sample.txt" is already exists and create new file only if not exists .
Option Explicit
Dim objFSO, objFSOText
Dim strDirectory, strFile
strDirectory = "C:\TestDir"
strFile = "\Sample.txt"

' Create the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")

' Check the folder "TestDir" is exists or not
If objFSO.FolderExists(strDirectory) Then
   WScript.Echo "Folder already exists : " & strDirectory
Else
   objFSO.CreateFolder(strDirectory)
   WScript.Echo "Folder created: " & strDirectory
End If

' Check the file "Sample.txt" is exists or not
If objFSO.FileExists(strDirectory & strFile) Then
      WScript.Echo "File already exists : " & strDirectory & strFile
Else
     objFSO.CreateTextFile(strDirectory & strFile)
Wscript.Echo "File created " & strDirectory & strFile
End If 
Wscript.Quit

Tuesday, 2 June 2015

Add AD Group Members using PowerShell Script

In this article, I am going to write powershell script samples to add members to Active Directory group and add AD group members from CSV file. You can add group members by using the Active Directory powershell cmdlet Add-ADGroupMember.
Add-ADGroupMember [-Identity] <ADGroup> [-Members] <ADPrincipal[]>
Identity - The Identity parameter specifies the Active Directory group that receives the new members. You can identify a group by its distinguished name (DN), GUID, SID or SamAccountName.

Members - The Members parameter specifies the new members to add to a group. You can identify a new member by its distinguished name (DN), GUID, SID or SamAccountName.

Add Active Directory Group Members

Add user accounts to AD Group by samAccountName:
Import-Module ActiveDirectory
Add-ADGroupMember "Domain Admins" "MorganTest1,MorganTest2";
Add AD Group members by distinguished name (DN):
Import-Module ActiveDirectory
Add-ADGroupMember "Domain Admins" "CN=MorganTest1,OU=TestOU,DC=TestDomain,DC=local";

Add Members to AD Group from CSV file

   1. Consider the CSV file Users.csv which contains set of Active Directory users to add as members to AD Group with the attribute samAccountName.
Disable Active Directory User Account using Powershell Script

   2. Copy the below Powershell script and paste in Notepad file.
   3. Change the Users.csv file path with your own csv file path.
   4. SaveAs the Notepad file with the extension .ps1 like Import-AD-Group-Members-From-CSV.ps1

Powershell script file: Download Import-AD-Group-Members-From-CSV.ps1
Import-Module ActiveDirectory
  $adGroup = "Powershell Admins"
Import-Csv "C:\Scripts\Users.csv" | ForEach-Object {
 $samAccountName = $_."samAccountName" 
 Add-ADGroupMember $adGroup $samAccountName;
 Write-Host "- "$samAccountName" added to "$adGroup
}
   5. Now run the file Import-AD-Group-Members-From-CSV.ps1 from Powershell to import Bulk Active Directory users from CSV and add as member to AD Group.
PS C:\Scripts>  .\Import-AD-Group-Members-From-CSV.ps1
Add Members to AD Group by Importing Members From CSV using Powershell Script

Note: I have placed script file in the location C:\Scripts, if you placed in any other location, you can navigate to that path using CD path command (like cd "C:\Downloads").

Monday, 1 June 2015

Run as different user

Running a program as different user is one of the easiest way to impersonate a Program/Application with some other user's privilege. For every administrators, this would be common need either for testing or to impersonate different user privilege.

Run as different user via Commandline:

You can run a program under a different user account by using the command line tool RunAs. Use the below command to open new CMD window under different user account.
RunAs /user:TestDomain\Smith CMD
Run as different user
You will be prompted to enter password when you execute this command. type password and click 'Enter' to open new cmd window under the different user 'TestDomain\Smith'.

Run as different user

Run as different user with Run as option:

Hold down the "Shift" key on your keyboard, then right-click the program you would like to launch and click the option Run as different user. This will works only on application launch files (EXE) or shortcuts to application launch files.
Run as different user