WinINet FtpFindFirstFile PInvokeStackImbalance

时间:2017-09-26 00:19:17

标签: .net vb.net ftp wininet

问题:
在对非托管函数进行托管调用时(在本例中为FtpFindFirstFile),我收到 PInvokeStackImbalance 异常。

我正在尝试做什么:
我试图检查FTP服务器上是否存在文件,这导致我使用FtpFindFirstFile作为实现此目的的方法。我成功使用了wininet.dll库的其他功能,但我对上述功能没有成功。

我迄今为止所做的一切:
更改托管呼叫的数据类型以匹配dll呼叫的数据类型。我也使用GetType()作为一种方法来确保我确实拥有我认为的数据类型,因为异常消息暗示我将数据错误地传递给函数的参数。看图像,所有这些布尔变量都返回true。

UnbalancedStackError

致电IsRemoteFileExist():
以下是对我正在进行的函数IsRemoteFileExist()的调用,这是调用FtpFindFirstFile()的函数。

\n

WinINet.DLL函数的定义
这是我的WinINet函数声明的粘贴。 WinINet Function Declarations

    Public Function WindowsTransferFile(arr_sSourceFiles As String(),
                                    sDirTarget As String,
                                    Optional bUploadTransfer As Boolean = False) As Boolean
    'TODO: check for file existence before upload or download
    'TODO: This needs a logic cleanup to accommodate downloading
    Dim bReturn As Boolean = False

    Dim nINet As Long
    Dim nINetConnection As Long

    Dim sTargetFileName As String

    Dim iFileTotalCount As Integer = arr_sSourceFiles.Count
    Dim lstFilesFailed As List(Of String) = New List(Of String)

    Try
        nINet = WinINet.InternetOpen("ftp_sync", WinINet.INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0)

        nINetConnection = WinINet.InternetConnect(nINet,
                                                  Me._sHostname,
                                                  21,
                                                  Me._sUsername,
                                                  Me._sPassword,
                                                  WinINet.INTERNET_SERVICE_FTP,
                                                  WinINet.INTERNET_FLAG_PASSIVE,
                                                  0)

        If nINetConnection = Nothing Then
            Throw New Exception("Connection Failed.") 'TODO: Detailed exception message..
        End If

        ConsoleFeedback.OutputToConsole("Beginning FTP transfer of " & iFileTotalCount.ToString() & " files.")

        For Each sFile As String In arr_sSourceFiles

            If bUploadTransfer Then
                sTargetFileName = sDirTarget & IO.Path.GetFileName(sFile)

                IsRemoteFileExist(sTargetFileName, nINetConnection)

                bReturn = UploadFile(nINetConnection, sFile, sTargetFileName, WinINet.INTERNET_FLAG_PASSIVE, 0)

                If Not bReturn Then
                    lstFilesFailed.Add(sTargetFileName)
                End If
            Else
                bReturn = DownloadFile(nINetConnection, sFile, sDirTarget, False, 0, WinINet.INTERNET_FLAG_PASSIVE, 0)
            End If
        Next

        If lstFilesFailed.Count > 0 Then
            Dim sErrorMsg As String = "Finished with failures: "

            For Each sFileFailed As String In lstFilesFailed
                sErrorMsg &= sFileFailed & vbCrLf
            Next

            ConsoleFeedback.OutputToConsole(sErrorMsg)
        Else
            ConsoleFeedback.OutputToConsole("Finished transferring files.")
        End If

    Catch ex As Exception
        Throw New Exception(ex.Message, ex)
    Finally
        WinINet.InternetCloseHandle(CInt(nINet))
    End Try

    Return bReturn
End Function

不确定如何继续这个,所有其他WinINet功能对我有用,它就是我遇到问题的那个。

修改
刚注意到lib是" WinINet",我把它更改为" wininet.dll"为了一致性。

旧宣言:

Imports System.Runtime.InteropServices

