JerryD Posted December 17, 2005 Posted December 17, 2005 In a script, I'm running WinZip command line to zip up some files. What I wanted to do was use RUN and then while the process ran use FileGetSize() to get the (temporary) zip file's size so I could display the progress. However, even though the file size regularly updates if I view the file in Windows Explorer, FileGetSize() reports the files size as zero. I thought I'd try using DLLCall and use the GetFileSize function in Kernel32.dll, but haven't been able to get it to work. At MSDN, it defines GetFileSize as follows: DWORD GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh ); Return Values: If the function succeeds, the return value is the low-order doubleword of the file size, and, if lpFileSizeHigh is non-NULL, the function puts the high-order doubleword of the file size into the variable pointed to by that parameter. If the function fails and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE. To get extended error information, call GetLastError. When lpFileSizeHigh is NULL, the results returned for large files are ambiguous, and you will not be able to determine the actual size of the file. It is recommended that you use GetFileSizeEx instead.I tried translating this into AutoIt as follows: $sFile = 'C:\psinfo.txt' $iSize=0 $Ret = DllCall ( 'Kernel32.dll', 'long', 'GetFileSize', 'int_ptr', $sFile, 'long_ptr', $iSize ) Although I'm not getting any error, I'm not getting any data either! I've tried a lot of different variable types for the different values with no success. Specific question - is there anyplace that has VBCode variable type to DLLCall variable type translation? For example, what should I be using for the 'HANDLE' type? I assume 'LPDWORD' would translate to 'long_ptr' in an AutoIt DLLCall. Can anyone help? Thanks in advance.
MrSpacely Posted December 18, 2005 Posted December 18, 2005 (edited) Hmm I gues the problem is that you need a filehandle not the filename. Maybe using the fileopen thing in autoit to get a filehandle might work as a filehandle. That only works if autoit uses externel handles for files in scripts. Maybe this helps you further I tested it and no difference. But lpFileSize [out] Pointer to a LARGE_INTEGER structure that receives the file size. That is a pointer I think you need to use dllstruct to get the data I'll check how that works(never tried it) Tried this but doesn't change the 345 I set. But its more the way it should be using the struct $str = "int64" $a = DllStructCreate($str) ;$sFile = FileOpen ( "debug.log", 0) $sFile = "debug.log" $iSize=0 DllStructSetData ( $a, 1, 345) $Ret = DllCall ( 'Kernel32.dll', 'long', 'GetFileSize', 'str', $sFile, 'long_ptr', DllStructGetPtr ( $a )) msgbox(0,"",DllStructGetData ( $a, 1 )) Maybe Its not the right handle try looking for CreateFile in the msdn and create a struct etc for that to get a windows filehandle Edited December 18, 2005 by MrSpacely
Valuater Posted December 18, 2005 Posted December 18, 2005 beacuse if this new zip program in Autoit... maybe you could just add a progreess to ithttp://www.autoitscript.com/forum/index.ph...pic=17727&st=0#just an idea8)
LxP Posted December 18, 2005 Posted December 18, 2005 Hmm I gues the problem is that you need a filehandle not the filename.Maybe using the fileopen thing in autoit to get a filehandle might work as a filehandle. That only works if autoit uses externel handles for files in scripts.My understanding is that AutoIt provides the scripter with pseudo-handles when they manipulate files. The actual Windows handles are kept hidden away.The v3.1.1 source uses a method that claims to work with 'in-use files'; it doesn't take the same approach that you are taking though.
MrSpacely Posted December 18, 2005 Posted December 18, 2005 My understanding is that AutoIt provides the scripter with pseudo-handles when they manipulate files. The actual Windows handles are kept hidden away.The v3.1.1 source uses a method that claims to work with 'in-use files'; it doesn't take the same approach that you are taking though.hmmI noticed I tried using the kernel32 to open a file and getting the handle but there is no working way to put that handle in variable and sending it to the next dllcall:SIs there a way to add HANDLE in the possible varibles or dllcall param types?hwnd is allready in there
Confuzzled Posted December 18, 2005 Posted December 18, 2005 Question: Are you seeing the actual temporary file that the ZIP program creates during the zipping process when you check the filesize? Isn't the filesize updated in the FAT/MFT table when the file is closed?
JerryD Posted December 18, 2005 Author Posted December 18, 2005 Question: Are you seeing the actual temporary file that the ZIP program creates during the zipping process when you check the filesize? Isn't the filesize updated in the FAT/MFT table when the file is closed?See the original post:However, even though the file size regularly updates if I view the file in Windows Explorer, FileGetSize() reports the files size as zero.So apparently not.
JerryD Posted December 18, 2005 Author Posted December 18, 2005 Hmm I gues the problem is that you need a filehandle not the filename. Maybe using the fileopen thing in autoit to get a filehandle might work as a filehandle. That only works if autoit uses externel handles for files in scripts. Maybe this helps you further I tested it and no difference. But lpFileSize [out] Pointer to a LARGE_INTEGER structure that receives the file size. That is a pointer I think you need to use dllstruct to get the data I'll check how that works(never tried it) Tried this but doesn't change the 345 I set. But its more the way it should be using the struct $str = "int64" $a = DllStructCreate($str) ;$sFile = FileOpen ( "debug.log", 0) $sFile = "debug.log" $iSize=0 DllStructSetData ( $a, 1, 345) $Ret = DllCall ( 'Kernel32.dll', 'long', 'GetFileSize', 'str', $sFile, 'long_ptr', DllStructGetPtr ( $a )) msgbox(0,"",DllStructGetData ( $a, 1 )) Maybe Its not the right handle try looking for CreateFile in the msdn and create a struct etc for that to get a windows filehandleNo matter what file name I use for $sFile, $Ret returns nothing, and DllStructGetData ( $a, 1 ) returns 340.
MrSpacely Posted December 18, 2005 Posted December 18, 2005 No matter what file name I use for $sFile, $Ret returns nothing, and DllStructGetData ( $a, 1 ) returns 340.I noticed it doesn't work. But ret should only return something in a array. os $ret would only show the size in $Ret[2] if it did works the problem is the file handle the internal filehandle of autoit is a pseudo file handle not a windows file handle so its not possible yet in my mind because you cannot transfer the windows filehandle in a autoit variable at least I think not
JerryD Posted December 19, 2005 Author Posted December 19, 2005 (edited) Well I took a different approach, and after plowing though documentation at MSDN, found a way to use a shell.application COM object. Here's what I came up with:expandcollapse popup#include-once ;=============================================================================== ; ; Function Name: _GetFileSize ( $sFileFullPath ) ; Description: Rerturns file size of file even if it's open and/or changing ; Parameter(s): $sFileFullPath - String: Full path to file ; Requirement(s): AutoIt 3.1.1.97+ (Requires COM object capability) ; Return Value(s): On Success - Returns the size of the file specified ; On Failure Returns: ; -1 - Couldn't create Shell object (don't know why this would happen) ; -2 - Couldn't get Folder object (typically because the directory doesn't exist) ; -3 - Couldn't get File object (typically because the file doesn't exist) ; Notes: $oShellObj.NameSpace($sDrive & $sPath) - doesn't appear to care if there ; is a trailing backslash after the path name ; Function can find hidden and system files. Untested if it can ; actually return their changing size though, but does return ; the size of pagefile.sys for instance. ; Author(s): JerryD ; ;=============================================================================== #include <File.au3> Func _GetFileSize ( $sFileFullPath ) Local $sDrive, $sPath, $sName, $sExt ; for call to _PathSplit Local $oShellObj, $oFolderObj, $oFolderItem; all Objects used in this function Local $RetErr_NoShellObj = -1 ; don't know what would cause this, but... Local $RetErr_NoFolderObj = -2 ; typically directory does not exist Local $RetErr_NoItemObj = -3 ; typically file does not exist _PathSplit ( $sFileFullPath, $sDrive, $sPath, $sName, $sExt ); This requires #include <File.au3> $oShellObj = ObjCreate ( 'shell.application' ) If NOT IsObj ( $oShellObj ) Then Return $RetErr_NoShellObj $oFolderObj = $oShellObj.NameSpace($sDrive & $sPath) If NOT IsObj ( $oFolderObj ) Then Return $RetErr_NoFolderObj $oFolderItem = $oFolderObj.ParseName ( $sName & $sExt ) If NOT IsObj ( $oFolderItem ) Then Return $RetErr_NoItemObj Return $oFolderItem.Size EndFunc; _GetFileSize()I'm using it in the script where I'm zipping up a gig of data, and instead of using RunWait in the script, I now use Run and then While ProcessExists ( 'wzzip.exe' ) and call the function within the While Loop to update a Progress bar and text. It's working exactly the way I need it to, and seems to work pretty quickly. Little or no degradation in the scripts performance in spite of the function being called every 1/4 second.Thanks to all for your help.UDF: http://www.autoitscript.com/fileman/users/public/JerryD/_GetFileSize.au3 Edited December 22, 2005 by JerryD
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now