Jump to content

DirGetSize() not changing after enabling compression on a folder


Sunblood
 Share

Recommended Posts

Simple script:
 

#RequireAdmin

$before = DirGetSize("C:\Windows\Installer")
$time = TimerInit()
RunWait("compact /c /s:C:\Windows\Installer")
$after = DirGetSize("C:\Windows\Installer")

MsgBox(0,"Complete","Size before: "&Round($before/1024/1024,2)&" MB"&@CRLF&"Size after: "&Round($after/1024/1024,2)&" MB"&@CRLF&"Total time: "&Round(TimerDiff($time)/1000,2)&" s")

This enables compression on C:\Windows\Installer, while storing the folder size before/after for comparison purposes. However when the end message displays, both $before and $after are the same value. Anyone know if there is some sort of refresh delay to account for, or if DirGetSize() always retrieves the uncompressed size (making my comparison essentially impossible?)

 

EDIT: after some testing, seems DirGetSize() does not return the "size on disk" value, but just the "Size" value which does not change when compression is enabled in Windows.

image.png.a06654af3493ec013f2f0676acb834db.png

Edited by Sunblood
Link to comment
Share on other sites

Interestingly enough, the DIR cmd also does not return the compressed (size on disk) size.  I could be off base here, but I suspect it may have to do with the underlying API call.  According to the MSDN article for the GetFileSize function, it is stated that, "...The GetFileSize function retrieves the uncompressed size of a file. Use the GetCompressedFileSize function to obtain the compressed size of a file." 

Perhaps the underlying API call isn't using that specific function, but I at least got a clue that it takes additional consideration to obtain the compressed size.  Looking at the function, it is specifically for files, which makes sense if you think about it as folders themselves do not have "sizes"--let's not get into how directories are stored in the File System right now...

I pieced together a simple function to recursively collect the compressed file sizes of a files within a directory using the GetCompressedFileSize function above, which I referenced from another post on the forum authored by Ascend4nt.

#include <File.au3>
#include <WinAPI.au3>

$sPath = "C:\Test"
$iDirSize = _DirGetCompressedSize($sPath)
Msgbox(0,$sPath,$iDirSize)

Func _DirGetCompressedSize($sPath)
    Local $aFileList = _FileListToArrayRec($sPath,Default,$FLTAR_FILES,$FLTAR_RECUR)
    Local $iDirSize = 0

    If Not IsArray($aFileList) Then Return SetError(1,0,0)
    For $iFile = 1 to $aFileList[0]
        $iDirSize += _FileGetCompressedSize($sPath & "\" & $aFileList[$iFile])
    Next

    Return $iDirSize
EndFunc

Func _FileGetCompressedSize($sFile)
    If Not IsString($sFile) Or $sFile='' Then Return SetError(1,0,-1)
    Local $aRet=DllCall('kernel32.dll','dword','GetCompressedFileSizeW','wstr',$sFile,'dword*',0)
    If @error Then Return SetError(2,0,-1)
#cs
    ; -------------------------------------------------------------------------------------------------------------------
    ; Per MSDN, a return of 0 in FileSizeHigh AND a return of INVALID_FILE_SIZE (0xFFFFFFFF) in FileSizeLow means failure
    ;   The size of a file on disk will NEVER be INVALID_FILE_SIZE, which is an odd # (4,294,967,295 bytes to be exact),
    ;   however on regular (uncompressed, non-sparse file) files, this IS possible.
    ;   This requires a third check using GetLastError API call. Non-zero means the call failed.
    ; -------------------------------------------------------------------------------------------------------------------
#ce
    ; Size is 'INVALID_FILE_SIZE' and GetLastError returns something other than 'NO_ERROR' (0)?
    If $aRet[2]=0 And $aRet[0]=0xFFFFFFFF And _WinAPI_GetLastError()<>0 Then Return SetError(3,0,-1)
    Local $stFileSize64=DllStructCreate("uint64"),$stFileSizePts=DllStructCreate("dword[2]",DllStructGetPtr($stFileSize64))
    DllStructSetData($stFileSizePts,1,$aRet[0],1)
    DllStructSetData($stFileSizePts,1,$aRet[2],2)
    Return DllStructGetData($stFileSize64,1)
EndFunc

In my testing, the value still showed to be larger than what the folder properties was showing, but marginally.  Still much closer than what the raw file size is.  At least it gives you something to play with.  

Edited by spudw2k
Link to comment
Share on other sites

You could use those in #include <WinAPIFiles.au3> :

Func _WinAPI_GetCompressedFileSize($sFilePath)

But this one seems a nice alternative:

Func _WinAPI_GetFileSizeOnDisk($sFilePath)
This value is a multiple of the sector or cluster size of the specified physical device.

Link to comment
Share on other sites

  • 2 weeks later...

@Nine  Thanks for pointing those out.  I always forget to check the WinAPI UDF and frequently there exists a function for an MSDN article I reference.  
 

@Sunblood In the example I made above, you should be able to swap out the _FileGetCompressedSize() function I made with the _WinAPI_GetCompressedFileSize() func included in the WinAPIFiles.au3 UDF as pointed out by Nine.  They both make calls to the same GetCompressedFileSize DLL call, but might as well use the one that is 'blessed' by and included with AutoIt.

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...