Compare the total capacity of two drives

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
coder_chick
Posts: 235
Joined: 05 Nov 2015, 10:43

Compare the total capacity of two drives

18 May 2017, 19:43

I need a script to compare the total capacity of a physical hard drive 0 to the free space of the destination path.

I should be able to use the following for free space of the destination path...
https://autohotkey.com/docs/commands/DriveSpaceFree.htm

However, the DriveGet command appears to only allow you to specify via drive letter, which is kind of stupid. You could have other partitions on a drive or unpartitioned space on a drive, so the capacity it returns is technically not that of the entire drive. https://autohotkey.com/docs/commands/DriveGet.htm

How can I accomplish this? I want to compare the two, and if there is not enough free space in the destination for the entire physical drive size, then it should pop up a message saying not enough space.

I might be able to do it using the WMI info found. Great script found here https://autohotkey.com/boards/viewtopic.php?t=1976#, but I just don't understand how to tell it to only look at \\.\PHYSICALDRIVE0 and to only pull the "Size:" value and store that in a variable. I'm not good with the way that code is written.
♥ ❤ ❥ coder_chick ♥ ❤ ❥
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Compare the total capacity of two drives

18 May 2017, 19:59

will share function shortly ...

[EDIT:] 7 minutes later.
I believe I wrote this function to get the hard disk space in bytes, so I could round it to the nearest megabyte, when installing applications, to determine how much hard disk space they took up.

According to MSDN, you might be able to pass a volume label to GetDiskFreeSpaceEx.

[EDIT:] Improved the function slightly. You could try passing a UNC name (see the MSDN page for GetDiskFreeSpaceEx) to the vDrive parameter, I don't ever use partitions or anything like that, so it would be interesting to know if it works. Cheers.

Code: Select all

;e.g. MsgBox, % JEE_DriveSpace("C")
;e.g. MsgBox, % JEE_DriveSpace("C", "g", "c")

JEE_DriveSpace(vDrive, vUnit="m", vType="f")
{
	if RegExMatch(vDrive, "^[A-Za-z]:?$") ;e.g. 'C' or 'C:' to 'C:\'
		vDrive := SubStr(vDrive, 1, 1) ":\"
	if (vUnit = "")
		vUnit := "m"
	vUnit := SubStr(vUnit, 1, 1)
	vType := SubStr(vType, 1, 1)

	if !RegExMatch(vUnit, "b|k|m|g|t|p|e")
		return
	if !RegExMatch(vType, "u|f|c")
		return

	DllCall("GetDiskFreeSpaceEx" (A_IsUnicode?"W":"A"), Str,vDrive, UInt64P,vFree, UInt64P,vCapacity, UInt64P,vFree2)
	vUsed := vCapacity - vFree
	vNum := (vType = "u") ? vUsed : (vType = "f") ? vFree : vCapacity

	(vUnit = "b") ? (vSpace := vNum) : ""
	(vUnit = "k") ? (vSpace := Floor(vNum/1024)) : ""
	(vUnit = "m") ? (vSpace := Floor(vNum/1024**2)) : ""
	(vUnit = "g") ? (vSpace := Floor(vNum/1024**3)) : ""
	(vUnit = "t") ? (vSpace := Floor(vNum/1024**4)) : ""
	(vUnit = "p") ? (vSpace := Floor(vNum/1024**5)) : ""
	(vUnit = "e") ? (vSpace := Floor(vNum/1024**6)) : ""
	return vSpace
}
[EDIT:] @Masonjar13: Cheers for the WMI code.
Last edited by jeeswg on 18 May 2017, 20:45, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: Compare the total capacity of two drives

18 May 2017, 20:40

This will allow you to use numbers (0-index) to get the size of a physical drive via wmi.

Code: Select all

; single drive
drive0SizeGB_1:=(drive0Size_1:=getDriveSize(0))/(1024**3)
msgbox % "GB: " . drive0SizeGB_1 . "`nBytes: " . drive0Size_1

