Sign in to follow this  
Followers 0
AndyS01

Error copying file from FTP using _FTP_FileGet()

15 posts in this topic

I have code that uses calls to functions in FTPEx.au3 to copy a file to a local directory, but the copy fails.
 
The steps I took were:
_FTP_Open()
_FTP_Connect()
_FTP_FileGet()
 
The _FTP_FileGet() returns a 0 (failed) and the file is not copied.  I've tried passing the full FTP pathname and just the base filename, and I've tried inserting a call to _FTP_DirSetCurrent() just before calling _FTP_FileGet(), but nothing worked.
 
Here is my test code:
#include <FTPex.au3>

_Main()

Func _Main()
    $ret = copyFile()
    $err = @error
    ConsoleWrite("..." & @CRLF)
    ConsoleWrite("+++: $err = " & $err & ", $ret = " & $ret & @CRLF)
EndFunc   ;==>_Main

Func copyFile()
    Local $sIP, $sUsername, $sPassword, $FTPDir, $localDir, $fname, $session
    Local $err, $hConn, $from, $to, $ret

    $sIP = "xxxxxx"
    $sUsername = "xxxxx"
    $sPassword = "xxxxx"

    $FTPDir = "/Andy"
    $localDir = "C:\Temp"
    $fname = "READ2ME.txt"
    $from = $FTPDir & "/" & $fname
    $to = $localDir & "\" & $fname

    $session = open()
    If ($session == 0) Then Return (0)

    $hConn = connect($session, $sIP, $sUsername, $sPassword)
    If ($hConn == 0) Then Return (0)

    ;$ret = setcurrent($hConn, $FTPDir) ; <-- returns '1' (not a dir name, like the help doc says)
    ;If ($ret == 0) Then Return (0)

    $ret = fileget($hConn, $from, $to)
    If ($ret == 0) Then Return (0)

    If (FileExists($to)) Then
        ConsoleWrite("--> File copied OK" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("--> File wasn't copied!!")
        Return (1)
    EndIf
EndFunc   ;==>copyFile

Func open()
    $session = _FTP_Open('_myFTP Control')

    $err = @error
    ConsoleWrite("+++: after  _FTP_Open(): @error = " & $err & ", $session = " & Hex($session) & @CRLF)
    If ($err <> 0) Or ($session == 0) Then
        ConsoleWrite("+++: _FTP_Open() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_Open() - OK" & @CRLF)
        Return ($session)
    EndIf
EndFunc   ;==>open

Func connect($session, $ip, $uname, $pwd)
    $hConn = _FTP_Connect($session, $ip, $uname, $pwd)

    $err = @error
    ConsoleWrite("+++: after  _FTP_Connect(): @error = " & $err & ", $hConn = " & Hex($hConn) & @CRLF)
    If ($err <> 0) Or ($hConn == 0) Then
        ConsoleWrite("+++: _FTP_Connect() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_Connect() - OK" & @CRLF)
        Return ($hConn)
    EndIf
EndFunc   ;==>connect

Func setcurrent($hConn, $fdir)
    $ret = _FTP_DirSetCurrent($hConn, $fdir) ; Note: returns '1' instead of the Dir name

    $err = @error
    ConsoleWrite("+++: after  _FTP_DirSetCurrent(): @error = " & $err & ", $ret = " & $ret & @CRLF)
    If ($err <> 0) Or ($ret == 0) Or ($ret == "") Then
        ConsoleWrite("+++: _FTP_DirSetCurrent() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_DirSetCurrent() - OK" & @CRLF)
        Return ($ret)
    EndIf
EndFunc   ;==>setcurrent

Func fileget($hConn, $from, $to)
    $ret = _FTP_FileGet($hConn, $from, $to, False)
    $err = @error
    ConsoleWrite("+++: after  _FTP_FileGet(): $ret = " & $ret & ", @error = " & $err & @CRLF)
    ConsoleWrite("+++: $from = " & $from & ", $to = " & $to & @CRLF)
    If ($err <> 0) Or ($ret <> 1) Then
        ConsoleWrite("+++: _FTP_FileGet() - FAILED " & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_FileGet() - OK" & @CRLF)
    EndIf
EndFunc   ;==>fileget

Here is the Console output:

+++: after  _FTP_Open(): @error = 0, $session = 00CC0004
+++: _FTP_Open() - OK
+++: after  _FTP_Connect(): @error = 0, $hConn = 00CC0008
+++: _FTP_Connect() - OK
+++: after  _FTP_FileGet(): $ret = 0, @error = -1
+++: $from = /Andy/READ2ME.txt, $to = C:\Temp\READ2ME.txt
+++: _FTP_FileGet() - FAILED 
...
+++: $err = 0, $ret = 0

Any help would be appreciated.

Andy

Share this post


Link to post
Share on other sites



Try this:

#include <FTPex.au3>

_Main()

Func _Main()
    $ret = copyFile()
    $err = @error
    ConsoleWrite("..." & @CRLF)
    ConsoleWrite("+++: $err = " & $err & ", $ret = " & $ret & @CRLF)
EndFunc   ;==>_Main

Func copyFile()
    Local $sIP, $sUsername, $sPassword, $FTPDir, $localDir, $fname, $session
    Local $err, $hConn, $from, $to, $ret

    $sIP = "xxxxxx"
    $sUsername = "xxxxx"
    $sPassword = "xxxxx"

    $FTPDir = "Andy"
    $localDir = "C:\Temp"
    $fname = "READ2ME.txt"
    $from = $fname
    $to = $localDir & "\" & $fname

    $session = open()
    If ($session == 0) Then Return (0)

    $hConn = connect($session, $sIP, $sUsername, $sPassword)
    If ($hConn == 0) Then Return (0)

    $ret = setcurrent($hConn, $FTPDir) ; <-- returns '1' (not a dir name, like the help doc says)
    If ($ret == 0) Then Return (0)

    $ret = fileget($hConn, $from, $to)
    If ($ret == 0) Then Return (0)

    If (FileExists($to)) Then
        ConsoleWrite("--> File copied OK" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("--> File wasn't copied!!")
        Return (1)
    EndIf
EndFunc   ;==>copyFile

Func open()
    $session = _FTP_Open('_myFTP Control')

    $err = @error
    ConsoleWrite("+++: after  _FTP_Open(): @error = " & $err & ", $session = " & Hex($session) & @CRLF)
    If ($err <> 0) Or ($session == 0) Then
        ConsoleWrite("+++: _FTP_Open() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_Open() - OK" & @CRLF)
        Return ($session)
    EndIf
EndFunc   ;==>open

Func connect($session, $ip, $uname, $pwd)
    $hConn = _FTP_Connect($session, $ip, $uname, $pwd)

    $err = @error
    ConsoleWrite("+++: after  _FTP_Connect(): @error = " & $err & ", $hConn = " & Hex($hConn) & @CRLF)
    If ($err <> 0) Or ($hConn == 0) Then
        ConsoleWrite("+++: _FTP_Connect() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_Connect() - OK" & @CRLF)
        Return ($hConn)
    EndIf
EndFunc   ;==>connect

Func setcurrent($hConn, $fdir)
    $ret = _FTP_DirSetCurrent($hConn, $fdir) ; Note: returns '1' instead of the Dir name

    $err = @error
    ConsoleWrite("+++: after  _FTP_DirSetCurrent(): @error = " & $err & ", $ret = " & $ret & @CRLF)
    If ($err <> 0) Or ($ret == 0) Or ($ret == "") Then
        ConsoleWrite("+++: _FTP_DirSetCurrent() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_DirSetCurrent() - OK" & @CRLF)
        Return ($ret)
    EndIf
EndFunc   ;==>setcurrent

Func fileget($hConn, $from, $to)
    $ret = _FTP_FileGet($hConn, $from, $to, False)
    $err = @error
    ConsoleWrite("+++: after  _FTP_FileGet(): $ret = " & $ret & ", @error = " & $err & @CRLF)
    ConsoleWrite("+++: $from = " & $from & ", $to = " & $to & @CRLF)
    If ($err <> 0) Or ($ret <> 1) Then
        ConsoleWrite("+++: _FTP_FileGet() - FAILED " & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_FileGet() - OK" & @CRLF)
    EndIf
EndFunc   ;==>fileget

Share this post


Link to post
Share on other sites

Nope, that failed also.  I assume that you actually tried it, so that leaves my FTP credentials.  The IP address I'm using is something like this: abc.def.com, instead of like this: 10.222.12.123.  Do you think that that matters?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I haven't tested any of the previously mentioned scripts.  Are you able to get a file list using _FTP_ListToArray or _FTP_ListToArrayEx?  I'm not clear where the script is failing--at _FTP_DirSetCurrent or at _FTP_FileGet?

#include <FTPEx.au3>
Global $sSite = "abc.def.com"
Global $sUser = "xxxxxx"
Global $sPass = "xxxxxx"
Global $sRemoteDir = "Andy" ; Could this be case-sensitive?
Global $sFile = "READ2ME.txt" ; Could this also be case-sensitive?
Global $sLocalDir = "C:\Temp\" ; This must exist before getting the file, so you may need to check if the folder exists and if not, create the folder first
Global $hOpen = _FTP_Open("My Site")
If @error Then ConsoleWrite("FTP Open Error: " & @error & @CRLF)
Global $hConnect = _FTP_Connect($hOpen, $sSite, $sUser, $sPass)
If @error Then ConsoleWrite("FTP Connect Error: " & @error & @CRLF)
_FTP_DirSetCurrent($hConnect, $sRemoteDir)
If @error Then ConsoleWrite("FTP Set Current Directory Error: " & @error & @CRLF)
_FTP_FileGet($hConnect, $sFile, $sLocalDir & $sFile)
If @error Then ConsoleWrite("FTP Get File Error: " & @error & @CRLF)
If FileExists($sLocalDir & $sFile) Then ShellExecute($sLocalDir & $sFile)
_FTP_Close($hOpen)
If @error Then ConsoleWrite("FTP Close Error: " & @error & @CRLF)
Edited by GMK

Share this post


Link to post
Share on other sites

I tried _FTP_ListToArray() in place of _FTP_FileGet() and it properly returned an array with the name of the only file in the FTP directory (READ2ME.txt).

So, I can see the names of the files on the FTP site, but _FTP_FileGet() fails.

If you look at this Console output (as I mentioned in my original post), you will see that the failure was the call to _FTP_FileGet().

+++: after  _FTP_Open(): @error = 0, $session = 00CC0004
+++: _FTP_Open() - OK
+++: after  _FTP_Connect(): @error = 0, $hConn = 00CC0008
+++: _FTP_Connect() - OK
+++: after  _FTP_FileGet(): $ret = 0, @error = -1
+++: $from = /Andy/READ2ME.txt, $to = C:\Temp\READ2ME.txt
+++: _FTP_FileGet() - FAILED 
...
+++: $err = 0, $ret = 0

Share this post


Link to post
Share on other sites

Have you tried switching _FTP_Connect to passive mode?

Share this post


Link to post
Share on other sites

Still fails

Share this post


Link to post
Share on other sites

Is the FTP site you're connecting to using secure FTP (i.e. SFTP)? Because if it is, then the built in FTP UDF won't work with it.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

AndyS01,

Make sure that the target directory exists and the script is authorized to write to it.

And, no, I have not tried it.

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites

Yes the target directory exists and I've copied files into it.  The _FTP_FileGet() got @error == 0 and _WinAPI_GetLastError() == 12003.  If you can, please try my test script.  That way, I can tell if it's me or not.

Share this post


Link to post
Share on other sites

Well, after "uncommenting" lines 32 and 33 and substituting my own server, username, password, remote directory and file, it worked for me.  I had to comment out line 36 if I wanted to see the confirmation from lines 38-44.

Share this post


Link to post
Share on other sites

hmmm...

What if I give you my credentials (off line, of course!)?  Or do you know of an FTP site that we both can get to?  That way, I could eliminate the FTP site as the problem.

BTW: I can run GoodSync and Core FTP LE (using the same credentials) to copy my file to the came local directory and they both copy the file successfully.

Share this post


Link to post
Share on other sites

How about this?

#include <FTPex.au3>

_Main()

Func _Main()
    $ret = copyFile()
    $err = @error
    ConsoleWrite("..." & @CRLF)
    ConsoleWrite("+++: $err = " & $err & ", $ret = " & $ret & @CRLF)
EndFunc   ;==>_Main

Func copyFile()
    Local $sIP, $sUsername, $sPassword, $FTPDir, $localDir, $fname, $session
    Local $err, $hConn, $from, $to, $ret

    ;ftp://mirror.esc7.net/pub/OpenBSD/doc/obsd-faq.txt
    $sIP = "mirror.esc7.net"
    $sUsername = ""
    $sPassword = ""

    $FTPDir = "/pub/OpenBSD/doc/"
    $localDir = "C:\Temp"
    $fname = "obsd-faq.txt"
    $from = $FTPDir & "/" & $fname
    $to = $localDir & "\" & $fname

    $session = open()
    If ($session == 0) Then Return (0)

    $hConn = connect($session, $sIP, $sUsername, $sPassword)
    If ($hConn == 0) Then Return (0)

    $ret = setcurrent($hConn, $FTPDir) ; <-- returns '1' (not a dir name, like the help doc says)
    If ($ret == 0) Then Return (0)

    $ret = fileget($hConn, $from, $to)
    If ($ret == 0) Then Return (0)

    If (FileExists($to)) Then
        ConsoleWrite("--> File copied OK" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("--> File wasn't copied!!")
        Return (1)
    EndIf
EndFunc   ;==>copyFile

Func open()
    $session = _FTP_Open('_myFTP Control')

    $err = @error
    ConsoleWrite("+++: after  _FTP_Open(): @error = " & $err & ", $session = " & Hex($session) & @CRLF)
    If ($err <> 0) Or ($session == 0) Then
        ConsoleWrite("+++: _FTP_Open() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_Open() - OK" & @CRLF)
        Return ($session)
    EndIf
EndFunc   ;==>open

Func connect($session, $ip, $uname, $pwd)
    $hConn = _FTP_Connect($session, $ip, $uname, $pwd)

    $err = @error
    ConsoleWrite("+++: after  _FTP_Connect(): @error = " & $err & ", $hConn = " & Hex($hConn) & @CRLF)
    If ($err <> 0) Or ($hConn == 0) Then
        ConsoleWrite("+++: _FTP_Connect() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_Connect() - OK" & @CRLF)
        Return ($hConn)
    EndIf
EndFunc   ;==>connect

Func setcurrent($hConn, $fdir)
    $ret = _FTP_DirSetCurrent($hConn, $fdir) ; Note: returns '1' instead of the Dir name

    $err = @error
    ConsoleWrite("+++: after  _FTP_DirSetCurrent(): @error = " & $err & ", $ret = " & $ret & @CRLF)
    If ($err <> 0) Or ($ret == 0) Or ($ret == "") Then
        ConsoleWrite("+++: _FTP_DirSetCurrent() - FAILED" & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_DirSetCurrent() - OK" & @CRLF)
        Return ($ret)
    EndIf
EndFunc   ;==>setcurrent

Func fileget($hConn, $from, $to)
    $ret = _FTP_FileGet($hConn, $from, $to, False, $FTP_TRANSFER_TYPE_ASCII)
    $err = @error
    ConsoleWrite("+++: after  _FTP_FileGet(): $ret = " & $ret & ", @error = " & $err & @CRLF)
    ConsoleWrite("+++: $from = " & $from & ", $to = " & $to & @CRLF)
    If ($err <> 0) Or ($ret <> 1) Then
        ConsoleWrite("+++: _FTP_FileGet() - FAILED " & @CRLF)
        Return (0)
    Else
        ConsoleWrite("+++: _FTP_FileGet() - OK" & @CRLF)
    EndIf
EndFunc   ;==>fileget

Share this post


Link to post
Share on other sites

That worked for me.  The error I was getting when I used my FTP credentials came from the _FTP_FileGet().  The transfer left the local file as Read-Only and 0 bytes, so subsequent calls failed because the file couldn't be overwritten.  I put in a file delete that cleared the Read-Only attribute before doing the delete.  I could run my test repeatedly and each time, the file name was created in my local directory, but as a Read-Only file that had a size of 0 bytes, and  _FTP_FileGet() returned a FAILURE.

I added a call to _FTP_GetLastResponseInfo($enum, $emsg) and here are the results:

$emsg = 200 Type set to I
200 PORT command successful
550 /Andy/READ2ME.txt: No such file or directory
550 /Andy/READ2ME.txt: No such file or directory
 
So I looked at the file on my FTP site and I saw that I was trying to copy a file called READ2ME.txt, but the file on my FTP server was READ2ME.TXT (same file, different letter case).
 
What a rookie mistake  :oops:  :doh:  
 
I started back at my real script where I had extracted the code into the test code I first sent out and the file name I used was for a file that actually existed on the FTP site, but when I copied a test file (READ2ME.txt) to the FTP site, I typed the destination file name in all uppercase.
 
So, I'm really sorry I took up your time on this and in the future, I'll be sure to set up a test script with all the basic stuff created correctly.
 
 

Share this post


Link to post
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
Sign in to follow this  
Followers 0

  • Similar Content

    • Yaerox
      By Yaerox
      Hey guys, I got a problem and rly need help.
      I try using FTP to get a file. Then the content of the file on the FTP-Server is getting changed, and I'm downloading this file again. This works, but the content of the file after downloading it the second time is the same like before...doesn't matter if I open and close the ftp session, or using the same. If I'm using manually FileZilla to get the File it works without any probs.
      #include <FTPEx.au3>; This line includes all the FTP functions you need. Open this file to see which functions contains exactly. $server = '' $username = '' $pass = '' $Open = _FTP_Open('MyFTP Control') $Conn = _FTP_Connect($Open, $server, $username, $pass) $Ftpp = _FTP_FileGet($Conn, '/EDI-Archiv-CD/bin/Status.txt', 'C:\Users\mwenzel\Documents\proUSBPacker\Customers\Status.txt', False, 128, $FTP_TRANSFER_TYPE_ASCII) ;$FTP_TRANSFER_TYPE_BINARY If @error Then ConsoleWrite("ERROR - " & @error & " - " & @extended & " - " & _WinAPI_GetLastErrorMessage() & @CR) $Ftpc = _FTP_Close($Open) MsgBox(0, "", "") $Open = _FTP_Open('MyFTP Control') $Conn = _FTP_Connect($Open, $server, $username, $pass) ;~ _FTP_FileGet($l_FTPSession, $s_RemoteFile, $s_LocalFile [, $fFailIfExists = False, [$dwFlagsAndAttributes = 0 [, $l_Flags = 0 [, $l_Context = 0]]]]) $Ftpp = _FTP_FileGet($Conn, '/EDI-Archiv-CD/bin/Status.txt', 'C:\Users\mwenzel\Documents\proUSBPacker\Customers\Status.txt', False, 128, $FTP_TRANSFER_TYPE_ASCII) ;$FTP_TRANSFER_TYPE_BINARY If @error Then ConsoleWrite( Please help me out guys. I need to get this finished :/
    • toofat
      By toofat
      If somebody could please explain to me why is function "_FTP_FindFileFirst" returning over and over again the same files that I have allready downloaded and deleted, and why does the function "_FTP_FileGet" reports "Succeeded" on downloading non-existing file? Only the function "_FTP_FileDelete" works OK (it reports Failed on all passes except the first).
      $iStatus = 0 $sServer = 'ftp.test.com' $sUsername = 'userftp' $sPass = 'passftp' $iInterval = 10 ConsoleWrite ('Opening a new FTP session ... ') $hOpen = _FTP_Open ('FTP Control ' & @AutoItPID) If @error Then ConsoleWrite ('Failed' & @CRLF) Sleep (5000) Exit EndIf ConsoleWrite ('Succeeded' & @CRLF) Dim $FTPTime = 1000*$iInterval, $FTPStart = TimerInit (), $FTPEnd = TimerDiff ($FTPStart) While 'FTP Connection' $FTPEnd = TimerDiff ($FTPStart) Select Case $FTPEnd > $FTPTime If NOT $iStatus Then ConsoleWrite ('Connecting to FTP server: ftp://' & $sUsername & ':' & $sPass & '@' & $sServer & ' ... ') $hConnect = _FTP_Connect ($hOpen, $sServer, $sUsername, $sPass, 1) If @error Then ConsoleWrite ('Failed' & @CRLF) $FTPStart = TimerInit () ContinueLoop EndIf ConsoleWrite ('Succeeded' & @CRLF) ConsoleWrite ('--------------------------------------------------' & @CRLF & @CRLF) EndIf $iStatus = _FTP_Command ($hConnect, 'STAT') If NOT $iStatus Then ConsoleWrite ('Connection to FTP server was lost' & @CRLF) $FTPStart = TimerInit () ContinueLoop EndIf Dim $h_Handle $aFile = _FTP_FindFileFirst ($hConnect, '/Dir1/Dir2/Dir3/', $h_Handle) If NOT @error Then While 'FTP Download/Delete' Sleep (10) ConsoleWrite ('File found: ' & $aFile[10] & @CRLF) ConsoleWrite ('Downloading file ... ') _FTP_FileGet ($hConnect, '/Dir1/Dir2/Dir3/' & $aFile[10], 'D:\TargetDir\' & $aFile[10], False) If @error Then ConsoleWrite ('Failed' & @CRLF) Else ConsoleWrite ('Succeeded' & @CRLF) ConsoleWrite ('Deleting file ... ') _FTP_FileDelete ($hConnect, '/Dir1/Dir2/Dir3/' & $aFile[10]) If @error Then ConsoleWrite ('Failed' & @CRLF) Else ConsoleWrite ('Succeeded' & @CRLF) EndIf EndIf ConsoleWrite ('--------------------------------------------------' & @CRLF) $aFile = _FTP_FindFileNext ($h_Handle) If @error Then ExitLoop WEnd EndIf $aClose = _FTP_FindFileClose ($h_Handle) ConsoleWrite ('No new files' & @CRLF) $FTPStart = TimerInit () EndSelect WEnd $hDisconnect = _FTP_Close ($hConnect) $hClose = _FTP_Close ($hOpen) Exit