在 Win32 中使用 IShellLinkA 和 IPersistFile 创建文件快捷方式时生成的 Unicode 文件名
Unicode filename generated when creating a fileshortcut with IShellLinkA and IPersistFile in Win32
我有在 Win32
中创建文件快捷方式的功能:
// prototype
HRESULT CreateLink(LPCSTR lpszPathObj, LPCSTR lpszPathLink, LPCSTR lpszDesc);
当我这样称呼它时:
StrCpyA(dst_file, argv[2]);
StrCpyA(src_file, argv[4]);
// concat ".lnk" to destination path
StrCatA(dst_file, ".lnk");
HRESULT res = CreateLink(src_file, dst_file, LINK_DESC);
它生成特定的快捷方式文件然后文件名是在argv[4]
中输入的文件名,像这样:
e.g. : file_shortcut.exe -src 1.bmp -dst 123
但是 文件属性 中的真实文件名是一个 unicode 名称 :
⸱浢p
即使我使用 MultiByteToWideChar()
将目标文件名转换为 WCHAR[]
:
INT wch_size = MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, wsz, wch_size);
在这个函数中,我使用了 IShellLink
和 IPersistFile
接口如下:
// function implementation
HRESULT CreateLink(LPCSTR lpszPathObj, LPCSTR lpszPathLink, LPCSTR lpszDesc)
{
HRESULT hres;
IShellLinkA* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH] = {0};
// Ensure that the string is Unicode.
INT wch_size = MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, wsz, wch_size);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
有什么建议吗?
我知道了:
因为我将 IShellLinkA* psl;
接口定义为 ANSI
而且我必须在波纹管函数中使用 IID_IShellLinkA
而不是 IID_IShellLink
:
// mismatch with IShellLinkA
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
// correct way used of IID_IShellLinkA instead of IID_IShellLink
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, (LPVOID*)&psl);
我有在 Win32
中创建文件快捷方式的功能:
// prototype
HRESULT CreateLink(LPCSTR lpszPathObj, LPCSTR lpszPathLink, LPCSTR lpszDesc);
当我这样称呼它时:
StrCpyA(dst_file, argv[2]);
StrCpyA(src_file, argv[4]);
// concat ".lnk" to destination path
StrCatA(dst_file, ".lnk");
HRESULT res = CreateLink(src_file, dst_file, LINK_DESC);
它生成特定的快捷方式文件然后文件名是在argv[4]
中输入的文件名,像这样:
e.g. : file_shortcut.exe -src 1.bmp -dst 123
但是 文件属性 中的真实文件名是一个 unicode 名称 :
⸱浢p
即使我使用 MultiByteToWideChar()
将目标文件名转换为 WCHAR[]
:
INT wch_size = MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, wsz, wch_size);
在这个函数中,我使用了 IShellLink
和 IPersistFile
接口如下:
// function implementation
HRESULT CreateLink(LPCSTR lpszPathObj, LPCSTR lpszPathLink, LPCSTR lpszDesc)
{
HRESULT hres;
IShellLinkA* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH] = {0};
// Ensure that the string is Unicode.
INT wch_size = MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, lpszPathLink, -1, wsz, wch_size);
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
有什么建议吗?
我知道了:
因为我将 IShellLinkA* psl;
接口定义为 ANSI
而且我必须在波纹管函数中使用 IID_IShellLinkA
而不是 IID_IShellLink
:
// mismatch with IShellLinkA
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
// correct way used of IID_IShellLinkA instead of IID_IShellLink
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, (LPVOID*)&psl);