我正在尝试在Delphi 2007中编写一个小程序,以便在插入Windows 7计算机时访问便携式USB驱动器中的文件。此驱动器不会显示为标准驱动器号。它出现在Windows资源管理器中的便携设备下。我编写了以下代码来枚举“计算机”下的所有项目:
Procedure TfrmMain.ComputerChanged(Var Msg: TMessage);
Var
Enum: IEnumIDList;
Fetched: Longword;
Item: PItemIDList;
Path: String;
Computer: IShellFolder;
StrRet: TSTRRET;
Begin
Status('Computer changed... Checking folders.');
fDesktop.BindToObject(fCompPidl, Nil, IID_IShellFolder, Computer);
If Assigned(Computer) And
(Computer.EnumObjects(Self.Handle, SHCONTF_FOLDERS, Enum) = NOERROR) Then
Begin
While (Enum.Next(1, Item, Fetched) = NOERROR) Do
Begin
FillChar(StrRet, SizeOf(StrRet), #0);
Computer.GetDisplayNameOf(Item, SHGDN_FORADDRESSBAR or SHGDN_NORMAL, StrRet);
Path := StrRetToStr(StrRet, Item);
Status(Path);
End;
End;
End;
(注意:Status过程只是向TMemo输出一条消息。)
每当我的应用程序收到Windows shell子系统的更改通知时,都会调用此方法。它列举了所有本地驱动器和网络驱动器,但没有其他内容(iCloud Photos驱动器也缺失)。
有谁知道如何访问这些虚拟驱动器上的文件?
答案 0 :(得分:4)
您很可能无法正确初始化COM。如果你不打电话给CoInitializeEx或者你打电话给它的价值不好,你的代码将会按原样运行,但便携式设备驱动程序需要使用公寓线程才能正常工作。
根据您的代码,这是一个正常运行并展示便携式设备的示例应用。如果您注释掉CoInitializeEx
/ CoUninitialize
来电或传入COINIT_MULTITHREADED
,它仍会有效,但它只会显示驱动器。
program ListMyComputer;
{$APPTYPE CONSOLE}
uses
ComObj, ShlObj, ShellApi, ShLwApi, ActiveX, Windows, SysUtils;
var
Enum: IEnumIDList;
Fetched: Longword;
CompPidl, Item: PItemIDList;
Path: PWideChar;
Desktop, Computer: IShellFolder;
StrRet: TSTRRET;
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
try
WriteLn('Computer changed... Checking folders.');
SHGetDesktopFolder(Desktop);
SHGetFolderLocation(0, CSIDL_DRIVES, 0, 0, CompPidl);
Desktop.BindToObject(CompPidl, Nil, IID_IShellFolder, Computer);
CoTaskMemFree(CompPidl);
If Assigned(Computer) And
(Computer.EnumObjects(0, SHCONTF_FOLDERS, Enum) = NOERROR) Then
Begin
While (Enum.Next(1, Item, Fetched) = NOERROR) Do
Begin
FillChar(StrRet, SizeOf(StrRet), #0);
Computer.GetDisplayNameOf(Item, SHGDN_FORADDRESSBAR or SHGDN_NORMAL, StrRet);
StrRetToStr(@StrRet, Item, Path);
WriteLn(Path);
CoTaskMemFree(Path);
End;
End;
WriteLn('Enumeration complete');
ReadLn;
finally
CoUninitialize
end;
end.
答案 1 :(得分:2)
感谢@SertacAkyuz指出需要使用Windows Portable Device API,这导致我this Experts Exchange question讨论相同的事情。 Sinisa Vuk提供了一个很棒的代码示例来回答我已经链接的这个问题(这个问题太长了,无法嵌入)这里有权限:http://pastebin.com/0hSWv5pE