GetLastError在SystemParametersInfo中返回错误2

时间:2013-02-03 07:19:18

标签: c++ winapi

#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,我尝试以管理员身份运行,区分大小写,更改斜线等等。我做错了什么?

3 个答案:

答案 0 :(得分:2)

错误2是File not found

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

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

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

答案 1 :(得分:1)

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

几乎所有Win32 API(所有以任何速率接收字符串)都有两个版本,一个以...结尾为ANSI(8位字符),另一个以...结尾为W char,又名UNICODE(技术上不是'真正的'unicode,但在这个回复中不仅仅是值得的。)

如果你在编译时有UNICODE #define d,那么普通的unadorned版本将#defined作为... W版本;否则它会被#defined视为...一个版本。看看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,您最终会使用...一个版本,它需要一个ANSI字符串,但是您传入一个UNICODE字符串 - 所以它不会不行。

你为实现它而做的“改变”不仅仅是一点点:你现在将ANSI字符串传递给...... 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 已弃用;如果有的话,那是相反的;典型的Win32练习,因为XP左右一直使用W-flavor字符串,所以它实际上是在Win32上被认为是“弃用”的普通“......”字符串。 (例如,许多COM API仅使用宽字符串。)

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

-

顺便说一下,这是David Herfernan在answer to your question the first time you posted -

中指出的
一些可能的原因让人想起:
...
  • 您的ANSI / Unicode编码不匹配。

答案 2 :(得分:-1)

如果你使用MinGW c ++编译器编译它看起来非常奇怪,它实际上是通过一些改变来编译的:

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

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