EWS Powershell – to Access Contacts on the Exchange Mailbox

Exchange Web Services can be used to do lots of stuffs in the mailbox like access email, reply the email, access calender contacts etc. EWS has made live easier for us. EWS was introduced from Exchange 2007 and earlier lots of legacy application used to use Webdev to do the same. Webdev does not provide the great flexibility to the programmers. EWS API  provides a easy access and lot more flexibility which webdev did not provide. Even as a Administrator we can use  EWS with Powershell to do lots of stuffs on the mailbox.

Below is the piece of code from Glen Scales(http://gsexdev.blogspot.com), who knows in and out of Exchange EWS and Powershell. I have modified it for a requirement. Lets have a requirement to get the list of all the yahoo contacts on all the mailbox in the Exchange organization in the spread Sheet.

We need to make sure we are using a account which has full access on all the mailbox in the organization. To pull of the contacts the EWS has to get into the mailbox and get the list.

Required configuration

1. Exchange 2007 Management Shell

2. .net 3.5

3. Exchange CAS -EWS Urls

4. Account which has access on all the mailbox in the organization

5. Below code can be executed in Lab. This is because normally lab will normally have only self signed certificate not a trusted SAN certificate installed on the CAS server and without certificate EWS may not work. To mitigate the issue we have  added few lines of code between 8 -36. In production you can remove this code and execute as you may have SAN certificate installed.

Start-Transcript c:\Transcript.txt$casserverName = "CASServer"$userName = "username"$password =  "password"$domain = "domainname"## Code From <a href="http://poshcode.org/624">http://poshcode.org/624</a>## Create a  compilation environment$Provider=New-Object  Microsoft.CSharp.CSharpCodeProvider$Compiler=$Provider.CreateCompiler()$Params=New-Object  System.CodeDom.Compiler.CompilerParameters$Params.GenerateExecutable=$False$Params.GenerateInMemory=$True$Params.IncludeDebugInformation=$False$Params.ReferencedAssemblies.Add("System.DLL")  | Out-Null$TASource=@' namespace  Local.ToolkitExtensions.Net.CertificatePolicy{ public class TrustAll :  System.Net.ICertificatePolicy { public TrustAll() { } public bool CheckValidationResult(System.Net.ServicePoint  sp, System.Security.Cryptography.X509Certificates.X509Certificate  cert, System.Net.WebRequest req, int problem) { return  true; } } }'@$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)$TAAssembly=$TAResults.CompiledAssembly## We now create an instance of the TrustAll and attach it to the  ServicePointManager$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll$dllpath = "C:\Program Files\Microsoft\Exchange\Web  Services\1.0\Microsoft.Exchange.WebServices.dll"[void][Reflection.Assembly]::LoadFile($dllpath)$service  = New-Object  Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)$windowsIdentity =  [System.Security.Principal.WindowsIdentity]::GetCurrent()$sidbind =  "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"$aceuser  = [ADSI]$sidbind$uri=[system.URI] ("<a href="https://%22/">https://"</a> + $casserverName +  "/ews/exchange.asmx")$service.Url = $uri$service.Credentials = New-Object  System.Net.NetworkCredential($username,$password,$domain)new-item -path c:\reportfile.csv -type file -forceget-mailbox -resultsize unlimited | Select PrimarySmtpAddress | foreach{$ContactsFolderid  = new-object  Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts,$_) $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000) $findResults = $Service.FindItems($ContactsFolderid,$view) if($findResults) { foreach($contact in  $findResults) { if($contact.EmailAddresses[0].address  -like "*yahoo.com") { $result = $_ + " , " +  $contact.EmailAddresses[0].address } Add-content  -path c:\reportfile.csv -value $result }}}Stop-Transcript

result file will be created with name C:\Reportfile.csv. It will have the list of users primarysmtpaddress and there list of contacts which has yahoo.com in it
Every one will have there own requirement and you can modify to suite your requirement. let me know if you have any requirement and i can help you on this.

Thanks Glen 🙂

Powershell to query Adsites and Domain Controllers Details

Below powershell command helps to get the list of all the Sites in Active directory and domain controller in each domain. We can filter this to find the dc on specific domain controller

[system.directoryservices.activedirectory.domain]::GetCurrentDomain().domainControllers | select sitename,name

If you wanted to perform specific operation and it has to run on all the domain controllers in every site then we can filter this out. Below powershell will get one DC on each site. Its simple logic but worth it..

[system.directoryservices.activedirectory.domain]::GetCurrentDomain().domainControllers | foreach {

$Sitename = $_.sitename
$dcname = $_.name
$repSite = “”
if($Sitename -ne $repSite)
 {
  Write-host $Sitename $dcname
 }

}

 

Installing Patches/Application remotely on windows Machine using Psexec

Installing pathes/Application on a remote computer is not a tough one when you have lots of Microsoft and third party application to do this for us.Chances that few companies still does not wanted to relay on software to install patches and Administrator manually installed this. You should ask this question to the Administrators who works on weekend installing patches manually, do you like this to do every weekend ? I am sure he will give you very dirty look for sure 🙂

Below is the small piece of code you may like to use it for installing pathces or any small application on various computer remotely.

Prerequisits
1. Download PSExec.exe from Microsoft.com (http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx) and copy to C:\Psexec.exe
2. Create C:\Hotfixes and dump the path here
3. Copy below code and save it as C:\patchinstall.vbs
4. Create C:\Servers.txt with list of servername
5. Rename with the appropriate name
6. Open command prompt type cscript C:\patchinstall.vbs

This code will copy the patch to all the remote computer mentioned in C:\Servers.txt under C:\Hotfixes and it uses psexec.exe to install the patch on the remote computer

Set objShell = CreateObject("Wscript.Shell")Set objFSO = CreateObject("Scripting.FileSystemObject") set filetxt = objFSO.OpenTextFile("C:\Servers.txt",1)strPSExec = "C:\PSExec.exe"rbcopy = "c:\Windows\System32\Robocopy.exe"strPSExec = objFSO.GetFile(strPSExec).ShortPathrbcopy = objFSO.GetFile(rbcopy).ShortPath do Until filetxt.AtEndOfStream strComputer = filetxt.Readline strComputer = trim(strComputer)   strCmd = "cmd /C " & rbcopy  & " C:\Hotfixes" & " \\" & strComputer & "\c$\Hotfixes" wscript.echo strcmd objShell.Run strCmd, 1, True  strCmd = "cmd /C " & strPSExec & " \\" & strComputer & " ""C:\Hotfixes\<Hotfixname.exe>"" /quite" wscript.echo strcmd objShell.Run strCmd, 1, TrueLoop

Powershell to Query Active directory

Powershell to Query Active directory and get the list of Domain controllers in the current AD Site which you server is located

%{[System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Servers | % { $_.Name} }

 

 

Powershell to Query Active directory to get the current AD sites

 [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().name

 

Exchange 2007/2010 Dynamic Distribution List filter customizing

As the name says Dynamic Distribution List is the group which maintains the list of users in the group dynamically. Every time it’s hard to maintain Static list. Static list needs to be manually managed for adding and removing users. If it’s the smaller list then it can be managed easily and if the group is very big and it bigger the problem

Dynamic Distribution list is can be created using Exchange management Console or Exchange management shell. Dynamic Distribution list manages the users using filter condition. Default filter condition provides us limited filter options like State, Department, Company, and other custom attributes like 1 to 15. Same has been shown in Figure 1.

Figure 1. List of Condition Options for filtering members to group

With this option we can build the Dynamic DL and these options some times can match our requirement and some times it may not.

For example we need to build a Dynamic DL with the list of users belonging to the specific Mailbox Server. Requirement option can vary depending on the business. Here i am just trying to take one example and explaining the concept.

Dynamic DL saves all the filters in the Active directory. AD Attribute msExchQueryFilter, msExchDynamicDLFilter has all filters settings.

msExchQueryFilter:
msExchQueryFilter hold the OPATH filters. OPATH is basis for the filtering syntax used by Powershell.

msExchDynamicDLFilter:
msExchDynamicDLFilter hold the LDAP filter which is available in msExchQueryFilter attribute

If we wanted to change the filter to match the requirement then we need to use ADSI Edit and edit the AD attributes and apply the new filter.

1. Access ADSI Edit from your computer and connect to Default naming context. Figure 2

Figure 2. connecting to Active Directory – Default naming context

2. Create the Dynamic DL in Advance and Browse the Adsiedit to the Dynamic DL which is create and right click and properties

3. Copy and paste the below OPATH filter on msExchangeQueryfilter and replace server name with the mailbox servrname, if clusterd then cluster CMS name

(((RecipientType -eq ‘UserMailbox’)) -and (-not(Name -like ‘SystemMailbox{*’)) -and (-not(Name -like ‘CAS_{*’) -and (ServerName -eq ‘Servername’)))

4. Now you have configured the filter. If you wanted to see if this filter is applied then you can use the below Powershell cmdlet. Replace DymamicDL with the name of the DL which we have worked on and it will get the result of all the users’ name that belongs to the specific server.

$DynamicDL = Get-DynamicDistributionGroup -Identity “DynamicDL”

Get-Recipient -RecipientPreviewFilter $DynamicDL.RecipientFilter |select name,servername

You can get this requirement if you wanted to send communication to specific users on the specific server when there is any maintenance etc. As I said earlier we can use similar filters based on the requirement to add users dynamically into the list. Technically you can get any Powershell filter into Dynamic DL

Powershell to work on Remote Registery

Working on Remote Registry is always challenging. If you are administrator, I am sure you would have come across various times that you wanted to update registry of the computer and you have to login to the each server and apply the registry. Powershell has made most of our administrator’s life easier. Let’s understand how we can access and edit registry of remote computer using powershell

Let’s understand code with example. Below Script take the list of server name in CSV file and reads each server name one by one and opens the registry Key and prints the value. In this fashion you can get any key and get the value. In the below script I am trying to get the value of HKEY_CurrentUsers. This is the reason current in OpenRemoteBaseKey. If you Access keys of HKEY_Localmachine and use LocalMachine

$csv = Import-Csv "C:\Server.csv"foreach($line in $csv){ $strComputer = $line.CMSName $curreg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('CurrentUser', $strComputer) $curkey="Software\Microsoft\Windows\CurrentVersion\Wintrust\Trust Providers\Software Publishing" $curregKey = $curreg.OpenSubKey($curkey) $curregkey.GetValue('State')} 

If you wanted to get the list of subfolder under the folder in the registry then use the below code. This will get list of all the subfolder MSExchangeIS\Clustername. Getsubkeynames() does this.

<strong>$csv = Import-Csv "C:\Server.csv"foreach($line in $csv) { $cmsName = $line.Node $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $strComputer) $key="SYSTEM\CurrentControlSet\Services\MSExchangeIS\$cmsName" $regKey = $reg.OpenSubKey($key) foreach($Rkey in $regKey.getsubkeynames())  {  $Rkey   } }

If you wanted to write or edit the remote registry then below code will help. This code will create the new key if the key does not exist else it will edit the existing key to the required value. Below code will create the Dword key if key does not exit there else it will edit the existing key to the required value on the entire computer mentioned in the CSV file.

$csv = Import-Csv "C:\Server.csv"foreach($line in $csv){ $strComputer = $line.Node $curreg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('CurrentUser', $strComputer) $curkey="Software\Microsoft\Windows\CurrentVersion\Wintrust\Trust Providers\Software Publishing" $curregKey = $curreg.OpenSubKey($curkey,$True) $curregkey.SetValue('State','100234','Dword')}