Improve and correct a Powershell script for Migration

Hi, I need to verify that the attached script would work, it is a straightforward script and the exchange portion executes succesfully.
However I would appreciate a powerscript scripter to look over the code and improve the efficiency and add any additional error checking.
This script calls an external vbscipt at one point - this is simply to migrate the ExchMailboxGUID attribute (so the mailbox can be migrated!) - if this can be done in Powershelll then great but so far adding in the Octet string succesfully vis PS is proving troublesome

This script block uses an input csv and all actions need to be completed on each user in the csv.
There is one portion where a user migrated into the target AD needs to be added into a new SAP group in the target AD. This group has the same name as the old group except it is suffixed with the name of the domain.
There are 10 such groups in source that are migrated to target, what I need to do is understand which of the 10 groups the user is a member then ADD that user to the new group that has the 'same name + targetDomain' name.

Hope someone can help, my current script is attached as a txt file.

Thanks.
migrate-script.txt
hasanzehnAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Chris DentPowerShell DeveloperCommented:

It's difficult to do.

There are a number of typographical errors in there, as well as undefined variables, such as $Mailbox and $SrcUser.

That said, you won't see a great deal of improvement, I would have used "ForEach-Object" more than "ForEach ($user in ..." but it's how I prefer to use PS more than need.

You still need to deal with this bit?

> # Need method to match existing SAP group (user is in only 1 of 10 groups) membership and then add
> user to corresponding new group in target AD (10 lots of if memberof add to, else etc??)

Otherwise is everything else working?

Chris
0
hasanzehnAuthor Commented:
Thanks Chris, here's my 'cleaner' script, the csv has the headers username,targetDB

I only need help with 2 bits

1\ In the section # Set target.com as primary SMTP - I'm trying to demote the current primary SMTP and elevate the '@target.com' to become the primary SMTP. With this being Exchange 2003 it is a headache.

2\ Also the adding to group is stil needed. Basically the source user is a member of 1 of 10 groups. Both the users and groups are migrated to target domain. We've created 10 new groups in the target domain that match these groups by name except the suffix is '-target'. I need to check which group the user is currently member of, and drop same user into equivalent new group. E.G the old group name is ABC-HRTeam-SourceDomainNetbios and the new group name is ABC-HRTeam-TargetDomainNetbios. Just to be clear the existing groups ARE migrated to target and synchornised automatically!

Cheers, Hasan
#Mailbox migration script

#March 2010

#Set logfile location and filename
$LogFilePath = “D:\MigrationLog.txt”

#Set source CSV location and filename
$SourceFile = “D:\MigrationList.csv”



#Mail enable users

Import-CSV $sourcefile | ForEach-Object {
$username = $_.username
$externalmail = $_.externalmail

enable -mailuser $username -externalemailaddress $externalmail

}

#Migrate Exchange Atrributes

cscript.exe copyattributes.vbs $SourceFile
Write-Host "Press any key ONLY when the batch file has completed ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

#Migrate Mailboxes

Import-CSV $sourcefile | ForEach-Object {
$username = $_.username
$targetDB = $_.targetdatabase
$error.clear()

$logmessage = “Moving Mailbox -> ” + $username
Add-Content $LogFilePath $message

New-MoveRequest -identity $username -remotelegacy -remoteglobalcatalog "source.com" -targetdatabase $targetDB -baditemlimit -1 -targetdeliverydomain target.local -RemoteCredential $cr

#Sucessfull move action

if ($error.count -eq 0){
$logmessage = “Moved User Mailbox  ” + $username + ” Sucessfully”
Add-Content $LogFilePath $message
}

else

#Failed move action

{$logmessage = “Moved User Mailbox ” + $username + ” FAILED”
Add-Content $LogFilePath $message}
}

# Connect to SOURCE

Connect-QADService source.com

# $Sourcefile = "c:\migrationlist.csv"

# Remove source.local from ProxyAdresses

Import-CSV $sourcefile | ForEach-Object {
Get-QADUser $_.username -SizeLimit 0 -DontUseDefaultIncludedProperties -IncludedProperties ProxyAddresses | Foreach-Object {
$pa = $_.ProxyAddresses  -inotmatch '@source.local'
 Set-QADUSer $_ -ObjectAttributes @{ProxyAddresses=$pa}
} 
}



# Change samaccountname and upn to suffix with '_source'

Import-CSV $sourcefile | ForEach-Object {
Get-QADUser $_.username –IncludedProperties samAccountName,userPrincipalName | Foreach-Object {
$sam = $_.samaccountname
 Set-QADUser $_ -ObjectAttributes @{userPrincipalName=$sam+"_sportex@sportex.com";samAccountName=$sam+"_source"}
}
}


