【问题标题】:Why FindFirstFileW always return -1?为什么 FindFirstFileW 总是返回 -1?
【发布时间】:2013-03-29 00:32:39
【问题描述】:

FindFirstFileA (ANSI) 可以正常工作,而FindFirstFileW (Unicode) 则不行。 Wide 版本总是返回 -1 (INVALID_HANDLE_VALUE),但为什么呢?

'Declarations:
Option Explicit

Private Const MAX_PATH  As Long = 260
Private Const ALTERNATE As Long = 14
Private Const INVALID_HANDLE_VALUE As Long = -1

Private Type FILETIME
    dwLowDateTime  As Long
    dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
        dwFileAttributes As Long
        ftCreationTime As FILETIME
        ftLastAccessTime As FILETIME
        ftLastWriteTime As FILETIME
        nFileSizeHigh As Long
        nFileSizeLow As Long
        dwReserved0 As Long
        dwReserved1 As Long
        cFileName As String * MAX_PATH
        cAlternate As String * ALTERNATE
End Type

Private Declare Function FindFirstFileW Lib "kernel32" _
    (ByVal lpFileName As String, _
    ByRef lpFindFileData As WIN32_FIND_DATA) As Long

Private Declare Function FindFirstFileA Lib "kernel32" _
    (ByVal lpFileName As String, _
    ByRef lpFindFileData As WIN32_FIND_DATA) As Long

Private Declare Function FindClose Lib "kernel32" _
    (ByVal hFindFile As Long) As Long

Public Declare Function GetLastError Lib "kernel32" () As Integer

'Test Functions:
Public Function TestA(ByVal sf As String) As Long
    If Len(sf) < 3 Then Exit Function
    Dim wfd As WIN32_FIND_DATA
    TestA = FindFirstFileA(sf, wfd)
    'Debug.Print "AE:" & GetLastError()
    If TestA <> INVALID_HANDLE_VALUE Then FindClose TestA
End Function

Public Function TestW(ByVal sf As String) As Long
    If Len(sf) < 3 Then Exit Function
    Dim wfd As WIN32_FIND_DATA
    TestW = FindFirstFileW(sf, wfd)
    'Debug.Print "WE:" & GetLastError()
    If TestW <> INVALID_HANDLE_VALUE Then FindClose TestW
End Function

'Example test
Private Sub Command1_Click()
    Dim sDir As String
    sDir = "C:\new"
    MsgBox "A: " & TestA(sDir) & vbCrLf _
         & "W: " & TestW(sDir)
End Sub

P.S. 感谢 Carey Gregory,但我仍然需要一些帮助来翻译 Wide 版本。 VB6中C/C++WCHAR的等价物是什么?

//WinBase.h
typedef struct _WIN32_FIND_DATAA {
    DWORD dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    DWORD nFileSizeHigh;
    DWORD nFileSizeLow;
    DWORD dwReserved0;
    DWORD dwReserved1;
    CHAR   cFileName[ MAX_PATH ];
    CHAR   cAlternateFileName[ 14 ];
#ifdef _MAC
    DWORD dwFileType;
    DWORD dwCreatorType;
    WORD  wFinderFlags;
#endif
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
typedef struct _WIN32_FIND_DATAW {
    DWORD dwFileAttributes;
    FILETIME ftCreationTime;
    FILETIME ftLastAccessTime;
    FILETIME ftLastWriteTime;
    DWORD nFileSizeHigh;
    DWORD nFileSizeLow;
    DWORD dwReserved0;
    DWORD dwReserved1;
    WCHAR  cFileName[ MAX_PATH ];    //WCHAR in VB6?
    WCHAR  cAlternateFileName[ 14 ]; //WCHAR in VB6?
#ifdef _MAC
    DWORD dwFileType;
    DWORD dwCreatorType;
    WORD  wFinderFlags;
#endif
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;

【问题讨论】:

    标签: winapi unicode syntax vb6


    【解决方案1】:

    WIN32_FIND_DATA 有两个版本,就像使用它们的函数一样:ANSI 版本和 Unicode 版本。您需要定义 WIN32_FIND_DATAA 和 WIN32_FIND_DATAW 并将它们与 'A' 和 'W' 函数一起使用。

    【讨论】:

    • 您能详细说明一下,W 版本的效果如何?
    • 正如您显然理解的那样,因为您的 TestATestW 函数,ANSI 和 Unicode 文本有单独的 Win32 API 函数。这些函数也需要单独的 WIN32_FIND_DATA 结构,因为该结构包含文本数据。看一下 winbase.h 中的 WIN32_FIND_DATA 定义,你需要做什么应该很明显了。
    • 感谢您的回答!我还需要一点帮助。请参阅我更新的问题。
    【解决方案2】:

    好吧,在重新阅读this article 之后,我发现了我的错误。这不是单独的WIN32_FIND_DATAW类型,而是需要将FindFirstFileW参数声明为LongByVal

    Private Declare Function FindFirstFileW Lib "kernel32" _
        (ByVal lpFileName As Long, _
        ByVal lpFindFileData As Long) As Long
    

    还需要用StrPtrVarPtr 给他们打电话。

    TestW = FindFirstFileW(StrPtr(sf), VarPtr(wfd))
    

    【讨论】:

    • 您仍然需要定义两个单独的 WIN32_FIND_DATA 结构,因为 Unicode 版本的 FindFirstFile 将返回一个 WIN32_FIND_DATAW 结构。我不是 VB 专家,但我的理解是您可以使用 ChrW 在 VB 中定义 WCHAR。
    • @CareyGregory - 我认为 WIN32_FIND_DATAW 的 VB 版本是不可能的,当然,如果有人知道方法,我将不胜感激。
    • 这并非不可能。只需将 cFileName 和 cAlternateFileName 分别声明为长度为 MAX_PATH * 2 和 14 * 2 的 Byte。在 VB6 中使用 WCHAR 类型的示例遍布网络。例如,here
    • 感谢您的帮助,我认为您的建议很有意义,看起来可行。但我发现 Byte 数组的值不同,例如 ex。 cFileName(1 To (260 + 16) * 2)cAlternate((14 * 2) - 1),不能确定哪个是正确的。在说明两种方式的具体优点/缺点之前,也许还需要进行更高级的测试。现在我想坚持大多数 vb-guys 所做的事情,即在我的回答中。
    猜你喜欢
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2020-08-19
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多