【问题标题】:GetLastError returns error 2 in SystemParametersInfoGetLastError 在 SystemParametersInfo 中返回错误 2
【发布时间】:2013-02-03 07:19:17
【问题描述】:
#include <iostream>
#include <windows.h>
using namespace std;

int main(){
    LPWSTR test = L"c:/aizen.png";
    int result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, test, SPIF_UPDATEINIFILE);
    if(result)
        cout << "Wallpaper set!";
    else
        cout << "Error: " << GetLastError();
    cin >> result;
    return 0;
}

该代码只是为了更改背景墙纸,但我不断收到错误:2,这意味着“找不到文件”。但是,文件在那里!我正在使用 microsoft visual studio 2010,我尝试以管理员身份运行、区分大小写、更改斜杠等。我做错了什么?

【问题讨论】:

  • 什么是 C:/ ??更改为 C:\\aizen.png
  • 请仔细阅读问题:我说我已经尝试过了,但没有成功。
  • 你定义了 UNICODE 吗?如果不是,您最终将使用 Unicode 字符串调用 SystemParametersInfo 的 ANSI 版本,因此它最终会将文件名视为“c”... SystemParamatersInfo 很棘手,因为 pvParam 是 void*,所以没有CHAR 与 WCHAR 类型检查,您可以使用其他强类型 API。尝试显式调用 Unicode 版本 SystemParamtersInfoW。

标签: c++ winapi


【解决方案1】:

错误 2 是 File not found

首先,确保aizen.png 实际上位于驱动器C:\ 的根文件夹中(这在Vista 及更高版本上不太可能,因为非管理员用户通常没有那里的写入权限)。

如果文件确实存在,则问题很可能是您没有正确转义反斜杠:

LPWSTR test = L"c:\\aizen.png";

【讨论】:

  • 请仔细阅读问题:我说我已经尝试过了,但没有成功。
  • 您的问题是“试图更改斜线”。它没有说明转义反斜杠,这是正确的解决方案。如果这不起作用,则该文件不存在于您认为存在的位置。
  • @DarrenSadr,正如 Ken 所说,a)您的文件不在 C 驱动器中使用该名称 b)您没有正确转义反斜杠。再次检查所有内容
  • 抱歉问题不清楚。但是,我尝试将正斜杠更改为双反斜杠,但仍然出现相同的错误。但是,使用 mingw g++ 编译通过一些修改解决了它。只要 stackoverflow 允许,我就会发布我的答案。
  • 我已经复制/粘贴了你的代码,它成功地改变了我的背景。我重新检查了代码,重新检查了WinXP和Win7,它仍然有效。确保没有管理访问问题,尝试使用其他路径运行您的代码,尝试使用管理权限运行(也许?),但它只是在这里工作。
【解决方案2】:

问题是您将 UNICODE 字符串 - LPWSTR - 传递给采用 ANSI 的 API。

几乎所有 Win32 API(无论如何都接受字符串)有两个版本,一个以 ...A 结尾的 ANSI(8 位字符),一个以 ...W 结尾的 Wide- char,又名 UNICODE(从技术上讲,它不是“真正的”unicode,但这比在这个回复中得到的更多)。

如果您在编译时有 UNICODE #defined,那么简单的未修饰版本将 #defined 为 ...W 版本;否则它会被 #defined 定义为 ...A 版本。看看winuer.h,你会看到:

WINUSERAPI
BOOL
WINAPI
SystemParametersInfoA(
    __in UINT uiAction,
    __in UINT uiParam,
    __inout_opt PVOID pvParam,
    __in UINT fWinIni);
WINUSERAPI
BOOL
WINAPI
SystemParametersInfoW(
    __in UINT uiAction,
    __in UINT uiParam,
    __inout_opt PVOID pvParam,
    __in UINT fWinIni);
#ifdef UNICODE
#define SystemParametersInfo  SystemParametersInfoW
#else
#define SystemParametersInfo  SystemParametersInfoA
#endif // !UNICODE

注意,Windows 有两个 SystemParametersInfo 函数; W 期望宽 LPWSTR 而 A 期望普通 LPSTR;以及是否定义了 UNICODE 选择哪个是“默认”。 (您始终可以手动添加 A 或 W 以显式调用。)

在您的原始代码中可能发生的情况是,由于您没有定义 UNICODE,您最终会使用 ...A 版本,它需要一个 ANSI 字符串,但您传递的是一个 UNICODE 字符串 - 所以它没有不行。

您为使其正常工作所做的“一点改变”不仅仅是一点点:您现在将一个 ANSI 字符串传递给 ...A 版本的 API,因此它可以正常工作:

int result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)"c:/aizen.jpg", SPIF_UPDATEINIFILE);

或者,您可以使用 LPWSTR 显式调用 W 版本:

int result = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, L"c:\\aizen.jpg", SPIF_UPDATEINIFILE);

或者,您可以在应用的开头定义 UNICODE,使用 L"..." 字符串和 API 的普通版本 - 只需在原始应用顶部的 #include 之前添加 #define UNICODE 即可。 (UNICODE 通常在 makefile 或编译器设置选项中定义,而不是在代码中显式定义,因此,如果您是 Win32 编程的新手,它可能会带来一些惊喜。)

请注意,LPWSTR 已被弃用;如果有的话,情况正好相反;自 XP 左右以来,典型的 Win32 实践一直是全面使用 W 风格的字符串,因此它实际上是在 Win32 上被视为“弃用”的普通“...”字符串。 (例如,许多 COM API 只使用宽字符串。)

大多数其他功能对此都有一些保护;如果您不小心尝试传递一个 ANSI 字符串来表示 SetWindowTextW,您将收到编译时错误,因为您传入的 LPSTR 与函数期望的预期 LPWSTR 类型不匹配。但是 SystemParamtersInfo 很棘手;它的 data 参数需要一个 void*,因此在编译时将接受 [几乎] anything,并且只有在运行时调用该函数时才会遇到错误。

--

顺便说一句,这就是 David Herfernan 在answer to your question the first time you posted 中指出的 -

一些可能的原因浮现在脑海中:
...
  • 您的 ANSI/Unicode 编码不匹配。

【讨论】:

    【解决方案3】:

    看起来很奇怪,如果你用 MinGW c++ 编译器编译它实际上会稍微改变一下编译:

    int main(){
            int result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)"c:/aizen.jpg", SPIF_UPDATEINIFILE);
    

    这可行,显然 LPWSTR 已被弃用... Visual Studio 可能存在权限问题。以管理员身份运行,然后重试。

    【讨论】:

    • Hrm,我没有投反对票 - 并且对投反对票的人感到羞耻,因为他们没有说明他们为什么这样做。无论如何,看起来问题是您正在使用 unicode 字符串调用 ANSI 函数,所以它失败了;现在你正在调用一个带有 ANSI 字符串的 ANSI 函数,所以它正在工作。更好的解决方法是使用宽/unicode 字符串调用宽/unicode 函数。更详细的解释见我的回答。
    • 我不明白。答案有什么问题?它提供了正确的代码和对我有用的解决方案。
    • 您的回答可能存在一些问题;这个问题不是“很奇怪”,LPWSTR 也没有被弃用,也没有与特权问题有关的问题。请阅读我的答案,了解为什么您的原始代码不起作用以及为什么您的更改可以修复它。编写代码不仅仅是改变事物直到它们看起来有效;了解为什么事情不工作或工作很重要。
    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 2011-03-01
    • 1970-01-01
    • 2017-06-10
    相关资源
    最近更新 更多