使用WinAPI获取C中当前用户的桌面路径

使用WinAPI获取C中当前用户的桌面路径,c,winapi,C,Winapi,我对WinAPI编程非常陌生。我想知道如何获得用户桌面的路径,然后打印出控制台的完整路径。这是我当前的代码: TCHAR* path = 0; HRESULT result = SHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path); if (result == S_OK) { printf("%s\n", path); } CoTaskMemFree(path) 它确实找到了路径,但它打印出路径的“C”,而不是带

我对WinAPI编程非常陌生。我想知道如何获得用户桌面的路径,然后打印出控制台的完整路径。这是我当前的代码:

TCHAR* path = 0;
HRESULT result = SHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path);
if (result == S_OK)
{
    printf("%s\n", path);
}
CoTaskMemFree(path)
它确实找到了路径,但它打印出路径的“C”,而不是带斜杠的整个路径。我错过了什么


谢谢

它只打印一个字符,因为您试图将宽字符串打印为窄字符串。您可能已经定义了UNICODE/\uUnicode,因此TCHAR就是WCHAR

如果您坚持使用TCHAR,则应使用TCHAR中的正确打印功能。h:

_tprintf(_T("%s\n"), path);
否则,您可以使用宽版本:

wprintf(L"%s\n", path);
或者,最糟糕的解决方案是将字符串转换为窄码页字符串:

printf("%ls\n", path); // This might not display all Unicode characters correctly

它只打印一个字符,因为您试图将宽字符串打印为窄字符串。您可能已经定义了UNICODE/\uUnicode,因此TCHAR就是WCHAR

如果您坚持使用TCHAR,则应使用TCHAR中的正确打印功能。h:

_tprintf(_T("%s\n"), path);
否则,您可以使用宽版本:

wprintf(L"%s\n", path);
或者,最糟糕的解决方案是将字符串转换为窄码页字符串:

printf("%ls\n", path); // This might not display all Unicode characters correctly
SHGetKnownFolderPath()
输出一个
wchar\u t*
指针,而不是
TCHAR*
指针。没有ANSI版本的
SHGetKnownFolderPath()
,因此在这种情况下不应该使用
TCHAR
。事实上,除非定义了
UNICODE
,这样
TCHAR
映射到
wchar\t
,否则代码不会编译

之所以只看到第一个字符,是因为您正在传递一个
wchar\u t*
,其中需要一个
char*
。在Windows上,
wchar\u t
为16位,因此
wchar\u t*
字符串以UCS-2或UTF-16LE编码。UCS-2/UTF-16LE中的所有ASCII字符的高8位都设置为0。您使用的
printf()
需要一个以null结尾的
char*
字符串,因此第一个
wchar\t
字符的高0x00字节被误解为null终止符

要执行所需操作,需要将返回的路径打印为宽字符串,而不是(被误解的)窄字符串

您可以将
%S
printf()一起使用,例如:

PWSTR path;
if (SHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path) == S_OK)
{
    printf("%S\n", path);
    CoTaskMemFree(path);
}
但这在编译器之间是不可移植的。您应该将
%s
wprintf()
一起使用:

PWSTR path;
if (SHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path) == S_OK)
{
    wprintf(L"%s\n", path);
    CoTaskMemFree(path);
}
SHGetKnownFolderPath()
输出一个
wchar\u t*
指针,而不是
TCHAR*
指针。没有ANSI版本的
SHGetKnownFolderPath()
,因此在这种情况下不应该使用
TCHAR
。事实上,除非定义了
UNICODE
,这样
TCHAR
映射到
wchar\t
,否则代码不会编译

之所以只看到第一个字符,是因为您正在传递一个
wchar\u t*
,其中需要一个
char*
。在Windows上,
wchar\u t
为16位,因此
wchar\u t*
字符串以UCS-2或UTF-16LE编码。UCS-2/UTF-16LE中的所有ASCII字符的高8位都设置为0。您使用的
printf()
需要一个以null结尾的
char*
字符串,因此第一个
wchar\t
字符的高0x00字节被误解为null终止符

要执行所需操作,需要将返回的路径打印为宽字符串,而不是(被误解的)窄字符串

您可以将
%S
printf()一起使用,例如:

PWSTR path;
if (SHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path) == S_OK)
{
    printf("%S\n", path);
    CoTaskMemFree(path);
}
但这在编译器之间是不可移植的。您应该将
%s
wprintf()
一起使用:

PWSTR path;
if (SHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path) == S_OK)
{
    wprintf(L"%s\n", path);
    CoTaskMemFree(path);
}

通常,您可以在函数名的末尾添加“A”来选择ASCII版本,但根据MSDN,这是一个win32函数,只有unicode版本--“Out PWSTR*ppszPath”,因此它不是SHGetKnownFolderPathW的别名,它不存在。@DaveS啊,是的,很好,我想到的是旧的特殊文件夹函数。使用“A”版本不是一个好主意,它不能处理所有Unicode路径也是一个选项?@zzxyz%S与此选项中的%ls相同case@Anders:这就是我的观点:TCHAR的全部要点是映射到char或wchar\t。在这种情况下,您不能这样做,因此它根本不应该使用TCHAR。它应该使用wchar_t(或wchar),因为它必须始终使用宽字符。通常,您可以在函数名的末尾添加“A”来选择ASCII版本,但根据MSDN,这是一个win32函数,只有unicode版本--“Out PWSTR*ppszPath”,因此它不是SHGetKnownFolderPathW的别名,这是不存在的。@DaveS啊,是的,很好,我想到的是旧的特殊文件夹函数。使用“A”版本不是一个好主意,它不能处理所有Unicode路径也是一个选项?@zzxyz%S与此选项中的%ls相同case@Anders:这就是我的观点:TCHAR的全部要点是映射到char或wchar\t。在这种情况下,您不能这样做,因此它根本不应该使用TCHAR。它应该使用wchar\u t(或wchar),因为它必须始终使用宽字符。TCHAR对您没有好处,因为您不支持Windows 98。因此,请使用wchar\u t并只使用本机Unicode API。TCHAR对您没有好处,因为您不支持Windows 98。因此,请使用wchar__t,并只使用本机Unicode API。