When you demoting a domain controller, you receive the “Failed to modify the necessary properties for the machine account. Access is denied” error message

Are you getting this error message when demoting a domain controller?

“The operation failed because: The Active Directory Domain Services Installation Wizard (DCpromo.exe) would not configure the computer account <2012 DC> on the remote Active Directory Domain Controller <2019 DC>. Verify that the user running dcpromo.exe is granted the “Enable computer and user accounts to be trusted for delegation” user right in the Default Domain Controllers Policy. The error was: Access is denied”

If you didn’t enable the GPO setting for “Enable computer and user accounts to be trusted for delegation”, by all means enable it and then run GPUpdate /force command on the domain controller before demoting the DC.

If the GPO setting is already enabled, AD replication is done, GPUpdate.exe updated the setting on the domain controllers and you see the setting enabled in RSOP.exe results. BUT you still getting the same freaking error again. What do you do now?

In my case, computer account for Domain Controller is enabled with the setting “Protect object from accidental deletion“. I disabled this check box, then demotion went without errors.

See the source image

Active Directory: Self-Signed certificate for LDAPs

While testing Active Directory on a closed private network, I needed LDAPs connections to the domain controllers. But I didn’t have any PKI/Certificate servers on the network and I didn’t want to build one.

So I decided to use a self-signed SSL certificate for LDAPs connections. If you reading this, you need one too. Here is how I did it.

  • Logon to the Domain Controller
  • Open PowerShell in elevated mode (Right-click on PowerShell, choose Run as Administrator)
  • Next Run the New-SelfSignedCetificate cmdlet. NOTE: Replace the DnsName to your server’s FQDN name and NetBIOS name.
New-SelfSignedCertificate -DnsName SanFran-DC01.company.com, sanfran-dc01 -CertStoreLocation cert:\LocalMachine\My 
  • This cmdlet will create a self-signed cert with given DNSName and place it at Local Computer certificate store.
  • Last step: Open Certificate console by click Start button & type Manage Computer Certificates and open it from the search results.
  • Expand Personal >> Certificates and also expand Trusted Root Certificates >> Certificates
  • Find the newly generated Self-Signed SSL Certificate in Personal >> Certificates.
  • Select the Self-Signed Certificate and drag & drop to Trusted Room Certificates >> Certificates to trust the certificate on the domain controller.
  • Close the Certificate console

Now you are ready to do LDAPs to this domain controller. If you want to validate it works, you can use LDP.exe tool.

  • Open LDP.exe on the domain controller (or any other computer on the network)
  • Click Connection menu and choose Connect…
  • Type the domain controller FDQN and Port number as 636 and click OK. You should see “Established connection to <domain controller>” and the Base DN details.

Did this blog help you? Leave me a reply!

Microsoft Teams: Direct link to start a chat with you

Do you use Microsoft Teams? Here is the direct Teams chat link to start a chat with you. I add this link to my Email signature. You can too.

https://teams.microsoft.com/l/chat/0/0?users= <Your-Email-Address>

e.g., https://teams.microsoft.com/l/chat/0/0?users=AwesomeAnand@USA.com

If you need the link for your Teams Channel, you can get it by right-clicking on the Teams Channel, like this:

PowerShell: Find if a computer is waiting for Reboot (pending reboot)

To find a computer is waiting for reboot to complete the Microsoft Update installation, I have found this information in Windows Update WMI object. This displays True (if Pending Reboot),or False (Not waiting for reboot).

-ComObject Microsoft.Update.SystemInfo).RebootRequired

But this only runs on the local computer. I needed to collect Pending Reboot state of all of our servers. That’s when I found this Gem – PowerShell Module – written by Brian Wilhite at Here.

It’s perfect. First you need to install this module on your local computer. Run this command on a elevated PowerShell (Run-As Administrator).

Install-Module -Name PendingReboot

You can close the elevated PowerShell. Use this module on your script to find Pending Reboot state and why it needs reboot.

Here is the example how it works:

PS E:\> Import-Module PendingReboot
PS E:> Test-PendingReboot -ComputerName SFOExch01 -Detailed -SkipConfigurationManagerClientCheck
ComputerName : SFOExch01
ComponentBasedServicing : False
PendingComputerRenameDomainJoin : False
PendingFileRenameOperations : True
PendingFileRenameOperationsValue : {\??\C:\Program Files\Common Files\Microsoft Shared\ClickToRun\ApiClient.dll.bak, , \??\C:\Program Files\Common Files\Microsoft
Shared\ClickToRun\C2RINTL.en-us.dll.bak, …}
SystemCenterConfigManager :
WindowsUpdateAutoUpdate : False
IsRebootPending : True

