Category Archives: Scripting and Programming

Solutions related to scripting and programming. This is usually a higher level category unless the post includes a mixed fix.

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
——-

DFSR Cleanup Script

I am a big fan of using DFSR to replicate various types of data.

One example is to use it to replicate my Windows Deployment Service (WDS) Images to other sites. (There are some caveats to it but that is another post.)

Now and then my replication seems to be broken. Most often it is due to lack of space as indicated when you run a health report or check eventvwr.

Often, this is due to large files in the DFSRprivate folder. DFS uses various stages in it’s replication. Files now and then seem to get stuck or orphaned for whatever reason.

I have had to do a forced copy of my main imaging site to correct the issue. Usually a copy fails until I can free up some space.

Going through the folders is a lengthy process.  I created a script that will do it for me. My sample script is designed for WDS on D: but it easy to modify.

As with any of my scripts, please be sure you understand what you are using it for.

<start of dfsrclean.bat>

net stop dfs
net stop dfsr

D:

cd “\RemoteInstall\DFSRPrivate”

REM create list of folders

dir /b /ad > dfslist.txt
for /F %%A IN (D:\RemoteInstall\DFSRPrivate\dfslist.txt) DO (

echo %%A
net share dfstemp=”D:\RemoteInstall\DFSRPrivate\%%A” /grant:Everyone,Full

rmdir \\localhost\dfstemp /s /q

Rem mkdir PreExisting in case removed
mkdir “D:\RemoteInstall\DFSRPrivate\%%A\PreExisting”

net share dfstemp /delete /y

)

REM cleanup dfslist.txt
del /q “D:\RemoteInstall\DFSRPrivate\dfslist.txt”
net start dfs
net start dfsr

c:

<end of dfsrclean.bat>

You can download it here: dfsrclean (rename to .bat)

Poor Man’s Virtual Machine Backup with PowerCLI (Updated)

This post is based on this wonderful script I found by Hugo Peeters of the Netherlands. His original script available here fit exactly what I was looking for. I already had “in-guest” VM-Backups. We did have a solution that would do virtual machines but it caused us nothing but grief.

I thought if I could just find a way to copy the  .vmx files, I could do a restore at our DR site from backup. I searched online and finally found Peeters’ script.

I tried it out but I ran into errors. I’m not sure what version of PowerCli his script was based on but it no longer worked with the latest one available.

New-PSDrive : Cannot bind parameter ‘Datastore’ to the target. Exception setting “Datastore”: “Invalid location type. Location accepts only VIDatastore objects.”

This failing command was stored as a function in a powercli in one of it’s library files.
New-DatastoreDrive was the function that was failing. It was calling New-PSDrive. Something about how it was being called it no longer liked. I found a working version.

Note: Prep work

As noted in the script, you can store your .vmx files in a subfolder. You have to use the same subfolder name in Windows and on your datastore. The one on your datastore will have to be manually created (for now.)

Scheduling

I actually run this as a scheduled task through a .bat file via task scheduler.
Here is what I put in my batch file:

C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe -PSConsoleFile “C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\vim.psc1″ ” &  “C:\Scripts\Backup-VMXFileRemote\Backup-VMXFilesRemote.ps1”

Restore

The restore process is a bit interesting (at either your main site or your backup site.)

  1. Create a new folder on your datastore with the name of your vm
  2. Copy your VM’s .vmx file into that folder
  3. Right-click and add .vmx to Inventory
  4. Update your nic to match the VM network if its not the same
  5. I have no .vmdk’s when I do this. I have to delete the hardrive’s from the config.
  6. Open the vmconfig.csv file that is stored with the .vmx copies. This will give you the size of HD(s) you will need.
  7. Create new hardrives in order of what is listed in the vmconfig.csv file
  8. Boot your vm with your restore media.

Download the updated script here (and rename it to .ps1): Backup-VMXFilesRemote

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.