PowerShell copy and delete question
- I have a script that I downloaded on the net and needed to modify a couple of items. I have bolded the three lines in question and comented them below.
Here is the script:
##
## Create a backup of all the vm's
##
$dest = "D:\VMbackup"
$dest2 = "D:\TapeBackup"
$Date = (Get-Date).toString('ddMMyyyy')
$Now = (Get-Date -Format ddMMyyy).AddDays(-21) <- powershell does not like this, but I not know how else to do it.
$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName <> Name"
foreach ($VM in [array] $ListOfVMs)
{
$VMReturnState = $VM.EnabledState
$VMName = $VM.ElementName
if (($VM.EnabledState -eq 2) -or ($VM.EnabledState -eq 32768) -or ($VM.EnabledState -eq 32770))
{
$VM.RequestStateChange(32769)
echo "Saving the state of $VMName"
}
while (!($VM.EnabledState -eq 32769) -and !($VM.EnabledState -eq 3))
{
Start-Sleep(1)
$VM = get-wmiobject -namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VMName'"
}
if ([IO.Directory]::Exists("$dest\TmpDir\$VMName"))
{
[IO.Directory]::Delete("$dest\TmpDir\$VMName", $True)
}
echo "Exporting the VM"
$status = $VM_Service.ExportVirtualSystem($VM.__PATH, $True, "$dest\TmpDir")
if ($status.ReturnValue -eq 4096)
{
$job = [Wmi]$status.Job
while (!($job.PercentComplete -eq 100) -and ($job.ErrorCode -eq 0))
{
Start-Sleep(5)
$job = [Wmi]$status.Job
echo $job.PercentComplete
}
}
## Store the files on in a temp directory before moving them to their location and then remove the old files.
if ([IO.Directory]::Exists("$dest\$VMName"))
{
[IO.Directory]::Move("$dest\$VMName", "$dest\$VMName-OldTmpDir")
[IO.Directory]::Copy("$dest\TmpDir\$VMName", "$dest2\$VMName") <- make a copy of this folder before move and put in another folder
[IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName-$Date")
[IO.Directory]::Delete("$dest\$VMName-$Now", $True) <- Delete the folder it the folder+date is equal to 21 days
[IO.Directory]::Delete("$dest\$VMName-OldTmpDir", $True)
}
else
{
[IO.Directory]::Move("$dest\TmpDir\$VMName", "$dest\$VMName-$DateD")
}
echo "Done with $VMName"
$VM.RequestStateChange($VMReturnState)
}
All Replies
- Hi,
Regarding your first bolded line : $Now = (Get-Date -Format ddMMyyy).AddDays(-21)
Here (Get-Date -Format ddMMyyy) returns a string not a DateTime object. So there is no method called AddDays on this object. You have to modify date using AddDays before formating it.
By Example : (Get-Date).AddDays(-21).ToString('ddMMyyyy')
Then, prefer to use built-in Copy-Item , Remove-Item or Move-Item Cmdlets for copying, removing or moving items.
Hope it helps.
Grégory Schiro - PowerShell MVP - PowerShell & MOF- Proposed As Answer byGrégory SchiroMVPFriday, July 03, 2009 8:26 AM
Hello
first one is easy to fix :)
$Now = (Get-Date -Format ddMMyyy).AddDays(-21)
should be
$Now = (Get-Date).AddDays(-21)
Cause the format function , causes the cmdlet to output a system.string instead of system.datetime, therefore you cannot run the adddays method (since it only exists on system.datetime).
i am looking into the others.
[IO.Directory]::Copy("$dest\TmpDir\$VMName", "$dest2\$VMName")
I am not sure why u are using these methods directly?
i would prefer to use the cmdlets provided by powershell.
you can use this command instead of the abiove line
Copy-Item -Recurse "$dest\TmpDir\$VMName" "$dest2\$VMName"
[IO.Directory]::Delete("$dest\$VMName-$Now", $True)
I am not sure what errors you get, but this command will not delete the folder if it is not empty.
i would again use the cmdlet instead like this:
Remove-Item -Recurse "$dest\$VMName-$Now"
Good luck
Best Regards
Jakob Gottlieb svendsen
Trainer/Consultant - Coretech A/S - Blog - MCT - MCTS - VB.NET - C#.NET - Powershell - VBScriptI have made the requested changes and for the most part it is working except for the rename-item part I have bolded below. I get this error
Rename-Item : Cannot rename because the target specified is not a path.
$dest1 = "D:\VMbackup"
$dest2 = "D:\TapeBackup"
$Date = (Get-Date).toString('ddMMyyyy')
$Now = (Get-Date).AddDays(-21)
$VM_Service = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemManagementService
$ListofVMs = get-wmiobject -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName <> Name"foreach ($VM in [array] $ListOfVMs)
{
$VMReturnState = $VM.EnabledState
$VMName = $VM.ElementNameif (($VM.EnabledState -eq 2) -or ($VM.EnabledState -eq 32768) -or ($VM.EnabledState -eq 32770))
{
$VM.RequestStateChange(32769)
echo "Saving the state of $VMName"
}while (!($VM.EnabledState -eq 32769) -and !($VM.EnabledState -eq 3))
{
Start-Sleep(1)
$VM = get-wmiobject -namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='$VMName'"
}
if ([IO.Directory]::Exists("$dest1\TmpDir\$VMName"))
{
[IO.Directory]::Delete("$dest1\TmpDir\$VMName", $True)
}echo "Exporting the VM"
$status = $VM_Service.ExportVirtualSystem($VM.__PATH, $True, "$dest1\TmpDir")
if ($status.ReturnValue -eq 4096)
{
$job = [Wmi]$status.Job
while (!($job.PercentComplete -eq 100) -and ($job.ErrorCode -eq 0))
{
Start-Sleep(5)
$job = [Wmi]$status.Job
echo $job.PercentComplete
}
}
## Store the files on in a temp directory before moving them to their location and then remove the old files.if ([IO.Directory]::Exists("$dest1\$VMName"))
{
Move-Item "$dest1\$VMName", "$dest1\$VMName-OldTmpDir"
Copy-Item -recurse -force "$dest1\TmpDir\$VMName", "$dest2\$VMName"
Move-Item "$dest1\TmpDir\$VMName", "$dest1\$VMName-$Date"
Remove-Item -recurse "$dest1\$VMName-$Now"
Remove-Item -recurse "$dest1\$VMName-OldTmpDir"
}
else
{
Move-Item $dest1\TmpDir\$VMName $dest1\$VMName
Rename-Item -path "$dest1\$VMName" -newname "$dest1\$VMName-$Now"
}
echo "Done with $VMName"
$VM.RequestStateChange($VMReturnState)
}
Thanks for the help...I am very close now!