Public Class WinINet

   Public Const INTERNET_OPEN_TYPE_PRECONFIG = 0 ' // use registry configuration
    Public Const INTERNET_OPEN_TYPE_DIRECT = 1 ' // direct to net
    Public Const INTERNET_OPEN_TYPE_PROXY = 3 ' // via named proxy
    Public Const INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY = 4 ' // prevent using java/script/INS

    Public Const INTERNET_SERVICE_FTP = 1       '
    Public Const INTERNET_SERVICE_GOPHER = 2    'Type of service to access.
    Public Const INTERNET_SERVICE_HTTP = 3      '

    Public Const INTERNET_OPTION_VERSION = 40   'Returns the version number of Wininet.dll.
    Public Const INTERNET_DEFAULT_FTP_PORT = 21 'Number of the TCP/IP port on the server to connect to.
    Public Const INTERNET_DEFAULT_GOPHER_PORT = 70
    Public Const INTERNET_DEFAULT_HTTP_PORT = 80
    Public Const INTERNET_DEFAULT_HTTPS_PORT = 443
    Public Const INTERNET_DEFAULT_SOCKS_PORT = 1080

    Public Const INTERNET_FLAG_PASSIVE As Long = &H8000000
    Public Const INTERNET_FLAG_EXISITING_CONNECT As Long = &H20000000
    Public Const INTERNET_FLAG_RELOAD As Long = &H80000000 'read from wire even if locally cached
    Public Const INTERNET_FLAG_ASYNC As Long = &H10000000  'this request is asynchronous (where supported)

    Public Structure FILETIME
        Dim dwLowDateTime As Long
        Dim dwHighDateTime As Long
    End Structure

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
    Structure WIN32_FIND_DATA
        Public dwFileAttributes As UInteger
        Public ftCreationTime As ComTypes.FILETIME
        Public ftLastAccessTime As ComTypes.FILETIME
        Public ftLastWriteTime As ComTypes.FILETIME
        Public nFileSizeHigh As UInteger
        Public nFileSizeLow As UInteger
        Public dwReserved0 As UInteger
        Public dwReserved1 As UInteger
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> Public cFileName As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> Public cAlternateFileName As String
    End Structure

    Public Declare Function internetopen Lib "wininet.dll" Alias "InternetOpenA" (ByVal lpszAgent As String, ByVal dwAccessType As Long, ByVal lpszproxyName As String, ByVal lpszproxyBypass As String, ByVal dwflags As Long) As Long
    Public Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal HINet As Integer) As Integer
    Public Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Integer, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Integer) As Integer
    Public Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Integer, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Integer, ByVal lFlags As Integer, ByVal lContext As Integer) As Integer
    Public Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" (ByVal hFtpSession As Integer, ByVal lpszRemoteFile As String, ByVal lpszNewFile As String, ByVal fFailIfExists As Boolean, ByVal dwFlagsAndAttributes As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Boolean
    Public Declare Function FtpPutFile Lib "wininet.dll" Alias "FtpPutFileA" (ByVal hFtpSession As Integer, ByVal lpszLocalFile As String, ByVal lpszRemoteFile As String, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Boolean
    Public Declare Function FtpFindFirstFile Lib "wininet.dll" Alias "FtpFindFirstFileA" (ByVal hFtpSession As IntPtr, ByVal lpszSearchFile As String, ByVal lpFindFileData As WIN32_FIND_DATA, ByVal dwFlags As Integer, ByVal dwContext As IntPtr) As IntPtr
    Public Declare Function InternetFindNextFile Lib "wininet.dll" Alias "InternetFindNextFileA" (ByVal hFind As Long, ByVal lpFindFileData As WIN32_FIND_DATA) As Long
    Public Declare Function FtpSetCurrentDirectory Lib "wininet.dll" Alias "FtpSetCurrentDirectoryA" (ByVal hFtpSession As Long, ByVal lpszDirectory As String) As Boolean
    Public Declare Function FtpGetCurrentDirectory Lib "wininet.dll" Alias "FtpGetCurrentDirectoryA" (ByVal hFtpSession As Long, ByVal lpszCurrentDirectory As String, ByVal lpdwCurrentDirectory As Long) As Long
    Public Declare Function FtpFindFirstFile Lib "WinInet" Alias "FtpFindFirstFileA" (ByVal hFtp As Long, ByVal lpszSearchFile As String, lpFindFileData As WIN32_FIND_DATA, ByVal dwFlags As Long, ByVal dwContext As Long) As Long

End Class

新声明:

Public Declare Function FtpFindFirstFile Lib "WinInet" Alias "FtpFindFirstFileA" (ByVal hFtp As Long, ByVal lpszSearchFile As String, lpFindFileData As WIN32_FIND_DATA, ByVal dwFlags As Long, ByVal dwContext As Long) As Long <br>

当然,这并没有解决我的问题。

0 个答案:

没有答案