Disk2VHD image backup with automatic removal of old images when backup drive is full

I've got the following script that I'm running as scheduled task each day.

It makes a VHD image of C: drive (447 GB) and copy it to F: drive (3,63 TB) and removes old vhd images when there is more than 4 of these.

I would like to modify it so it would take current disk space usage from C drive and compare it with current disk usage of F drive. If there will be less space on F than it's needed to backup whole C then the last image would be removed.

It would be good to use fsutil utility:

C:\Users\Marek>fsutil volume diskfree c:
Całkowita liczba bajtów wolnych           : 244490219520
Całkowita liczba bajtów                   : 480127946752
Całkowita liczba dostępnych bajtów wolnych: 244490219520

C:\Users\Marek>fsutil volume diskfree f:
Całkowita liczba bajtów wolnych           : 324223422464
Całkowita liczba bajtów                   : 4000575385600
Całkowita liczba dostępnych bajtów wolnych: 324223422464

REM
REM A simple backup system using disk2vhd
REM
REM version 1.3, by J.E.B., 2011-02-22
REM
REM requires 'disk2vhd.exe' to be in the path
REM

setLocal EnableDelayedExpansion

REM "DRIVES" can be one drive identifier with colon, multiple separated by spaces,
REM or asterisk for all.  
REM "DEST" can be a drive letter or a UNC.

SET DRIVES="C:"
SET DEST="F:"

REM Keep most recent 4 VHD files in DEST, delete the rest

for /f "skip=4 tokens=* delims= " %%a in ('dir/b/o-d %DEST%\*.VHD') do (
del %DEST%\%%a
)

REM Backup to VHD

C:
cd \
DISK2VHD %DRIVES% %DEST%\%COMPUTERNAME%--%date:~-10,3%%date:~-7,2%%date:~-4,4%.VHD

EXIT /B n
SpacedustPLAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Tony JLead Technical ArchitectCommented:
I've just knocked up the following powershell script but can't easily test it's individual components.

It's possibly not the most graceful solution, if I'm honest, but it should work.

I put the /1073741824 in whilst I was testing as it made for easier numbers on the eye. There's no functional reason for it to remain unless you wanted to pipe some of the variables out.

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force
}

