WININET Problem. Please Help.

Just starting out? Need help? Post your questions and find answers here.
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

WININET Problem. Please Help.

Post 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.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Read this: http://msdn2.microsoft.com/En-US/library/aa384146.aspx
It says it can only be used once (!).
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Post 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.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Can you post the blitz code?
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post 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
Last edited by Flype on Tue Jun 19, 2007 8:25 am, edited 3 times in total.
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
maw

Post 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.
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Post 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
AndyMK
Enthusiast
Enthusiast
Posts: 582
Joined: Wed Jul 12, 2006 4:38 pm
Location: UK

Post 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 :)
maw

Post 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 :lol:
User avatar
Flype
Addict
Addict
Posts: 1542
Joined: Tue Jul 22, 2003 5:02 pm
Location: In a long distant galaxy

Post 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

;============================================ 
No programming language is perfect. There is not even a single best language.
There are only languages well suited or perhaps poorly suited for particular purposes. Herbert Mayer
Post Reply