Scott Fell
asked on
Powershell Move Files In A Folder
My code below is part of a larger script that loops through files in a folder and sends an email with attachment. After each email, I would like the file to be moved to a new folder. I am getting an error that a file is in use. It seems to loop through all files ok, but one can never be used because it is in use. Short code and Error below with full code.
I have also tried putting the move command after the loop. It always leaves one file.
My full code is
PS C:\Users\scott> $Path = "C:\temp\"
$NewPath = "C:\temp\sent"
$files = Get-ChildItem C:\temp\*.*
ForEach ($file in $files) {
$attachment = $path+$file.name
#send mail
Move-Item $attachment $NewPath -force
}
ERRORMove-Item : The process cannot access the file because it is being used by another process.
At line:6 char:5
+ Move-Item $attachment $NewPath -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\temp\test2.txt:FileInfo) [Move-Item], IOException
+ FullyQualifiedErrorId : MoveFileInfoItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
I have also tried putting the move command after the loop. It always leaves one file.
PS C:\Users\scott> $Path = "C:\temp\"
$NewPath = "C:\temp\sent"
$files = Get-ChildItem C:\temp\*.*
ForEach ($file in $files) {
$attachment = $path+$file.name
#send mail
}
Move-Item $attachment $NewPath -force
My full code is
$Path = "C:\temp\"
$NewPath = "C:\temp\sent"
$files = Get-ChildItem C:\temp\*.*
ForEach ($file in $files) {
$SMTPServer = "smtp.example.com"
$SMTPPort = "587"
$Username = "me@example.com"
$Password = "abc134"
$to = "you@example.com"
$subject = "Email Subject"
$body = "Insert body text here"
$attachment = $path+$file.name
$message = New-Object System.Net.Mail.MailMessage
$message.subject = $subject
$message.body = $body
$message.to.add($to)
#$message.cc.add($cc)
$message.from = $username
$message.attachments.add($attachment)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)
#write-host "Mail Sent"
# Move-Item $attachment $NewPath -force
}
Move-Item "C:\temp\*.*" $NewPath -force
ASKER
>I'm curious why you're not using the Send-MailMessage cmdlet
Because I am not very familiar with Powershell. I'm open though.
Because I am not very familiar with Powershell. I'm open though.
ASKER
the .Dispose() didn't work. I think it is because of the looping. When I try the first sample code with 8 lines the same thing happens.
Actually, it might be necessary to use.
$message.Dispose()
or even just setting the attachments property to $null.
Testing would be needed to determine the impact, but some efficiency could be had by moving elements that don't change out of the foreach loop. Maybe just keeping the $message.attachments.add($ attachment ) and $smtp.send() bits in there.
If you've got PS 3.0+, then I'd just use Send-MailMessage. I think the syntax is easier.
$message.Dispose()
or even just setting the attachments property to $null.
Testing would be needed to determine the impact, but some efficiency could be had by moving elements that don't change out of the foreach loop. Maybe just keeping the $message.attachments.add($
If you've got PS 3.0+, then I'd just use Send-MailMessage. I think the syntax is easier.
If it's happening with just that sample (where a mail send isn't really happening), then something else is locking the file. I'd use Process Explorer or handles.exe (Sysinternals) to try to determine what.
ASKER
The key was to use both!
$smtp.Dispose()
$message.Dispose()
$smtp.Dispose()
$message.Dispose()
ASKER
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
On Windows 10, I used both $message.Dispose() and $smtp.Dispose() but on server 2008 RT it I had to only use $message.Dispose() because $smtp.Dispose() generated an error.
If you think it is being locked by the mail send process, then I would insert the following at line 30.
$smtp.Dispose()
I could see how that would happen. You could also try throwing in a delay (Start-Sleep).
I'm curious why you're not using the Send-MailMessage cmdlet. Unless you're using an older version of PS, all the functionality is there.