使用系统API创建快捷方式时SetPath的参数研究

有个项目需要将一个快捷方式和一些程序转移到另一台电脑上,要求移到另一台电脑时快捷方式能够正常指向更改保存路径后的程序。

我在打包拷贝时将原快捷方式的路径前缀设置为##PATH##之类的字符串,然后在拷贝到新电脑之后用更改的保存路径来替换这串字符串,然后修改快捷方式。

但是使用过程中发现IShellLink::SetPath有对命名上的要求,有些参数会导致SetPath失败,有些参数虽然调用成功,但是会有速度上的减慢或者结果上的不正确,采用各种参数如下测试:
//shortCutInfo.path = _T("C:\\##install##\\test.bmp"); //&lt;速度非常快,并且成功 //shortCutInfo.path = _T("<a>\\\\127.0.0.1\\##install##\\test.bmp");//</a>&lt;速度一般(3秒左右),但也成功 //shortCutInfo.path = _T("\\\\notexistdomain\\##install##\\test.bmp");//&lt;速度非常慢(10秒左右),但也成功。可能是系统去验证这个文件是否存在了。 //shortCutInfo.path = _T("##install##\\test.bmp");//&lt;速度非常快,但成功后路径被改成了“C:\##install##\test.bmp” //shortCutInfo.path = _T("Z:\\##12345678910##\\123456789.bmp");//&lt;速度非常快,并且成功,但路径被改成了 Z:\##123456\12345678.bmp, 使用一单个不存在的驱动器,会使路径中间的文件名都变成8个字符 但是使用**[\\Z:\\##install](file://\\Z:\\##install)##能够生成正常的路径:Z:\\##install##**

//shortCutInfo.path = _T("Z:\\12345678910\\123456789.bmp");结果同上,证明跟#号无关 //shortCutInfo.path = _T("XYZ:\\##12345678910##\\123456789.bmp");//&lt;成功,速度快。但快捷方式那显示的路径是灰色,并且只显示了XYZ:,并且使用用GetPath调用失败 //shortCutInfo.path = _T("%install%\test.bmp"); //&lt;返回E_INVALIDARG

附:创建快捷方式代码
IPersistFile* ppf = NULL; IShellLink* psl = NULL ;

HRESULT hr = ::CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
if (!SUCCEEDED (hr) || (psl == NULL) )
{
//assert(false);///<是不是未初使化COM
return false ;
}

hr = psl->SetPath(linkInfo.path.c_str()) ;//设置路径
hr = psl->SetHotkey(linkInfo.hotKey) ; //设置快捷键、热键
hr = psl->SetArguments(linkInfo.args.c_str());
hr = psl->SetDescription(linkInfo.description.c_str());
hr = psl->SetIconLocation(linkInfo.iconPath.c_str(), linkInfo.iconIndex);
hr = psl->SetWorkingDirectory(linkInfo.workingDirectory.c_str());
hr = psl -> QueryInterface( IID_IPersistFile, (void**)&ppf);//获取IPersistFile接口
if(!SUCCEEDED (hr))
return FALSE ;
hr = ppf -> Save( linkFileName.c_str(), STGM_READWRITE) ;//保存快捷方式
ppf->Release();//释放IPersistFile和IShellLink接口
psl->Release();

// 通知SHELL变化
//SHChangeNotify( ….) ;//从略,具体可以参考该函数定义,一般创建后通知本目录和父目录即可。
return TRUE;