Need help with two powershell scripts.

i need to export all mailboxes to psts for a project and i need to have each users exported pst mailbox named with their email address for the company.

i ran this script on a 32bit xp vm that has outlook installed and EMS. i am using a domain admin account with full privileges on the exchange server and all the mailboxes. when i run the command i get this error:

get-mailbox -database “ftlx5\Fourth Storage Group\Mailbox Database 3” | foreach-object {$email=“$_.alias+$domain” export-mailbox -PSTfolderpath “Y:\FOSG-MD3$email.pst”}
Unexpected token ‘export-mailbox’ in expression or statement.
At line:1 char:129

  • get-mailbox -database “ftlx5\Fourth Storage Group\Mailbox Database 3” | foreach-object {$email=“$_.alias+$domain” export-mailbox <<<< -PSTfolderpath “Y:\FOSG-MD3$email.pst”}
    • CategoryInfo : ParserError: (export-mailbox:String) , ParentContainsErrorRecordException
    • FullyQualifiedErrorId : UnexpectedToken

Can anyone provide any guidance on resolving this error to get this script to run

my second script that i am trying to create has to do with checking a file version then invoking a product install or copying files. i have this so far and tested it and it is working to give me the file version.

(Get-Command ‘C:\Program Files\autodesk\autocad map 3d 2012\acdgnls.dbx’).FileVersionInfo

what i want to be able to do is check a file version and use some conditional logic, operators, etc to see if a file is less than 18.2. If it is then rename current file with .bak extension then copy new files into product install directory. If file is equal to or greater than 18.2 then exit script.

Looks like you’ve got two lines of code mashed into one (perhaps due to copying and pasting from a website where the newlines didn’t carry over properly, or something). Export-Mailbox should be on its own line after the $email= command. The way you’re concatenating $_.alias and $domain is off as well; you either need to ditch the double quotes (if you want to use the + operator), or change the string inside the quotes. I’ve included examples of both in this post; the second one is commented out.

get-mailbox -database "ftlx5\Fourth Storage Group\Mailbox Database 3" |
foreach-object {
    $email = $_.alias + $domain
    # $email = "$($_.alias)$domain"
    export-mailbox -PSTfolderpath "Y:\FOSG-MD3\$email.pst"
}

Note: I haven’t tested this code and I’m not all that familiar with Exchange. It may not work as written; I’ve just modified what you posted slightly to address the formatting error.

Hi Dave & anyone else who wants to chime in… :slight_smile:

So i tried to run the script and it stops and asks me to supply values for the following parameters (see attached file).

How can i get this script to run and not prompt me for any input?

what i am looking for when it runs the export-mailbox cmdlet is to use the alias of of their mailbox and then append the domain name of their email addresses.

jdoe@mycompany.com

Thanks again for your help.

Looks like you’re not piping the object from Get-Mailbox to Export-Mailbox, so it’s expecting you to enter an Identity instead. Try this:

$_ | export-mailbox -PSTfolderpath "Y:\FOSG-MD3\$email.pst"

does Powershell have some issue writing to mapped network drives? after fixing the piping, i am getting this message (see attached).
i can see the drive in my xp vm. i can read & write to it through the windows gui. i have the firewall turned off as well and no AV software running on this box. attached is the script as well again just to make sure it is correct.

ok, so i added a virtual disk on this xp vm and reran it and got passed that mapped drive issue (although still curious as to why powershell won’t write the output to my Y drive). i have full permissions and am running powershell as a domain admin.

see attached file. it seems to be taking the users fullname and appending it to the email address:

john doe.alias@mycompany.com

Looks like you’re still doing “$_.alias+$domain” in double quotes, which isn’t going to work. I suggested two alternative ways of writing that statement in my first reply.

i removed the quotes that i had and tried your two options. the script works but when it exports the mailbox it is not passing the alias and domain variables to the file name. so instead of it showing up as jdoe@mycompany.com it just exports as .pst.

You’ll need to do some debugging, then. What’s in the $email variable right before the call to Export-Mailbox? What about $domain and $_.Alias?

I can’t test this code, as I don’t have an Exchange environment up at the moment.