(Ver 2) PowerShell: Create Unique Log File Name out of Date & Time

I have blogged to create a log file name in PowerShell, so we can create unique readable file names to store data or logs: https://anandthearchitect.com/2019/06/13/powershell-create-a-unique-log-file-name-out-of-date-time/

Now I have an better idea of generating file name with slightly different idea (since I found out GetDateTimeFormats() function in returned object from Get-Date cmdlet).

Here is the function that returns the valid date time format to form a log file name:

Function Date_Time {
Return ((Get-Date).GetDateTimeFormats())[44].Replace('/','-').Replace(' ','_').Replace(':','-')

Here is how you use the function:

PS E:> "Customer-Data-" + (Date_Time) + ".csv"

You may have your own date format in the file name. To find out the list of available date/time display formats, run this command:

$i=0 ;  (Get-Date).GetDateTimeFormats() | % { Write-Host $i $_  ; ++$i}

It list the all the formats with the item number (see below). Find the display format you want, note down the item/index number & use it with the above function.

PS E:> $i=0 ;  (Get-Date).GetDateTimeFormats() | % { Write-Host $i $_  ; ++$i}

0 8/29/2019
1 8/29/19
2 08/29/19
3 08/29/2019
4 19/08/29
5 2019-08-29
6 29-Aug-19
7 Thursday, August 29, 2019
8 August 29, 2019
9 Thursday, 29 August, 2019
10 29 August, 2019
11 Thursday, August 29, 2019 7:59 PM
12 Thursday, August 29, 2019 07:59 PM
13 Thursday, August 29, 2019 19:59
14 Thursday, August 29, 2019 19:59
15 August 29, 2019 7:59 PM
16 August 29, 2019 07:59 PM
17 August 29, 2019 19:59
18 August 29, 2019 19:59
19 Thursday, 29 August, 2019 7:59 PM
20 Thursday, 29 August, 2019 07:59 PM
21 Thursday, 29 August, 2019 19:59
22 Thursday, 29 August, 2019 19:59
23 29 August, 2019 7:59 PM
24 29 August, 2019 07:59 PM
25 29 August, 2019 19:59
26 29 August, 2019 19:59
27 Thursday, August 29, 2019 7:59:36 PM
28 Thursday, August 29, 2019 07:59:36 PM
29 Thursday, August 29, 2019 19:59:36
30 Thursday, August 29, 2019 19:59:36
31 August 29, 2019 7:59:36 PM
32 August 29, 2019 07:59:36 PM
33 August 29, 2019 19:59:36
34 August 29, 2019 19:59:36
35 Thursday, 29 August, 2019 7:59:36 PM
36 Thursday, 29 August, 2019 07:59:36 PM
37 Thursday, 29 August, 2019 19:59:36
38 Thursday, 29 August, 2019 19:59:36
39 29 August, 2019 7:59:36 PM
40 29 August, 2019 07:59:36 PM
41 29 August, 2019 19:59:36
42 29 August, 2019 19:59:36
43 8/29/2019 7:59 PM
44 8/29/2019 07:59 PM
45 8/29/2019 19:59

Exchange: How to list memberOf groups of a distribution group?

When I wrote a script to migrate distribution groups to Office 365 from On-Prem Exchange server, I had a requirement to list the parent (memberOf) groups. So I can migrate them in order or do not lose the group memberships during migration.

So how do we list the parent groups of a DL? There are different methods to get the memberOf groups for on-premises or Office 365 environment.


I am using AD cmdlets, because they are very easy use. This command will display the parent (memberof) groups of their Email:

Get-ADGroup <Group Name> -Properties memberOf | Select-Object memberOf | Where-Object { $dn =[string] $_.memberOf ; Get-ADObject $dn -Properties mail | Select-Object mail}

Office 365/Exchange Online

I end up using Exchange Online cmdlets in Exchange online. It may be little slower then On-Prem command. Idea is run Get-Group command with a filter if the group show up in any group’s members. This will list the memberOf groups (of them email address).

$GroupDN = (Get-Group ).distinguishedName
$filter = "Members -eq '$GroupDN'"
(Get-Group -Filter $filter).WindowsEmailAddress

Office 365: How to correct UserPrincipalName for On-premises AD sync’ed account?

Say you end up with a wrong UserPrincipalName for an MSOL account which is sync’ed from On-Prem Active Directory like this: username@company.onmicrosoft.com, Which is obviously wrong UPN. The correct UPN supposed to be like username@company.com and it should match the user’s PrimarySMTPAddress.

I am sure you tried to correct it in Office 365 Admin Center, where UPN is grayed out. You may have tried MSOL PowerShell command Set-MSOLUser which does not have the parameter -UserPrincipalName. Right? That why you are here.

Solution: Easy Peacy. You have to use the another MSOL PowerShell command like this:

-UserPrincipalName username4892@company.onmicrosoft.com -NewUserPrincipalName username@company.com 

That’s it. You have done it. Have an coffee! You deserve it! 🙂

Active Directory: Send password expiry Email notice to users

Here is very useful script written by me. Feel free to use on your network.

This script queries the local Active Directory for users whose password is expiring in given number of days, then send email notice to the user.

Download the PowerShell Script

The source code:

    ** Script: Email-PasswordExpiry-Notice.ps1                                                      **
    ** Purpose: Send Email Notice to users before their AD passwrod expires                         **
    ** Note: Make sure to provide your own values with the comment "$# <--- "" in this script       **
    **                                                                                              **
    ** Written by: Anand, the Awesome, Venkatachalapathy                                            **

$DaysBeforeExpiry = 5 # <--- Change your own number of days before password expiry (to start SPAMing users)

# Query AD for users whose password is expiring close to $DaysBeforeExpiry days
$users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} –Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed","mail"  `
| Where-Object {$_.mail -ne $null } `
| Select-Object -Property "Displayname",@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}},"Mail","SamAccountName" `
| Where-Object {$_.ExpiryDate -lt (Get-Date).AddDays($DaysBeforeExpiry) -and $_.ExpiryDate -gt (Get-Date) } 