# Set target.com as primary SMTP

Import-CSV $sourcefile | ForEach-Object {
Get-QADUser $_.username -SizeLimit 0 -DontUseDefaultIncludedProperties -IncludedProperties ProxyAddresses | Foreach-Object {
 $primarySMTP = $_.ProxyAddresses -imatch 'target.com'
} 
$primarySMTP.substring(5,$primarySMTP.length - 5)
}

# Cleanly disconnect from SOURCE Domain

Disconnect-QADService


#Connect to TARGET Domain
Connect-QADService target.com

# Add migrated user to new SAP group

Import-CSV $sourcefile | ForEach-Object {
Get-QADGroup $_.username -IncludedProperties groupname |# need more code here!


# Cleanly disconnect from TARGET Domain
Disconnect-QADService

Open in new window

0
Chris DentPowerShell DeveloperCommented:

While I'm looking at that, and out of interest, what does CopyAttributes actually do for you?

Chris
0
Introducing the "443 Security Simplified" Podcast

This new podcast puts you inside the minds of leading white-hat hackers and security researchers. Hosts Marc Laliberte and Corey Nachreiner turn complex security concepts into easily understood and actionable insights on the latest cyber security headlines and trends.

Chris DentPowerShell DeveloperCommented:

Obviously this will need properly testing (because I haven't done that), but here you go.

Chris
#Mailbox migration script

#March 2010

#Set logfile location and filename
$LogFilePath = “D:\MigrationLog.txt”

#Set source CSV location and filename
$SourceFile = “D:\MigrationList.csv”

$Users = Import-CSV $SourceFile

#Mail enable users

$Users | %{ Enable -MailUser $($_.Username) -ExternalEmailAddress $($_.ExternalMail) }

#Migrate Exchange Atrributes

cscript.exe copyattributes.vbs $SourceFile
Write-Host "Press any key ONLY when the batch file has completed ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

#Migrate Mailboxes

$Users | %{
  $Error.Clear()

  "Moving Mailbox -> $($_.Username)" >> $LogFilePath

  New-MoveRequest $($_.Username) -RemoteLegacy -RemoteGlobalCatalog "source.com" `
    -TargetDatabase $($_.TargetDatabase) -BadItemLimit -1 -TargetDeliveryDomain target.local -RemoteCredential $cr

  if ($Error.Count -eq 0) {
    #Sucessfull move action
    "Moved User Mailbox $($_.Username) Sucessfully" >> $LogFilePath
  } else {
    #Failed move action
    "Moved User Mailbox $($_.Username) FAILED" >> $LogFilePath
  }
}

# Connect to SOURCE

Connect-QADService source.com

# $Sourcefile = "c:\migrationlist.csv"

$Users | %{
  Get-QADUser $_.Username -IncludedProperties ProxyAddresses | %{ 

    # Drop source.local addresses
    $PA = $_.ProxyAddresses -NotMatch '@source.local'
    # Change the primary address
    For ($i = 0; $i -lt $PA.Count; $i++)
    {
      If ($PA[$i] -Match "target.com")
      {
        $PA[$i] -CReplace "smtp:", "SMTP:"
      }
      Else
      {
        $PA[$i] -CReplace "SMTP:", "smtp:"
      }
    }

    # Apply addresses and change samaccountname and upn to suffix with '_source'
    Set-QADUser $_ -ObjectAttributes @{ ProxyAddresses=$PA } `
      -UserPrincipalName "$($_.SamAccountName)_sportex@sportex.com" -SamAccountName "$($_.SamAccountName)_source"
  }
}

# Cleanly disconnect from SOURCE Domain

Disconnect-QADService

#Connect to TARGET Domain
Connect-QADService target.com

# Add migrated user to new SAP group

$Users | %{ Add-QADGroupMember "GroupName" -Member $($_.Username) }

# Cleanly disconnect from TARGET Domain
Disconnect-QADService

Open in new window

0
hasanzehnAuthor Commented:
the copyattributes.vbs migrates the msExchMailboxGUID for me without which the mailbox will not come across. Microsoft make the assumption you'd use ILM.
0
Chris DentPowerShell DeveloperCommented:

Oh yes of course, you did say.

It's certainly possible in PS, shouldn't even be very hard, but I don't really have anything to test it on which doesn't help.

Chris
0
hasanzehnAuthor Commented:
thanks chris, any ideas on the group matching/adding user?
0
Chris DentPowerShell DeveloperCommented:

Yeah, I added those to the example above :)