First post here on this forum, with that said try this out:

Get-Mailbox -Database "ftlx5\Fourth Storage Group\Mailbox Database 3" |
Foreach-Object {
    Export-Mailbox $_.Identity -PSTfolderpath "Y:\FOSG-MD3\$($_.PrimarySmtpAddress).pst"
}

Hopefully that helps. I don’t have an Exchange 2007 server (assuming that’s what you’re using) to test with.

i have manually set the variable for $domain and verified with get-variable domain and it appears in my PS session. if i do a get-variable for $email it shows me email but the value is empty and $_.alias nothing comes up and errors out saying object not found.

what i have noticed is that it seems that $_ in $email =“$_.alias+$domain” is pulling the users first and last name such as: John Doe.alias@mycompany.com. If i use your 2 methods the script works except it wont pass the variable $email into the file name at the end of the script but it will create a pst file of the users mailbox with the name .pst

If i remove the $_.alias and leave $domain part from: | foreach-object { $email= $domain
in the script it i see in the error show up as @mycompany.com.

it seams like the issue is just with the $_.alias part. is there another way to call on the exchange user mailboxes alias? can how could i say to use the primarysmtpaddress and append that to the file name (primarysmtpaddress.pst)

hope all that makes sense. i tried using a set_psbreakpoint debug option but it didnt show me any information that was helpful. if you need me to rerun it and post the output, or if you need me to run some other form of debugging please let me know. i am still new to powershell so pardon some of my ignorance. :slight_smile:

If you run it as I posted it above, you don’t need to manually create the email address by adding $alias and $domain. $_.PrimarySmtpAddress is already a property of the mailbox and should be the user’s email address. Sorry if I’m not clear on what you’re trying to accomplish.

As far as your second question, something like this might work (although I’m sure there’s a better way of doing it):

$File = 'C:\Program Files\autodesk\autocad map 3d 2012\acdgnls.dbx’
$FileVersionInfo = (Get-Command $File).FileVersionInfo
[int]$CurrentVersion = "$($FileVersionInfo.FileMajorPart).$($FileVersionInfo.FileMinorPart)"
if ($CurrentVersion -lt 18.2) {
    Write-Host 'Renaming File'
    ren $File $File.Replace('acdgnls.dbx’,'acdgnls.bak’)
    Write-Host 'Copying File'
    copy '<source>' '<target>'
}
else {
    return
}

Edited - accidentally renamed file to .exe and not .bak when I first posted.

i will give it a shot and report back on monday if i dont get to it this weekend.

thank you both for you help!

i just gave it a run and it worked great. i just added the -confirm:$false so i do not have to answer the prompts to confirm each user mailbox export.

Get-Mailbox -Database “ftlx5\Fourth Storage Group\Mailbox Database 3” |
Foreach-Object {
Export-Mailbox $.Identity -PSTfolderpath "Y:\FOSG-MD3$($.PrimarySmtpAddress).pst" -confirm:$false
}

[quote=13264]If you run it as I posted it above, you don’t need to manually create the email address by adding $alias and $domain. $_.PrimarySmtpAddress is already a property of the mailbox and should be the user’s email address. Sorry if I’m not clear on what you’re trying to accomplish.

As far as your second question, something like this might work (although I’m sure there’s a better way of doing it):

$File = 'C:\Program Files\autodesk\autocad map 3d 2012\acdgnls.dbx’
$FileVersionInfo = (Get-Command $File).FileVersionInfo
[int]$CurrentVersion = "$($FileVersionInfo.FileMajorPart).$($FileVersionInfo.FileMinorPart)"
if ($CurrentVersion -lt 18.2) {
    Write-Host 'Renaming File'
    ren $File $File.Replace('acdgnls.dbx’,'acdgnls.bak’)
    Write-Host 'Copying File'
    copy '<source>' '<target>'
}
else {
    return
}

Edited – accidentally renamed file to .exe and not .bak when I first posted.
[/quote]

Thanks again for the help with the scripts. I need to add some more logic to the second script that you provided about file version checking. So the script worked perfectly, but what i found out is that i am missing autocad service packs possibly on machines that need to be deployed before running the original script you provided. So i need to have it check for which version the acad.exe file is under: 'C:\Program Files\autodesk\autocad map 3d 2012\acad.exe’

i have three version to check:
autocad - no service pack installed - version: R18.2.51.0.0
autocad - service pack 1 installed - version: R18.2.107.0.0
autocad - service pack 2 installed - version: R18.2.205.0.0

Service Pack 1 & 2 are .msp files that need to be installed. Can i just run msiexec within the powershell script?
msiexec.exe /update “\remoteserver\VOL2\Program Files\AutoCAD Map 3D 2012\updates\map2012_x64_sp1.msp” /lv “%WINDIR%\Temp\map2012_x64_sp1.log”
msiexec.exe /update “\remoteserver\VOL2\Program Files\AutoCAD Map 3D 2012\updates\autocadmap3d2012_sp2_x64.msp” /l
v “%WINDIR%\Temp\autocadmap3d2012_sp2_x64.log”

Logic:
file check acad.exe. if <= version: R18.2.51.0.0 then apply SP1 & SP2 then go to file check acdgnls.dbx file check script
file check acad.exe. if > version: R18.2.51.0.0 but <= version: R18.2.107.0.0 then apply SP2 then go to file check acdgnls.dbx file check script
file check acad.exe. if > version: R18.2.107.0.0 but <= version: R18.2.205.0.0 then apply no service packs then go to file check acdgnls.dbx file check script

I am trying to break this down into smaller scripts since i am not that good with powershell yet! :slight_smile: so i made some modifications to reuse the existing script (which i have bolded). when i run it in powershell ise to test it i get the errors below.

$File = 'C:\Program Files\autodesk\autocad map 3d 2012\acad.exe
$FileVersionInfo = (Get-Command $File).FileVersionInfo
[int]$CurrentVersion = “$($FileVersionInfo.FileMajorPart).$($FileVersionInfo.FileMinorPart)”
if ($CurrentVersion -le R18.2.51.0.0) {
Start-Process “\ftlsan1\VOL2\Program Files\AutoCAD Map 3D 2012\updates\map2012_x64_sp1.msp” /qn -Wait }

else {
return
}
You must provide a value expression on the right-hand side of the ‘-le’ operator.
At line:4 char:21

Unexpected token ‘R18.2.51.0.0’ in expression or statement.
At line:4 char:25

Hi,

You need quotes in your if statement. Replace

if ($CurrentVersion -le R18.2.51.0.0) {

With

if ($CurrentVersion -le 'R18.2.51.0.0') {

Also you are using the -le operator on a string object. I am on my iPad one, however I newer use anything else than -eq or -ne operators with strings. Looks like you will need to parse the string and create a custom object if you want to any do fancy operator action on current version. For instance:

Damn Ipad…

Oh by the way, this line:
[int]$CurrentVersion = “$($FileVersionInfo.FileMajorPart).$($FileVersionInfo.FileMinorPart)”

will never become an [INT] since you have a “.” on the right hand side of the assignment. How can you compare an [int] to an [string] with letters? Also I have never used the cmdlet “Get-Command” against an exe-file to get version info, or maybe I forgot. I don’t know that the FileMajorPart and FileMinorPart properties will return. however you I will give you an example:

[string] $Major = ‘R18.2’
[string] $Minor= ‘51.0.0’

$MajorArray = $Major.Split(“.”)
$MinorArray = $Minor.split(“.”)

Now $MajorArray[0] (the first item in the array returned from the split function), should be R18 (still a String object).

Lets create a new variable and remove the R in the item

$MajorString = $MajorArray[0].Replace(“R”,“”)

$MajorInt = [int]::Parse(MajorString)

Now we can build a switch statement and less than and greater than statements

Switch ($MajorInt)
{
{$_ -lt 18}
{
“Major version is less than 18”
}
}

Someone can probably also give you an Regular expression that will match the string object. I never use (or very very rarely) them. Makes your script hard to read in the future (and by others that don’t know it) if you don’t use them on a frequent basis.

Cheers