0

好的,我的程序有问题。我之前提出了一个问题,但没有人真正理解我的问题,所以这次我尝试了一种新的方法。

如果你好奇这是我的问题:

我的程序以 的形式接受参数char* argv[],并且我无法创建指向正在argv[1]使用的任何内容的指针LPWSTR,因为它只指向const wchar_t*对象。

这是我试图解决我的问题的新事物(我已经尝试了多种方法,但我需要知道如何去做我在想的事情,或者如果可能的话)

基本上,我的想法是#define某种函数,它接受任何内容并用该值argv[1]定义 a 。const wchar_t*

像这样的东西:

#define path       ((const wchar_t*)argv[1])

我不确定这是做我想做的事情的正确方法(或者即使这是可能的)......

如果您有更好的方法来解决我的问题,请(请)告诉我如何帮助我,我一直在考虑这个问题很长时间!

我的程序说明:

我正在制作一个接收参数的程序。参数是驱动器的名称,例如“F:”。CreateFile然后它使用带有驱动器号的函数。如果你去这里,看到函数的第一个参数,我想你会明白我的意思......问题是我要制作一个 LPWSTR,我需要一个 const wchat_t* 对象......我希望这次我的问题很清楚,上次人们并没有真正理解我想要做什么。

无论如何,谢谢!编辑 1:这是我的程序的求解行(这是我必须做的工作,没有参数)(我在这里使用了一个固定值)

int main()
{

HANDLE device;

device = CreateFile(L"\\\\.\\F:",    // Drive to open
    GENERIC_READ | GENERIC_WRITE,       // Access mode
    FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
    NULL,                   // Security Descriptor
    OPEN_EXISTING,          // How to create
    0,                      // File attributes
    NULL);  
}

这是带参数的(不起作用)

int main(int argc, char* argv[])
{

HANDLE device;

device = CreateFile(argv[1],    // Drive to open
    GENERIC_READ | GENERIC_WRITE,       // Access mode
    FILE_SHARE_READ | FILE_SHARE_WRITE, // Share Mode
    NULL,                   // Security Descriptor
    OPEN_EXISTING,          // How to create
    0,                      // File attributes
    NULL);                  // Handle to template
}

^ 这显示了我想要做什么

编辑 2:我将其更改CreateFileCreateFileA,这是它给我的 eroor 代码(驱动器 D 是 USB,它不是硬盘驱动器) 错误

因此,除非我输入错误的路径来输入路径,否则它总是会给我错误。我想我会尝试另一种方法来解决问题,或者如果有人知道为什么会发生错误,请告诉!

4

1 回答 1

7

编辑 2:我将 CreateFile 更改为 CreateFileA ,这是它给我的 eroor 代码(驱动器 D 是 USB,它不是硬盘驱动器)

这是一个完全不同的问题,与wchar_t.

在您的第一次剪辑中,您通过了"\\\\.\\F:"(AKA\\.\F:一旦我们删除了 C 转义);在您从命令行进行的所有尝试中,您从未提供过此路径,但分别是:

  • D- 所以它试图打开一个D在当前目录中命名的文件,但它没有找到它(错误 2,又名ERROR_FILE_NOT_FOUND);
  • D:\- 无法打开的根目录CreateFile(错误 3,aka ERROR_PATH_NOT_FOUND),
  • D:- 驱动器 D: 上的当前目录,再次无法打开CreateFile(错误 5,又名ERROR_ACCESS_DENIED);
  • \D:- 当前驱动器根目录中名为“D:”的文件,如果D:不是有效的文件名(错误 123,又名ERROR_INVALID_NAME),则无法创建该文件。

要将驱动器作为设备打开,必须使用\\.\X:路径(X驱动器号在哪里);你不能只是把你脑海中浮现的任何东西都扔掉,然后希望它会起作用。从命令行传递调用您的程序"\\.\D:",它会正常工作。

当然,如果您想让用户更简单,您可以只接受命令行上的驱动器号并编写一些代码来创建CreateFile基于它所需的字符串。

if(argc<1) {
    printf("Not enough arguments\n");
    return 1;
}
const char *drive = argv[1];
char d = drive[0];
// accept both `d` and `d:` as argument for the drive
if(!((d>='a' && d<='z') || (d>='A' && d<='Z')) ||
     (drive[1]!=0 && drive[1]!=':') ||
      drive[2]!=0) {
    printf("Invalid drive specifier: `%s`\n", drive);
    return 2;
}
char path[]="\\\\.\\X:";
path[4] = d;
// now you can use path as argument to CreateFileA

接下来是原始答案,它仍然有效,但它解决了一个完全不同的问题,与 OP 遇到的实际问题无关

您不能LPWSTR指向 a char *,尤其是不能通过粗暴地转换指针 - 转换指针只会使编译器关闭,它不会改变您指向的不是wchar_t字符串的事实。如果要将 a 传递char *给期望 a 的函数wchar_t *,则必须对指向的数据执行实际转换。

现在,您有几种可能的解决方案:

  • 您可以直接使用_wmain和接收命令行参数作为宽字符;
  • 您可以使用MultiByteToWideChar等函数将本地编码字符串转换为 UTF-16 字符串;这可以封装在一个返回 a 的函数std::wstring
  • 您可以只调用 ANSI 版本的 API 并让它处理它;几乎所有 Win32 API 都有 ANSI 和 Unicode 版本,后缀为 A 和 W(CreateFile只是一个扩展为CreateFileACreateFileW依赖于宏的_UNICODE宏)。因此,您可以CreateFileA按原样使用并传递您的字符串。

最后两个解决方案不是很好,因为使用本地编码字符串作为命令行参数会阻止您的程序使用任意 Unicode 字符打开文件。OTOH,wchar_t几乎在任何地方都使用是相当可怕的,因为它们几乎“感染”了应用程序的每个字符串处理角落。正确的(恕我直言)出路是在任何地方使用 UTF-8,并在与操作系统交谈时即时转换;详情见这里

于 2017-06-16T08:51:10.617 回答