164VS2022下VC++调用CreateFile文件名不能接受char*,包括强制转换成LPCWSTR的char*也会出错

Posted zhangchao19890805

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了164VS2022下VC++调用CreateFile文件名不能接受char*,包括强制转换成LPCWSTR的char*也会出错相关的知识,希望对你有一定的参考价值。

错误代码

#include <stdio.h>
#include <iostream>
#include "Windows.h"

using namespace std;

int main(int argc, char* argv[]) 
	char* str = argv[1];

	char cFilename[256] =  0 ;
	HANDLE hFile;
	DWORD dwReturn;
	
	sprintf_s(cFilename, "D:\\\\ws\\\\tmpdir\\\\%s.txt", str);
	cout << cFilename << endl;

	hFile = CreateFile((LPCWSTR)cFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	cout << "hFile=" << hFile << endl;
	cout << "INVALID_HANDLE_VALUE=" << INVALID_HANDLE_VALUE << endl;
	if (hFile == INVALID_HANDLE_VALUE)
	
		cout << "hFile INVALID_HANDLE_VALUE" << endl;
		return 1;
	
	hFile = INVALID_HANDLE_VALUE;
	return 0;

上面这段代码在VS2022中,编码格式为GB2312,使用VC++编译,不会报错,但是执行代码不会创建文件。要想明白原因需要看一下 CreateFile 的定义:


WINBASEAPI
HANDLE
WINAPI
CreateFileA(
    _In_ LPCSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );

WINBASEAPI
HANDLE
WINAPI
CreateFileW(
    _In_ LPCWSTR lpFileName,
    _In_ DWORD dwDesiredAccess,
    _In_ DWORD dwShareMode,
    _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    _In_ DWORD dwCreationDisposition,
    _In_ DWORD dwFlagsAndAttributes,
    _In_opt_ HANDLE hTemplateFile
    );

#ifdef UNICODE
#define CreateFile  CreateFileW
#else
#define CreateFile  CreateFileA
#endif // !UNICODE

由于编译和运行环境的不同,这里会走 #define CreateFile CreateFileW 分支,也就是说第一个参数必须是LPCWSTR。上面的错误例子中,就算把 char* 强制转换成 LPCWSTR,也只是编译器不报错,但是实际运行程序的时候还是无法创建文件。

正确的写法

把 CreateFile 函数替换成 CreateFileA 函数,即可正常创建文件。


#include <stdio.h>
#include <iostream>
#include "Windows.h"

using namespace std;

int main(int argc, char* argv[]) 
	char* str = argv[1];

	char cFilename[256] =  0 ;
	HANDLE hFile;
	
	sprintf_s(cFilename, "D:\\\\ws\\\\tmpdir\\\\%s.txt", str);
	cout << cFilename << endl;

	hFile = CreateFileA(cFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	cout << "hFile=" << hFile << endl;
	cout << "INVALID_HANDLE_VALUE=" << INVALID_HANDLE_VALUE << endl;
	if (hFile == INVALID_HANDLE_VALUE)
	
		cout << "hFile INVALID_HANDLE_VALUE" << endl;
		return 1;
	
	hFile = INVALID_HANDLE_VALUE;
	return 0;


以上是关于164VS2022下VC++调用CreateFile文件名不能接受char*,包括强制转换成LPCWSTR的char*也会出错的主要内容,如果未能解决你的问题,请参考以下文章

166VS2022调试通过海康人脸抓拍SDK的C++代码

VC6.0和VS2005:C++和C#编写调用COM组件

QT 调用VS2015编写的Dll

2015.3.5 VS2005调用VC6 dll 时结构参数的传递

VC6.0编译DLL,使用VS2010调用问题及解决方法

VS怎么打开Call Stack窗口