#Once enough free space has been created on F: this function creates the latest VHD
Function CreateVHD {
$filename = (get-date -uformat %d%b%y) + "_"  + $Env:COMPUTERNAME + ".vhd"
.\disk2vhd c: ("F:\" +$filename) # The .\ assumes disk2vhd is in the same folder as this script;
}

#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
Do {
if ($fdisk -lt $Cdiskused) {
write-host "Not enough free space on F: Drive. Deleting oldest image"
DelVHD
diskspace
}
}
until ($fdisk -gt $Cdiskused)

write-host "Enough free space on F:\ found...creating latest VHD"
CreateVHD

Open in new window

0
SpacedustPLAuthor Commented:
I'm running on Windows 7 Ultimate and nothing happens:

C:\Users\Marek>powershell -noexit "& ""C:\backup2.ps1"""
0
Tony JLead Technical ArchitectCommented:
No errors?

I just ran it and as far as I can (no disk2vhd etc) it tries to remove oldest files due to a lack of disk space.

Running powershell as an Adminitrator?

For debugging I prefer to use the powershell ISE
0
Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

Tony JLead Technical ArchitectCommented:
I just created a few thousand empty files and I can see them being deleted in the correct order. I can also see the disk space count going up, so the tests for free space and the deletion function are definitely working for me.
0
Tony JLead Technical ArchitectCommented:
Oh I just noticed - powershell -noexit "& ""C:\backup2.ps1""" won't work

Try:

powershell -noexit -command C:\backup2.ps1
0
SpacedustPLAuthor Commented:
Even running under 64-bit PowerShell ISE doesn't show any errors. It's just running but nothing is moving on.
0
SpacedustPLAuthor Commented:
It seems the first part is working. It stops when trying to run disk2vhd.

Get it here: https://download.sysinternals.com/files/Disk2vhd.zip (it's free).
0
Tony JLead Technical ArchitectCommented:
I need a bit more info - as I say, it's running fine for me here but I am running PS as an administrator;

When you say it's running but nothing is moving on...?

Have you made sure that disk2vhd.exe is in the same folder as the script or change this line to an explicit path:

.\disk2vhd <-- e.g. C:\Disk2VHD (also try adding the .exe).

Do you see either of the following lines output?

Enough free space on F:\ found...creating latest VHD

or

Not enough free space on F: Drive. Deleting oldest image
?

If the latter, can you see any .VHD files being deleted? Remembe the script assumes they're in the root of the F: drive.
0
Tony JLead Technical ArchitectCommented:
I may also have misformed the vhd2disk line -

Try changing it to

.\disk2vhd c: "F:\"$filename
0
SpacedustPLAuthor Commented:
disk2vhd.exe and backup2.ps1 is in the same path (root of C:\ drive).

I do not see any output just blinking cursor.

I'm currently making the drive full so I can see if it removes old images.

Changing .\disk2vhd c: "F:\"$filename or to .\disk2vhd.exe c: "F:\"$filename does not help either.
0
Tony JLead Technical ArchitectCommented:
Ok so you run the script and it does what? Says there's enough free space or not enough free space?

If it's the latter, it's going to take it a fair amount of time to delete a 400-odd GB file and you'll get no feedback at that point until it's deleted the file.

If there's then enough space, you should see the message saying so at which point it will try to create the VHD.

Not sure you get any visual feedback from disk2vhd when it's run from a command line.
0
SpacedustPLAuthor Commented:
It says nothing but when I've just leave the first part till

#Once enough free space has been created on F: this function creates the latest VHD

then it ends as I have enough disk space.

I will check again when the disk is full now.
0
Tony JLead Technical ArchitectCommented:
Grumble... my bad.

Change the CreateVHD function to:

#Once enough free space has been created on F: this function creates the latest VHD
Function CreateVHD {
$filename = (get-date -uformat %d%b%y) + "_"  + $Env:COMPUTERNAME + ".vhd"
$filename = "F:\"+$Filename
write-host .\disk2vhd c: $filename # The .\ assumes disk2vhd is in the same folder as this script;
}

Open in new window


You will notice the slight change of the filename parameter
0
Tony JLead Technical ArchitectCommented:
The original was adding in an additional space so it effectively appeared like this:

.\disk2vhd c: F:\ 21Sep15_TESTBED.vhd <-- See the space between the \ and the 2 ?

Whereas now it resolves correctly:

.\disk2vhd c: F:\21Sep15_TESTBED.vhd <-- No space!
0
SpacedustPLAuthor Commented:
Please see how it looks:

Screenshot
0
Lionel MMSmall Business IT ConsultantCommented:
try
for /F "tokens=* skip=4" %%A in ('dir /b /a-d /o-d "%DRIVES%\%DEST%\*.VHD"') do del "%DEST%\%%~A"
please note the ''' (3) after VHD and that the entire command "%DRIVES%\%DEST%\*.VHD" is in " " too
0
Tony JLead Technical ArchitectCommented:
I'm an idiot and this is what you get for not clearing out variables.

Need to move where diskpace is called!

#This loop kicks everything off - it gets the free disk space, deletes files one at a time on D: as required and then creates the VHD when there is sufficient disk space freed up.
Do {
if ($fdisk -lt $Cdiskused) {
diskspace
write-host "Not enough free space on D: Drive. Deleting oldest image"
DelVHD
}
}
until ($fdisk -gt $Cdiskused)

Open in new window

0
SpacedustPLAuthor Commented:
Still nothing. Just blinking cursor.
0
Tony JLead Technical ArchitectCommented:
How very odd

I am looking at the same thing on my PC merrily deleting files.

Can you try just running this snippet?

#This function is called repeatedly until the space on the D: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}
diskspace

Open in new window


It should just return the free space on F: and the used space on C:, nothing more.
0
SpacedustPLAuthor Commented:
That works well ;)

PS C:\Users\Marek> powershell -noexit -command C:\test.ps1
82,8459358215332
221,111248016357

Open in new window

0
Tony JLead Technical ArchitectCommented:
Good.

Now can we expand to simply delete files?

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force
}


#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
Do {
if ($fdisk -lt $Cdiskused) {
diskspace
write-host "Not enough free space on F: Drive. Deleting oldest image"
DelVHD
}
}
until ($fdisk -gt $Cdiskused)
diskspace

Open in new window

0
SpacedustPLAuthor Commented:
Blinking cursor again - no output ;)

Also nothing is removed. I got two VHD images waiting in the root of F: drive.
0
Tony JLead Technical ArchitectCommented:
How big are the files?

Might be that they are going but it will take a while.
0
SpacedustPLAuthor Commented:
231 GB each - it takes about 2-3 seconds to remove them normally from Seagate 5900 rpm 4 TB drive.
0
SpacedustPLAuthor Commented:
Also I got about 4% CPU (2x Intel Xeon X5675) usage when running this script - it's probably some infinite loop.
0
SpacedustPLAuthor Commented:
This is how my F: drive look like:


    Directory: F:\


Mode                LastWriteTime     Length Name                                                                                                                                             
----                -------------     ------ ----                                                                                                                                             
-ar--        2015-04-15     20:49        528 MediaID.bin                                                                                                                                      
d----        2015-05-02     19:22            WindowsImageBackup6                                                                                                                              
d----        2015-05-06     13:37            WindowsImageBackup7                                                                                                                              
d----        2015-05-12     12:00            WindowsImageBackup8                                                                                                                              
d----        2015-05-17     12:00            WindowsImageBackup9                                                                                                                              
d----        2015-05-22     20:51            WindowsImageBackup10                                                                                                                             
d----        2015-05-24     13:53            WindowsImageBackup11                                                                                                                             
d----        2015-06-01     12:00            WindowsImageBackup12                                                                                                                             
d----        2015-06-03     15:07            WindowsImageBackup13                                                                                                                             
d----        2015-06-08     12:18            WindowsImageBackup14                                                                                                                             
d----        2015-06-15     12:01            WindowsImageBackup15                                                                                                                             
d----        2015-06-19     12:01            WindowsImageBackup16                                                                                                                             
d----        2015-06-26     12:01            WindowsImageBackup17                                                                                                                             
d----        2015-07-10     12:47            WindowsImageBackup18                                                                                                                             
d----        2015-07-23     12:01            WindowsImageBackup19                                                                                                                             
d----        2015-08-03     12:01            WindowsImageBackup20                                                                                                                             
d----        2015-08-08     13:22            WindowsImageBackup21                                                                                                                             
d----        2015-08-11     12:01            WindowsImageBackup22                                                                                                                             
d----        2015-09-02     22:35            WindowsImageBackup23                                                                                                                             
d----        2015-09-16     16:58            WindowsImageBackup                                                                                                                               
-a---        2015-09-16     16:55 2311530024 MACPRO--2015-9-16.VHD                                                                                                                            
                                          96                                                                                                                                                  
-a---        2015-09-21     14:10 2311530024 MACPRO--2015-9-21.VHD                                                                                                                            
                                          96                         

Open in new window

0
SpacedustPLAuthor Commented:
This seems to be working:

Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force

but asks for confirmation
0
SpacedustPLAuthor Commented:
When put inside a function it doesn't make anything - it quits immediately:

#This function will simply delete the oldest file in the root of the F: drive
function test {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force
}

Open in new window

0
Tony JLead Technical ArchitectCommented:
You have to call it:

#This function will simply delete the oldest file in the root of the F: drive
function test {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force
}
test

Open in new window

0
Tony JLead Technical ArchitectCommented:
Hmm the -force should make it assume "Yes"
0
Tony JLead Technical ArchitectCommented:
And yes...I created some 500MB files to test and they went in seconds.
0
SpacedustPLAuthor Commented:
I got it :) I've needed to add -Recurse parameter because I got some folder from WindowsImageBackup:

#This function will simply delete the oldest file in the root of the F: drive
function test {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}
test

Open in new window

0
SpacedustPLAuthor Commented:
So this works for me so far - the oldest one is removed ;)

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}

DelVHD

Open in new window

0
SpacedustPLAuthor Commented:
Also I don't know why it removing the oldest folders first instead of files ;)
0
Tony JLead Technical ArchitectCommented:
Interesting - you shouldn't really have required the recurse switch.

What happens if you now add on the function to test for free space?

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}

Do {
if ($fdisk -lt $Cdiskused) {
diskspace
write-host "Not enough free space on D: Drive. Deleting oldest image"
DelVHD
}
}
until ($fdisk -gt $Cdiskused)

Open in new window

0
Tony JLead Technical ArchitectCommented:
Duh..I just spotted you have folders. Yeah that'd need the recurse switch.
0
SpacedustPLAuthor Commented:
Again blinking cursor and nothing is moving on ;(

Something is wrong here:

Do {
if ($fdisk -lt $Cdiskused) {
diskspace
write-host "Not enough free space on D: Drive. Deleting oldest image"
DelVHD
}
}
until ($fdisk -gt $Cdiskused)

Open in new window

0
Tony JLead Technical ArchitectCommented:
I am losing it.

That _exact_ piece of code gives this on mine (I just dropped a few 500MB files into the folder):

0.267337799072266
107.147037506104
Not enough free space on F: Drive. Deleting oldest image
0.697784423828125
107.147037506104
Not enough free space on F: Drive. Deleting oldest image
1.12823104858398
107.147037506104
Not enough free space on F: Drive. Deleting oldest image
1.55867767333984
107.147037506104
Not enough free space on F: Drive. Deleting oldest image
1.9891242980957
107.147037506104

Open in new window

0
SpacedustPLAuthor Commented:
Maybe a typo here ? See the USed or used:

$CdiskUSed = $CdiskCapacity-$CDiskFree

Open in new window


and here:

if ($fdisk -lt $Cdiskused) {

Open in new window


or here:

until ($fdisk -gt $Cdiskused)

Open in new window

0
Tony JLead Technical ArchitectCommented:
powershell isn't case sensitve. :)
0
SpacedustPLAuthor Commented:
Even If I do something like this:

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}


#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
if ($fdisk -gt $Cdiskused) {
write-host "Not enough free space on F: Drive. Deleting oldest image"
}
diskspace

Open in new window


it doesn't work properly:

PS C:\Users\Marek> C:\backup2.ps1
1153,06732559204
221,418174743652

Open in new window

0
Tony JLead Technical ArchitectCommented:
Can you try a slight change to yours?

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function DiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
$fdisk = $fdisk.freespace/1073741824

return $Fdisk, $cdiskUsed
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}


#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
diskspace
if ($fdisk -gt $Cdiskused) {
write-host "Not enough free space on F: Drive. Deleting oldest image"
}
diskspace

Open in new window


You will notice I've added an additional call to the diskspace function
0
SpacedustPLAuthor Commented:
I got this:
PS C:\Users\Marek> C:\backup2.ps1
1153,06732559204
221,421562194824
1153,06732559204
221,421562194824

Open in new window

0
Tony JLead Technical ArchitectCommented:
Sorry for the delay replying.

So if I nulled the values I got the same result as you. It would appear that the values weren't coming back from the function correctly and rather than try to waste our time looking into why, it was quicker to rewrite slightly.

Could you try the following:

# Null all the values
$Cdisk = $null
$Fdisk = $null
$CdiskCapacity =  $null
$CdiskFree =  $null
$CdiskUSed =  $null

#This function is called to determine the used space on the C: drive
function UsedDiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
return $cdiskUsed
}

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function FreeDiskSpace() {
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$fdisk = $fdisk.freespace/1073741824
return $Fdisk
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}

#Once enough free space has been created on F: this function creates the latest VHD
Function CreateVHD {
$filename = (get-date -uformat %d%b%y) + "_"  + $Env:COMPUTERNAME + ".vhd"
$filename = "F:\"+$Filename
.\disk2vhd c: $filename # The .\ assumes disk2vhd is in the same folder as this script;
}

#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.

Do {
$c = useddiskspace
$f = freediskspace


if ($f -lt $c) {

write-host "Space used on C: = "$c"
write-host "Free space on F: = "$f"
write-host "Not enough free space on F: Drive. Deleting oldest image"
DelVHD
}
}
until ($fdisk -gt $Cdiskused)

write-host "Enough free space on F:\ found...creating latest VHD"
CreateVHD

Open in new window


I have this working, even with the values all nicely nulled.
0
SpacedustPLAuthor Commented:
Still nothing - just blinking cursor ;(
0
SpacedustPLAuthor Commented:
The good thing is - this works for me - disk2vhd is started ;)

# Null all the values
$Cdisk = $null
$Fdisk = $null
$CdiskCapacity =  $null
$CdiskFree =  $null
$CdiskUSed =  $null

#This function is called to determine the used space on the C: drive
function UsedDiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
return $cdiskUsed
}

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function FreeDiskSpace() {
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$fdisk = $fdisk.freespace/1073741824
return $Fdisk
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}

#Once enough free space has been created on F: this function creates the latest VHD
Function CreateVHD {
$filename = (get-date -uformat %d%b%y) + "_"  + $Env:COMPUTERNAME + ".vhd"
$filename = "F:\"+$Filename
.\disk2vhd c: $filename # The .\ assumes disk2vhd is in the same folder as this script;
}

#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
write-host "Enough free space on F:\ found...creating latest VHD"
CreateVHD

Open in new window

0
Tony JLead Technical ArchitectCommented:
Typo crept in (I am trying to manage two copies as I don't have an F: drive and I don't want everything in my D: drive deleted, just a test folder).

change
until ($fdisk -gt $Cdiskused)

Open in new window


to

until ($f -gt $c)

Open in new window

0
SpacedustPLAuthor Commented:
If I change

if ($f -lt $c) {

Open in new window


to

if ($f -gt $c) {

Open in new window


Then it works - removes all the images on the disk ;)
0
Tony JLead Technical ArchitectCommented:
Ok hopefully this time round I've got rid of any legacy typo's

# Null all the values
$Cdisk = $null
$Fdisk = $null
$CdiskCapacity =  $null
$CdiskFree =  $null
$CdiskUSed =  $null

#This function is called to determine the used space on the C: drive
function UsedDiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
return $cdiskUsed
}

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function FreeDiskSpace() {
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$fdisk = $fdisk.freespace/1073741824
return $Fdisk
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}


#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.

Do {
$c = useddiskspace
$f = freediskspace


if ($f -lt $c) {

write-host "Space used on C: = "$c
write-host "Free space on F: = "$f
write-host "Not enough free space on F: Drive. Deleting oldest image"
DelVHD
}
}
until ($f -gt $c)

write-host "Enough free space on F:\ found...creating latest VHD"
CreateVHD

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
SpacedustPLAuthor Commented:
Good - it works now,

Would be great to hide Disk2Vhd inside a tray icon ;)
0
Tony JLead Technical ArchitectCommented:
Yeah unfortunately it doesn't look like there is a command line to do that :)

Sorry it took so many iterations....I shouldn't think "Hmmm...5 minute script will do this"
0
SpacedustPLAuthor Commented:
I will be testing it for a few days now ;)
0
Tony JLead Technical ArchitectCommented:
Let me know how you get on!

One of the reasons I like powershell is it's fairly easy to set up scheduled tasks to run jobs like this overnight in the background.
0
SpacedustPLAuthor Commented:
It works well but I got this Windows Powershell left opened when the script is finished ;)

Maybe we can add some exit out there ?
0
Tony JLead Technical ArchitectCommented:
You still running it with the noexit switch?...
0
SpacedustPLAuthor Commented:
Yes - that's probably the reason ;) Now it closes itself.

Is there any possibility to hide Disk2VHD window ?
0
Tony JLead Technical ArchitectCommented:
Ok I'll caveat this by saying it's another quick hit but my equally quick test suggests it'll work:

# Null all the values
$Cdisk = $null
$Fdisk = $null
$CdiskCapacity =  $null
$CdiskFree =  $null
$CdiskUSed =  $null
$Hidden = $null

#This function is called to determine the used space on the C: drive
function UsedDiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
return $cdiskUsed
}

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function FreeDiskSpace() {
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$fdisk = $fdisk.freespace/1073741824
return $Fdisk
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}

#Actually create the VHD
Function CreateVHD($Hidden) {
$filename = (get-date -uformat %d%b%y) + "_"  + $Env:COMPUTERNAME + ".vhd"
$filename = "F:\"+$Filename
    If ($Hidden -eq $True){.start-process -WindowStyle Hidden .\disk2vhd.exe c: $filename } # The .\ assumes disk2vhd is in the same folder as this script;
    ElseIf ($Hidden -eq $False){.\disk2vhd.exe c: $filename } # The .\ assumes disk2vhd is in the same folder as this script;
}


#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
Do {
$c = useddiskspace
$f = freediskspace


if ($f -lt $c) {

write-host "Space used on C: = "$c
write-host "Free space on F: = "$f
write-host "Not enough free space on F: Drive. Deleting oldest image"
DelVHD
}
}
until ($f -gt $c)

write-host "Enough free space on F:\ found...creating latest VHD"
CreateVHD $True #$True to hide the process; $False to have it run visible

Open in new window

0
SpacedustPLAuthor Commented:
OK. I will check it out ;)
0
SpacedustPLAuthor Commented:
It doesn't work. Disk2VHD does not start ;(
0
SpacedustPLAuthor Commented:
See this error:

PS C:\> C:\backup.ps1
Enough free space on F:\ found...creating latest VHD
.start-process : The term '.start-process' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, v
erify that the path is correct and try again.
At C:\backup.ps1:34 char:28
+     If ($Hidden -eq $True){.start-process -WindowStyle Hidden .\disk2vhd.exe c:  ...
+                            ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (.start-process:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Open in new window

0
SpacedustPLAuthor Commented:
Also please note: You can use 1GB instead of 1073741824.
0
Tony JLead Technical ArchitectCommented:
Oh man. Shouldn't be a . In front of start-process
0
SpacedustPLAuthor Commented:
Now I got this ;)

PS C:\> C:\backup.ps1
Enough free space on F:\ found...creating latest VHD
Start-Process : A positional parameter cannot be found that accepts argument 'F:\23wrz15_MACPRO.vhd'.
At C:\backup.ps1:34 char:28
+     If ($Hidden -eq $True){start-process -WindowStyle Hidden .\disk2vhd.exe c: $ ...
+                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand

Open in new window

0
Tony JLead Technical ArchitectCommented:
This the problem when your test environment is ever so slightly different.

Needed to pass the arguments separately to the start-process line:

# Null all the values
$Cdisk = $null
$Fdisk = $null
$CdiskCapacity =  $null
$CdiskFree =  $null
$CdiskUSed =  $null

#This function is called to determine the used space on the C: drive
function UsedDiskSpace() {
$Cdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size,FreeSpace
$CdiskCapacity = $Cdisk.size/1073741824
$CdiskFree = $Cdisk.freespace/1073741824
$CdiskUSed = $CdiskCapacity-$CDiskFree
return $cdiskUsed
}

#This function is called repeatedly until the space on the F: drive is greater than the used space on the C: drive
function FreeDiskSpace() {
$Fdisk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='F:'" | Select-Object Size,FreeSpace
$fdisk = $fdisk.freespace/1073741824
return $Fdisk
}

#This function will simply delete the oldest file in the root of the F: drive
Function DelVHD {
Get-ChildItem F:\ | Sort CreationTime | Select -First 1 | Remove-Item -force -Recurse
}

#Create the VHD - pass $true to run the Disk2VHD program hidden; $False for visible. First run should be false to allow agreement of EULA.!
Function CreateVHD($Hidden) {
$filename = (get-date -uformat %d%b%y) + "_"  + $Env:COMPUTERNAME + ".vhd"
$filename = "F:\"+$Filename
    If ($Hidden -eq $True){
        start-process -WindowStyle Hidden .\disk2vhd.exe -argumentlist 'c:', $filename # The .\ assumes disk2vhd is in the same folder as this script;
    }
        ElseIf ($Hidden -eq $False){.\disk2vhd.exe c: $filename # The .\ assumes disk2vhd is in the same folder as this script;
    }
}

#This loop kicks everything off - it gets the free disk space, deletes files one at a time on F: as required and then creates the VHD when there is sufficient disk space freed up.
Do {
$c = useddiskspace
$f = freediskspace


if ($f -lt $c) {

write-host "Space used on C: = "$c
write-host "Free space on F: = "$f
write-host "Not enough free space on F: Drive. Deleting oldest image"
DelVHD
}
}
until ($f -gt $c)

write-host "Enough free space on F:\ found...creating latest VHD"
CreateVHD $true #NOTE - Run with $False so the Disk2VHD window is visible at least the first time in order to accept the EULA

Open in new window

0
SpacedustPLAuthor Commented:
It works now, but disk2vhd window is still visible ;(
0
Tony JLead Technical ArchitectCommented:
For goodness sake...it would appear that if you don't pass additional command line parameters to disk2vhd it's perfectly happy to run hidden...the moment you pass them it displays

Which is somewhat backwards, in my humble opinion.

Sorry mate...looks like visible is the only option. :(
0
SpacedustPLAuthor Commented:
Probably I would need to run it with some tray minimizer ;)
0
SpacedustPLAuthor Commented:
Found what I was looking for ;) http://www.whitsoftdev.com/trayconizer/
0
SpacedustPLAuthor Commented:
It's not working - must be too old for Windows 7 SP1
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Storage Software

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.