Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Mailbox Size Script

Status
Not open for further replies.

Aaron333

Technical User
Jun 8, 2011
15
US
Hello, I have the following script on my Exchange server for determining mailbox sizes. When I run it manually, it works fine. However, when I schedule it to run daily, it sends the same file to me every time. So, it's not writing over the text file in c:\scripts. If I delete the file manually, then run the script I get a new result file. I've tried to add a remove-item in the script, but I get the following error when I do:

Remove-Item : Cannot remove item C:\scripts\mailboxes.txt: The process cannot access the file 'C:\scripts\mailboxes.txt' because it is being used by another process.
At C:\scripts\SendMailboxStats.ps1:24 char:12
+ remove-item <<<< c:\scripts\mailboxes.txt -force
+ CategoryInfo : WriteError: (C:\scripts\mailboxes.txt:FileInfo)
[Remove-Item], IOException
+ FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand

Code:
###Send mailbox statistics script

###First, the administrator must change the mail message values in this section
$FromAddress = "mailboxreport@foo.com"
$ToAddress = "alewis@foo.com"
$MessageSubject = "Mailbox Size Report"
$MessageBody = "Attached is the current list of mailbox sizes."
$SendingServer = "foo.net"

###Now get the stats and store in a text file
Get-MailboxStatistics | Sort-Object TotalItemSize -Descending | ft DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount -auto > c:\scripts\mailboxes.txt


###Create the mail message and add the statistics text file as an attachment
$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, 
$MessageSubject, $MessageBody
$Attachment = New-Object Net.Mail.Attachment("c:\scripts\mailboxes.txt")
$SMTPMessage.Attachments.Add($Attachment)

###Send the message
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SMTPClient.Send($SMTPMessage)

remove-item c:\scripts\mailboxes.txt -force

exit
 
Does the account used to run the scheduled task have at least Modify permission to the C:\Scripts folder? From your description it sounds like it only has permission to create files and not also delete, which would be required to overwrite the existing file.
 
The scheduled task runs as the SYSTEM account.
 
What's the need for the text file? Does it need to be an attachment? You should be able to gather your stats and just email them without using a text file.

Not able to test right now, but

Code:
$stats = Get-MailboxStatistics | Sort TotalItemSize -Descending | select DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount

Should give you the info you need.

Stop by the new Tek-Tips group at LinkedIn. Come say hi, look for a job, have some fun.
Pat Richard MVP
 
Also, try

Code:
Get-MailboxStatistics | Sort-Object TotalItemSize -Descending | [url=http://technet.microsoft.com/en-us/library/dd315291.aspx]Select-Object[/url] DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount -auto | [url=http://technet.microsoft.com/en-us/library/dd315303.aspx]Out-File[/url] -FilePath "c:\scripts\mailboxes.txt"

Stop by the new Tek-Tips group at LinkedIn. Come say hi, look for a job, have some fun.
Pat Richard MVP
 
Pat, in your 2nd option the file remains open and I get the same result as in my script. However, I've solved it by running a batch file later in the day that deletes the mailboxes.txt file so that a new one is created and emailed each morning. A bit of a kluge, but it works.
 
You were right, commenting out those two lines stopped the error.
 
Okay, so it's the attachment part that's locking the file.

Trying throwing the following just above your "Remove-Item" line:

Code:
Remove-Variable SMTPMessage
Remove-Variable FromAddress
Remove-Variable ToAddress
Remove-Variable MessageSubject
Remove-Variable MessageBody
Remove-Variable Attachment
Remove-Variable SMTPClient
Remove-Variable SendingServer

Stop by the new Tek-Tips group at LinkedIn. Come say hi, look for a job, have some fun.
Pat Richard MVP
 
Unfortunately, removing the variables didn't work either. Since we know it's the attachment code locking it, I also tried your first option like so:

Code:
$stats = Get-MailboxStatistics | Sort TotalItemSize -Descending | select DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount

$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, 
$MessageSubject, $stats

###Send the message
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SMTPClient.Send($SMTPMessage)

However, the email contains nothing in the body. $stats doesn't seem to be capturing the output of Get-MailboxStatistics like using the stdout to a text file.
 
Okay. You should still leave the Remove-Variables in the script just to release the memory that those are using.

I found the issue. But first, let's clean up your code a little (for the sake of best practices).

First, define the file once in a variable, and call the variable in the various spots of your script, instead of the actual file name.

Second, use Select-Object, not ft. Ft is for screen output, and can cause some heartburn when trying to output data to a file.

Third, use Out-File to output to a file, not a redirection such as ">".

Fourth, Get-MailboxStatistics requires an identity value. We can feed it all of the mailboxes by pipelining a Get-Mailbox command before that.

Last, we can use .Dispose() to free and kill the file.

Code:
###Send mailbox statistics script
###First, the administrator must change the mail message values in this section
[string]$FromAddress = "mailboxreport@foo.com"
[string]$ToAddress = "alewis@foo.com"
[string]$MessageSubject = "Mailbox Size Report"
[string]$MessageBody = "Attached is the current list of mailbox sizes."
[string]$SendingServer = "foo.net"
[string]$file = "c:\scripts\mailboxes.txt"

###Now get the stats and store in a text file
Get-MailboxStatistics | Sort-Object TotalItemSize -Descending | Select-Object DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount | Out-File $file

###Create the mail message and add the statistics text file as an attachment
$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, $MessageSubject, $MessageBody
$Attachment = New-Object Net.Mail.Attachment($file)
$SMTPMessage.Attachments.Add($Attachment)

###Send the message
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SMTPClient.Send($SMTPMessage)
$Attachment.Dispose()
Remove-Variable SMTPMessage
Remove-Variable FromAddress
Remove-Variable ToAddress
Remove-Variable MessageSubject
Remove-Variable MessageBody
Remove-Variable Attachment
Remove-Variable SMTPClient
Remove-Variable SendingServer
Remove-Variable File

If the report is always going to go to the same person, from the same address, you don't need to define those variables. You can hard code those right into the $SMTPMessage line, such as
Code:
# [URL unfurl="true"]http://www.tek-tips.com/viewthread.cfm?page=1&qid=1652631[/URL]
###Send mailbox statistics script
###First, the administrator must change the mail message values in this section
[string]$file = "e:\mailboxes.txt"

###Now get the stats and store in a text file
Get-Mailbox | Get-MailboxStatistics | Sort-Object TotalItemSize -Descending | Select-Object DisplayName,@{label="TotalItemSize(KB)";expression={$_.TotalItemSize.Value.ToKB()}}, ItemCount | Out-File $file

###Create the mail message and add the statistics text file as an attachment
$SMTPMessage = New-Object System.Net.Mail.MailMessage "mailboxreport@foo.com", "alewis@foo.com", "Mailbox Size Report", "Attached is the current list of mailbox sizes."
$Attachment = New-Object Net.Mail.Attachment($file)
$SMTPMessage.Attachments.Add($Attachment)

###Send the message
$SMTPClient = New-Object System.Net.Mail.SMTPClient("foo.net")
$SMTPClient.Send($SMTPMessage)
$Attachment.Dispose()
Remove-Variable SMTPMessage
Remove-Variable SMTPClient
Remove-Variable Attachment
Remove-Variable File

Stop by the new Tek-Tips group at LinkedIn. Come say hi, look for a job, have some fun.
Pat Richard MVP
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top