; all drives (array will be 0-index)
allDrives:=(getDriveSize())
for i,a in allDrives
    msgbox,,% "Drive: " . i,% "GB: " . a/(1024**3) . "`nBytes: " . a

getDriveSize(driveNum=-1){
    wmi:=comObjGet("winmgmts:{impersonationLevel=impersonate}!\\" . a_computerName . "\root\cimv2")
    wmiq:="Select Size From Win32_DiskDrive"
    dd:=wmi.ExecQuery(wmiq)._NewEnum
    driveSizes:=object()
    while dd[ddObj] {
        if(a_index=1)
            driveSizes[0]:=ddObj["Size"]
        else
            driveSizes.push(ddObj["Size"])
    }
    if(driveNum>=0)
        return driveSizes[driveNum]
    return driveSizes
}
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
coder_chick
Posts: 235
Joined: 05 Nov 2015, 10:43

Re: Compare the total capacity of two drives

18 May 2017, 20:56

Mason, something is up with the numbers. Your popup says my Drive 0 is 1863 GB (but disk management says 465.77 GB)
♥ ❤ ❥ coder_chick ♥ ❤ ❥
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: Compare the total capacity of two drives

19 May 2017, 04:26

Image
I can't replicate your issue. What OS are you on?
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Compare the total capacity of two drives

19 May 2017, 05:10

How I would do with wmi:

Code: Select all

for k, v in Win32_DiskDrive(0, 1)
    MsgBox % "Disk " k " -> " v.Size " GB"


