Category Archives: Powershell Scripts

Powershell tricks, tips and complete scripts. These can be an entire script or a small tidbit I had trouble getting to work.

Exchange 2013 – Anonymous relay requires one more step

Here is something I have gotten bit by and would like to save others from the same problem.

I recently migrated from Exchange 2010 SP3 to Exchange 2013.

I went through settings on the old system including Receive Connectors. We always had one called Anonymous Relay for copiers that do scan to email. We also have some standalone systems that need to relay.

It turns out that just setting a receive connector in the Admin center in 2013 isn’t enough.

You also need to issue a command in the CLI. (In 2010, based on technet, the CLI method is an alternative.) In 2013, the CLI is a compliment to the other part. By checking the Anonymous box in the admin center, some permissions are added but not all of them.

Here is the command to use in the CLI and note, if you only have one server, you may not need to specify:

Get-ReceiveConnector “Servername\Receive Connector Name” | Add-ADPermission -User “NT AUTHORITY\ANONYMOUS LOGON” -ExtendedRights “Ms-Exch-SMTP-Accept-Any-Recipient”

Hope this saves someone a lot of grief and headaches.

How to export email addresses of distribution list members in powershell

This is a quick one-liner I had to figure out to respond to a request to have the actual email addresses of all members in a distribution list. To complicate it further, I always use nested groups.
I wasn’t having much luck doing it via exchange powershell but I did find a way to run it in powershell on one of our DC’s.
The first step is to load ActiveDirectory in your powershell session
Import-Module ActiveDirectory
this line will get members of group_name and recursively go through any other groups that are members. It will then output only the user email. You can always add more fields to select-object if needed.
get-adgroupmember group_name -recursive | get-aduser -properties mail | select-object mail
Output:
mail
——-

Restoring a deleted AD object and avoiding a common error

I accidentally removed some accounts in a non-production domain. I was trying to do a restore using ldp.exe. That wasn’t working well and I came across powershell commands.

I tried the commonly found command everyone has posted:

Get-ADObject -Filter {samaccountname -eq “jsmith”} -IncludeDeletedObjects | Restore-ADObject

and got this error:

Restore-ADObject : Illegal modify operation. Some aspect of the modification is
 not permitted

I tried another version which was more detailed.

Get-ADObject -filter ‘samaccountname -eq “jsmith”‘ -IncludeDeletedObjects | Foreach-Object {Restore-ADObject $_.DistinguishedName -NewName _.Name -TargetPath $_.LastKnownParent}

The idea from reading was that you needed to specify the NewName and the TargetPath. It failed with a different error:

Restore-ADObject : Cannot validate argument on parameter ‘TargetPath’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

To understand why, we need to look at what information we are actually giving it. The command below will list what is standard output

Get-ADObject -Filter {samaccountname -eq “jsmith”} -IncludeDeletedObjects

Deleted : True
DistinguishedName : CN=jsmih\0ADEL:1ead7f6c-ec52-3450-a847-b1307e0e8e23,CN=Deleted Objects,DC=DOMAIN,DC=loc
Name : jsmith
DEL:1ead7f6c-ec52-3450-a847-b1307e0e8e23
ObjectClass : user
ObjectGUID : 1ead7f6c-ec52-3450-a847-b1307e0e8e23

This command will return all properties and explain what is going wrong when you look closely.

Get-ADObject -Filter {samaccountname -eq “jsmith”} -IncludeDeletedObjects -Properties *

CanonicalName : DOMAIN.loc/Deleted Objects/jsmith DEL:1aed7e6c-ab52-4305-a397-b1307e0e8e23

CN : jsmith
DEL:1ead7f6c-ec52-3450-a847-b1307e0e8e23
Created : 2014-10-06 12:34:25 PM
createTimeStamp : 2014-10-06 12:34:25 PM
Deleted : True
Description :
DisplayName :
DistinguishedName : CN=jsmith\0ADEL:1ead7f6c-ec52-3450-a847-b1307e0e8e23,CN=Deleted
Objects,DC=DOMAIN,DC=loc
instanceType : 4
isDeleted : True
isRecycled : True
LastKnownParent : Users,DC=DOMAIN,DC=loc
Modified : 2014-10-07 12:35:01 PM
modifyTimeStamp : 2014-10-07 12:35:01 PM
Name : jsmith
DEL:1ead7f6c-ec52-3450-a847-b1307e0e8e23
nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity
ObjectCategory :
ObjectClass : user
ObjectGUID : 1ead7f6c-ec52-3450-a847-b1307e0e8e23
objectSid : S-1-5-21-18311500-3280029727-3500224-5374
ProtectedFromAccidentalDeletion : False
sAMAccountName : jsmith
sDRightsEffective : 15
userAccountControl : 514
uSNChanged : 84182
uSNCreated : 83954
whenChanged : 2014-10-07 12:35:01 PM
whenCreated : 2014-10-06 12:34:25 PM

