Zedna Posted April 13, 2007 Share Posted April 13, 2007 Here is my code snippet (simplified from my bigger FTP app). I started to play with _FtpFileFindFirst and _FtpFileFindNext but there was problems to get data in correct data format - time and size are as 64 bit number stored in two 32 bit places and I didn't know how to convert them. Then I havent time, so it stays unfinished ... So you can take it as start point ... #include <GuiConstants.au3> #include <ftp.au3> Dim $Handle, $DllRect $dllhandle = DllOpen('wininet.dll') $Open = _FTPOpen ('MyFTP Control',0) If @error Then Failed("Open") $Conn = _FTPConnect ($Open, 'ftp.microsoft.com', 'anonymous', 'anonymous') If @error Then Failed("Connect") $FileInfo = _FtpFileFindFirst ($Conn, "/Products/frontpage/*.*", $Handle, $DllRect) While $FileInfo[0] ConsoleWrite("Find: " & $FileInfo[1] & @CR & $FileInfo[2] & @CR & $FileInfo[3] & @CR & $FileInfo[4] & @CR & $FileInfo[5] & @CR & $FileInfo[6] & @CR & $FileInfo[7] & @CR & $FileInfo[8] & @CR & $FileInfo[9] & @CR & $FileInfo[10]) ; The size of the file is equal to (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow. MAXDWORD = 0xffffffff $file_name = $FileInfo[10] $file_size = BitShift($FileInfo[8],-32) + $FileInfo[9] ;~ $file_size = $FileInfo[8] * 4294967296 + $FileInfo[9] $file_time = BitShift($FileInfo[7],-32) + $FileInfo[6] ; probably bad!! maybe is wrong uint[2] ;~ $file_time = $FileInfo[6] * 4294967296 + $FileInfo[7] ConsoleWrite("Final: " & $file_name & ' ' & $file_size & ' ' & $file_time & @CRLF) $FileInfo = _FtpFileFindNext ($Handle, $DllRect) WEnd _FtpFileFindClose ($Handle, $DllRect) _FTPClose ($Open) DllClose($dllhandle) Func Failed($error) MsgBox(48, 'Error', $error) Exit EndFunc Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
lolwut Posted April 14, 2007 Share Posted April 14, 2007 Absolutely great UDF, in fact this should be included in the installer! Link to comment Share on other sites More sharing options...
joeyb1275 Posted April 15, 2007 Share Posted April 15, 2007 Added some new functions to FTP.au3 _FTPFindFirstFile() _FTPFindNextFile() _FTPGetLinkStringInfo() _FileTimeToSystemTime() There are comments in the code to see how to use these and what they do. The biggest change might be with the FTPFindFirstFile(), where it only returns the search hwnd and FTPFindNextFile() will return the filenames or an array of attributes. I think I solved the time converting problem with the high and low words but run the scripts and see if it works. I also add a few constants at the beginning. Here is a run down of the new functions: expandcollapse popup;=============================================================================== ; Function Name: _FTPFindFirstFile() ; Description: Returns a search handle to be used with _FTPFindNextFile() ; Parameter(s): $hConnect - The long from _FTPConnect() ; $lpszSearchFile - The remote Location for the file. ; $dwFlags - use the dwFlags parameter to specify 1 for transferring the file in ASCII (Type A transfer method) or 2 for transferring the file in Binary (Type I transfer method). ; $dwContext - lContext is used to identify the application context when using callbacks (Default: 0) ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - Returns Search Handle ; On Failure - 0; Sets @error = -1 ; Comments: Tested with Current Remote Directory only, use _FtpSetCurrentDir() to change directory before calling _FTPFindFirstFile() ; Remember to call _FTPClose($SearchHwnd) to close the search handle ;=============================================================================== Func _FTPFindFirstFile($hConnect, $lpszSearchFile = "",$dwFlags = 0, $dwContext = 0) $WIN32_FIND_DATA = DllStructCreate($s_WIN32_FIND_DATA) Local $ai_FTPFirstFile = DllCall('wininet.dll', 'hwnd', 'FtpFindFirstFile', _ 'long', $hConnect, _ ;HINTERNET hConnect 'str', $lpszSearchFile, _ ;LPCTSTR lpszSearchFile 'ptr',DllStructGetPtr($WIN32_FIND_DATA), _ ;LPWIN32_FIND_DATA lpFindFileData 'long',$dwFlags, _ ;DWORD dwFlags 'long', $dwContext) ;DWORD_PTR dwContext If @error OR $ai_FTPFirstFile[0] = 0 Then SetError(-1) Return 0 EndIf Return $ai_FTPFirstFile[0] EndFunc ;==> _FTPFindFirstFile() ;=============================================================================== ; Function Name: _FTPFindNextFile() ; Description: Find Next File on an FTP server. ; Parameter(s): $hFind - The search hwnd returned by _FTPFindFirstFile() ; $sFilter - Search Filter (Default = "*.*"). ; $sFlag - 0(Default) Return both files and folders names ; - 1 Return file names only (Folders are returned as -1) ; - 2 Return folder names only (Files are returned as -1) ; - 3 Return Attributes Array (includes file/folder name) ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - Filename or Attributes Array ; On Failure - Last Filename or Attributes Array and @error = -1 ;=============================================================================== Func _FTPFindNextFile($hFind,$sFilter = "*.*", $sFlag = 0) Local $LastFilename Local $FileAttributes = DllStructGetData($WIN32_FIND_DATA, 1) ; File Attributes Switch $sFlag Case 0 $LastFilename = DllStructGetData($WIN32_FIND_DATA, 9) Case 1 If $FileAttributes <> $FILE_ATTRIBUTE_DIRECTORY Then $LastFilename = DllStructGetData($WIN32_FIND_DATA, 9) Else $LastFilename = -1 EndIf Case 2 If $FileAttributes == $FILE_ATTRIBUTE_DIRECTORY Then $LastFilename = DllStructGetData($WIN32_FIND_DATA, 9) Else $LastFilename = -1 EndIf Case 3 Local Const $MAXDWORD = 4294967295 Dim $a_FTPFileList[8] $a_FTPFileList[0] = 7 $a_FTPFileList[1] = DllStructGetData($WIN32_FIND_DATA, 1) ; File Attributes $FILETIME = DllStructCreate("dword;dword") DllStructSetData($FILETIME, 1, DllStructGetData($WIN32_FIND_DATA, 2, 1)); Creation Time Low DllStructSetData($FILETIME, 2, DllStructGetData($WIN32_FIND_DATA, 2, 2)); Creation Time High $a_FTPFileList[2] = _FileTimeToSystemTime(DllStructGetPtr($FILETIME)) $FILETIME = 0 $FILETIME = DllStructCreate("dword;dword") DllStructSetData($FILETIME, 1, DllStructGetData($WIN32_FIND_DATA, 3, 1)); Access Time Low DllStructSetData($FILETIME, 2, DllStructGetData($WIN32_FIND_DATA, 3, 2)); Access Time High $a_FTPFileList[3] = _FileTimeToSystemTime(DllStructGetPtr($FILETIME)) $FILETIME = 0 $FILETIME = DllStructCreate("dword;dword") DllStructSetData($FILETIME, 1, DllStructGetData($WIN32_FIND_DATA, 4, 1)); Last Write Time Low DllStructSetData($FILETIME, 2, DllStructGetData($WIN32_FIND_DATA, 4, 2)); Last Write Time High $a_FTPFileList[4] = _FileTimeToSystemTime(DllStructGetPtr($FILETIME)) $FILETIME = 0 ;The size of the file is equal to (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow $a_FTPFileList[5] = (DllStructGetData($WIN32_FIND_DATA, 5) * ($MAXDWORD + 1)) + DllStructGetData($WIN32_FIND_DATA, 6) $a_FTPFileList[6] = DllStructGetData($WIN32_FIND_DATA, 9); File Name $a_FTPFileList[7] = DllStructGetData($WIN32_FIND_DATA, 10) ; Altername ;~ _ArrayDisplay($a_FTPFileList,"$a_FTPFileList") EndSwitch Local $ai_FTPNextFile = DllCall('wininet.dll', 'int', 'InternetFindNextFile', _ 'long', $hFind, _ ;HINTERNET hFind 'ptr',DllStructGetPtr($WIN32_FIND_DATA)) ;LPVOID lpvFindData If @error OR $ai_FTPNextFile[0] = 0 Then $WIN32_FIND_DATA = 0 ;free memory SetError(-1) If $sFlag == 3 Then Return $a_FTPFileList Else Return $LastFilename EndIf EndIf If $sFlag == 3 Then Return $a_FTPFileList Else Return $LastFilename EndIf EndFunc ;==> _FTPFindNextFile() ;=============================================================================== ; Function Name: _FTPGetLinkStringInfo() ; Description: Gets Information about an ftp string (ie. "ftp://user:pass@servername:port/path/" or "servername:port/path" ; Parameter(s): $s_FTPLink - [in]The string to get the information from (ie. "ftp://user:pass@servername:port/") ; $s_ServerName - [in/out] Name of the Server (ie. name.host.net) ; $s_Username - [in/out] Name of the user if found in $s_FTPLink ; $s_Password - [in/out] Password for user if found in $s_FTPLink ; $i_ServerPort - [in/out] Port toi connect on if found in $s_FTPLink (Default: 21) ; Requirement(s): None ; Return Value(s): On Success - Returns the path from $s_FTPLink ; - Sets Extended to 1 for $s_FTPLink to ahve form of "ftp://...../" ; - Sets Extended to 2 for $s_FTPLink to ahve form of " name.host.net...." ; On Failure - 0 and @error = -1 ;=============================================================================== Func _FTPGetLinkStringInfo($s_FTPLink,ByRef $s_ServerName, ByRef $s_Username, ByRef $s_Password, ByRef $i_ServerPort) Local $errFlag = 0,$extFlag = 0 Local $s_ServerPort,$s_FTPPath If StringInStr($s_FTPLink,"ftp://") Then ;Written as Link ie. ftp://user:pass@servername:port/path/) $extFlag = 2 If StringInStr($s_FTPLink,"@") Then ;has info about username and password (ie. ftp://user:pass@servername/) $s_Username = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,":",0,2) - StringInStr($s_FTPLink,"ftp://") - 6) $s_Password = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,2) + 1,StringInStr($s_FTPLink,"@") - StringInStr($s_FTPLink,":",0,2)-1) If StringInStr($s_FTPLink,":",0,3) Then ;has info about port (ftp://user:pass@servername:port or ftp://user:pass@servername:port/) If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://user:pass@servername:port/path/) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1,StringInStr($s_FTPLink,":",0,3) - StringInStr($s_FTPLink,"@") - 1) $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,3) + 1,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-1) $i_ServerPort = Number($s_ServerPort) $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/" Else ;no trailing slash (ftp://user:pass@servername:port) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1,StringInStr($s_FTPLink,":",0,3) - StringInStr($s_FTPLink,"@")-1) $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,3) + 1) $i_ServerPort = Number($s_ServerPort) $s_FTPPath = "/" EndIf Else ; no info about port assume default: 21 (ftp://user:pass@servername or ftp://user:pass@servername/) $i_ServerPort = 21 If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://user:pass@servername/path/) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"@")-1) $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/" Else ;no trailing slash (ftp://user:pass@servername) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"@") + 1) $s_FTPPath = "/" EndIf EndIf Else ;no info about username and password (ie. ftp://servername/ or ftp://servername:port) If StringInStr($s_FTPLink,":",0,2) Then ;has info about port (ftp://servername:port or ftp://servername:port/) If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://servername:port/path/) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,":",0,2) - StringInStr($s_FTPLink,"ftp://")-6) $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,2) + 1,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-1) $i_ServerPort = Number($s_ServerPort) $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/" Else ;no trailing slash (ftp://servername:port) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,":",0,2) - StringInStr($s_FTPLink,"ftp://")-6) $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":",0,2) + 1) $i_ServerPort = Number($s_ServerPort) $s_FTPPath = "/" EndIf Else ; no info about port assume default: 21 (ie. ftp://servername or ftp://servername/) $i_ServerPort = 21 If StringInStr($s_FTPLink,"/",0,3) Then ;trailing slash exists or a path was included (ie. ftp://servername/path/) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-6) $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/",0,3)) ;including root "/" Else ;no trailing slash (ftp://servername) $s_ServerName = StringMid($s_FTPLink,StringInStr($s_FTPLink,"ftp://") + 6,StringInStr($s_FTPLink,"/",0,3) - StringInStr($s_FTPLink,"ftp://")-6) $s_FTPPath = "/" EndIf EndIf EndIf ElseIf StringInStr($s_FTPLink,".") Then ;Written with ftp servername not as Link ie. servername:port/path $extFlag = 1 If StringInStr($s_FTPLink,":") Then ;port number exists servername:port or servername:port/path $s_ServerName = StringMid($s_FTPLink,1,StringInStr($s_FTPLink,":") - 1) If StringInStr($s_FTPLink,"/") Then ;path info exists servername:port/path $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":") + 1,StringInStr($s_FTPLink,"/") - StringInStr($s_FTPLink,":")-1) $i_ServerPort = Number($s_ServerPort) $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/")) Else ;no slash found servername:port $s_ServerPort = StringMid($s_FTPLink,StringInStr($s_FTPLink,":") + 1) $i_ServerPort = Number($s_ServerPort) $s_FTPPath = "/" EndIf Else ; no port info assume default: 21 (ie. servername or servername/path) $i_ServerPort = 21 If StringInStr($s_FTPLink,"/") Then ;path info exists $s_ServerName = StringMid($s_FTPLink,1,StringInStr($s_FTPLink,"/") - 1) $s_FTPPath = StringMid($s_FTPLink,StringInStr($s_FTPLink,"/")) Else $s_ServerName = $s_FTPLink $s_FTPPath = "/" EndIf EndIf Else ;might not be a string containg ftp information $extFlag = 0 $errFlag = -1 $s_FTPPath = 0 EndIf SetExtended($extFlag) SetError($errFlag) Return $s_FTPPath EndFunc ;=============================================================================== ; Function Name: _FileTimeToSystemTime() ; Description: Converts the FILETIME struct to more useful information. ; Parameter(s): $p_FILETIME - [in] pointer to the FILETIME struct ; Requirement(s): DllCall, Kernel32.dll ; Return Value(s): On Success - A pipe delimited string (ie. Year|Month|DayOfWeek|Day|Hour|Minute|Second|Milliseconds|; ; On Failure - 0 and Sets @error = -1 ;=============================================================================== Func _FileTimeToSystemTime($p_FILETIME) ;uses Kernel32.dll $SYSTEMTIME = DllStructCreate("short;short;short;short;short;short;short;short") Local $ai_FileTime = DllCall('Kernel32.dll', 'int', 'FileTimeToSystemTime', _ 'ptr', $p_FILETIME, _ ;const FILETIME* lpFileTime 'ptr',DllStructGetPtr($SYSTEMTIME)) ;LPSYSTEMTIME lpSystemTime If @error OR $ai_FileTime[0] = 0 Then SetError(-1) Return 0 EndIf Local $s_FileTime = "" For $i = 1 To 8 If $i == 3 Then ;day of the week Switch DllStructGetData($SYSTEMTIME,$i) Case 0 $s_FileTime &= "Sunday" & "|" Case 1 $s_FileTime &= "Monday" & "|" Case 2 $s_FileTime &= "Tuesday" & "|" Case 3 $s_FileTime &= "Wednesday" & "|" Case 4 $s_FileTime &= "Thursday" & "|" Case 5 $s_FileTime &= "Friday" & "|" Case 6 $s_FileTime &= "Saturday" & "|" EndSwitch EndIf $s_FileTime &= DllStructGetData($SYSTEMTIME,$i) & "|" Next $SYSTEMTIME = 0 ;free memory Return $s_FileTime EndFuncFTP.au3 Link to comment Share on other sites More sharing options...
JohnBailey Posted April 16, 2007 Share Posted April 16, 2007 joeyb1275 nice job!! I was trying to figure out how to do that on Friday, but didn't get to the point you did. thank you!Guys, questions: 1. What does Time Low and Time High mean? I found http://msdn2.microsoft.com/en-us/library/ms724284.aspx, but I don't really understand what it means. 2. The return data for the times are 1601|1|Monday|1|1|0|0|0|0| 1601|1|Monday|1|1|0|0|0|0| 2001|3|Thursday|4|29|0|0|0|0|what do the placements mean? I can't find a doc on MSDN (yet) that explains it.Thanks! A decision is a powerful thing Link to comment Share on other sites More sharing options...
JohnBailey Posted April 16, 2007 Share Posted April 16, 2007 (edited) Wrote too soonThis explains what the return time info is http://msdn2.microsoft.com/en-us/library/ms724950.aspx;=============================================================================== ; Function Name: _FileTimeToSystemTime() ; Description: Converts the FILETIME struct to more useful information. ; Parameter(s): $p_FILETIME - [in] pointer to the FILETIME struct ; Requirement(s): DllCall, Kernel32.dll ; Return Value(s): On Success - A pipe delimited string (ie. Year|Month|DayOfWeek|Day|Hour|Minute|Second|Milliseconds|; ; On Failure - 0 and Sets @error = -1 ; ; Note(s): Retruns _SYSTEMTIME {WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds} ;=============================================================================== Edited April 16, 2007 by JohnBailey A decision is a powerful thing Link to comment Share on other sites More sharing options...
Zedna Posted April 16, 2007 Share Posted April 16, 2007 (edited) Added some new functions to FTP.au3 _FTPFindFirstFile() _FTPFindNextFile() _FTPGetLinkStringInfo() _FileTimeToSystemTime() There are comments in the code to see how to use these and what they do. The biggest change might be with the FTPFindFirstFile(), where it only returns the search hwnd and FTPFindNextFile() will return the filenames or an array of attributes. I think I solved the time converting problem with the high and low words but run the scripts and see if it works. I also add a few constants at the beginning. Here is a run down of the new functions: Good work joeyb1275!! But I have some ideas: 1) _FileTimeToSystemTime() shouldn't return data your way. The worst is conversion DayOfWeek to English string. What about non English? By me it could be good to use new DllStruct feature with named items. So in FTP.au3 UDF make global constants with definitions of structures, for example: Global Const $s_SYSTEMTIME = "short Year;short Month;short DayOfWeek;short Day;short Hour;short Minute;short Second;short Milliseconds" Func _FileTimeToSystemTime($p_FILETIME) ;uses Kernel32.dll $SYSTEMTIME = DllStructCreate($s_SYSTEMTIME) Local $ai_FileTime = DllCall('Kernel32.dll', 'int', 'FileTimeToSystemTime', _ 'ptr', $p_FILETIME, _ ;const FILETIME* lpFileTime 'ptr',DllStructGetPtr($SYSTEMTIME)) ;LPSYSTEMTIME lpSystemTime If @error OR $ai_FileTime[0] = 0 Then SetError(-1) Return 0 EndIf Return $SYSTEMTIME EndFunc oÝ÷ ÙìZ^¡û¬y«¢+Ø¥¹±Õ±ÐíÑÀ¹ÔÌÐì((ÀÌØíµå}Ñ¥µô}¥±Q¥µQ½MåÍѵQ¥µ ÀÌØíÁ}%1Q%5¤) ½¹Í½±]É¥Ñ ÀÌØíµå}Ñ¥µ¹eȵÀìÅÕ½Ðì´ÅÕ½ÐìµÀìµå}Ñ¥µ¹5½¹Ñ µÀìÅÕ½Ðì´ÅÕ½ÐìµÀìÀÌØíµå}Ñ¥µ¹ä¤) ½¹Í½±]É¥Ñ ÀÌØíµå}Ñ¥µ¹å=]¬µÀìÅÕ½Ðì´´ØÈìÅÕ½ÐìµÀì} ½¹ÙÉÑå=]¹±¥Í ÀÌØíµå}Ñ¥µ¹å=]¬¤¤(ÀÌØíµå}Ñ¥µôÀìÉÍÑÉÕеµ½Éä()Õ¹} ½¹ÙÉÑå=]¹±¥Í ÀÌØíå=]¬¤(%MÝ¥Ñ ÀÌØíå=]¬($% ÍÀ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíMÕ¹äÅÕ½Ðì($% ÍÄ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½Ðí5½¹äÅÕ½Ðì($% ÍÈ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíQÕÍäÅÕ½Ðì($% ÍÌ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½Ðí]¹ÍäÅÕ½Ðì($% ÍÐ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíQ¡ÕÉÍäÅÕ½Ðì($% ÍÔ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíÉ¥äÅÕ½Ðì($% ÍØ($$$ÀÌØíÍ}ÉÑÕɸôÅÕ½ÐíMÑÕÉäÅÕ½Ðì(%¹MÝ¥Ñ ($(%IÑÕɸÀÌØíÍ}ÉÑÕɸ)¹Õ¹(oÝ÷ Ù*jǺw-ìéxêÚú+jYiººh±ëÙÞÂ¥¥êߺw-ìq©Ûy§]y×èú+«b u«ZÂëÞ¯'jü¢¸ßÛ)ººh±ëÙ8^±©jeÉ©l¢ÅLñbÑb®ËEWÑS Note: This code wasn't tested but I think this way it will be good general purpose functions for make them UDF EDIT: corrected some bugs in code examples Edited April 17, 2007 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
joeyb1275 Posted April 17, 2007 Share Posted April 17, 2007 So base functions remain general for all purposes and new helper functions can be added for formating of data - which every can modify for it's purposes.2) The same apply also on _FTPFindFirstFile()and _FTPFindNextFile() So return rather whole struct with named items and let users to simply use whatever they want.Here my NEW idea for defining structure for pairs of 32bit integers for Low/Hig as one 64bit itemsomething like this (only concept not tested):Thanks for the feedback! I changed my code so that _FileTimeToSystemTime() doesn't handle the conversion to DayOfWeek, but I'm still kind of new to using structs in Autoit. I think the creation of a struct with elements and using the dot operator to refer to its elements is new to Autoit (ie. "$structvar.elementname"). It doesn't work for me because I'm not running the beta. The one thing I wonder with the idea of returning the whole stuct is, what is the memory management like when passing structs. For example if I call _FileTimeToSystemTime() in a for loop 1000 times or more and it is returning a struct everytime do I have to worry about filling my memory? However the new struct notation is nice "$structvar.elementname", it makes reading code maybe a little easier, but my experiance with structs in other languages is that the more you create the bigger and slower you program becomes. Maybe this is not a concern, I couldn't find anything about structs and memory management in the Autoit help file so I'm still researching...I do have one question though, why do I need to call DllOpen('wininet.dll') before using FTP functions and then DllClose when I'm done? I was looking though the posts and saw that this was a solution so that the connection was not lost, but I didn't see why it solved the problem. I wondered if the DllOpen('wininet.dll') could be incorporated into the _FTPOpen() and DllClose into the _FTPClose() this way the user does not have to worry about opening and closing it. Is this not a good way to handle it? Link to comment Share on other sites More sharing options...
Zedna Posted April 17, 2007 Share Posted April 17, 2007 Thanks for the feedback! I changed my code so that _FileTimeToSystemTime() doesn't handle the conversion to DayOfWeek, but I'm still kind of new to using structs in Autoit. I think the creation of a struct with elements and using the dot operator to refer to its elements is new to Autoit (ie. "$structvar.elementname"). It doesn't work for me because I'm not running the beta. The one thing I wonder with the idea of returning the whole stuct is, what is the memory management like when passing structs. For example if I call _FileTimeToSystemTime() in a for loop 1000 times or more and it is returning a struct everytime do I have to worry about filling my memory? However the new struct notation is nice "$structvar.elementname", it makes reading code maybe a little easier, but my experiance with structs in other languages is that the more you create the bigger and slower you program becomes. Maybe this is not a concern, I couldn't find anything about structs and memory management in the Autoit help file so I'm still researching... I do have one question though, why do I need to call DllOpen('wininet.dll') before using FTP functions and then DllClose when I'm done? I was looking though the posts and saw that this was a solution so that the connection was not lost, but I didn't see why it solved the problem. I wondered if the DllOpen('wininet.dll') could be incorporated into the _FTPOpen() and DllClose into the _FTPClose() this way the user does not have to worry about opening and closing it. Is this not a good way to handle it? Really named struct items are new in one of latest betas: 3.2.3.0 (09th March, 2007) - Added: Struct variables Don't worry about loop 1000 times. Struct is handled as ByRef parameter. So it's created/alocated inside this function and you must clear it after you use it, see this example: Func _FormatTime($Time) $my_time = _FileTimeToSystemTime($Time) $result = $my_time.Year & "-" & my_time.Month & "-" & $my_time.Day & " " & my_time.Hour & ":" & my_time.Minute & ":" & $my_time.Second $my_time = 0 Return $result EndFunc DllOpen('wininet.dll') is workaround to avoid problem with inposibility to open FTP connection after some internal AutoIt change with DllCall() functionality that has been done in some beta version of AutoIt after version 3.2.0. There are several ways to do this workaround. I used this one. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
theguy0000 Posted April 17, 2007 Share Posted April 17, 2007 oh, a sticky! way to go! The cake is a lie.www.theguy0000.com is currentlyUP images.theguy0000.com is currentlyUP all other *.theguy0000.com sites are DOWN Link to comment Share on other sites More sharing options...
Jazkal Posted April 17, 2007 Share Posted April 17, 2007 Can someone tell me how to get _FTPGetFile to use 'passive' mode? Link to comment Share on other sites More sharing options...
JohnBailey Posted April 17, 2007 Share Posted April 17, 2007 (edited) this should work $INTERNET_FLAG_PASSIVE = 0x08000000 ;=============================================================================== ; ; Function Name: _FTPConnect() ; Description: Connects to an FTP server. ; Parameter(s): $l_InternetSession - The Long from _FTPOpen() ; $s_ServerName - Server name/ip. ; $s_Username - Username. ; $s_Password - Password. ; $i_Passive - Passive connection ; $i_ServerPort - Server port ( 0 is default (21) ) ; $l_Service - I dont got a clue what this does. ; $l_Flags - Special flags. ; $l_Context - I dont got a clue what this does. ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - Returns an indentifier. ; On Failure - 0 and sets @ERROR ; Author(s): Wouter van Kesteren, nitro323 ; ;=============================================================================== Func _FTPConnect($l_InternetSession, $s_ServerName, $s_Username, $s_Password, $i_Passive, $i_ServerPort = 0, $l_Service = 1, $l_Flags = 0, $l_Context = 0) If $i_Passive == 1 then $l_Flags = 0x08000000 Local $ai_InternetConnect = DllCall('wininet.dll', 'long', 'InternetConnect', 'long', $l_InternetSession, 'str', $s_ServerName, 'int', $i_ServerPort, 'str', $s_Username, 'str', $s_Password, 'long', $l_Service, 'long', $l_Flags, 'long', $l_Context) If @error OR $ai_InternetConnect[0] = 0 Then SetError(-1) Return 0 EndIf Return $ai_InternetConnect[0] EndFunc;==> _FTPConnect() Replace the old the previous one Edited April 17, 2007 by JohnBailey A decision is a powerful thing Link to comment Share on other sites More sharing options...
JohnBailey Posted April 17, 2007 Share Posted April 17, 2007 BTW, depending on what you're trying to do remember this is at the top ; define some constants - can be used with _FTPPutFile and _FTPGetFile and ftp open flags Global Const $INTERNET_FLAG_PASSIVE = 0x08000000 Global Const $INTERNET_FLAG_TRANSFER_ASCII = 0x00000001 Global Const $INTERNET_FLAG_TRANSFER_BINARY = 0x00000002 Global Const $INTERNET_DEFAULT_FTP_PORT = 21 Global Const $INTERNET_SERVICE_FTP = 1 Global $INTERNET_OPEN_TYPE_PRECONFIG = 0 Global $INTERNET_OPEN_TYPE_DIRECT = 1 Global $INTERNET_OPEN_TYPE_PROXY = 3 A decision is a powerful thing Link to comment Share on other sites More sharing options...
Jazkal Posted April 17, 2007 Share Posted April 17, 2007 Maybe I'm missing something basic, can someone look at this and tell me why it isn't working? $passive = 0x08000000 $server = 'ftp.mozilla.org' $username = 'anonymous' $pass = 'anonymous' $dllhandle = DllOpen('wininet.dll') $Open = _FTPOpen('MyFTP Control') $Conn = _FTPConnect($Open, $server, $username, $pass, 1) If $Conn = 0 Then MsgBox (0, "Error", "Error! Can't connect to ftp.mozilla.org") Exit EndIf $Ftpp = _FtpGetFile($Conn, "/pub/mozilla.org/firefox/releases/2.0.0.3/win32/en-US/Firefox Setup 2.0.0.3.exe", @ScriptDir&"\Firefox Setup 2.0.0.3.exe", $passive, 0) $Ftpc = _FTPClose($Open) DllClose($dllhandle) Link to comment Share on other sites More sharing options...
JohnBailey Posted April 17, 2007 Share Posted April 17, 2007 #include <GuiConstants.au3> #include "..\Include\OFTP.au3" Dim $Handle, $DllRect $server = 'ftp.mozilla.org' $username = 'anonymous' $pass = 'anonymous' $dllhandle = DllOpen('wininet.dll') $Open = _FTPOpen('MyFTP Control',0) If @error Then Failed("Open") $Conn = _FTPConnect($Open, $server, $username, $pass, 1) If @error Then Failed("Connect") $Ftpp = _FtpGetFile($Conn, "/pub/mozilla.org/firefox/releases/2.0.0.3/win32/en-US/Firefox Setup 2.0.0.3.exe", @ScriptDir&"\FirefoxSetup2003.exe", $INTERNET_FLAG_PASSIVE, 0) If $Ftpp = 0 Then Failed("Could not get") $Ftpc = _FTPClose($Open) _FTPClose ($Open) DllClose($dllhandle) Func Failed($error) MsgBox(48, 'Error', $error) Exit EndFunc the above works for me works A decision is a powerful thing Link to comment Share on other sites More sharing options...
Jazkal Posted April 17, 2007 Share Posted April 17, 2007 Thanks, that works for me. Now I need to take them apart and figure out where I screwed up. Thanks again. Link to comment Share on other sites More sharing options...
JohnBailey Posted April 17, 2007 Share Posted April 17, 2007 Anyone have any good ideas for building a progressbar for downloads and uploads? I'm researching it right now. A decision is a powerful thing Link to comment Share on other sites More sharing options...
Zedna Posted April 17, 2007 Share Posted April 17, 2007 Anyone have any good ideas for building a progressbar for downloads and uploads? I'm researching it right now.I did one such script for FTP downloads with progressbar (in Total Commander style also with speed and estimated time)You can get size of file and use InetGet with download at background. Then in loop calculate all needed informations a show them. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
joeyb1275 Posted April 19, 2007 Share Posted April 19, 2007 Just a few more functions to add to FTP.au3... _FTPOpenFile() _FTPReadFile() _FTPCloseFile() Here is the code... expandcollapse popupGlobal Const $GENERIC_READ = 0x80000000 Global Const $GENERIC_WRITE = 0x40000000 Global Const $FTP_TRANSFER_TYPE_UNKNOWN = 0 ;Defaults to FTP_TRANSFER_TYPE_BINARY. Global Const $FTP_TRANSFER_TYPE_ASCII = 1 ;Transfers the file using FTP's ASCII (Type A) transfer method. Control and formatting information is converted to local equivalents. Global Const $FTP_TRANSFER_TYPE_BINARY = 2 ;Transfers the file using FTP's Image (Type I) transfer method. The file is transferred exactly as it exists with no changes. This is the default transfer method. ;=============================================================================== ; Function Name: _FTPOpenFile() ; Description: Initiates access to a remote file on an FTP server for reading or writing. Use _FTPCloseFile() ; to close the ftp file. ; Parameter(s): $hConnect - The long from _FTPConnect() ; $lpszFileName - String of the ftp file to open ; $dwAccess - GENERIC_READ or GENERIC_WRITE (Default is GENERIC_READ) ; $dwFlags - Settings for the transfer see notes below (Default is 2 for FTP_TRANSFER_TYPE_BINARY) ; $dwContext - (Not Used) See notes below ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - Returns the handle to ftp file for read/write with _FTPReadFile() ; On Failure - 0 and Sets @error = -1 ;Notes: ;~ hConnect ;~ [in] Handle to an FTP session. ;~ lpszFileName ;~ [in] Pointer to a null-terminated string that contains the name of the file to be accessed. ;~ dwAccess ;~ [in] File access. This parameter can be GENERIC_READ or GENERIC_WRITE, but not both. ;~ dwFlags ;~ [in] Conditions under which the transfers occur. The application should select one transfer type and any of ; the flags that indicate how the caching of the file will be controlled. ;~ The transfer type can be one of the following values. ;~ FTP_TRANSFER_TYPE_ASCII Transfers the file using FTP's ASCII (Type A) transfer method. Control and ; formatting information is converted to local equivalents. ;~ FTP_TRANSFER_TYPE_BINARY Transfers the file using FTP's Image (Type I) transfer method. The file is ; transferred exactly as it exists with no changes. This is the default transfer method. ;~ FTP_TRANSFER_TYPE_UNKNOWN Defaults to FTP_TRANSFER_TYPE_BINARY. ;~ INTERNET_FLAG_TRANSFER_ASCII Transfers the file as ASCII. ;~ INTERNET_FLAG_TRANSFER_BINARY Transfers the file as binary. ;~ The following values are used to control the caching of the file. The application can use one or more of these values. ;~ INTERNET_FLAG_HYPERLINK Forces a reload if there was no Expires time and no LastModified time returned from the server ; when determining whether to reload the item from the network. ;~ INTERNET_FLAG_NEED_FILE Causes a temporary file to be created if the file cannot be cached. ;~ INTERNET_FLAG_RELOAD Forces a download of the requested file, object, or directory listing from the origin server, ; not from the cache. ;~ INTERNET_FLAG_RESYNCHRONIZE Reloads HTTP resources if the resource has been modified since the last time it was ; downloaded. All FTP and Gopher resources are reloaded. ;~ dwContext ;~ [in] Pointer to a variable that contains the application-defined value that associates this search with any ; application data. This is only used if the application has already called InternetSetStatusCallback to set ; up a status callback function. ;=============================================================================== Func _FTPOpenFile($hConnect,$lpszFileName,$dwAccess = 0x80000000,$dwFlags = 2,$dwContext = 0) Local $ai_FTPOpenFile = DllCall('wininet.dll', 'hwnd', 'FtpOpenFile', _ 'hwnd', $hConnect, _ ;HINTERNET hConnect 'str', $lpszFileName, _ ;LPCTSTR lpszFileName 'udword', $dwAccess , _ ;DWORD dwAccess 'dword', $dwFlags, _ ;DWORD dwFlags 'dword',$dwContext) ;DWORD_PTR dwContext If @error OR $ai_FTPOpenFile[0] == 0 Then SetError(-1) Return 0 EndIf Return $ai_FTPOpenFile[0] EndFunc ;=============================================================================== ; Function Name: _FTPReadFile() ; Description: Reads data from a handle opened by _FTPOpenFile() ; Parameter(s): $h_File - Handle returned by _FTPOpenFile to the ftp file ; $dwNumberOfBytesToRead - Number of bytes to read ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - Returns the binary/string read. ; On Failure - 0 and Sets @error = -1 for end-of-file, @error = 1 for other errors ;Notes: (InternetReadFile() parameters) ;~ hFile ;~ [in] Handle returned from a previous call to InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest. ;~ lpBuffer ;~ [out] Pointer to a buffer that receives the data. ;~ dwNumberOfBytesToRead ;~ [in] Number of bytes to be read. ;~ lpdwNumberOfBytesRead ;~ [out] Pointer to a variable that receives the number of bytes read. InternetReadFile sets this value to zero before doing any work or error checking. ;=============================================================================== Func _FTPReadFile($h_File,$dwNumberOfBytesToRead) Local $s_FileRead = "" $lpBuffer = DllStructCreate("byte[" & $dwNumberOfBytesToRead & "]") $lpdwNumberOfBytesRead = DllStructCreate("long") Local $ai_FTPReadFile = DllCall('wininet.dll', 'int', 'InternetReadFile', _ 'hwnd', $h_File, _ ;HINTERNET hFile 'ptr', DllStructGetPtr($lpBuffer), _ ;LPVOID lpBuffer 'dword', $dwNumberOfBytesToRead, _ ;DWORD dwNumberOfBytesToRead 'ptr',DllStructGetPtr($lpdwNumberOfBytesRead)) ;LPDWORD lpdwNumberOfBytesRead If @error OR $ai_FTPReadFile[0] == 0 Then If DllStructGetData($lpdwNumberOfBytesRead,1) == 0 Then $lpBuffer = 0 $lpdwNumberOfBytesRead = 0 SetError(-1) Return 0 Else $lpBuffer = 0 $lpdwNumberOfBytesRead = 0 SetError(1) Return 0 EndIf EndIf $s_FileRead = DllStructGetData($lpBuffer,1) ;index is omitted so the entire array is written into $s_FileRead as a BinaryString $lpBuffer = 0 $lpdwNumberOfBytesRead = 0 Return $s_FileRead EndFunc ;=============================================================================== ; Function Name: _FTPCloseFile() ; Description: Closes the Handle returned by _FTPOpenFile. ; Parameter(s): $l_InternetSession - The handles from _FTPOpenFile.() ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - 1 ; On Failure - 0 Sets @error = -1 ;=============================================================================== Func _FTPCloseFile($l_InternetSession) Local $ai_InternetCloseHandle = DllCall('wininet.dll', 'int', 'InternetCloseHandle', 'hwnd', $l_InternetSession) If @error OR $ai_InternetCloseHandle[0] = 0 Then SetError(-1) Return 0 EndIf Return $ai_InternetCloseHandle[0] EndFunc I have test this for reading files only. I will test more and add an example scripts later. It should be easy to use acts like FileRead(). Link to comment Share on other sites More sharing options...
JohnBailey Posted April 19, 2007 Share Posted April 19, 2007 joeyb1275 WAY TO GO!!! Thanks I'm putting this in the UDF on my system right now A decision is a powerful thing Link to comment Share on other sites More sharing options...
joeyb1275 Posted April 22, 2007 Share Posted April 22, 2007 Update for _FTPReadFile() I found an error in my _FTPReadFile() function it only come out when you read a single byte. The following code will correct the error (see the return values for the fix) expandcollapse popup;=============================================================================== ; Function Name: _FTPReadFile() ; Description: Reads data from a handle opened by _FTPOpenFile() ; Parameter(s): $h_File - Handle returned by _FTPOpenFile to the ftp file ; $dwNumberOfBytesToRead - Number of bytes to read ; Requirement(s): DllCall, wininet.dll ; Return Value(s): On Success - Returns the binary/string read. ; On Failure - 0 and Sets @error = -1 for end-of-file, @error = 1 for other errors ;Notes: (InternetReadFile() parameters) ;~ hFile ;~ [in] Handle returned from a previous call to InternetOpenUrl, FtpOpenFile, GopherOpenFile, or HttpOpenRequest. ;~ lpBuffer ;~ [out] Pointer to a buffer that receives the data. ;~ dwNumberOfBytesToRead ;~ [in] Number of bytes to be read. ;~ lpdwNumberOfBytesRead ;~ [out] Pointer to a variable that receives the number of bytes read. InternetReadFile sets this value to zero before doing any work or error checking. ;=============================================================================== Func _FTPReadFile($h_File,$dwNumberOfBytesToRead) Local $s_FileRead = "",$BytesRead = 0 $lpBuffer = DllStructCreate("byte[" & $dwNumberOfBytesToRead & "]") $lpdwNumberOfBytesRead = DllStructCreate("long") Local $ai_FTPReadFile = DllCall('wininet.dll', 'int', 'InternetReadFile', _ 'hwnd', $h_File, _ ;HINTERNET hFile 'ptr', DllStructGetPtr($lpBuffer), _ ;LPVOID lpBuffer 'dword', $dwNumberOfBytesToRead, _ ;DWORD dwNumberOfBytesToRead 'ptr',DllStructGetPtr($lpdwNumberOfBytesRead)) ;LPDWORD lpdwNumberOfBytesRead $BytesRead = DllStructGetData($lpdwNumberOfBytesRead,1) If @error OR $ai_FTPReadFile[0] == 0 Then $lpBuffer = 0 $lpdwNumberOfBytesRead = 0 If $BytesRead == 0 Then SetError(-1) ;end-of-file error Else SetError(1) ;general error EndIf Return 0 EndIf $s_FileRead = DllStructGetData($lpBuffer,1);index is omitted so the entire array is written into $s_FileRead as a BinaryString $lpBuffer = 0 $lpdwNumberOfBytesRead = 0 If $BytesRead = 1 Then Return Chr($s_FileRead) ;without this a 1 byte read will return a decimal value of the 8 bits read Else Return $s_FileRead ;return as binarystring (character string where all 0-255 ASCII values are allowed) EndIf EndFunc Link to comment Share on other sites More sharing options...
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