This is the group part:

$Users | %{ Add-QADGroupMember "GroupName" -Member $($_.Username) }

And this is potentially the primary address switch (combined with removal of source.local):

    # Drop source.local addresses
    $PA = $_.ProxyAddresses -NotMatch '@source.local'
    # Change the primary address
    For ($i = 0; $i -lt $PA.Count; $i++)
    {
      If ($PA[$i] -Match "target.com")
      {
        $PA[$i] -CReplace "smtp:", "SMTP:"
      }
      Else
      {
        $PA[$i] -CReplace "SMTP:", "smtp:"
      }
    }

I changed -INotMatch to NotMatch, case-insensitive is the default, for the Replace it uses C to enforce case-sensitivity.

Chris
0
hasanzehnAuthor Commented:
Hi Chris, setting the Primary SMTP is now the major issue. The method you outlined unfortunately doesn't work, it seems to execute but the smtp portion remains lowercase and currently the test user has no primary SMTP (as the deletion of the old one was succesful).

I know you cannot remove a primary address unless you assign another as primary first, perhaps this is the problem? Also the method of assigning the primary, I do not think it is as simple as replacing smtp: with uppercase string unfortunately. Bit of a challenge this, but I'll keep trying.

As for the Groups, I've got something like this in mind as below. Can you verify the best way of formatting the If statement please? Thanks so far!
$Users | % {
$groups = Get-QADUser $_.username | Get-QADMemberof -Name 'SAP*'

If ($groups.name = 'SAP-OldDomain') {
add-QADGroupMember 'SAP-NewDomain' -member $_.username}

ElseIf ($groups.name = 'SAP123-OldDomain') {
add-QADGroupMember 'SAP123-NewDomain' -member $_.username}

etc. etc. repeated for another 8 possiblities of matching.

Open in new window

0
Chris DentPowerShell DeveloperCommented:

> I know you cannot remove a primary address unless you assign another as primary first, perhaps this is the problem?

You can do what you please with the string array returned by Proxy Addresses. It doesn't validate when you apply it either, it does in the GUI, but that's a different story. I would suggest that this match is failing:

      If ($PA[$i] -Match "target.com")

If that doesn't catch the replace will never fire. I guess target.com exists as an address on the account at this stage?

> etc. etc. repeated for another 8 possiblities of matching.

Use Switch, it'll be neater if you have a lot of matching to do:

Switch ($Groups.Name)
{
  "SAP-OldDomain" { Add-QADGroupMember 'SAP-NewDomain' -member $_.Username }
  "SAP123-OldDomain" { Add-QADGroupMember 'SAP123-NewDomain' -member $_.Username }
}

It has some fun options as well, you can set a default case using the "default" keyword as the last statement in the switch, or you can use a Regular Expression match (-RegEx parameter), rather powerful.

Chris
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
hasanzehnAuthor Commented:
OK, got it to work, the if statement has to use 'like' as below (can you tell I'm new to scripting!)
just has to recurse 9 more times thru ElseIf:
If ($groups.name -like 'SAP-OldDomain') { 
add-QADGroupMember 'SAP-NewDomain' -member $_.username}

Open in new window

0
Chris DentPowerShell DeveloperCommented:

> just has to recurse 9 more times thru ElseIf:

That's a lot, I would definitely use switch, but it's up to you, both will work :)

Chris
0
hasanzehnAuthor Commented:
hmmm, switch command is interesting. Thanks Chris!
0
hasanzehnAuthor Commented:
>If that doesn't catch the replace will never fire. I guess target.com exists as an address on the account at this stage?

Yes, the target.com address exists and is already set as the primary smtp. What happens during the migration is that it sets source.local as the primary smtp, but the target.com address is there from account creation in source and is still there post migration (just demoted to non-primary).

For mail to flow correctly we need thr target.com reset as primary.

I've seen this suggestion, but cannot understand how to translate his code so it works for my csv.

http://mostlymail.blogspot.com/2008/03/modify-exchange-2003-users-primary-smtp.html

cheers, hasan
0
Chris DentPowerShell DeveloperCommented:

That adds a new address, but you want to modify an existing address don't you?

Might be worth trying Like there as well:

For ($i = 0; $i -lt $PA.Count; $i++)
    {
      If ($PA[$i] -Like "*@target.com")
      {
        $PA[$i] -CReplace "smtp:", "SMTP:"
      }
      Else
      {
        $PA[$i] -CReplace "SMTP:", "smtp:"
      }
    }
0
hasanzehnAuthor Commented:
Question mostly answered!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.