I noticed I was able to restore an object when I used this command after I got the information I needed from above. (Note: NewName is for sAMAccountName)

restore-adobject -identity “1ead7f6c-ec52-3450-a847-b1307e0e8e23” -NewName “jsmith” -targetpath “OU=Users,DC=DOMAIN,DC=loc”

Above I tried using the information in $_.name. It sounds right until you look at what $_.name contains. It has the objectguid we need but it also includes extras and the most important extra is a colon (:) which is an illegal character for sAMAccountName.

Name : jsmith
DEL:1ead7f6c-ec52-3450-a847-b1307e0e8e23

Knowing this and looking over what the information of what is available, I created this command which provides proper values and actually does work:

Get-ADObject -filter ‘samaccountname -eq “jsmith”‘ -IncludeDeletedObjects -properties * | Foreach-Object {Restore-ADObject $_.objectguid -NewName $_.samaccountname -TargetPath $_.LastKnownParent}

Please note -NewName now instead is given $_.samaccountname

The first item after Restore-ADObject can be either one of these:

$_.objectGUID
$_.distinguishedname

The AD object is restored. There is still a lot of work to do as it no longer has any groups and some of the information on the account tab needs to be filled it. If I find any way to add these, I will edit the post.

Powershell script to move renamed computers

In my environment, I have specific policies related to each site. (I should note for server admin’s that by site I mean an OU related to a location and not Sites and Services).

All computers are named based on a 4 letter code that designates a site. I noticed that if a tech renames a computer for a different site, it will just sit in the old location with a mismatched name.  (Re-imaging would of course not be an issue as it would be a new object and SID).

For new computers, I have a script that runs on a regular basis to re-locate them based on name.

I created a script that will find and move misnamed computers to my new computer OU for processing.

Below is my script. I run this via task scheduler through a batch file. I believe I already posted how on here.

Import-Module ActiveDirectory
$schoolinfo = import-csv “C:\Scripts\SchoolInfo.csv”

#loop through each site

foreach ($si in $schoolinfo) {

$shortname = $si.shortname

#debug line
Write-Host $shortname

$searchroot = “domain.loc/sites/$shortname”
#debug line
Write-Host $searchroot

#$command = “Get-ADComputer -LDAPFilter ” + [char]34 + “(!(name=” + $shortname + “*))” + [char]34 + ” -SearchBase ” + [char]34 + “OU=$searchroot,OU=Sites,DC=domain,DC=loc” + “| Move-ADObject -TargetPath ‘OU=_New_Computers,OU=Sites,DC=domain,DC=loc'”
$command = “Get-ADComputer -LDAPFilter ” + [char]34 + “(!(name=” + $shortname + “*))” + [char]34 + ” -SearchBase ” + [char]34 + “OU=$shortname,OU=Sites,DC=domain,DC=loc” + [char]34 + ” | Move-ADObject -TargetPath ‘OU=_New_Computers,OU=Sites,DC=domain,DC=loc'”
# Get-ADComputer -LDAPFilter “(!(name=”& $searchroot & “*))” & [char]34 -SearchBase “OU=$searchroot,OU=Sites,DC=domain,DC=loc” | Move-ADObject -TargetPath ‘OU=_New_Computers,OU=Sites,DC=domain,DC=loc’

#debug line
Write-Host $command

Invoke-Expression -command $command
#search for computers in this site that don’t match the start and move to _New_Computers
# Get-ADComputer -LDAPFilter “(!(name=”& $searchroot & “*))” & [char]34 -SearchBase “OU=$searchroot,OU=Sites,DC=domain,DC=loc” | Move-ADObject -TargetPath ‘OU=_New_Computers,OU=Sites,DC=domain,DC=loc’

} #foreach ($si in $schoolinfo) {

How to schedule a PowerShell script

Here is how I schedule PowerShell scripts to run via task scheduler.I routinely like to update account info to match the OU they are in. This is just to save some work when we move users. 

Before you schedule any scripts, I’d advise testing the .bat file from a commmand line so you can confirm it’s working fine.

You will most likely need to change the execution policy in powershell

Set-ExecutionPolicy RemoteSigned

The above will require scripts downloaded from the internet be signed but should be fine for your own.

You can pick unrestricted as an option but this is risky.

 

Here is the line I put in a batch file to run my scripts from task scheduler.

C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe -nologo -command “& {C:\Scripts\UserAccountManagement\UpdateUserInfo\UpdateUserInfo.ps1}”