如何在C++中将SHGetKnownFolderPath输出提供给CopyFile

How to feed SHGetKnownFolderPath output to CopyFile in C++?

本文关键字:CopyFile 输出 SHGetKnownFolderPath C++ 中将      更新时间:2023-10-16

我想通过SHGetKnownFolderPath获得FOLDERID_ProgramFiles,并通过以下代码将当前运行的文件复制到它:

char ModuleFileName[24];
GetModuleFileName(NULL, ModuleFileName, MAX_PATH) ;
PWSTR path = NULL;
SHGetKnownFolderPath(FOLDERID_ProgramFiles,0,NULL,&path);
CopyFile(ModuleFileName,path,FALSE);

但我没有锁,因为PWSTRwchar_t*CopyFile需要const char*,我试着把星号放在Path之前,并使用wcstombs函数进行转换,但没有锁!

我该怎么修?

PS:我有这个错误:

error: cannot convert ‘PWSTR {aka wchar_t*}’ to ‘LPCSTR {aka const char*}’ for argument ‘2’ to ‘WINBOOL CopyFileA(LPCSTR, LPCSTR, WINBOOL)’

我应该提到我使用的是Mingw g++编译器,所以使用wprintf(L"%lsn",[STR] );打印这些变量有点困难,而且我在输出中会得到很多坏字符。

使用API函数的*W变体(GetModuleFileNameW、CopyFileW等(,并在整个过程中使用wchar_t字符而不是字符。

您的另一种选择是从SHGetKnownFolderPath中获取返回的路径,并使用WideCharToMultiByte将路径转换为字符,但第一种方法更可取(例如,它不会对与用户区域设置匹配的字符进行dpend(。

您正在调用CopyFile()的ANSI版本,并在第二个参数中向其传递Unicode字符串。这就是为什么你会得到一个编译器错误。请改用GetModuleFileName()CopyFile()的Unicode版本。

此外,您的ModuleFileName的大小只有24个chars,但您告诉GetModuleFileNameW()它的大小是MAX_PATH(260(个字符。

此外,CopyFile()需要文件路径,而不是文件夹路径。您需要从ModuleFileName中提取文件名,并在将其传递给第二个参数时将其附加到path的末尾。

试试类似的东西:

WCHAR ModuleFileName[MAX_PATH] = {};
GetModuleFileNameW(NULL, ModuleFileName, MAX_PATH);
PWSTR path = NULL;
SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, NULL, &path);
WCHAR NewFileName[MAX_PATH] = {};
PathCombineW(NewFileName, path, PathFindFileNameW(ModuleFileName));
CoTaskMemFree(path);
CopyFileW(ModuleFileName, NewFileName, FALSE);

PathCombine()还有其他替代品,例如:

WCHAR NewFileName[PATHCCH_MAX_CCH] = {};
PathCchCombine(NewFileName, PATHCCH_MAX_CCH, path, PathFindFileNameW(ModuleFileName));
// use NewFileName as needed...
PWSTR NewFileName = NULL;
PathAllocCombine(path, PathFindFileNameW(ModuleFileName), 0, &NewFileName);
// use NewFileName as needed...
LocalFree(NewFileName);
#include <string>
std::wstring NewFileName(path);
if (NewFileName.back() != L'')
NewFileName += L'';
NewFileName += PathFindFileNameW(ModuleFileName);
// use NewFileName as needed...
#include <filesystem>
std::wstring NewFileName = (std::filesystem::path(path) / PathFindFileNameW(ModuleFileName)).wstring();
// use NewFileName as needed...