Wednesday, 30 December 2015

Office 365 License Vs Usage Report with Powershell

Office 365 introduced the new reporting powershell cmdlet Get-LicenseVsUsageSummaryReport to retrieve a summary report that identifies the number of active users across each installed software licenses (Exchange Online, SharePoint Online, Skype for Business Online, and Microsoft Yammer).

Note: Before proceed, Connect Exchange Online Remote PowerShell.

The following command gets a summary report of the number of entitled users for the workload, the number of provisionally entitled (trial) users for the workload and the count of active licensed users.
Get-LicenseVsUsageSummaryReport

Export License Vs Usage Summary Report:

Use the below powershell command to export the license vs usage summary report to CSV file.
Get-LicenseVsUsageSummaryReport | Select Date,TenantGuid,Workload,NonTrialEntitlements,TrialEntitlements,ActiveUsers |
Export-CSV "C:\\LicenseVsUsageSummaryReport.csv" -NoTypeInformation -Encoding UTF8

Sample License Usage Report:

Office 365 License Vs Usage Report with Powershell

Tuesday, 29 December 2015

Create Office 365 Mailbox with Powershell

We can use the office 365 exchange powershell cmdlet New-Mailbox to create new mailbox, this command also creates an office 365 user account along with mailbox.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

The below script creates an Exchange Online mailbox and Office 365 user account for the user Steve Smith. The optional parameter ResetPasswordOnNextLogon will require the user to reset their password the first time they sign in to Office 365.
New-Mailbox -Alias ssmith -Name ssmith -FirstName Steve -LastName Smith -DisplayName "Steve Smith" -MicrosoftOnlineServicesID ssmith@mts.onmicrosoft.com -Password (ConvertTo-SecureString -String 'MyP@ssw0rd' -AsPlainText -Force) -ResetPasswordOnNextLogon $true
After the mailbox creation, you will get below warning message
WARNING: After you create a new mailbox, you must go to the Office 365 Admin Center and assign the mailbox a license,
or it will be disabled after the grace period.
Once you created a mailbox by running this script, you have to activate this user account by assigning a license. To assign a license, refer this article: Manage Office 365 License with Powershell

Thursday, 19 November 2015

Disable Office 365 License Plans with Powershell

While we set a new license to an user, we can enable or disable only a particular set of service plans of the new license. we can use the powershell cmdlet New-MsolLicenseOptions to set license plans or features that we want to disable (or remove) from new license and we have to pass this disabled license options to Set-MsolUserLicense cmdlet with the parameter -LicenseOptions.

Note: Before proceed, Install and Configure Azure AD PowerShell

Disable office 365 service plans while adding new license:

To add a new license or disable service plans, we need to use AccountSkuId for the particular license, you can list all the available licenses and its AccountSkuId by running the following command.
Get-MsolAccountSku | Select AccountSkuId,SkuPartNumber,ActiveUnits,ConsumedUnits
You can get the list of all the available service plans in a particular license by using below command:
Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq 'mts:O365_BUSINESS_PREMIUM'} | ForEach-Object {$_.ServiceStatus}
#1 Create a new license options that we want to disable from the license that we are going to set to an user.
$options = New-MsolLicenseOptions -AccountSkuId mts:O365_BUSINESS_PREMIUM -DisabledPlans OFFICE_BUSINESS,MCOSTANDARD
#2 Now, we can add new license by passing new license's AccountSkuId to Set-MsolUserLicense cmdlet and set the license options in the paramater -LicenseOptions.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' –AddLicenses mts:O365_BUSINESS_PREMIUM -LicenseOptions $options

Enable or Disable License Plans in existing License:

Instead of disabling license plans while adding new license, you might also come across the need of enable or disable service plans in existing license. You can achieve this need by using the same office 365 powershell cmdlets Set-MsolUserLicense and New-MsolLicenseOptions. You can do it by just ignoring the parameter –AddLicenses in Set-MsolUserLicense cmdlet.

#1 Create the new license options that we want to disable from the existing license applied for the user.
$options = New-MsolLicenseOptions -AccountSkuId mts:O365_BUSINESS_PREMIUM -DisabledPlans OFFICE_BUSINESS,MCOSTANDARD
Note: There is no options like -EnabledPlans, you have use the same paramater -DisabledPlans to enable service plans in existing license by disabling other license plans

#2 Now, we can set this new license options in the Set-MsolUserLicense cmdlet with the paramater -LicenseOptions.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' -LicenseOptions $options

Monday, 16 November 2015

Powershell: Unable to find a default server with Active Directory Web Services running

Problem:

Today I experienced the error “Unable to find a default server with Active Directory Web Services running.” in Powershell with Windows 2012 Server. This message was occurred when I try to create bulk AD users using the New-ADUser command.
New-ADUser : Unable to find a default server with Active Directory Web Services running.
At line:6 char:1
+ New-ADUser `
+ ~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [New-ADUser], ADServerDownException
    + FullyQualifiedErrorId : ActiveDirectoryServer:1355,Microsoft.ActiveDirectory.Management.Commands.NewADUser

Add-ADGroupMember : Unable to find a default server with Active Directory Web Services running.
At line:12 char:2
+  Add-ADGroupMember "Domain Admins" $userName;
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (Domain Admins:ADGroup) [Add-ADGroupMember], ADServerDownException
    + FullyQualifiedErrorId : ActiveDirectoryServer:1355,Microsoft.ActiveDirectory.Management.Commands.AddADGroupMembe
   r

Solution:

From this blog post https://jorgequestforknowledge.wordpress.com/2011/12/12/the-active-directory-web-service-adws/ , I have learned that the AD Powershell Module is depends on the windows service "Active Directory Web Service (ADWS)". So, I have checked the service "Active Directory Web Services" in "services.msc" console and re-started it, now the problem resolved successfully.

Saturday, 14 November 2015

Manage Office 365 Users License using Powershell

We can use the Azure AD Powershell cmdlet Set-MsolUserLicense to manage Office 365 license for a user. You can add a new license, remove an existing license and update existing license features (enable or disable license sub features) using this cmdlet.

Summary:

Add New License to Office 365 User:

To add a new license, we need to get AccountSkuId for the particular license, you can list all the available licenses and its AccountSkuId by running the following command.

Note: Before proceed, Install and Configure Azure AD PowerShell
Get-MsolAccountSku | Select AccountSkuId,ActiveUnits,ConsumedUnits
You can also get the list of all the available service plans in a particular license by using below command:
Get-MsolAccountSku | Where-Object {$_.AccountSkuId -eq 'mts:O365_BUSINESS_PREMIUM'} | ForEach-Object {$_.ServiceStatus}
Next, we need to set Usage Location for the user. This is required for every individual user. If you are re-assigning the license, the usage location is not mandatory. We have to use the Azure AD powershell cmdlet Set-MsolUser to set usage location.
Set-MsolUser -UserPrincipalName 'morgan@mts.com' -UsageLocation "US"
Now, we can assign the new license by using below powershell command.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' -AddLicenses 'mts:O365_BUSINESS_PREMIUM'
To add multiple licenses, you have to pass AccountSkuId of all the licenses as comma (,) separated values.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' -AddLicenses mts:O365_BUSINESS_PREMIUM,mts:AAD_PREMIUM

Add License with certain features:

While adding new license to an user, we can enable or disable only particular set of sub components of a new license. we have to use the powershell cmdlet New-MsolLicenseOptions with the option -DisabledPlans to set license features that we want to disable (or remove) from new license.
$options = New-MsolLicenseOptions -AccountSkuId 'mts:O365_BUSINESS_PREMIUM' -DisabledPlans OFFICE_BUSINESS,MCOSTANDARD
Now, we can pass this license options to Set-MsolUserLicense cmdlet using the paramater -LicenseOptions.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' –AddLicenses 'mts:O365_BUSINESS_PREMIUM' -LicenseOptions $options
Note: There is no option EnabledPlans like DisabledPlans, so we can't set only required features in straightforward way, we can achieve this only by excluding non-required features by using DisabledPlans option.

Update Features in existing License (Enable and Disable sub feature)

If you want to update or disable license features in existing license, you have to set only LicenseOptions in Set-MsolUserLicense cmdlet (exclude the parameter –AddLicenses).
$options = New-MsolLicenseOptions -AccountSkuId 'mts:O365_BUSINESS_PREMIUM' -DisabledPlans OFFICE_BUSINESS,MCOSTANDARD
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' -LicenseOptions $options

Re-Assigning License of an Office 365 User:

We can easily re-assign or replace new license by removing old license by using single command. The below powershell command remove the license mts:O365_BUSINESS_PREMIUM from the user morgan and add the license mts:ENTERPRISEPACK.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' -AddLicenses 'mts:ENTERPRISEPACK' -RemoveLicenses 'mts:O365_BUSINESS_PREMIUM'

Remove Licenses from Office 365 User:

We can easily remove an existing license from an user by passing the license's AccountSkuId to the parameter –RemoveLicenses in Set-MsolUserLicense cmdlet.
Set-MsolUserLicense -UserPrincipalName 'morgan@mts.com' –RemoveLicenses 'mts:O365_BUSINESS_PREMIUM'
To remove multiple licenses, you have to give AccountSkuId of all the licenses as comma (,) separated values.

Find and Export User License Details:

We can find and get the applied license details of all the office 365 users by using the Azure AD powershell cmdlet Get-MsolUser. The Get-MsolUser cmdlet returns the user's license details and applied license sub features (enabled license plans).
$users = Get-MsolUser | Where-Object { $_.IsLicensed }
$users | Foreach-Object{ 
  $licenseDetail = '' 
  $licenses='' 
  if($_.licenses -ne $null) {
ForEach ($license in $_.licenses){
  switch -wildcard ($($license.Accountskuid.tostring())) { 
           '*POWER_BI_STANDALONE' { $licName = 'POWER BI STANDALONE' } 
           '*CRMSTANDARD' { $licName = 'CRM Online' }
           '*O365_BUSINESS_PREMIUM' { $licName = 'Office 365 BUSINESS PREMIUM' } 
           '*ENTERPRISEPACK' { $licName = 'Office 365 (Plan E3)' }  
           default { $licName = $license.Accountskuid.tostring() }
        }         

  if($licenses){  $licenses = ($licenses + ',' + $licName) } else { $licenses = $licName}
ForEach ($row in $($license.servicestatus)) {

if($row.ProvisioningStatus -ne 'Disabled') {          
       switch -wildcard ($($row.ServicePlan.servicename)) { 
           'EXC*' { $thisLicence = 'Exchange Online' }  
           'LYN*' { $thisLicence = 'Skype for Business' }
           'SHA*' { $thisLicence = 'Sharepoint Online' }       
           default { $thisLicence = $row.ServicePlan.servicename }  
       }         
 if($licenseDetail){ $licenseDetail = ($licenseDetail + ',' + $thisLicence) }  Else { $licenseDetail = $thisLicence}}
}}}
New-Object -TypeName PSObject -Property @{    
    UserName=$_.DisplayName   
    Licenses=$licenses 
    LicenseDetails=$licenseDetail }
}  | Select UserName,Licenses,LicenseDetails |
Export-CSV "C:\\Office-365-User-License-Report.csv" -NoTypeInformation -Encoding UTF8

Thursday, 12 November 2015

If Statement in Windows PowerShell

All of us should come across the need of If check when we create a powershell script. The If condition might be needed for different cases, i.e, to compare two integer values, compare string values, check a string value contains another string values. etc...In this article, I am going to write different IF condition statements.

If check with Integer value :

$a = 10

If($a -eq 10)  { '$a equals 10' 
} else { '$a not equals 10' }

If with Not Equal check:

$a = 10
If($a -ne 11)  { '$a not equals 10' }

If check with String value :

$str = 'Hello World'

# case insensitive check: This if check ignore the case sensitive.

If($str -eq 'hello world')  { 'True' 
} else { 'False' }
By default, all comparison operators are case-insensitive. To make a comparison operator case-sensitive, precede the operator name with a "c".
$str = 'Hello World'

# case sensitive check: This if statement checks with case sensitive.

If($str -ceq 'hello World')  { 'True' 
} else { 'False' }

If with Not Equal check:

$str = 'Hello World'

If($str -ne 'hello worlddd')  { 'True' }

If with contains (or like ) check:

$str = 'Hello World'

If($str -like '*hello*')  { 'True'
} else { 'False' }

If with not contains (or not like ) check:

$str = 'Hello World'

If($str -notlike '*helloddd*') { 'True' 
} else { 'False' }

Thursday, 22 October 2015

Office 365 Users License Report with Powershell

We can find and list the applied license details of all the office 365 users by using the Azure AD powershell cmdlet Get-MsolUser. The Get-MsolUser cmdlet returns the user's license details along with other common user information.

Note: Before proceed, Install and Configure Azure AD PowerShell

Export Office 365 Users License Detail to CSV

The following powershell script gets the applied license detail for all the office 365 users by using Get-MsolUser cmdlet and it exports the output to csv file by using Export-CSV cmdlet.
$users = Get-MsolUser -All
$users | Foreach-Object{ 
  $licenseDetail = '' 
  $licenses='' 
  if($_.licenses -ne $null) {
ForEach ($license in $_.licenses){
  switch -wildcard ($($license.Accountskuid.tostring())) { 
           '*POWER_BI_STANDALONE' { $licName = 'POWER BI STANDALONE' } 
           '*CRMSTANDARD' { $licName = 'CRM Online' }
           '*O365_BUSINESS_PREMIUM' { $licName = 'Office 365 BUSINESS PREMIUM' } 
           '*ENTERPRISEPACK' { $licName = 'Office 365 (Plan E3)' }  
           default { $licName = $license.Accountskuid.tostring() }
        }         

  if($licenses){  $licenses = ($licenses + ',' + $licName) } else { $licenses = $licName}
ForEach ($row in $($license.servicestatus)) {

if($row.ProvisioningStatus -ne 'Disabled') {          
       switch -wildcard ($($row.ServicePlan.servicename)) { 
           'EXC*' { $thisLicence = 'Exchange Online' }  
           'LYN*' { $thisLicence = 'Skype for Business' } 
           'SHA*' { $thisLicence = 'Sharepoint Online' }       
           default { $thisLicence = $row.ServicePlan.servicename }  
       }         
 if($licenseDetail){ $licenseDetail = ($licenseDetail + ',' + $thisLicence) }  Else { $licenseDetail = $thisLicence}}
}}}
New-Object -TypeName PSObject -Property @{    
    UserName=$_.DisplayName  
    IsLicensed=$_.IsLicensed 
    Licenses=$licenses 
    LicenseDetails=$licenseDetail }
}  | Select UserName,IsLicensed,Licenses,LicenseDetails |
Export-CSV "C:\\Office-365-User-License-Report.csv" -NoTypeInformation -Encoding UTF8

Wednesday, 7 October 2015

How to make a Program run on Startup in Windows

Programs or shortcuts placed in the Startup folder will run automatically open whenever Windows starts. Follow the below steps to make a program run on windows startup.

1. Click the Start button and click Run...(or simply press Windows key + 'R').
2. Type the command "Shell:startup" in the Run dialog, and press Enter.

How to make a Program run on Startup in Windows
3. Now, you can see the Windows Startup folder.
4. Open the location that contains the item to which you want to create a shortcut.
5. Right-click the item, and then click Create Shortcut...
6. Copy the shortcut and Paste it into this Startup folder and Windows will automatically load them when you sign into your computer.

How to make a Program run on Startup in Windows

Tuesday, 6 October 2015

Convert Username to SID using VBScript

We can easily convert username to sid by using the WMI service class Win32_UserAccount with VBScript.

1. Copy the below example vb script code and paste it in notepad or a VBScript editor.
2. Save the file with a .vbs extension, for example: ConvertUsertoSID.vbs.
3. Double-click the vbscript file (or Run this file from command window).
4. Enter username and domain name and click Enter to resolve username to sid.
Option Explicit
Dim objWMIService,objAccount 
Dim strUserName,strSID,strDomainName,server

' Asks username and domain name from user.
strUserName = InputBox ("Please enter user name")
strDomainName = InputBox ("Please enter domain name")

  server = "."
  Set objWMIService = GetObject("winmgmts:\\" & server & "\root\cimv2") 
  Set objAccount = objWMIService.Get("Win32_UserAccount.Name='" & strUserName & "',Domain='" & strDomainName & "'")
  If Err.Number <> 0 Then
       Msgbox Err.Description
        Err.Clear
  Else
    Msgbox "User SID: " & vbtab & objAccount.SID & vbcrlf
  End If

Convert SID to Username using VBScript

We can easily convert object sid value to user friendly username by using the WMI service class Win32_SID with VBScript.

1. Copy the below example vb script code and paste it in notepad or a VBScript editor.
2. Save the file with a .vbs extension, for example: ConvertSIDtoUser.vbs.
3. Double-click the vbscript file (or Run this file from command window).
4. Enter the sid value that you want resolve as user name and click Enter.
Option Explicit
Dim objWMIService,objAccount 
Dim strUserName,strSID,strDomainName,server

' Asks object sid from user.
strSID = InputBox ("Please enter user sid value")
   If strSID = "" then
      Msgbox "No sid value entered"
   end if

  server = "."
  Set objWMIService = GetObject("winmgmts:\\" & server & "\root\cimv2")
  Set objAccount = objWMIService.Get("Win32_SID.SID='" & strSID & "'")
  strUserName = objAccount.AccountName
  strDomainName = objAccount.ReferencedDomainName
  If Err.Number <> 0 Then
       Msgbox Err.Description
        Err.Clear
  Else
 Msgbox "User name: " & vbtab & UCase(strUserName) & vbcrlf & "Domain name: " & vbtab & UCase(strDomainName)
  End If

Wednesday, 30 September 2015

Office 365 Non Delivery Reports with Powershell

The article helps you to get non delivery messages and failure reason from Office 365 by using powershell. In Exchange Online, we can generate message traffic reports by using the powershell cmdlet Get-Messagetrace.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

The following command gets all the message traffic details for last 7 days.
Get-Messagetrace -Start (Get-Date).AddDays(-7).ToString() -End (Get-Date).ToString()
You need to apply filter if you want to track only non delivered messages.
Get-Messagetrace -Start (Get-Date).AddDays(-7).ToString() -End (Get-Date).ToString() | Where-Object { $_.Status -eq 'Failed'}
The Get-Messagetrace cmdlet returns the columns Received (Message Time), Sender Address, Recipient Address, Subject and Status. For non delivered message, the status column returns the value 'Failed' and it doesn't return the actual reason for the failure message. So, we need to use the another cmdlet Get-MessageTraceDetail to get failure reason of the non delivered message.

The following powershell script lists office 365 non delivered messages and its failure reason.
$failedTraces = Get-Messagetrace -Start (Get-Date).AddDays(-7).ToString() -End (Get-Date).ToString() | Where-Object { $_.Status -eq 'Failed'}
$failedTraces | Foreach-Object{
     $trace = $_      
     $stats = $trace |Get-MessageTraceDetail -event FAIL  
     New-Object -TypeName PSObject -Property @{
     MessageTime = $trace.Received
     Sender = $trace.SenderAddress
     Recipients = $trace.RecipientAddress
     Subject =$trace.Subject
     MessageSize = $trace.Size     
     StatusMessage =$stats.Detail
   }} 

Export Office 365 Non Delivery Reports to CSV

We can use the powershell cmedlet Export-CSV to export powershell output into CSV file. The following script exports all non delivered (failed) messages and its failure reason to csv file.
$failedTraces = Get-Messagetrace -Start (Get-Date).AddDays(-7).ToString() -End (Get-Date).ToString() | Where-Object { $_.Status -eq 'Failed'}
$failedTraces | Foreach-Object{
     $trace = $_      
     $stats = $trace |Get-MessageTraceDetail -event FAIL  
     New-Object -TypeName PSObject -Property @{
     MessageTime = $trace.Received
     Sender = $trace.SenderAddress
     Recipients = $trace.RecipientAddress
     Subject =$trace.Subject
     MessageSize = $trace.Size     
     StatusMessage =$stats.Detail
   }} |
Export-CSV "C:\\Office365NonDeliveryReport.csv" -NoTypeInformation -Encoding UTF8

List Distribution Group Members in office 365 Powershell

The article helps you to list distribution group members from office 365 by using powershell script. We can list distribution groups by using the powershell cmdlet Get-DistributionGroup and get distribution group members by using the cmdlet Get-DistributionGroupMember.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

The following command lists all the office 365 distribution groups.
Get-DistributionGroup | Select DisplayName,GroupType,PrimarySmtpAddress

List Office 365 Distribution Group Members

Use the below powershell command to select members of single distribution group.
Get-DistributionGroupMember -Identity '[group_name]'
If you want to list members of all the cloud exchange distribution groups, first, we need to get the results of the Get-DistributionGroup cmdlet to a variable. Then we can pipe the variable to ForEach-Object and get members for all the distribution groups.
$Groups = Get-DistributionGroup
$Groups | ForEach-Object {
$group = $_.Name
Get-DistributionGroupMember $group | ForEach-Object {
      New-Object -TypeName PSObject -Property @{
       Group = $group
       Member = $_.Name
       EmailAddress = $_.PrimarySMTPAddress
       RecipientType= $_.RecipientType
}}}

Export All Distribution Group Members to CSV

We can export powershell output into CSV file using Export-CSV cmdlet. The following command exports all the office 365 distribution group members to CSV file.
$Groups = Get-DistributionGroup
$Groups | ForEach-Object {
$group = $_.Name
Get-DistributionGroupMember $group | ForEach-Object {
      New-Object -TypeName PSObject -Property @{
       Group = $group
       Member = $_.Name
       EmailAddress = $_.PrimarySMTPAddress
       RecipientType= $_.RecipientType
}}} |

Export-CSV "C:\\DistributionGroupMembers.csv" -NoTypeInformation -Encoding UTF8

List Distribution Groups in Office 365 Powershell

We can get all the office 365 distribution groups by using the powershell cmdlet Get-DistributionGroup. Before proceed, Connect Exchange Online Remote PowerShell.

The below command select and lists all the office 365 distribution groups.
Get-DistributionGroup | Select DisplayName,GroupType,PrimarySmtpAddress

List Distribution Group Members

We can use the powershell cmdlet Get-DistributionGroupMember to find and list office 365 distribution group members.
Get-DistributionGroupMember -Identity '<group_name>'
The following powershell command list all the distribution group members.
$Groups = Get-DistributionGroup
$Groups | ForEach-Object {
$group = $_.Name
Get-DistributionGroupMember $group | ForEach-Object {
      New-Object -TypeName PSObject -Property @{
       Group = $group
       Member = $_.Name
       EmailAddress = $_.PrimarySMTPAddress
       RecipientType= $_.RecipientType
}}}

Saturday, 26 September 2015

Set Office 365 user password via Powershell

We can set an Office 365 user password by using the Azure Active Directory powershell cmdlet Set-MsolUserPassword. To use this cmdlet we need to install Microsoft Online Services Sign-In Assistant and Azure Active Directory Powershell Module.

Note: Before proceed, Install and Configure Azure AD PowerShell

Set-MsolUserPassword –UserPrincipalName [UserPrincipalName] –NewPassword [New Password] -ForceChangePassword $False
The below command set the password for the user "Kevin@mts.com"
Set-MsolUserPassword –UserPrincipalName 'Kevin@mts.com' –NewPassword 'MyPa$$w0rd' -ForceChangePassword $False

Thursday, 24 September 2015

Change Password - Exception has been thrown by the target of an invocation

You may receive the error "System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation" when you try to change an AD user password with System.DirectoryServices.DirectoryEntry in C#.NET with following code.
var userEntry = new DirectoryEntry("LDAP://<GUID=" + guid + ">");
    userEntry.Invoke("ChangePassword", new object[] { oldPassword, newPassword });
    userEntry.CommitChanges();

Solution:

The error "Exception has been thrown by the target of an invocation" is a common error, it may occurs due to following cases:

1) The new password doesn't meet the domain complexity requirements.

2) Minimum Password Age is > 0.

3) Enforce password history may configured.

4) Any of the passwords is incorrect.

5) The user property "UserCannotChangePassword" set as True (Account options: User cannot change password).

You might have received on of the below error message.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
   --- End of inner exception stack trace ---
   at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)
   at System.DirectoryServices.AccountManagement.SDSUtils.ChangePassword(DirectoryEntry de, String oldPassword, String newPassword)
   at System.DirectoryServices.AccountManagement.ADStoreCtx.ChangePassword(AuthenticablePrincipal p, String oldPassword, String newPassword)
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.DirectoryServices.DirectoryServicesCOMException (0x8007202F): A constraint violation occurred. (Exception from HRESULT: 0x8007202F)

Exception has been thrown by the target of an invocation - Access is denied

Problem:

I have received the error "System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) --- End of inner exception stack trace --- at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args) at System.DirectoryServices.AccountManagement.SDSUtils.ChangePassword(DirectoryEntry de, String oldPassword, String newPassword) at System.DirectoryServices.AccountManagement.ADStoreCtx.ChangePassword(AuthenticablePrincipal p, String oldPassword, String newPassword)" when I try to change an AD user password using C# code.

This is my C# code:

var userEntry = new DirectoryEntry("LDAP://<GUID=" + guid + ">");
    userEntry.Invoke("ChangePassword", new object[] { oldPassword, newPassword });
    userEntry.CommitChanges();

Solution:

In my case, the reason for this error is that the problematic user has the property "UserCannotChangePassword" as true. You can check the user's Account options: User cannot change password through ADUC console.

Change AD Password Exception has been thrown by the target of an invocation - Access is denied

Saturday, 19 September 2015

Get AD Nested Group Members with Powershell

This article helps you to query nested AD group members using powershell. We can get group members by using the Active Directory powershell cmlet Get-ADGroupMember. The Get-ADGroupMember cmdlet provides the option to get all the nested group members by passing the parameter -Recursive. This powershell script also handles circular membership (infinite loop) problem.
Import-Module ActiveDirectory

function Get-ADNestedGroupMembers {
  [cmdletbinding()]
  param ( [String] $Group )            
  Import-Module ActiveDirectory
  $Members = Get-ADGroupMember -Identity $Group -Recursive
  $members
}

Get-ADNestedGroupMembers "Domain Admins" | Select Name,DistinguishedName

Export Nested Group Members to CSV:

We can export the nested group members output to csv file by using the powershell cmdlet Export-CSV.
Import-Module ActiveDirectory

function Get-ADNestedGroupMembers {
  [cmdletbinding()]
  param ( [String] $Group )            
  Import-Module ActiveDirectory
  $Members = Get-ADGroupMember -Identity $Group -Recursive
  $members
}

Get-ADNestedGroupMembers "Domain Admins" | Select Name,DistinguishedName |
Export-CSV "C:\\ADNestedGroupMembers.csv" -NoTypeInformation -Encoding UTF8

Friday, 18 September 2015

Multiple LEFT JOINs in MS Access Database

If you are joining related link tables in MS Access database as like SQL Server database, it will work fine for a single link table, but it will not work for more than one join query. The below single join query will work fine in both MS Access and SQL database.
SELECT A.ca, B.cb
FROM TableA AS A LEFT JOIN TableB AS B ON B.id = A.id

Join more than one table in MS Access

If you want to join more than one tables, the below sql like join query will work only in SQl database.
SELECT A.ca, B.cb, C.cc
FROM TableA AS A LEFT JOIN TableB AS B ON B.id = A.id
LEFT JOIN TableC AS C ON C.id = A.id
If you run the above query in MS Access database, you will get the error "Syntax error (missing operator) in query expression".

To make multiple joins work in MS Access database, we need to enclose join query with parentheses.
SELECT A.ca, B.cb, C.cc
FROM (TableA AS A LEFT JOIN TableB AS B ON B.id = A.id)
LEFT JOIN TableC AS C ON C.id = A.id

Join more than two or more tables in MS Access

Like the above query, we need to add parentheses for every join query to make multiple joins work in MS Access database.
SELECT A.ca, B.cb, C.cc,D.cd
FROM ((TableA AS A LEFT JOIN TableB AS B ON B.id = A.id)
LEFT JOIN TableC AS C ON C.id = A.id)
LEFT JOIN TableD AS D ON D.id = A.id

Saturday, 12 September 2015

Remove Full Access Permission Office 365 Powershell

We can remove full access permission from an Exchange Online mailbox using the powershell cmdlet Remove-MailboxPermission.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

Run the following command to remove the user Morgan's full access permission from Kevin’s mailbox.
Remove-MailboxPermission -Identity "Kevin@mts.com" -User "Morgan@mts.com" -AccessRights FullAccess
Identity - The name of the user on which the full access permission to be removed.
User - The mailbox that has the full access permission.

List mailbox permissions

Use the below command to list permissions of a mailbox.
Get-MailboxPermission -Identity 'Kevin@mts.com' | Select User, AccessRights, Deny
Use the below command to list permissions of all the mailboxes.
Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission | Select Identity, User, AccessRights, Deny

Set Full Access Permissions Office 365 Powershell

We can set or grant full access permission for an office 365 mailbox using the powershell cmdlet Add-MailboxPermission .

Note: Before proceed, Connect Exchange Online Remote PowerShell.

Run the following command to grant full access permission to Morgan on the user Kevin’s mailbox.
Add-MailboxPermission -Identity "Kevin@mts.com" -User "Morgan@mts.com" -AccessRights FullAccess
Identity - The name of the user on which the full access permission should be added.
User - The mailbox that should be granted the full access permission.

Grant Full Access to all Mailboxes in Office 365

Use the below powershell script to configure full access permission for all the mailbox users in your Office 365.
Get-Mailbox -ResultSize Unlimited | Add-MailboxPermission -User "Morgan@mts.com" -AccessRights FullAccess

List mailbox permissions

If you want to list permissions of a mailbox, use the below command.
Get-MailboxPermission -Identity 'Kevin@mts.com' | Select User, AccessRights, Deny

Friday, 11 September 2015

Get AD Nested Group Membership with Powershell

This article helps you to understand how to query nested group memberships using powershell. The Microsoft given AD powershell cmdlet Get-ADPrincipalGroupMembership doesn’t provide option to get all the groups part of a nested group membership.

The below powershell command returns only direct memberships of a user.
Get-ADPrincipalGroupMembership "[username]"

Consider the scenario:

  • Consider the user "Smith" is member of the group "DG1".
  • And "DG1" in-turn member of the group "DG2".
  • And "DG2" in-turn member of the group "DG3".
In this case, if you run the above command, you will get only "DG1" as user Smith's membership group. But the user is member of all the three groups ("DG1","DG2","DG3") through nested members hierarchy. To address this need, you can use the below powershell function that helps you to get all direct and indirect membership of a user in Active Directory. This function will recursively enumerate memberships of a given user along with nesting level and parent group information and it will also handle circular membership (infinite loop) problem by holding nested group names in a hashtable.
Import-Module ActiveDirectory

function GetNestedADGroupMembership {
Param([parameter(Mandatory=$true)] $user,
  [parameter(Mandatory=$false)] $grouphash = @{})

   $groups = @(Get-ADPrincipalGroupMembership -Identity $user | select -ExpandProperty distinguishedname)
   foreach ($group in $groups) {
      if ( $grouphash[$group] -eq $null) {
         $grouphash[$group] = $true
         $group
         GetNestedADGroupMembership $group $grouphash
      }
   }
}

GetNestedADGroupMembership 'CN=Smith,OU=TestOU,DC=TestDomain,DC=com'

Thursday, 10 September 2015

Class not registered at ADOX.CatalogClass.Create

Problem:

When i try to create MS Access database (.mdb) file, I am getting an error "Class not registered at ADOX.CatalogClass.Create(String ConnectString) from Microsoft OLE DB Service Components". I am using below C# code to create MS Access .mdb file using OLEDB Connection.
ADOX.Catalog cat = new ADOX.Catalog();
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\test.mdb");
Received below error message:
Class not registered : at ADOX.CatalogClass.Create(String ConnectString) at MyApp.DB.CreateDatabase()

Solution 1:

The OLEDB provider is supported only 64 bit application, so, to fix this problem, we have to change our application's build configuration to 32 bit mode.

Solution 2:

For me, the problem solved after changing my C# project's build configuration to x86 platform. If you received this error from IIS Server, follow the below steps to fix the issue.
  • Go to IIS and Application Pools in the left menu.
  • Right-click on the problematic Application Pool.
  • Click Advanced Settings. 
  • In General Tab, make the Enable 32 Bit Applications entry to "True"
Microsoft OLE DB - Class not registered - Microsoft.Jet.OLEDB.4.0

ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified

Problem:

When i tried to connect MS Access database. I am getting an error "ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified". I am using below C# code to connect MS Access .mdb file using Odbc Connection.
using (OdbcConnection myConnection = new OdbcConnection())
{
    myConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};" + "Dbq=C:\\test.mdb";
    myConnection.Open();    
};

Solution 1:

The ODBC Driver Manager is supported only 64 bit application, so, we have to force our application to build in 32 bit mode.

Solution 2:

The problem solved for me after changing my C# project's build configuration to x86 platform. If you faced this error from IIS service, do the below steps to fix the problem.
  • Go to IIS and Application Pools in the left menu.
  • Right-click on the problematic Application Pool.
  • Click Advanced Settings. 
  • In General Tab, make the Enable 32 Bit Applications entry to "True"
ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified

Wednesday, 9 September 2015

Convert SID to Username using C#

In C#, we can use the P-Invoke function LookupAccountSid to resolve user name from sid and we can also use the C# .NET class SecurityIdentifier to translate security identifier (SID) to user name and use NTAccount class to translate user name to security identifier (SID).

Summary:

Convert SID to Username using P-Invoke:

The below C# code resolve user name from security identifier (SID).
const int NO_ERROR = 0;
const int ERROR_INSUFFICIENT_BUFFER = 122;

enum SID_NAME_USE
{
    SidTypeUser = 1,
    SidTypeGroup,
    SidTypeDomain,
    SidTypeAlias,
    SidTypeWellKnownGroup,
    SidTypeDeletedAccount,
    SidTypeInvalid,
    SidTypeUnknown,
    SidTypeComputer
}

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
    string lpSystemName, [MarshalAs(UnmanagedType.LPArray)] byte[] Sid, StringBuilder lpName,
    ref uint cchName, StringBuilder ReferencedDomainName, ref uint cchReferencedDomainName, out SID_NAME_USE peUse);

static void Main(string[] args)
{
    // Sid for BUILTIN\Administrators
    GetUsernameFromSID("S-1-5-21-745457877-148782331-813991262-500");
}

private static void GetUsernameFromSID(string strSid)
{
    StringBuilder name = new StringBuilder();
    uint cchName = (uint)name.Capacity;
    StringBuilder referencedDomainName = new StringBuilder();
    uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;
    SID_NAME_USE sidUse;

    var sid = new SecurityIdentifier(strSid);
    byte[] byteSid = new byte[sid.BinaryLength];
    sid.GetBinaryForm(byteSid, 0);

    int err = NO_ERROR;
    if (!LookupAccountSid(null, byteSid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
    {
        err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
        if (err == ERROR_INSUFFICIENT_BUFFER)
        {
            name.EnsureCapacity((int)cchName);
            referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
            err = NO_ERROR;
            if (!LookupAccountSid(null, byteSid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
        }
    }
    if (err == 0)
        Console.WriteLine(@"Found account {0} : {1}\{2}", sidUse, referencedDomainName.ToString(), name.ToString());
    else
        Console.WriteLine(@"Error : {0}", err);
}

Convert SID to Username using SecurityIdentifier:

The below C# code translate security identifier (SID) to username using SecurityIdentifier class.
private static void GetUsernameFromSID(string sid)
{
    SecurityIdentifier s = new SecurityIdentifier(sid);
    string username = s.Translate(typeof(NTAccount)).Value;
    Console.WriteLine(username);
}

Convert Username to SID using NTAccount:

The below C# code translate user account to SID using NTAccount class.
private static void GetSIDFromUsername(string username)
{
    NTAccount ntAcc = new NTAccount(username);
    string objectsid = ntAcc.Translate(typeof(SecurityIdentifier)).Value;
    Console.WriteLine(objectsid);
}

Tuesday, 8 September 2015

Convert SID to Username using Powershell

You might come across the object sid value in Active Directory environment. We can use the .NET Framework class System.Security.Principal.SecurityIdentifier in Windows PowerShell script to translate security identifier (SID) to user name and we can use the class System.Security.Principal.NTAccount to translate user name to security identifier (SID).

Convert SID to Username using Powershell

The below powershell script converts security identifier (SID) to user name. You can replace the variable $SID with your own sid value that you want to translate into user name.
$SID ='S-1-5-21-1924530255-1943933946-939161726-500'
$objSID = New-Object System.Security.Principal.SecurityIdentifier($SID)
$objUser = $objSID.Translate([System.Security.Principal.NTAccount])
Write-Host "Resolved user name: " $objUser.Value

Convert Username to SID using Powershell

The below powershell script converts user name to security identifier (SID). You can replace the variable $user with your own user account that you want to translate into sid.
$user ='TestDomain\Morgan'
$objUser = New-Object System.Security.Principal.NTAccount($user)
$objSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
Write-Host "Resolved user's sid: " $objSID.Value

Monday, 7 September 2015

Export Office 365 Mailbox Size Report Powershell

We can get mailbox size and total messages count by using the office 365 powershell cmdlet Get-MailboxStatistics.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

The below powershell command returns total mailbox size and messages count for the office 365 user 'Kevin'.
Get-MailboxStatistics -Identity 'Kevin' | Select DisplayName,ItemCount,TotalItemSize

Export all Mailbox Sizes to CSV on Office 365:

We have to use the powershell cmdlet Get-Mailbox to get all the Office 365 mailboxes and pipe the results into Get-MailboxStatistics cmdlet to get mailbox size and total messages count for all the Mailbox users. The below powershell script exports all mailbox sizes to csv and the output is sorted by mailbox size in descending order.
Get-Mailbox -ResultSize Unlimited  | Get-MailboxStatistics |
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression= {$_.ItemCount}},
@{label=”Total Size (MB)”;expression={[math]::Round(`
($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}} |
Sort "Total Size (MB)" -Descending |
Export-CSV "C:\\Office-365-Mailbox-Size.csv" -NoTypeInformation -Encoding UTF8

