当文件存在时,CreateFile失败并显示错误代码2

时间:2015-08-17 17:02:29

标签: c++ c winapi

我尝试通过CreateFile打开现有文件,但它总是失败errorcode 2 - 就像文件不存在一样,但它存在 - 它在可执行文件夹中。

hFile = CreateFile( argv[ 1 ], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
    printf( "\nError: Unable to open file (%d)\n", GetLastError( ) );
    return -1;
}

即使用硬编码的文件名字符串替换argv[1],它也会失败。 应用程序以管理员身份运行。

2 个答案:

答案 0 :(得分:4)

错误代码准确无误。找不到该文件。可能的解释包括:

  • 您使用了错误的文件名。
  • 您使用了相对路径,并且流程工作目录不是您期望的那样。

如果您希望将文件名解释为相对于可执行文件所在的目录,请执行此操作。从包含可执行文件的目录和指定的文件名形成绝对路径。

没有理由期望进程工作目录是可执行文件所在的目录。

答案 1 :(得分:1)

您正在尝试使用相对路径名打开文件。相对路径名相对于当前工作目录(请参阅GetCurrentDirectory)。当前工作目录不一定是可执行映像所在的目录。由于多种原因,它可能有所不同,例如:

  • 应用程序是通过显式设置工作目录的快捷方式启动的。
  • 该应用程序名为SetCurrentDirectory
  • 应用程序是通过命令解释程序从可执行文件目录以外的目录启动的。

如果要打开相对于应用程序可执行映像的文件,则需要根据可执行文件的位置和所需的文件名构造一个完全限定的路径名​​。以下代码检索可执行文件的目录 1)

#include <windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <string>
#include <vector>

std::wstring GetExePath() {
    // Retrieve fully qualified module pathname
    std::vector<wchar_t> buffer( MAX_PATH );
    DWORD cbSize = ::GetModuleFileNameW( nullptr, buffer.data(),
                                         static_cast<DWORD>( buffer.size() ) );
    while ( cbSize == buffer.size() ) {
        buffer.resize( buffer.size() + MAX_PATH );
        cbSize = ::GetModuleFileNameW( nullptr, buffer.data(),
                                       static_cast<DWORD>( buffer.size() ) );
    }
    if ( cbSize == 0 ) {
        throw ::GetLastError();
    }

    // Remove filename from fully qualified pathname
    if ( ::PathRemoveFileSpecW( buffer.data() ) ) {
        ::PathAddBackslashW( buffer.data() );
    }

    // Construct string object from character buffer
    std::wstring str( &buffer[0] );
    return str;
}

可以使用如下:

int wmain( int argc, const wchar_t* argv[] ) {

    if ( argc <= 1 ) {
        return -1;
    }

    std::wstring pathname = GetExePath();
    pathname += argv[1];
    HANDLE hFile = ::CreateFileW( pathname.c_str(), GENERIC_READ,
                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
                                  NULL, OPEN_EXISTING, 0, NULL );
    if ( hFile == INVALID_HANDLE_VALUE )
    {
        wprintf( L"\nError: Unable to open file (%d)\n", GetLastError() );
        return -1;
    }

    // ...

    ::CloseHandle( hFile );
    return 0;
}

<小时/> 1)代码定位Windows 8及更高版本应使用PathCchRemoveFileSpecPathCchAddBackslash代替。