很遗憾,我认为您无法在Windows 7上使用常规文件系统运行代码而不需要正确的Shell ID列表。正确的代码首先应该提供一个CIDL:
var data = new DataObject();
var files = new StringCollection() { @"T:\Test.doc" };
data.SetFileDropList(files);
data.SetData("Preferred DropEffect", true, new MemoryStream(new byte[] { 5, 0, 0, 0 }));
data.SetData("Shell IDList Array", true, CreateShellIDList(files));
Clipboard.SetDataObject(data, true);
CreateShellIDList
函数创建了一个CIDA(CFSTR_SHELLIDLIST)结构的二进制表示,下面是其实现:
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr ILCreateFromPath(string path);
[DllImport("shell32.dll", CharSet = CharSet.None)]
public static extern void ILFree(IntPtr pidl);
[DllImport("shell32.dll", CharSet = CharSet.None)]
public static extern int ILGetSize(IntPtr pidl);
private static MemoryStream CreateShellIDList(StringCollection filenames)
{
int pos = 0;
byte[][] pidls = new byte[filenames.Count][];
foreach (var filename in filenames)
{
IntPtr pidl = ILCreateFromPath(filename);
int pidlSize = ILGetSize(pidl);
pidls[pos] = new byte[pidlSize];
Marshal.Copy(pidl, pidls[pos++], 0, pidlSize);
ILFree(pidl);
}
int pidlOffset = 4 * (filenames.Count + 2);
var memStream = new MemoryStream();
var sw = new BinaryWriter(memStream);
sw.Write(filenames.Count);
sw.Write(pidlOffset);
pidlOffset += 4;
foreach(var pidl in pidls)
{
sw.Write(pidlOffset);
pidlOffset += pidl.Length;
}
sw.Write(0);
foreach(var pidl in pidls) sw.Write(pidl);
return memStream;
}
我不能完全自己创造这个,我一段时间以前发现了这个CIDA代码,只是将其移植到C#。我真的记不得原始来源,但到目前为止它运行良好(我也在TrueCrypt上测试过)。