#Send Email to the users from the above query results
$from = "IT-Town-Crier@company.com"  # <--- Change your own From Email address
$smtpserver = "smtp.compnay.com"     # <--- Type your local SMTP server

foreach($user in $users)
    $expirydays = (([DateTime]$user.ExpiryDate) - (get-date)).Days
    $to = $user.mail
    $username = $user.SamAccountName
    $domainname = env:USERDOMAIN
    $subject = "Your Password Will Expire in $expirydays Days"

    $body = @"
Your Active Directory account ($domainname\$username) Password Will Expire in $expirydays Days. 

Change your password when possible. On Windows computer, press Control-Alt-Delete & choose change password. 

--Your Friendly Neighbourhood IT 
    '*' * 80
    Send-MailMessage -Body $body -From $from -SmtpServer $smtpserver -Priority High -Subject $subject -To $to 


    ***************** The End of the Script *****************

Active Directory – PowerShell – Cannot search by null value attributes

If you tried to filter results with any AD cmdlets in PowerShell, you quickly finds out it is not possible with “-Filter” option. For example, I tried to list any user with no Mail attribute value is null:

PS E:> Get-ADUser -Filter { mail -ne $null }
 Get-ADUser : Variable: 'null' found in expression: $null is not defined.
 At line:1 char:1
+ Get-ADUser -Filter { mail -ne $null }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       + CategoryInfo : InvalidArgument: (:) [Get-ADUser], ArgumentException
       + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.GetADUser 

Well, the solution is to use -LDAPFilter instead of -Filter option. Here is the working command:

PS E:> Get-ADUser -LDAPFilter '(!mail=*)' -ResultSetSize 5 -Properties mail | Select-Object Name,Mail
 Name          Mail
 ----          ----
 Josh Doe         

So the trick is ‘(mail=*)’ filter brings all user accounts with mail account has any value. Adding [NOT] operator in front of mail ‘(!mail=*)’ in the LDAPFilter results with all user accounts with mail attribute is empty.

So use the filter string with any AD property to search like this: -LDAPFilter ‘(!mail=*)’

Active Directory: Password Expiry date Report for all accounts

I had a requirement to generate password expiry date report for all accounts to validate a password policy change. Here is what I came up with (who know someone have same need for this report).

Important point is the calculated property msDS-UserPasswordExpiryTimeComputed. Which is in Long Date format.

It will create an CSV file on the same directory on where the script runs.

Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False}  –Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed"
 | Select-Object -Property "Displayname",@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} `
 | Export-Csv -path .\Password-Expiry-Report.csv -NoTypeInformation

Here is the same report:

“Tim Dangthatsme”,”8/23/2019 9:23:10 AM”
“Don Anonymous”,”7/31/2014 3:17:20 AM”
“Robert Dome”,”12/17/2019 8:14:17 AM”
“Introvert Hopkins”,”9/6/2019 10:57:07 AM”