使用IShellLink和IPersistFile创建快捷方式,如何等待保存完成?

mamutu02 2016-12-26 12:32:29
C++调用COM组件创建快捷方式。
创建完成后,马上要把创建好的.lnk文件复制到另一个位置,结果失败。
但是在创建完成后Sleep一段时间,就成功了。
推测是IPersistFile还没来得及写入文件。
我应该如何得知文件已经保存完成?

大致代码如下:


bool create_succ = false;

CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkA, (void**)&pShellLink);
if (SUCCEEDED(hres))
{
pShellLink->SetPath(target_path);
IPersistFile *pPersistFile;
hres = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile);
if (SUCCEEDED(hres))
{
hres = pPersistFile->Save(link_file, TRUE);
if (SUCCEEDED(hres))
{
create_succ = true;
}
pPersistFile->Release();
}
pShellLink->Release();
}
CoUninitialize();

// Sleep(1000); // 加上这句就能成功

if (create_succ)
{
CopyFile(link_file, dest);
}


之前没怎么用过COM,望知道的指点一下,多谢~
...全文
1326 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
mamutu02 2017-10-30
  • 打赏
  • 举报
回复
既然已经解决了,我就再说一下。 其实最后的动作不是CopyFile。。我写的是这么一个程序,检测到U盘弹出通知,就在U盘上创建快捷方式,然后U盘继续弹出。。 接下来重新拔插弹出的U盘,发现刚才创建的快捷方式坏掉了。。 这其实是Windows写入缓存机制在作怪。在CreateFile的时候,使用FILE_FLAG_WRITE_THROUGH,就可以避免这个问题。我测试的补全到4k也可以,原因是测试环境中写缓存大小为4k。。 我是按照正常流程,右下角选择“弹出该设备”,等到Windows显示“设备已安全弹出”,才拔下U盘的。我怎么也想不到这种情况下文件也会损坏。也就是说Windows并没有把缓存中的数据写入U盘,就告诉我该设备已可以安全拔出了。。按照我的理解(可能也是所有精神正常的人的理解),只有在硬拔U盘的时候写缓存数据才会丢失,没想到微软再次突破的我的思维常规。
引用 4 楼 ole_master 的回复:
逆向了下,是同步的,不过什么补全肯定是不对的,闻所未闻,另外可以用CreateSymbolicLink
所以对4楼这位大神,我只能说你没逆对地方、、如果把Windows负责U盘插拔的地方,和负责文件写缓存的地方逆一下,应该就能见到这部分有BUG的代码。。。
赵4老师 2017-01-03
  • 打赏
  • 举报
回复
Linux的坑就不多吗?!
Yofoo 2016-12-28
  • 打赏
  • 举报
回复
ntfs系统的小文件有很多类似问题, 微软的Bug 比如删掉一个文件, 然后再创建一个同样名称的文件, 这时新的文件的创建时间变成原来的文件时间 ntfs的小文件的储存跟其他文件的储存方式不一样, 直接存在了MFT
ole_master 2016-12-27
  • 打赏
  • 举报
回复
逆向了下,是同步的,不过什么补全肯定是不对的,闻所未闻,另外可以用CreateSymbolicLink
ole_master 2016-12-26
  • 打赏
  • 举报
回复
调用SaveCompleted,系统Release时写估计是异步
mamutu02 2016-12-26
  • 打赏
  • 举报
回复
要结帖了。大家来回复拿分吧。
mamutu02 2016-12-26
  • 打赏
  • 举报
回复
已解决。最后证明不是COM和IPersistFile的问题。 刚刚创建的小于4KB(簇大小)的文件,立即使用会产生问题。不光是IPersistFile::Save(),就连CopyFile、CreateFile创建的文件,如果小于4KB,也有这个问题。需要补全才能用。另外,如果在可移动磁盘内创建小文件不补全,驱动器又在短时间内请求弹出的话,还会弹出失败。 补全流程: 1. 读取IPersistFile创建的lnk文件至内存。 2. 如果大小小于4KB,在后面用空白数据填充至4KB。 3. 新建一个文件,把填充后的lnk文件内容全部写入,关闭。 在原文件后面附加数据补全不行,必须新建文件! Windows这种缓存文件的行为,MSDN里面好像也没说过,反正我没看到。这里真想吐槽一下。。。微软的东西坑实在是太多了。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