Page 1 of 1
WININET Problem. Please Help.
Posted: Mon Jun 18, 2007 2:40 pm
by AndyMK
Hi, im accessing an FTP server from PB4.02 using the WININET API. Everything works except listing files in a directory. The first time i run the list code, it works but any time after that during the same session, it does not. I will post some basic/messy code to show what i am doing. Help would be much appreciated. Thanks.
Code: Select all
#INTERNET_SERVICE_FTP=1
#INTERNET_OPEN_TYPE_DIRECT=1
#FTP_PORT=21
#FTP_TRANSFER_ASCII=1
#FTP_TRANSFER_BINARY=2
Proxy.s=""
ProxyBypass.s=""
ServerName.s="demosite.homeftp.net"
UserName.s="vac"
Password.s="vac"
acc$="Home"
If OpenWindow(0, 0, 0, 210, 150, "BlahBlah", #PB_Window_ScreenCentered)
event=WaitWindowEvent()
gadget=EventGadget()
etype=EventType()
hInternet=InternetOpen_("FTP",#INTERNET_OPEN_TYPE_DIRECT,Proxy,ProxyBypass,0)
If hInternet
hConnect=InternetConnect_(hInternet,ServerName,#FTP_PORT,UserName,Password,#INTERNET_SERVICE_FTP,0,0)
If hConnect
Repeat
WindowEvent()
Delay(1000)
hFind=FtpFindFirstFile_(hConnect,"*.jpg",@FTPFile.WIN32_FIND_DATA,0,0)
If hFind
Find=1
Debug PeekS(@FTPFile\cFileName) ;Directories
While Find
Find=InternetFindNextFile_(hFind,@FTPFile)
If Find
Debug PeekS(@FTPFile\cFileName) ;Files
EndIf
Wend
EndIf
ForEver
InternetCloseHandle_(hInternet)
EndIf
EndIf
EndIf
Most of the code was taken from Purearea Code Archives.
Posted: Mon Jun 18, 2007 3:52 pm
by Trond
Posted: Mon Jun 18, 2007 4:15 pm
by AndyMK
How strange? I have some code in BlitzPlus using the same WININET API that works refreshing the directory during the same session... Oh well.. Thanks for the reply.
Posted: Mon Jun 18, 2007 4:27 pm
by Trond
Can you post the blitz code?
Posted: Mon Jun 18, 2007 4:29 pm
by Flype
Hello,
you should use file attribute to recognize if it is a directory or a file :
Code: Select all
hFile\dwFileAttributes & #FILE_ATTRIBUTE_DIRECTORY
Posted: Mon Jun 18, 2007 5:20 pm
by maw
Actually, if you really read the MSDN page you notice that you can only have one instance of FtpFindFirstFile() per FTP-session. So all you have to do is close the handle once you are done with the FtpFindFirstFile(), then you should be able to start another.
So, do a InternetCloseHandle() on the handle you get from the FtpFindFirstFile() before trying to run it again.
Posted: Mon Jun 18, 2007 6:21 pm
by AndyMK
maw, tried it and still nothing. The only way so far is to disconnect from the server and reconnect.
Here is a chunk of code from Blitz doing exactly what maw explained.
Code: Select all
Function FTPGetFileList(remoteDirectory$="")
Delete Each ftpfile
If remoteDirectory$ = "" Then remoteDirectory$ = gCurrentDirectory$
lpFindFileData = CreateBank (320)
hInternet = FtpFindFirstFile(ghFTPSession,remoteDirectory$,lpFindFileData,INTERNET_FLAG_RELOAD,0)
If hInternet = 0
FreeBank lpFindFileData
If GetLastError() = ERROR_NO_MORE_FILES Then Return succeeded ;no files or subdirectories
Return failed
EndIf
;Iterate through the files in the directory and store each in a type.
Repeat
ftpfile.ftpfile = New ftpfile
ftpfile\directory$ = remoteDirectory$
ftpfile\fileName$ = ReadAPIString$(lpFindFileData,44)
If PeekInt(lpFindFileData,0) = 16 Then ftpfile\typeOfFile = 2 ;directory (FILE_ATTRIBUTE_DIRECTORY)
If PeekInt(lpFindFileData,0) = 128 Then ftpfile\typeOfFile = 1 ;file (FILE_ATTRIBUTE_NORMAL)
ftpfile\sizeofFile = PeekInt(lpFindFileData,32) ;nFileSizeLow is enough, accurate for files < 2.1 gigs (that's huge)
Until InternetFindNextFile(hInternet,lpFindFileData) = 0
result = InternetCloseHandle(hInternet)
FreeBank lpFindFileData
Return succeeded
End Function
Posted: Mon Jun 18, 2007 6:39 pm
by AndyMK
Ok, maw was right, it does work.
Code: Select all
Procedure.l FTPInit()
ProcedureReturn InternetOpen_("FTP",1,"","",0)
EndProcedure
Procedure.l FTPConnect(hInternet,Server.s,User.s,Password.s,port.l)
ProcedureReturn InternetConnect_(hInternet,Server,port,User,Password,1,0,0)
EndProcedure
Procedure.l FTPDir(hConnect.l)
hFind=FtpFindFirstFile_(hConnect,"*.*",@FTPFile.WIN32_FIND_DATA,0,0)
If hFind
Find=1
Debug PeekS(@FTPFile\cFileName) ;Directories
While Find
Find=InternetFindNextFile_(hFind,@FTPFile)
If Find
Debug PeekS(@FTPFile\cFileName) ;Files
EndIf
Wend
InternetCloseHandle_(hFind)
EndIf
EndProcedure
Procedure.l FTPSetDir(hConnect.l,Dir.s)
ProcedureReturn FtpSetCurrentDirectory_(hConnect,Dir)
EndProcedure
Procedure.l FTPCreateDir(hConnect.l,Dir.s)
ProcedureReturn FtpCreateDirectory_(hConnect,Dir)
EndProcedure
Procedure.l FTPDownload(hConnect.l,Source.s,Dest.s)
ProcedureReturn FtpGetFile_(hConnect,Source,Dest,0,0,0,0)
EndProcedure
Procedure.l FTPUpload(hConnect.l,Source.s,Dest.s)
ProcedureReturn FtpPutFile_(hConnect,Source,Dest,0,0)
EndProcedure
Procedure.l FTPClose(hInternet.l)
ProcedureReturn InternetCloseHandle_(hInternet)
EndProcedure
hInternet=FTPInit()
If hInternet
hConnect=FTPConnect(hInternet,"demosite.homeftp.net","vac","vac",21)
If hConnect
While Not hFind
FTPDir(hConnect)
Delay(5000)
Wend
EndIf
EndIf
Thanks

Posted: Mon Jun 18, 2007 6:42 pm
by maw
Works here, it retrieves the filelist every second without disconnecting:
Code: Select all
#INTERNET_SERVICE_FTP=1
#INTERNET_OPEN_TYPE_DIRECT=1
#FTP_PORT=21
#FTP_TRANSFER_ASCII=1
#FTP_TRANSFER_BINARY=2
Proxy.s=""
ProxyBypass.s=""
ServerName.s="demosite.homeftp.net"
UserName.s="vac"
Password.s="vac"
acc$="Home"
If OpenWindow(0, 0, 0, 210, 150, "BlahBlah", #PB_Window_ScreenCentered)
event=WaitWindowEvent()
gadget=EventGadget()
etype=EventType()
hInternet=InternetOpen_("FTP",#INTERNET_OPEN_TYPE_DIRECT,Proxy,ProxyBypass,0)
If hInternet
Repeat
hConnect=InternetConnect_(hInternet,ServerName,#FTP_PORT,UserName,Password,#INTERNET_SERVICE_FTP,0,0)
If hConnect
hFind=FtpFindFirstFile_(hConnect,"*.jpg",@FTPFile.WIN32_FIND_DATA,0,0)
If hFind
Find=1
Debug PeekS(@FTPFile\cFileName) ;Directories
While Find
Find=InternetFindNextFile_(hFind,@FTPFile)
If Find
Debug PeekS(@FTPFile\cFileName) ;Files
EndIf
Wend
EndIf
InternetCloseHandle_(hConnect)
EndIf
While WindowEvent() : Wend
Delay(1000)
ForEver
EndIf
EndIf
Edit: Damnit, I also need to code faster

Posted: Mon Jun 18, 2007 10:01 pm
by Flype
don't know if this can help but here is one way of examining recursively a ftp folder (using linked list).
Code: Select all
;============================================
EnableExplicit
#FTP_TRANSFER_ASCII = 1
#FTP_TRANSFER_BINARY = 2
#INTERNET_SERVICE_FTP = 1
#INTERNET_OPEN_TYPE_DIRECT = 1
Import "shlwapi.lib"
StrFormatByteSize64A(Size.q, *BufStr, BufSize.l)
EndImport
Procedure.s StrByteSize(nBytes.q)
Protected string.s{64}
If StrFormatByteSize64A(nBytes, @string, 64)
ProcedureReturn PeekS(@string, -1, #PB_Ascii)
EndIf
EndProcedure
;============================================
Structure FILESIZE
High.l
Low.l
EndStructure
Structure WIN32_FIND_DATA_2
dwFileAttributes.l
ftCreationTime.FILETIME
ftLastAccessTime.FILETIME
ftLastWriteTime.FILETIME
nFileSizeLow.l
nFileSizeHigh.l
dwReserved0.l
dwReserved1.l
cFileName.s{260} ; replaced by fixed string
cAlternate.s{14} ; replaced by fixed string
dummy.w
EndStructure
Macro FtpOpen(Proxy = "", ProxyBypass = "")
InternetOpen_("FTP", #INTERNET_OPEN_TYPE_DIRECT, Proxy, ProxyBypass, 0)
EndMacro
Macro FtpClose(hInternet)
InternetCloseHandle_(hInternet)
EndMacro
Macro FtpConnect(hInternet, Host, User, Pwd, Port = 21)
InternetConnect_(hInternet, Host, Port, User, Pwd, #INTERNET_SERVICE_FTP, 0, 0)
EndMacro
Macro FtpDisconnect(hConnect)
InternetCloseHandle_(hConnect)
EndMacro
;============================================
Procedure.l FtpListAll(hConnect.l, folder.s = "/", depth.l = 0)
Protected hFind.l, Size.q, NewList find.WIN32_FIND_DATA_2()
If FtpSetCurrentDirectory_(hConnect, folder) And AddElement(find())
hFind = FtpFindFirstFile_(hConnect, 0, find(), 0, 0)
If hFind
While AddElement(find()) And InternetFindNextFile_(hFind, find())
; Delay(1)
Wend
InternetCloseHandle_(hFind)
DeleteElement(find())
EndIf
EndIf
ForEach find()
If find()\dwFileAttributes & #FILE_ATTRIBUTE_DIRECTORY
AddGadgetItem(0, -1, "[DIR] " + find()\cFileName, 0, depth)
FtpListAll(hConnect, folder + find()\cFileName + "/", depth + 1)
Else
PokeL(@Size + 4, find()\nFileSizeLow)
PokeL(@Size + 0, find()\nFileSizeHigh)
AddGadgetItem(0, -1, "[FILE] " + find()\cFileName + " (" + StrByteSize(Size) + ")", 0, depth)
EndIf
Next
EndProcedure
;============================================
Define ftp.l, conn.l
If OpenWindow(0, 0, 0, 640, 480, "Ftp", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
If CreateGadgetList(WindowID(0))
TreeGadget(0, 10, 10, 620, 460, #PB_Tree_AlwaysShowSelection)
EndIf
ftp = FtpOpen()
If ftp
conn = FtpConnect(ftp, "localhost", "user", "pwd")
If conn
FtpListAll(conn, "/") ; <---- recursive proc
FtpDisconnect(conn)
EndIf
FtpClose(ftp)
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow: Break
Case #PB_Event_SizeWindow: ResizeGadget(0, #PB_Ignore, #PB_Ignore, WindowWidth(0)-20, WindowHeight(0)-20)
EndSelect
ForEver
EndIf
;============================================