HI
我们有大量远程计算机可将视频捕获到磁盘驱动器上。每个摄像头都有自己独特的目录,任何一个磁盘上最多可以有16个目录。
我正在尝试找到磁盘上最旧的视频文件,但使用FindFirst/FindNext
来比较文件创建日期时间需要永久。
有人知道找到目录中最旧文件的更有效方法吗?我们从HO中心位置远程连接到电脑。
问候,彼得
- 更新
谢谢大家的答案。最后我使用了以下内容。
windows.WNetAddConnection2
psexec \\<IPAddress> -i /accepteula -w "c:\windows\system32" cmd.exe "/c dir q:\video /OD /TC /B > q:\dir.txt"
windows.WNetCancelConnection2
答案 0 :(得分:1)
您还可以尝试FindFirstFileEx
FindExInfoBasic
参数,在Windows 7或Server 2008 R2或更高版本,FIND_FIRST_EX_LARGE_FETCH
should improve performance。
答案 1 :(得分:0)
首先,从how to run a DOS program and pipe its output to a TStrings上的此页面获取RunDosAppPipedToTStrings例程。该示例使用TMemo的Lines属性,但您可以传入任何TStrings,例如TStringList。请注意,如果CreateProcess返回false,这将无提示失败。您可能希望将 else 大小写添加到引发异常的“if CreateProcess”块中。
然后在与EXE相同的文件夹中创建一个简单的批处理文件。称之为getdir.bat
。它应该说是:
dir %1
这将生成您传递给它的任何文件夹的目录列表。不幸的是,“dir”是DOS关键字命令,而不是程序,所以你不能直接调用它。将它包装在批处理文件中可以解决这个问题。这有点像黑客,但它确实有效。如果你能找到更好的方式来运行DIR,那就更好了。
您需要使用如下所示的代码调用RunDosAppPipedToTStrings:
procedure GetDirListing(dirname: string; list: TStringList);
const
CMDNAME = '%s\getdir.bat "%s"';
var
path: string;
begin
list.Clear;
path := ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
RunDosAppPipedToTStrings(format(CMDNAME, [path, dirname]), list, false);
end;
然后剩下要做的就是解析输出,提取日期和时间以及文件名,按日期和时间排序,并获取具有最低日期的文件的文件名。我会给你留下那么多。
答案 2 :(得分:0)
如果你可以在远程计算机上运行可以迭代目录的东西,那将是最快的方法。如果您想使用Mason的示例,请尝试使用来自SysInternals的PsExec启动它。
如果你只能在本地运行一个应用程序,那么就没有比FindFirst / FindNext更快的方法,你做的任何事情最终都会归结为最终。如果您的本地计算机运行的是Windows 7,则可以使用FindFirstFileEx
,它有标志表示它应该使用更大的缓冲区进行传输,并且它不应该读取8.3别名,这可以帮助提高速度。
答案 3 :(得分:0)
我在开发的传真服务器软件上遇到了几乎相同的问题。我必须按照收到的传真顺序发送传真(全部存储在目录中)。我采用的解决方案(启动速度慢但运行速度快)是使用
制作所有文件的排序列表SearchRec.Time
作为关键。文件在列表中后,我将文件的属性设置为faSysFile:
NewAttributes := Attributes or faSysFile;
现在,当我使用
进行新搜索时FileAttrs := (faAnyFile and not faDirectory);
仅显示不是faSysFile的文件,因此我可以将新文件添加到列表中。 现在,您有一个列表,其中包含按时间排序的所有文件。 不要忘记,当您启动应用程序时,第一步是从文件夹中的文件中删除faSysFile属性,以便可以再次处理它们。
procedure FileSetSysAttr(AFileName: string);
var
Attributes, NewAttributes: Word;
begin
Attributes := FileGetAttr(AFileName);
NewAttributes := Attributes or faSysFile;
FileSetAttr(AFileName, NewAttributes);
end;
procedure FileUnSetSysAttr(AFileName: string);
var
Attributes, NewAttributes: Word;
begin
Attributes := FileGetAttr(AFileName);
NewAttributes := Attributes and not faSysFile;
FileSetAttr(AFileName, NewAttributes);
end;
procedure PathUnSetSysAttr(APathName: string);
var
sr: TSearchRec;
FileAttrs: Integer;
begin
FileAttrs := (faAnyFile and not faDirectory) and (faAnyFile or faSysFile);
APathName := IncludeTrailingBackslash(APathName);
if SysUtils.FindFirst(APathName + '*.*', FileAttrs, sr) = 0 then
try
repeat
if (sr.Attr and faDirectory) = 0 then
FileUnSetSysAttr(APathName + sr.Name);
until SysUtils.FindNext(sr) <> 0;
finally
SysUtils.FindClose(sr);
end;
end;
我知道这不是最好的解决方案,但对我有用。