Avatar of SpacedustPL
SpacedustPL
 asked on

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
Storage SoftwareWindows Server 2008Storage Hardware

Avatar of undefined
Last Comment
SpacedustPL

8/22/2022 - Mon
Tony J

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

SpacedustPL

ASKER
I'm running on Windows 7 Ultimate and nothing happens:

C:\Users\Marek>powershell -noexit "& ""C:\backup2.ps1"""
Tony J

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
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Tony J

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.
Tony J

Oh I just noticed - powershell -noexit "& ""C:\backup2.ps1""" won't work

Try:

powershell -noexit -command C:\backup2.ps1
SpacedustPL

ASKER
Even running under 64-bit PowerShell ISE doesn't show any errors. It's just running but nothing is moving on.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
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).
Tony J

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.
Tony J

I may also have misformed the vhd2disk line -

Try changing it to

.\disk2vhd c: "F:\"$filename
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
SpacedustPL

ASKER
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.
Tony J

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.
SpacedustPL

ASKER
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.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Tony J

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
Tony J

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!
SpacedustPL

ASKER
Please see how it looks:

Screenshot
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Lionel MM

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
Tony J

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

SpacedustPL

ASKER
Still nothing. Just blinking cursor.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Tony J

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.
SpacedustPL

ASKER
That works well ;)

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

Open in new window

Tony J

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

Your help has saved me hundreds of hours of internet surfing.
fblack61
SpacedustPL

ASKER
Blinking cursor again - no output ;)

Also nothing is removed. I got two VHD images waiting in the root of F: drive.
Tony J

How big are the files?

Might be that they are going but it will take a while.
SpacedustPL

ASKER
231 GB each - it takes about 2-3 seconds to remove them normally from Seagate 5900 rpm 4 TB drive.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
Also I got about 4% CPU (2x Intel Xeon X5675) usage when running this script - it's probably some infinite loop.
SpacedustPL

ASKER
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

SpacedustPL

ASKER
This seems to be working:

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

but asks for confirmation
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
SpacedustPL

ASKER
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

Tony J

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

Tony J

Hmm the -force should make it assume "Yes"
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Tony J

And yes...I created some 500MB files to test and they went in seconds.
SpacedustPL

ASKER
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

SpacedustPL

ASKER
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

All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
SpacedustPL

ASKER
Also I don't know why it removing the oldest folders first instead of files ;)
Tony J

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

Tony J

Duh..I just spotted you have folders. Yeah that'd need the recurse switch.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
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

Tony J

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

SpacedustPL

ASKER
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

Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Tony J

powershell isn't case sensitve. :)
SpacedustPL

ASKER
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

Tony J

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
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
I got this:
PS C:\Users\Marek> C:\backup2.ps1
1153,06732559204
221,421562194824
1153,06732559204
221,421562194824

Open in new window

Tony J

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.
SpacedustPL

ASKER
Still nothing - just blinking cursor ;(
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
SpacedustPL

ASKER
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

Tony J

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

SpacedustPL

ASKER
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 ;)
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Tony J

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
Good - it works now,

Would be great to hide Disk2Vhd inside a tray icon ;)
Tony J

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"
SpacedustPL

ASKER
I will be testing it for a few days now ;)
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Tony J

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.
SpacedustPL

ASKER
It works well but I got this Windows Powershell left opened when the script is finished ;)

Maybe we can add some exit out there ?
Tony J

You still running it with the noexit switch?...
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
Yes - that's probably the reason ;) Now it closes itself.

Is there any possibility to hide Disk2VHD window ?
Tony J

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

SpacedustPL

ASKER
OK. I will check it out ;)
Your help has saved me hundreds of hours of internet surfing.
fblack61
SpacedustPL

ASKER
It doesn't work. Disk2VHD does not start ;(
SpacedustPL

ASKER
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

SpacedustPL

ASKER
Also please note: You can use 1GB instead of 1073741824.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Tony J

Oh man. Shouldn't be a . In front of start-process
SpacedustPL

ASKER
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

Tony J

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

This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
SpacedustPL

ASKER
It works now, but disk2vhd window is still visible ;(
Tony J

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. :(
SpacedustPL

ASKER
Probably I would need to run it with some tray minimizer ;)
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
SpacedustPL

ASKER
Found what I was looking for ;) http://www.whitsoftdev.com/trayconizer/
SpacedustPL

ASKER
It's not working - must be too old for Windows 7 SP1