- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在 session 之间保留 pidls ,以便我的应用程序可以记住用户的文件夹选择,无论它们位于命名空间中的任何位置,即使它们不是文件系统文件夹。
我有一种感觉,执行此操作的方法是写出 ITEMIDLIST
本身的二进制内容,但我无法确定这一点,因为这些内容应该是不透明的,并由提供商决定。我不知道重新启动后,甚至在另一个进程中,该数据是否有效。据我所知,它可能包含指针。
保存并稍后重建 pidl 的正确方法是什么?
Jerry Coffin has suggested 一对函数似乎完全符合我的要求。然而,还有一个问题。
正如 Joel Spolsky points out 和 Raymond Chen seems to imply 所说,保存 ITEMIDLIST
的二进制内容确实是持久保存 pidl 的正确方法,从中可以推断 ILSaveToStream
和 ILLoadFromStream
是执行此操作的辅助函数。
但是,我找不到证明这一点的文档。由于这个项目是用 C# 语言编写的,因此我希望避免为 IL...
函数互操作 IStream
,并且如果可能的话,我自己保留二进制数据。有人能确认这是正确的吗?
查看 ILSaveToStream 和 ILLoadFromStream 的文档,我发现这些函数直到 shell 5.0 版本(Windows 2000)才存在。那么在 Win2K 之前这是如何实现的呢?经过一些测试后,我得出的结论是,正如我所怀疑的和 Joel Spolsky 所假设的那样,写出原始 ITEMIDLIST
是正确的方法。
C# 中的简单实现如下:
unsafe{
byte* start = (byte*)pidl.ToPointer();
byte* ptr = start;
ushort* length;
do{
length = (ushort*)ptr;
ptr += *length;
}while(*length != 0);
byte[] rtn = new byte[ptr + 2 - start];
Marshal.Copy(pidl, rtn, 0, rtn.Length);
return rtn;
}
当然,这可以在没有指针的情况下使用Marshal.ReadInt16
来完成:
int offset = 0;
int length;
do{
length = Marshal.ReadInt16(pidl, offset);
offset += length;
}while(length != 0);
byte[] rtn = new byte[offset + 2];
Marshal.Copy(pidl, rtn, 0, rtn.Length);
return rtn;
它只花费了几个时钟周期,但它仍然需要完全信任,因此除了远离看起来像“scaaaary”的指针之外,它并没有真正带来什么好处。
重建 pidl 甚至更容易,因为数据的总长度已经知道,甚至不需要任何指针:
byte[] itemidlist = ReadPidl();
IntPtr pidl = Marshal.AllocCoTaskMem(itemidlist.Length);
Marshal.Copy(itemidlist, 0, pidl, itemidlist.Length);
以这种方式保留和重建 pidls 在我的所有跨进程测试中都有效,在有限的情况下,甚至跨机器。我还没有测试过重新启动,因为我不愿意关闭所有内容并重新启动我的机器,但考虑到明显的跨机器兼容性,我对这个解决方案充满信心。
我接受 Joel Spolsky 的答案作为解决方案,但确实想向 future 的路人提出警告:Joel 谈到写出一个 SHITEMID
结构,但这并不是故事的全部。 ITEMIDLIST
(这是 pidl 所指向的)实际上是这些可变长度 SHITEMID
结构的空终止列表,并且必须保留整个列表。这就是上面的代码执行循环来确定总长度的原因。它在此列表中从一个元素跳转到另一个元素,读取每个元素的长度以找出到下一个元素的偏移量。只有读取到长度为零的元素后,才能知道整个列表的长度。
最佳答案
根据雷蒙德陈 you can persist a pidl -- 或者,更具体地说,一个 SHITEMID结构,只需写出项目的长度,然后写出字节。
请注意,此结构是典型的 Windows 可变长度结构,其中有一个 cb(“字节数”)元素指定该结构的长度(以字节为单位),后跟其余数据。也就是说,要写结构体,就需要写cb字节。要读取它,您需要分配cb字节的内存并设置cb字段。
请注意不要使用 sizeof(SHITEMID),因为它的声明方式假定 abID 字段只有一个字节,因此不够大。
关于winapi - 保留 pidl (ITEMIDLIST),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1774508/
我想在 session 之间保留 pidls ,以便我的应用程序可以记住用户的文件夹选择,无论它们位于命名空间中的任何位置,即使它们不是文件系统文件夹。 我有一种感觉,执行此操作的方法是写出 ITEM
我有一个 Shell 文件夹,它是一个控制面板项。我正在尝试获取相同的 ITEMIDLIST。我有 Shell 文件夹 GUID。 看文档 https://msdn.microsoft.com/en-
看起来可以在一两次调用中完成,但是我有/必须/应该使用哪些函数? 我正在寻找最佳实践方法,例如:专为路径 -> idl 转换设计的 API。 最佳答案 如果它真的是一个文件系统路径,调用ILCreat
是否有任何已知的方法(无论是否记录在案)来创建 ITEMIDLIST来自路径的结构,例如 ILCreateFromPath ,同时绕过 MAX_PATH限制长度? 最佳答案 您可以使用 SHParse
Microsoft 提供了一个类 CMFCShellTreeCtrl 用于浏览 shell 命名空间层次结构(本质上与资源管理器窗口的左侧相同)。 此控件使用 SHGetPathFromIDList(
我是一名优秀的程序员,十分优秀!