Win32_DiskDrive(disks*)
{
    static DDRIVE := []
    for objItem in ComObjGet("winmgmts:").ExecQuery("SELECT * FROM Win32_DiskDrive") {
        for index, disk in disks
            if (objItem.Index = disk)
                DDRIVE[objItem.Index, "Size"] := Round(objItem.Size / 1024**3, 2)
    }
    return DDRIVE
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Compare the total capacity of two drives

19 May 2017, 06:59

(Repeating from earlier.) I would be grateful if someone could try passing a UNC name (see the MSDN page for GetDiskFreeSpaceEx) to the vDrive parameter in my function, I don't ever use partitions or anything like that, so it would be interesting to know if it works. Thanks.

GetDiskFreeSpaceEx function (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Ovg
Posts: 23
Joined: 19 Feb 2017, 01:13

Re: Compare the total capacity of two drives

19 May 2017, 07:23

2jeeswg

I have tried for local share(\\My PC\Share_Dir) and for network share (\\Server\Dir)- both working fine!
It's impossible to lead us astray for we don't care even to choose the way.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Compare the total capacity of two drives

19 May 2017, 07:25

Woah that's great, cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Compare the total capacity of two drives

19 May 2017, 07:32

Sure it works.. Why should not?
If this parameter is NULL, the function uses the root of the current disk.
If this parameter is a UNC name, it must include a trailing backslash, for example, "\\MyServer\MyShare\".
This parameter does not have to specify the root directory on a disk. The function accepts any directory on a disk.

Code: Select all

MsgBox % GetDiskFreeSpaceEx("D:\").total
MsgBox % GetDiskFreeSpaceEx("\\192.168.1.2\shared").total


GetDiskFreeSpaceEx(disk := "C:\")    ; https://msdn.microsoft.com/en-us/library/aa364937(v=vs.85).aspx
{
	static DISK_SPACE := {}
    if !(DllCall("GetDiskFreeSpaceEx", "str", disk, "uint64*", free, "uint64*", total, "uint64*", 0))
        throw Exception("GetDiskFreeSpaceEx failed: " A_LastError, -1)
    DISK_SPACE.free := StrFormatByteSizeEx(free), DISK_SPACE.total := StrFormatByteSizeEx(total)
    return DISK_SPACE
}

StrFormatByteSizeEx(int, flags := 0x2)    ; https://msdn.microsoft.com/en-us/library/bb892884(v=vs.85).aspx
{
    size := VarSetCapacity(buf, 0x0104, 0)
    if (DllCall("shlwapi.dll\StrFormatByteSizeEx", "int64", int, "int", flags, "str", buf, "uint", size) != 0)
        throw Exception("StrFormatByteSizeEx failed", -1)
    return buf
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Compare the total capacity of two drives

19 May 2017, 07:54

I'm not that familiar with UNC names or partitions. I'd imagined it could do special drives and subfolders, but I wasn't sure if it could also do partitions.

Btw a curious distinction:
- lpFreeBytesAvailable: 'A pointer to a variable that receives the total number of free bytes on a disk that are available to the user who is associated with the calling thread.'
- lpTotalNumberOfFreeBytes: 'A pointer to a variable that receives the total number of free bytes on a disk.'

It wasn't immediately clear which number the function should report back. I.e. which number does the OS show.

==================================================

[EDIT:] Btw @jNizM, cheers for this: ['C:\' to '\Device\HarddiskVolume2\']
Find the process that is locking a file/folder - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 285#p80285

Although I'm not sure if it's possible to do that in reverse directly.

Does '\Device\HarddiskVolume2\' qualify as a UNC name? This didn't work:

Code: Select all

MsgBox, % JEE_DriveSpace("\Device\HarddiskVolume2\")
MsgBox, % JEE_DriveSpace("\\Device\HarddiskVolume2\")
Is that a volume label, separate from a UNC name?
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
coder_chick
Posts: 235
Joined: 05 Nov 2015, 10:43

Re: Compare the total capacity of two drives

19 May 2017, 09:42

Masonjar13 wrote:Image
I can't replicate your issue. What OS are you on?
Win 10
♥ ❤ ❥ coder_chick ♥ ❤ ❥
User avatar
coder_chick
Posts: 235
Joined: 05 Nov 2015, 10:43

Re: Compare the total capacity of two drives

19 May 2017, 10:40

Thank you all. I figured it out. Here is my code. I am sure there is a million ways to do this, but your code examples helped point me in the right direction.

Code: Select all

;source = \\.\PHYSICALDRIVE2
source = C:
destination = G:


;Gather size of source HDD (if physical) in MB
IfInString, source, \\.\PHYSICALDRIVE ; if the source conatins PHYSICALDRIVE then follow this process
{
	source_drivenumber := SubStr(source, InStr(source, "PHYSICALDRIVE") + 13) ; grab drive number after \\.\PHYSICALDRIVE
    ;MsgBox, % source_drivenumber
    
for k, v in Win32_DiskDrive(source_drivenumber) ;gathers the HDD size of the source drive
    source_size := v.Size
	msgbox, %source_size%
}

;Gather size of source parition (if logical)
IfInString, source, : ; if the source conatins colon then follow this process
{
DriveGet, source_size, capacity, %source%  ;grabs logical size in MB
;source_partition_size_GB := source_partition_size_MB / 1024
msgbox, % source_size
}

;Gather free space size in MB of destination
IfInString, destination, : ; if the destination conatins a colon (which it always should)
{
DriveSpaceFree, destination_partition_freespace, %Destination%  ;grabs logical size in MB
msgbox, % destination_partition_freespace
}


;check if source can fit on destination

source_size := source_size + 3072  ;add another 3GB of buffer

if (source_size) > (destination_partition_freespace)
{
msgbox, you don't have enough room to store in the destination
}

if (source_size) < (destination_partition_freespace)
{
msgbox, You have enough room
}

;~ for k, v in Win32_DiskDrive(0, 1)
    ;~ MsgBox % "Disk " k " -> " v.Size " GB"

Win32_DiskDrive(disks*) ;gather size of physical disks on system
{
    static DDRIVE := []
    for objItem in ComObjGet("winmgmts:").ExecQuery("SELECT * FROM Win32_DiskDrive") {
        for index, disk in disks
            if (objItem.Index = disk)
                DDRIVE[objItem.Index, "Size"] := Round(objItem.Size / 1024**2, 2) ; change **2 to **3 to change to GB
    }
    return DDRIVE
}
♥ ❤ ❥ coder_chick ♥ ❤ ❥

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: JoeWinograd and 143 guests