我尝试通过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]
,它也会失败。
应用程序以管理员身份运行。
答案 0 :(得分:4)
错误代码准确无误。找不到该文件。可能的解释包括:
如果您希望将文件名解释为相对于可执行文件所在的目录,请执行此操作。从包含可执行文件的目录和指定的文件名形成绝对路径。
没有理由期望进程工作目录是可执行文件所在的目录。
答案 1 :(得分:1)
您正在尝试使用相对路径名打开文件。相对路径名相对于当前工作目录(请参阅GetCurrentDirectory)。当前工作目录不一定是可执行映像所在的目录。由于多种原因,它可能有所不同,例如:
如果要打开相对于应用程序可执行映像的文件,则需要根据可执行文件的位置和所需的文件名构造一个完全限定的路径名。以下代码检索可执行文件的目录 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及更高版本应使用PathCchRemoveFileSpec和PathCchAddBackslash代替。