?
Solved

Improve and correct a Powershell script for Migration

Posted on 2010-03-29
16
Medium Priority
?
541 Views
Last Modified: 2012-05-09
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
0
Comment
Question by:hasanzehn
  • 8
  • 8
16 Comments
 
LVL 71

Expert Comment

by:Chris Dent
ID: 29067612

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
 

Author Comment

by:hasanzehn
ID: 29070085
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 29070354

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

Chris
0
SMB Security Just Got a Layer Stronger

WatchGuard acquires Percipient Networks to extend protection to the DNS layer, further increasing the value of Total Security Suite.  Learn more about what this means for you and how you can improve your security with WatchGuard today!

 
LVL 71

Expert Comment

by:Chris Dent
ID: 29071798

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
 

Author Comment

by:hasanzehn
ID: 29076568
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 29076662

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
 

Author Comment

by:hasanzehn
ID: 29076821
thanks chris, any ideas on the group matching/adding user?
0
 
LVL 71

Expert Comment

by:Chris Dent
ID: 29077064

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
 

Author Comment

by:hasanzehn
ID: 29090575
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
 
LVL 71

Accepted Solution

by:
Chris Dent earned 1500 total points
ID: 29091263

> 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
 

Author Comment

by:hasanzehn
ID: 29091857
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
 
LVL 71

Expert Comment

by:Chris Dent
ID: 29092196

> 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
 

Author Comment

by:hasanzehn
ID: 29096274
hmmm, switch command is interesting. Thanks Chris!
0
 

Author Comment

by:hasanzehn
ID: 29180567
>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
 
LVL 71

Assisted Solution

by:Chris Dent
Chris Dent earned 1500 total points
ID: 29180765

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
 

Author Closing Comment

by:hasanzehn
ID: 31710894
Question mostly answered!
0

Featured Post

Evaluating UTMs? Here's what you need to know!

Evaluating a UTM appliance and vendor can prove to be an overwhelming exercise.  How can you make sure that you're getting the security that your organization needs without breaking the bank? Check out our UTM Buyer's Guide for more information on what you should be looking for!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In my humble opinion (IMHO), TouchDown from Symantec is the best in class for this type of application, but Symantec has end-of-lifed it and although one can keep using it, it will no longer be supported or upgraded.  Time to look for alternatives t…
The PowerShell Core 6.0 of .NET release is just the beginning. The upcoming PowerShell Core 6.1 would have artificial intelligence and internet of things capabilities. So many things to look forward to in the upcoming release.
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…
Suggested Courses

601 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question