Check Mailbox Size Office 365 with Powershell

We can find mailbox size of all users by using the office 365 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.

Note: Before proceed, Connect Exchange Online Remote PowerShell.

The below powershell command returns mailbox size and total mail count for the office 365 user 'Kevin'
Get-MailboxStatistics -Identity 'Kevin' | Select DisplayName,ItemCount,TotalItemSize

Get Mailbox size and usage for all Office 365 users:

You can use the powershell cmdlet Get-Mailbox to get all the mailboxes and pipe the results into Get-MailboxStatistics cmdlet to get mailbox size and total message count for all the users.
Get-Mailbox -ResultSize Unlimited  | Get-MailboxStatistics |
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression= {$_.ItemCount}},
@{label=”Total Size (MB)”;expression={[math]::Round(`
($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}}
Use the below command to sort mailbox list by mailbox size in descending order.
Get-Mailbox -ResultSize Unlimited  | Get-MailboxStatistics |
Select-Object -Property @{label=”User”;expression={$_.DisplayName}},
@{label=”Total Messages”;expression= {$_.ItemCount}},
@{label=”Total Size (MB)”;expression={[math]::Round(`
($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}} |
Sort "Total Size (MB)" -Descending

Wednesday, 2 September 2015

Exchange Server Role - msExchCurrentServerRoles attribute

We can use the Active Directory schema attribute "msExchCurrentServerRoles" to determine the role installed on the server. You can use this attribute, if you want to find the server role information through LDAP instead of exchange powershell. This attribute resides on the exchange server objects that exists in the Configuration container. You can check it through ADSIEdit by selecting Configuration context as well known Naming Context.
CN=<Servername>,CN=Servers,CN=Exchange Administrative Group,CN=Administrative Groups,CN=<Organization name>,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=<Domain Name>,DC<com>
The attribute msExchCurrentServerRoles holds maskable integer value, it includes the following values.
Mailbox role – 2
Client Access role (CAS) – 4
Unified Messaging role – 16
Hub Transport role – 32
Edge Transport role – 64
Use the below LDAP filters to get exchange servers by filtering with exchange server role:

Mailbox role:

(&(objectCategory=msExchExchangeServer)(msExchCurrentServerRoles:1.2.840.113556.1.4.803:=2))

Client Access role (CAS):

(&(objectCategory=msExchExchangeServer)(msExchCurrentServerRoles:1.2.840.113556.1.4.803:=4))

Unified Messaging role:

(&(objectCategory=msExchExchangeServer)(msExchCurrentServerRoles:1.2.840.113556.1.4.803:=16))

Hub Transport role:

(&(objectCategory=msExchExchangeServer)(msExchCurrentServerRoles:1.2.840.113556.1.4.803:=32))

Edge Transport role:

(&(objectCategory=msExchExchangeServer)(msExchCurrentServerRoles:1.2.840.113556.1.4.803:=64))

Find name of Exchange Organization in C#

In .NET C#, you can find the name your Exchange Organization using DirectoryEntry class from Configuration context store. Use the below C# code to get the name of your Exchange Organization by passing global catalog server.
//using System.DirectoryServices;
//-------------------------
private static string GetExchangeOrganizationName(string global_catalog_server)
{
    string organization = string.Empty;
    DirectoryEntry rootDSE = new DirectoryEntry("LDAP://" + global_catalog_server + "/rootDSE");
    string configDN = rootDSE.Properties["configurationNamingContext"].Value.ToString();
    string exOrgPath = "CN=Microsoft Exchange,CN=Services," + configDN;
    DirectoryEntry orgEntry = new DirectoryEntry("LDAP://" + global_catalog_server + "/" + exOrgPath);
    if (orgEntry.Children != null)
    {
        foreach (DirectoryEntry child in orgEntry.Children)
        {
            organization = child.Name.ToString().Replace("CN=", "");
            break;
        }
    }
    return organization;
}

Monday, 31 August 2015

Send on Behalf vs Send As Permissions

Both Send on Behalf and Send As are similar permissions, however, there is one difference between these two permissions. Send on Behalf will allow a user to send as another user, when an email message arrives, the email message that is being sent on behalf of the mailbox owner is displayed. For example, Morgan sends an email message on behalf of Kevin. On other hand, the Send As permission allow a user to send mail as another person, in this case, the recipient should have no idea about who sent the message. Send As permission can be more useful where you are send message as a mail-enabled distribution group (ex: support@org.com).

Consider the scenario:

- Admin1 has Send on Behalf permision on User1
- Admin2 has Send As permision on User2

If the "Admin1" send message as "User1" with Send on Behalf permission, the recipient receive the message with the From field "Admin1 on behalf of User1".

If the "Admin2" send message as "User2" with Send As permission, the recipient receive the message with the From field only "User1", the recipient should have no idea about "Admin2".

Grant Send on Behalf Permission:

We can grant send on behalf permissions for a mailbox user using the powershell cmdlet Set-Mailbox with the parameter GrantSendOnBehalfTo.

The following command grants "Morgan" send on behalf permission to Kevin’s mailbox.
Set-Mailbox "Kevin" -GrantSendOnBehalfTo @{add="Morgan"}

Grant Send As Permission:

We can grant Send As permission for a mailbox user using the Add-ADPermission powershell cmdlet. To perform this task, your account need to be added in the server roles Organization Management and Recipient Management.

The following command grants "Morgan" send as permission to Kevin’s mailbox.
Add-ADPermission -Identity "Kevin" -User "Morgan" -Extendedrights "Send As"

Saturday, 29 August 2015

Powershell Where-Object Filter Examples

We can use the cmdlet Where-Object to filter data returned by other cmdlets. The below command filter the result form Get-Process command and select processes which name is equal to "svchost".
Get-Process | Where-Object {$_.Name -eq "svchost"}
The below command looking for processes where handles were greater than or equal to 200
Get-Process | Where-Object {$_.handles -ge 200}
You can also use the -and and -or parameters.
Get-Process | Where-Object {$_.handles -gt 200 -and $_.name -eq "svchost"}
You can also filter by Boolean value (True/False).
Get-Service | Where-Object {$_.CanStop}
Get-Service | Where-Object { -not $_.CanStop}

Other useful conditional operators are:

-lt -- Less than
-le -- Less than or equal to
-gt -- Greater than
-ge -- Greater than or equal to
-eq -- Equal to
-ne -- Not equal to
-like -- Like; uses wildcards for pattern matching

Powershell Select –ExpandProperty [PropertyName]

We use select-object command to get properties from powershell output. Things are always fine with select-object if select the single valued property, but if we select multi-valued property or grouped property, the powershell returns the result as comma-separated values, sometimes the value can not be readable format, in this case, we should use ExpandProperty to expand multi-valued (or grouped) property.

The below command returns the Dependent Services for the windows service EventSystem, the DependentServices property is multi-valued property, so the below command returns value as comma separated values.
 Get-Service | Where-Object {$_.Name -eq "EventSystem"} | Select DependentServices
You can expand the multi-valued property by using –ExpandProperty and get as separated values.
 Get-Service | Where-Object {$_.Name -eq "EventSystem"} | Select -ExpandProperty  DependentServices

Set-Mailbox : No provisioning handler is installed.

I am receiving the error "No provisioning handler is installed" when I run the Set-Mailbox cmdlet in normal powershell console.
PS C:\Users\Morgan> Set-Mailbox "Kevin" -GrantSendOnBehalfTo "Morgan"
Set-Mailbox : No provisioning handler is installed.
At line:1 char:12
+ Set-Mailbox <<<<  "Kevin" -GrantSendOnBehalfTo "Morgan"
    + CategoryInfo          : NotSpecified: (:) [Set-Mailbox], InvalidOperationException
    + FullyQualifiedErrorId : 79CAD31B,Microsoft.Exchange.Management.RecipientTasks.SetMailbox
From this link Exchange 2010 Mailbox Role Install fails - No Provisioning Handler is Installed, I have got the below solution:
Make sure that your account is in the member of:

1. Exchange Organization Administrators (Organization Management group).

2. Local Administrators
I have added the user account into above two groups but still I faced the same error in Powershell console, but it is working well in Exchange Management Shell.

Remove Send on Behalf permissions using Powershell

We can remove send on behalf permission from a exchange mailbox user using the powershell cmdlet Set-Mailbox with the parameter GrantSendOnBehalfTo. Use the below command to remove send on behalf permission.
Set-Mailbox "[Identity]" -GrantSendOnBehalfTo @{remove="[User]"}
[Identity] - The name of the mailbox user from the send on behalf permission to be removed.
[User] - The user that has send on behalf permission.

The following command removes send on behalf permission of the user "Morgan" from Kevin’s mailbox.
Set-Mailbox "Kevin" -GrantSendOnBehalfTo @{remove="Morgan"}
You can also remove permission for multiple users by giving user names as comma separated values.
Set-Mailbox "Kevin" -GrantSendOnBehalfTo @{remove="User1","User2"}
You can check the final permissions by using below command.
Get-Mailbox "Kevin" | Select -ExpandProperty GrantSendOnBehalfTo | Select Name,Parent

Remove Send-on-Behalf permission for multiple user mailboxes

We can use the exchange management powershell cmdlet Get-Mailbox to get specific set of user mailboxes and pipe the results to Set-Mailbox cmdlet. The following command removes send on behalf permission of the user "Morgan" from all the mailboxes.
Get-Mailbox | Set-Mailbox -GrantSendOnBehalfTo @{remove="Morgan"}
You can also apply filters in Get-Mailbox cmdlet to select particular set of users. The following command select mailbox users from TestOU and pipe the results to Set-Mailbox cmdlet to remove send on behalf rights.
Get-Mailbox | Where {$_.DistinguishedName -like "*OU=TestOU,DC=TestDomain,DC=com*"} |
Set-Mailbox -GrantSendOnBehalfTo @{remove="User1","User2"}

Friday, 28 August 2015

Grant Send on Behalf Permissions using Powershell

We can set or grant send on behalf permission for a exchange mailbox user using the powershell cmdlet Set-Mailbox with the parameter GrantSendOnBehalfTo. Use the below command to set send on behalf permission.
Set-Mailbox "[Identity]" -GrantSendOnBehalfTo @{add="[User]"}
[Identity] - The name of the mailbox user on which the send on behalf permission to be added.
[User] - The user to be granted the send on behalf permission.

The following command grants "Morgan" send on behalf permission to Kevin’s mailbox.
Set-Mailbox "Kevin" -GrantSendOnBehalfTo @{add="Morgan"}
You can also grant permission for multiple users by giving user names as comma separated values.
Set-Mailbox "Kevin" -GrantSendOnBehalfTo @{add="User1","User2"}
The above commands add permission with existing send on behalf permissions and it does not overwrite the existing permissions (this is required for most cases). You can check the applied permissions by using below command.
Get-Mailbox "Kevin" | Select -ExpandProperty GrantSendOnBehalfTo | Select Name,Parent

Grant Send-on-Behalf permission for multiple user mailboxes

We can use the exchange management powershell cmdlet Get-Mailbox to get specific set of user mailboxes and pipe the results to Set-Mailbox cmdlet. The following command grants send on behalf permission for "Morgan" to all the mailboxes.
Get-Mailbox | Set-Mailbox -GrantSendOnBehalfTo @{add="Morgan"}
You can also apply filters in Get-Mailbox cmdlet to select particular set of users. The following command select mailbox users from TestOU and pipe the results to Set-Mailbox cmdlet to set send on behalf rights.
Get-Mailbox | Where {$_.DistinguishedName -like "*OU=TestOU,DC=TestDomain,DC=com*"} |
Set-Mailbox -GrantSendOnBehalfTo @{add="User1","User2"}

Grant Send on Behalf Permission using EMC

We can easily set or grant a user Send on Behalf permissions to another user's mailbox using the Exchange Management Console (EMC).

Follow the below steps to grant Send on Behalf rights:

1. Start the Exchange Management Console (EMC).
2. Open Recipient Configuration in the navigation pane, select and right click on the user mailbox you want give another user permissions to send on behalf of and select Properties.

How to Grant Send on Behalf Permission using EMC

3. Select the Mail Flow Settings tab and select Delivery Options and click Properties.

How to Set Send on Behalf Permission using EMC
4. Now, you can add or remove send on behalf permissions and click OK to save changes.

How to Set Send on Behalf Permission using EMC

Thursday, 27 August 2015

Get System Information in C#

In C#, we can get system information like Operation System , Processor Architecture and Drive Details using the built-in class Environment and we can also extract information through WMI service.

Get System Information using Environment

The below C# function get system information using Environment method.
public static void ShowSystemInformation()
{
    StringBuilder systemInfo = new StringBuilder(string.Empty);

    systemInfo.AppendFormat("Operation System:  {0}\n", Environment.OSVersion);
    systemInfo.AppendFormat("Processor Architecture:  {0}\n", Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"));
    systemInfo.AppendFormat("Processor Model:  {0}\n", Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER"));
    systemInfo.AppendFormat("Processor Level:  {0}\n", Environment.GetEnvironmentVariable("PROCESSOR_LEVEL"));
    systemInfo.AppendFormat("SystemDirectory:  {0}\n", Environment.SystemDirectory);
    systemInfo.AppendFormat("ProcessorCount:  {0}\n", Environment.ProcessorCount);
    systemInfo.AppendFormat("UserDomainName:  {0}\n", Environment.UserDomainName);
    systemInfo.AppendFormat("UserName: {0}\n", Environment.UserName);
    //Drives
    systemInfo.AppendFormat("LogicalDrives:\n");
    foreach (System.IO.DriveInfo DriveInfo1 in System.IO.DriveInfo.GetDrives())
    {
        try
        {
            systemInfo.AppendFormat("\t Drive: {0}\n\t\t VolumeLabel: " +
                "{1}\n\t\t DriveType: {2}\n\t\t DriveFormat: {3}\n\t\t " +
                "TotalSize: {4}\n\t\t AvailableFreeSpace: {5}\n",
                DriveInfo1.Name, DriveInfo1.VolumeLabel, DriveInfo1.DriveType,
                DriveInfo1.DriveFormat, DriveInfo1.TotalSize, DriveInfo1.AvailableFreeSpace);
        }
        catch
        {
        }
    }
    systemInfo.AppendFormat("Version:  {0}", Environment.Version);
    Console.WriteLine(systemInfo);
    Console.ReadKey();
}

Output:

Operation System:  Microsoft Windows NT 6.1.7601 Service Pack 1
Processor Architecture:  AMD64
Processor Model:  Intel64 Family 6 Model 42 Stepping 7, GenuineIntel
Processor Level:  6
SystemDirectory:  C:\Windows\system32
ProcessorCount:  2
UserDomainName:  TESTDomain
UserName: Administrator
LogicalDrives:
  Drive: C:\
   VolumeLabel: 
   DriveType: Fixed
   DriveFormat: NTFS
   TotalSize: 43240292352
   AvailableFreeSpace: 10865721344
  Drive: D:\
   VolumeLabel: Local Disk
   DriveType: Fixed
   DriveFormat: NTFS
   TotalSize: 42183159808
   AvailableFreeSpace: 12267360256
  Drive: E:\
   VolumeLabel: VBOXADDITIONS_4.
   DriveType: CDRom
   DriveFormat: CDFS
   TotalSize: 64770048
   AvailableFreeSpace: 0
  Drive: F:\
   VolumeLabel: VBOX_Downloads
   DriveType: Network
   DriveFormat: VBoxSharedFolderFS
   TotalSize: 729626107904
   AvailableFreeSpace: 371810705408
Version:  2.0.50727.5420

Get System Information using WMI class in C#

The below C# function get system information using WMI class. You need to add reference
public static void SystemInformation()
{
    StringBuilder processorInfo = new StringBuilder(string.Empty);
    ManagementClass mgmntClass = new ManagementClass("Win32_OperatingSystem");
    ManagementObjectCollection mgmntObj = mgmntClass.GetInstances();
    PropertyDataCollection properties = mgmntClass.Properties;
    foreach (ManagementObject obj in mgmntObj)
    {
        foreach (PropertyData property in properties)
        {
            try
            {
                processorInfo.AppendLine(property.Name + ":  " +
                    obj.Properties[property.Name].Value.ToString());
            }
            catch
            {
            }
        }
        processorInfo.AppendLine();
    }
    Console.WriteLine(processorInfo);
    Console.ReadKey();
}

Output:

BootDevice:  \Device\HarddiskVolume1
BuildNumber:  7601
BuildType:  Multiprocessor Free
Caption:  Microsoft Windows Server 2008 R2 Enterprise 
CodeSet:  1252
CountryCode:  1
CreationClassName:  Win32_OperatingSystem
CSCreationClassName:  Win32_ComputerSystem
CSDVersion:  Service Pack 1
CSName:  DC1
CurrentTimeZone:  330
DataExecutionPrevention_32BitApplications:  True
DataExecutionPrevention_Available:  True
DataExecutionPrevention_Drivers:  True
DataExecutionPrevention_SupportPolicy:  3
Debug:  False
Description:  
Distributed:  False
EncryptionLevel:  256
ForegroundApplicationBoost:  2
FreePhysicalMemory:  284236
FreeSpaceInPagingFiles:  0
FreeVirtualMemory:  43384
InstallDate:  20140628143731.000000+330
LastBootUpTime:  20150826015035.016594+330
LocalDateTime:  20150827194243.001000+330
Locale:  0409
Manufacturer:  Microsoft Corporation
MaxNumberOfProcesses:  4294967295
MaxProcessMemorySize:  8589934464
MUILanguages:  System.String[]
Name:  Microsoft Windows Server 2008 R2 Enterprise |C:\Windows|\Device\Harddisk0\Partition3
NumberOfLicensedUsers:  0
NumberOfProcesses:  83
NumberOfUsers:  4
OperatingSystemSKU:  10
Organization:  
OSArchitecture:  64-bit
OSLanguage:  1033
OSProductSuite:  274
OSType:  18
Primary:  True
ProductType:  2
RegisteredUser:  Windows User
SerialNumber:  55041-507-1081103-84377
ServicePackMajorVersion:  1
ServicePackMinorVersion:  0
SizeStoredInPagingFiles:  0
Status:  OK
SuiteMask:  274
SystemDevice:  \Device\HarddiskVolume3
SystemDirectory:  C:\Windows\system32
SystemDrive:  C:
TotalVirtualMemorySize:  4093680
TotalVisibleMemorySize:  4095544
Version:  6.1.7601
WindowsDirectory:  C:\Windows
You can also get Processor and Drive information by using the WMI classes Win32_Processor and Win32_LogicalDisk.

Tuesday, 25 August 2015

Remove Full Access Permission using Powershell

We can use the Remove-MailboxPermission cmdlet to remove full access permission from a user's mailbox. To perform this task, your account need to be added in the server roles Organization Management and Recipient Management.

Run the below command to load Exchange cmdlets to use the Remove-MailboxPermission cmdlet.
Add-PSSnapin *Exchange*
The following example removes user Morgan's full access rights from Kevin's mailbox.
Remove-MailboxPermission -Identity "Kevin" -User "Morgan" -AccessRights FullAccess -InheritanceType All
Identity - The name of the user on which the full access permission to be removed.
User - The mailbox that has the full access permission.

Remove Full Access Permission for Bulk Users from Text file:

Use the below powershell script to remove full access permissions for bulk exchange mailbox users from text file. First create the text file Mailboxes.txt which includes one mailbox in each line.
Get-Content C:\Mailboxes.txt | ForEach-Object{
 $mailbox = $_
 Remove-MailboxPermission -Identity $mailbox -User "Admin" -AccessRights FullAccess -InheritanceType All         -Confirm:$Y -WhatIf
}

Remove Full Access Permission for multiple mailbox users:

Use the below powershell command to remove full access permission for multiple exchange mailbox users.
$mailboxes = "TestUser1","TestUser2"
$mailboxes  | ForEach-Object{
 $mailbox = $_
 Remove-MailboxPermission -Identity $mailbox -User "Admin" -AccessRights FullAccess -InheritanceType All         -Confirm:$Y -WhatIf
}

Grant Full Access Permission using Powershell

We can grant full access permission for a exchange mailbox user using the Add-MailboxPermission powershell cmdlet. To perform this task, your account need to be added in the server roles Organization Management and Recipient Management.

Run the below command to load Exchange cmdlets to use the Add-MailboxPermission cmdlet.
Add-PSSnapin *Exchange*
The following example grants "Morgan" full access permission to Kevin’s mailbox.
Add-MailboxPermission -Identity "Kevin" -User "Morgan" -AccessRights FullAccess -InheritanceType All
Identity - The name of the user on which the full access permission should be added.
User - The mailbox that should be granted the permission.

Set Full Access Permission for Bulk Users from Text file:

Use the below powershell script to configure full access permissions for bulk exchange mailbox users from text file. First create the text file Mailboxes.txt which includes one mailbox in each line.
Get-Content C:\Mailboxes.txt | ForEach-Object{
 $mailbox = $_
 Add-MailboxPermission -Identity $mailbox -User "Admin" -AccessRights FullAccess -InheritanceType All
}

Configure Full Access Permission for multiple Mailboxes:

Use the below powershell command to grant full access permission for multiple exchange mailbox users.
$mailboxes = "TestUser1","TestUser2"
$mailboxes  | ForEach-Object{
 $mailbox = $_
  Add-MailboxPermission -Identity $mailbox -User "Admin" -AccessRights FullAccess -InheritanceType All
}

Saturday, 8 August 2015

Set Environment Variable using Powershell Script

We can get, set, modify and remove environment variables using the .NET class [Environment]. The following command list all the environment variables.
[Environment]::GetEnvironmentVariables()
You can also use the below .NET function to return the value of particular environment variable:
[Environment]::GetEnvironmentVariable("Temp","User")
Temp - The name of the environment variable we want to retrieve;
User - The type of environment variable. The User type is an environment variable tied to a user profile. You can also retrieve Machine environment variables by passing the parameter "Machine".

Create/Set Environment Variable:

We can create two kinds of variables, process-level environment variable (temporary) and permanent environment variable.

Process-level Environment variable (temporary):

The process-level environment variable is a temporary variable, its value lasts only as long as your current powershell session alive. Use the below command to create a temporary environment variable.
$Env:TestVariable = "This is a temporary environment variable."

Permanent Environment variable:

To create a permanent environment variable you need to use the .NET method SetEnvironmentVariable . The below command creates a user-level environment variable named TestVariable:
[Environment]::SetEnvironmentVariable("TestVariable", "This is a permanent variable.", "User")
If TestVariable does not exist. powershell will create the new environment variable. If TestVariable already exist, then powershell will update the value "This is a permanent variable." in TestVariable.

Delete/Remove Environment Variables:

We can remove Environment variable if it no longer needed, by using Remove-Item cmdlet.
Remove-Item Env:\TestVariable
You can also remove Environment variable by assigning the variable value as null using SetEnvironmentVariable method:
[Environment]::SetEnvironmentVariable("TestVariable",$null,"User")
But, if you use SetEnvironmentVariable method to remove, the deleted variable might still show up when you call Get-ChildItem, at least until you restart powershell. But the environment variable will no longer exist when you call GetEnvironmentVariables.
[Environment]::GetEnvironmentVariable("TestVariable","User")

Friday, 7 August 2015

Powershell Get Environment variable from Remote machine

We can find and list the environment variables using the .NET class [Environment]. The following command list all the environment variables in local machine.
[Environment]::GetEnvironmentVariables()
We can also list only computer specific environment variables or user specific environment variables by using below commands
[Environment]::GetEnvironmentVariables("Machine")
[Environment]::GetEnvironmentVariables("User")
Instead of listing all the environment variables, we can get the value of specific environment variable by using the function "[Environment]::GetEnvironmentVariable".
[Environment]::GetEnvironmentVariable("ComputerName")

Get Environment variable from Remote machine:

We can get an environment variable from remote machine by running the above commands using Invoke-Command. Before proceed, we should enable powershell remoting to run remote commands. Read this article : How to enable Powershell Remoting

Syntax of remote powershell command:

Invoke-Command -ComputerName $Target -ScriptBlock { $COMMAND } -Credential $USERNAME
$Target - The name of the computer to connect.
$COMMAND - The powershell command to run in remote computer.
$USERNAME - The user account to run the command as on the remote computer. You will be prompted to enter a password for the username. The Credential parameter is optional one.

The following command gets the name of the remote machine.
Invoke-Command -ComputerName "ESVR01" -ScriptBlock {[Environment]::GetEnvironmentVariable(“ComputerName”)}
The below command gets the "Temp" directory path of the remote computer "ESVR01".
Invoke-Command -ComputerName "ESVR01" -ScriptBlock {[Environment]::GetEnvironmentVariable(“Temp”,”Machine”)}
The below command gets the "Temp" directory path for the user "Kevin" in the remote machine "ESVR01".
Invoke-Command -ComputerName "ESVR01" -ScriptBlock {[Environment]::GetEnvironmentVariable(“Temp”,”User”)} -Credential Kevin

Powershell - Get Environment Variables using Get-Childitem

We can get the complete list of environment variables using Get-Childitem cmdlet. The following command list all the local environment variables.
Get-ChildItem Env:
Instead of listing all the environment variables, you can also get the value of specific environment variable by passing the specified variable name.

The below command gets the current computer name.
Get-Childitem Env:computername

Get list of environment variables from Powershell

We can get the list of environment variables using the .NET class [Environment]::. The following command list all the local environment variables.
[Environment]::GetEnvironmentVariables()
You can list machine specific environment variables or user specific environment variables using this function. The below command lists only computer specific environment variables
[Environment]::GetEnvironmentVariables("Machine")
Likewise, the below command lists only user specific environment variables
[Environment]::GetEnvironmentVariables("User")

Find specific (single) environment variable:

Instead of listing all the environment variables, we can use the function "[Environment]::GetEnvironmentVariable" to get the value of specific environment variable.
[Environment]::GetEnvironmentVariable("ComputerName")
The below command gets the current user's "Temp" directory path.
[Environment]::GetEnvironmentVariable("Temp","User")
Likewise, the below command gets the current computer's "Temp" directory path.
[Environment]::GetEnvironmentVariable("Temp","Machine")

Get environment variable from Remote machine:

We can get an environment variable from remote machine by running the above command using Invoke-Command. Before proceed, we should enable powershell remoting to run remote commands. Check this article : How to enable Powershell Remoting

Syntax of remote powershell command:

Invoke-Command -ComputerName $Target -ScriptBlock { $COMMAND } -Credential $USERNAME
$Target - The name of the computer to connect.
$COMMAND - The powershell command to run in remote computer.
$USERNAME - The user account to run the command as on the remote computer. You will be prompted to enter a password for the username. The Credential parameter is optional one.

The following command gets the name of the remote machine.
Invoke-Command -ComputerName "ESVR1" -ScriptBlock {[Environment]::GetEnvironmentVariable(“ComputerName”)}
The below command gets the "Temp" directory path of the remote computer "ESVR1".
Invoke-Command -ComputerName "ESVR1" -ScriptBlock {[Environment]::GetEnvironmentVariable(“Temp”,”Machine”)}
The below command gets the "Temp" directory path for the user "Morgan" in the remote machine "ESVR1".
Invoke-Command -ComputerName "ESVR1" -ScriptBlock {[Environment]::GetEnvironmentVariable(“Temp”,”User”)} -Credential Morgan

Wednesday, 5 August 2015

Remove Send As Permissions using Powershell

We can remove send as permission from a exchange mailbox for a particular Admin user using the Remove-ADPermission powershell cmdlet. To perform this task, your account need to be added in the server roles Organization Management and Recipient Management.

Before proceed, run the following command to enable Exchange cmdlets if you are working with Powershell console instead of Exchange Management Shell.
Add-PSSnapin *Exchange*
Use the following command to remove "Send As Permissions"
Remove-ADPermission -Identity "Kevin" -User "Morgan" -Extendedrights "Send As" -Confirm:$False
Identity - The name of the mailbox on which the Send As permission should be removed.
User - The name of the user object that will have permissions to be removed.

Remove Send As Permission from multiple Mailboxes:

Use the below powershell command to remove Send As permissions from multiple exchange mailbox users.
$mailboxes = "TestUser1","TestUser2"
$mailboxes  | ForEach-Object{
 $mailbox = $_
 Remove-ADPermission -Identity $mailbox -User "Morgan" -Extendedrights "Send As" -Confirm:$False
}

Grant Send As Permission using Powershell

We can grant send as permission for a exchange mailbox using the Add-ADPermission powershell cmdlet. To perform this task, your account need to be added in the server roles Organization Management and Recipient Management.

Run the following command to load Exchange cmdlets to use the Add-ADPermission cmdlet.
Add-PSSnapin *Exchange*
Use the following command to configure "Send As Permissions"
Add-ADPermission -Identity "Kevin" -User "Morgan" -Extendedrights "Send As"
Identity - The name of the mailbox on which the Send As permission should be added.
User - The mailbox that should be granted the permission.

Set Send As Permission for Bulk Mailboxes from Text file:

Use the below powershell script to configure send as permissions for bulk exchange mailbox users from text file. First create the text file Mailboxes.txt which includes one mailbox in each line.
Get-Content C:\Mailboxes.txt | ForEach-Object{
 $mailbox = $_
 Add-ADPermission -Identity $mailbox -User "Morgan" -Extendedrights "Send As"
}

Configure Send As Permission for multiple Mailboxes:

Use the below powershell command to grant send as permission for multiple exchange mailbox users.
$mailboxes = "TestUser1","TestUser2"
$mailboxes  | ForEach-Object{
 $mailbox = $_
 Add-ADPermission -Identity $mailbox -User "Morgan" -Extendedrights "Send As"
}

Monday, 3 August 2015

TokenGroups vs MemberOf

We might come across these attributes when we build applications that require role-based security. In this article, I am just going to list out what are the differences between memberOf and tokenGroups. Both are Active Directory schema attributes that used to retrieve user's group membership in different manner. The memberOf attribute holds only user's direct group membership while as the tokenGroups attribute retrieves direct group membership and nested group memberships.

Memberof Attribute:

  • This is multi-valued back link attribute (computed attribute) that contains the list of distinguished names for groups. 
  • This attribute holds only user's direct group membership and it does not contain the recursive list of nested groups. 
  • Holds both Security groups and Distribution lists. 
  • It does not contain the user's primary group. (we can retrieve this group by using user's primaryGroupID). 
  • As this is a back link attribute (computed attribute), the group object always holds the member attribute (forward link). The memberOf attribute is a calculated from the group member object. The group membership is always managed from the group object side of the relationship and the back link is updated by the system automatically. 
  •  Dot NET Application developers can read both ways, from SearchResult and DirectoryEnrty (using System.DirectoryServices).

TokenGroups Attribute:

  • The tokenGroups attribute is multi-valued constructed attribute that holds the list of security identifiers (SID) for groups.
  • This attribute holds both direct group membership and the recursive list of nested groups.
  • Holds only Security groups and it does not include Distribution lists. 
  • Includes the user's primary group. 
  • As this is constructed attribute, its valued will be calculated only when we read the attribute.
  • Dot NET Application developers can read only through DirectoryEnrty (using System.DirectoryServices) and you need to use RefreshCache in user's DirectoryEntry to get attribute value. .
See the below C# sample code to retrieve nested group memberships.
//----using System.DirectoryServices;
private static List<string> GetNestedGroupMembershipsByTokenGroup(string userDN)
{
    List<string> nestedGroups=new List<string>();
 
    DirectoryEntry userEnrty = new DirectoryEntry("LDAP://" + userDN);
    // Use RefreshCach to get the constructed attribute tokenGroups.
    userEnrty.RefreshCache(new string[] { "tokenGroups" });
 
    foreach (byte[] sid in userEnrty.Properties["tokenGroups"])
    {
        string groupSID = new SecurityIdentifier(sid, 0).ToString();
        DirectoryEntry grpuEnrty = new DirectoryEntry("LDAP://<SID=" + groupSID + ">");
        nestedGroups.Add(grpuEnrty.Properties["samAccountName"][0].ToString());
    }
 
    return nestedGroups;
}

Saturday, 1 August 2015

C#: Get nested group membership for AD user

In .NET C#, we can get the list of AD user group memberships using two methods. In first method, we can get nested groups from the constructed attribute TokenGroups, it requires the dll reference System.DirectoryServices (It is available from .NET Framework 2.0). In second method, we can find and list all the nested groups using UserPrincipal class, it requires the dll reference System.DirectoryServices.AccountManagement (It is available from .NET Framework 3.5).

Get nested group memberships for AD user using TokenGroups:

The following C# function returns all the nested groups for the given user. Since TokenGroups is the constructed attribute, we need to use RefreshCache in user's DirectoryEntry to get attribute value.
//----using System.DirectoryServices;
private static List<string> GetNestedGroupMembershipsByTokenGroup(string userDN)
{
    List<string> nestedGroups=new List<string>();

    DirectoryEntry userEnrty = new DirectoryEntry("LDAP://" + userDN);
    // Use RefreshCach to get the constructed attribute tokenGroups.
    userEnrty.RefreshCache(new string[] { "tokenGroups" });

    foreach (byte[] sid in userEnrty.Properties["tokenGroups"])
    {
        string groupSID = new SecurityIdentifier(sid, 0).ToString();
        DirectoryEntry grpuEnrty = new DirectoryEntry("LDAP://<SID=" + groupSID + ">");
        nestedGroups.Add(grpuEnrty.Properties["samAccountName"][0].ToString());
    }

    return nestedGroups;
}

Get nested group memberships for AD user using UserPrincipal:

The following C# function returns the nested group memberships for the given user using UserPrincipal class.
//----using System.DirectoryServices.AccountManagement;
private static List<string> GetNestedGroupMembershipsByUserPrincipal(string username)
{
    List<string> nestedGroups = new List<string>();

    UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(
                        new PrincipalContext(ContextType.Domain), username);
    foreach (Principal group in userPrincipal.GetGroups())
    {
        nestedGroups.Add(group.SamAccountName);
    }

    return nestedGroups;
}

Friday, 31 July 2015

Difference between single and double quotes in Powershell

You might have come across the question "What are the differences between single and double quotes in Powershell" when you are working with string manipulation. Both quotes are used to delimit string values. In general, you should use single quotes, unless you are required to replace a string variable with concatenation of two string values (string literal and string variable).

If you put double quotes, inside double quotes, powershell looks for the $ character. If it finds it, it assumes that any following characters up to the next white space are a variable name. It replaces the variable reference with the variable’s contents. Consider the following scenario:
$x = "Hello"
$y = "$x World"
The $y variable will now contain "Hello World" because the double quote concatenates the content of the variable $x with remaining string value. In general, use only single quotes if you don't have the above need.

Create Bulk Mailbox Users from CSV using Powershell

We can use the Exchange Powershell cmdlet New-Mailbox to create mailbox AD user.In this article, I am going write powershell script create bulk exchange mailbox users from csv and enable mailboxes for existing AD users.

Before proceed, run the following command to enable Exchange cmdlets if you are working with Powershell console instead of Exchange Management Shell.
Add-PSSnapin *Exchange*
The following command creates the Active Directory user "Tim Brensan" in the TestOU, with a mailbox on the "TestDBStore" database and set the "Change Password at Next Logon" flag as true.
New-Mailbox -UserPrincipalName timbrensan@testdomain.com -Alias 'TimBrensan' -Database 'TestDBStore' -Name TimBrensan –OrganizationalUnit TestOU -Password (ConvertTo-SecureString 'MyP@ssw0rd1' -AsPlainText -Force) -FirstName Tim -LastName Brensan -DisplayName 'Tim Brensan' -ResetPasswordOnNextLogon $True

Create Bulk Exchange Mailbox Users from CSV

1. Consider the CSV file MailboxUsers.csv which contains set of new exchange mailboxes to create with the attributes name, alias, userPrincipalName, database, firstName, lastName, displayName and ParentOU.
Create Bulk Mailbox AD Users from CSV file using Powershell
2. Copy the below Powershell script and paste in Notepad file.
3. Change the MailboxUsers.csv file path with your own csv file path.
4. SaveAs the Notepad file with the extension .ps1 like Create-Bulk-Mailbox-AD-Users.ps1
Import-Csv "C:\Scripts\MailboxUsers.csv" | ForEach-Object {
New-Mailbox -UserPrincipalName $_.'userPrincipalName' -Alias $_.'alias' -Database $_.'database' -Name $_.'name' –OrganizationalUnit $_.'ParentOU' -Password (ConvertTo-SecureString 'MyPassword123' -AsPlainText -Force) -FirstName $_.'firstName' -LastName $_.'lastName' -DisplayName $_.'displayName' -ResetPasswordOnNextLogon $True }
5. Now run the file Create-Bulk-Mailbox-AD-Users.ps1 in powershell to create bulk Active Directory users and Mailboxes from CSV file.

Create Bulk Mailboxes for existing AD Users

1. Consider the CSV file ADUsers.CSV which contains set of existing AD users that we want to enable mailbox with the attributes name, alias and database.
Create Mailbox for Bulk AD Users from CSV using Powershell
2. Copy the below Powershell script and paste in Notepad file.
3. Change the ADUsers.CSV file path with your own csv file path.
4. SaveAs the Notepad file with the extension .ps1 like Create-Mailbox-for-Bulk-AD-Users.ps1
Import-Csv "C:\Scripts\ADUsers.csv" | ForEach-Object {
Enable-Mailbox -Identity:$_.'name' -Alias:$_.'alias' -Database:$_.'database'
}
5. Now run the file Create-Mailbox-for-Bulk-AD-Users.ps1 in Powershell to create Bulk Active Directory users and Mailboxes from CSV file.

Thursday, 30 July 2015

How to get Remote Desktop Sessions (RDP) using Powershell

In Powershell, we can get a list of remote desktop sessions (rdp) using the commands QWinsta and Query.

List Remote Desktop Sessions using QWinsta:

QWinsta /server:[Server name or IP]
Replace the parameter [Server name or IP] with the name or IP address of the remote machine.
QWinsta /server:210.168.1.54

Get Remote Desktop Sessions using Query:

Query user /server:[Server name or IP]
Replace the parameter [Server name or IP] with the name or IP address of the remote computer.
Query user /server:210.168.1.54
You can use the below powershell command to get clear output.
(Query user /server:210.168.1.54) -replace '\s{2,}', ',' | ConvertFrom-Csv
The following command exports the output to CSV file.
(Query user /server:210.168.1.54) -replace '\s{2,}', ',' | ConvertFrom-Csv |
Export-CSV "C:\\RDPSessions.csv" -NoTypeInformation -Encoding UTF8