Subversion Repositories indexer_suite

Compare Revisions

No changes between revisions

Regard whitespace Rev 1 → Rev 2

/trunk/DB/files.sql
0,0 → 1,42
USE [Indexer]
GO
 
SET ANSI_NULLS ON
GO
 
SET QUOTED_IDENTIFIER ON
GO
 
SET ANSI_PADDING ON
GO
 
CREATE TABLE [dbo].[files](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[filename] [nvarchar](450) NOT NULL,
[size] [bigint] NULL,
[created] [datetime] NULL,
[modified] [datetime] NULL,
[md5hash] [varchar](32) NULL,
[error] [nvarchar](200) NULL,
CONSTRAINT [PK_files] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
 
GO
 
CREATE UNIQUE NONCLUSTERED INDEX [ix_files_filename] ON [dbo].[files]
(
[filename] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
 
CREATE NONCLUSTERED INDEX [ix_files_md5hash] ON [dbo].[files]
(
[md5hash] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
 
SET ANSI_PADDING OFF
GO
/trunk/ExplorerForm.dfm
0,0 → 1,95
object frmExplorer: TfrmExplorer
Left = 0
Top = 0
Caption = 'Offline Explorer'
ClientHeight = 370
ClientWidth = 787
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIChild
OldCreateOrder = False
Visible = True
OnClose = FormClose
OnShow = FormShow
DesignSize = (
787
370)
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 40
Top = 8
Width = 31
Height = 13
Caption = 'Label1'
end
object SpeedButton1: TSpeedButton
Left = 11
Top = 4
Width = 23
Height = 22
Caption = '..'
OnClick = SpeedButton1Click
end
object ListView1: TListView
Left = 8
Top = 32
Width = 767
Height = 330
Anchors = [akLeft, akTop, akRight, akBottom]
Columns = <
item
Caption = 'Filename'
Width = 300
end
item
Caption = 'Type'
end>
LargeImages = ImageListLarge
PopupMenu = PopupMenu1
SmallImages = ImageListSmall
TabOrder = 0
OnDblClick = ListView1DblClick
OnKeyDown = ListView1KeyDown
end
object Button2: TButton
Left = 694
Top = 8
Width = 81
Height = 25
Anchors = [akTop, akRight]
Caption = 'View'
TabOrder = 1
OnClick = Button2Click
end
object ImageListSmall: TImageList
Left = 32
Top = 32
end
object ImageListLarge: TImageList
Left = 104
Top = 32
end
object Timer1: TTimer
Interval = 50
OnTimer = Timer1Timer
Left = 456
Top = 264
end
object PopupMenu1: TPopupMenu
Left = 416
Top = 152
object Checkifdirisredundant1: TMenuItem
Caption = 'Check if item is redundant'
OnClick = Checkifdirisredundant1Click
end
object ReIndexthisitem1: TMenuItem
Caption = 'Re-Index this item'
OnClick = ReIndexthisitem1Click
end
end
end
/trunk/ExplorerForm.pas
0,0 → 1,441
unit ExplorerForm;
 
// TODO: Detailansicht: - Skalieren der Spalten
// - Mehr Eigenschaften zeigen, die in der SQL-Datenbank sind
 
interface
 
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls,
System.ImageList, Vcl.ImgList, Data.DB, Data.Win.ADODB, Vcl.Samples.Gauges,
Vcl.Buttons, Vcl.ExtCtrls, Vcl.Menus;
 
type
TfrmExplorer = class(TForm)
ListView1: TListView;
Button2: TButton;
ImageListSmall: TImageList;
ImageListLarge: TImageList;
Label1: TLabel;
SpeedButton1: TSpeedButton;
Timer1: TTimer;
PopupMenu1: TPopupMenu;
Checkifdirisredundant1: TMenuItem;
ReIndexthisitem1: TMenuItem;
procedure Button2Click(Sender: TObject);
procedure ListView1DblClick(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
procedure Checkifdirisredundant1Click(Sender: TObject);
procedure ReIndexthisitem1Click(Sender: TObject);
procedure ListView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormShow(Sender: TObject);
private
FCurrentFolder: string;
FCurrentDepth: integer;
procedure SetCurrentFolder(const Value: string);
procedure SetCurrentDepth(const Value: integer);
property CurrentFolder: string read FCurrentFolder write SetCurrentFolder;
property CurrentDepth: integer read FCurrentDepth write SetCurrentDepth;
protected
procedure FillListView(sl: TStrings);
public
procedure OpenFolder(const folder: string);
procedure ListDevices;
procedure PrevFolder;
function conn: TAdoConnection;
function TableName: string;
end;
 
implementation
 
{$R *.dfm}
 
uses
ShellAPI, System.Types, AdoConnHelper, RedundancyForm, IndexCreatorForm, MainForm,
IniFiles;
 
function AddTransparentIconToImageList(ImageList: TImageList; Icon: TIcon; DoGreyscale: boolean=False): integer;
// http://www.delphipages.com/forum/showthread.php?t=183999
 
function RealIconSize(H: HIcon): TPoint;
// http://www.delphipages.com/forum/showthread.php?t=183999
var
IconInfo: TIconInfo;
bmpmask: TBitmap;
begin
result := Point(0, 0);
 
if H <> 0 then
begin
bmpmask := TBitmap.Create;
try
IconInfo.fIcon := true;
try
GetIconInfo(H, IconInfo);
bmpmask.Handle := IconInfo.hbmMask;
bmpmask.Dormant; //lets us free the resource without 'losing' the bitmap
finally
DeleteObject(IconInfo.hbmMask);
DeleteObject(IconInfo.hbmColor)
end;
result := Point(bmpmask.Width, bmpmask.Height);
finally
bmpmask.Free;
end;
end;
end;
 
function ToGray(PixelColor: Longint): Longint;
var
Red, Green, Blue, Gray: Byte;
begin
Red := PixelColor;
Green := PixelColor shr 8;
Blue := PixelColor shr 16;
Gray := Round(0.299 * Red + 0.587 * Green + 0.114 * Blue);
result := Gray + Gray shl 8 + Gray shl 16;
end;
 
var
buffer, mask: TBitmap;
p: TPoint;
x, y: integer;
begin
// result := ImageList.AddIcon(ico);
// --> In Delphi 6, Icons with half-transparency have a black border (e.g. in ListView)
 
p := RealIconSize(icon.handle);
 
buffer := TBitmap.Create;
mask := TBitmap.Create;
try
buffer.PixelFormat := pf24bit;
mask.PixelFormat := pf24bit;
 
buffer.Width := p.X;
buffer.Height := p.Y;
buffer.Canvas.Draw(0, 0, icon);
buffer.Transparent := true;
buffer.TransparentColor := buffer.Canvas.Pixels[0,0];
 
if (ImageList.Width <> p.X) or (ImageList.Height <> p.Y) then
begin
ImageList.Width := p.X;
ImageList.Height := p.Y;
end;
 
// create a mask for the icon.
mask.Assign(buffer);
mask.Canvas.Brush.Color := buffer.Canvas.Pixels[0, buffer.Height -1];
mask.Monochrome := true;
 
if DoGreyscale then
begin
for x := 0 to buffer.Width - 1 do
begin
for y := 0 to buffer.Height - 1 do
begin
buffer.Canvas.Pixels[x, y] := ToGray(buffer.Canvas.Pixels[x, y]);
end;
end;
end;
 
result := ImageList.Add(buffer, mask);
finally
mask.Free;
buffer.Free;
end;
end;
 
procedure TfrmExplorer.Button2Click(Sender: TObject);
begin
// TODO: Refreshen wegen Anzeigefehler
ListView1.ViewStyle := TViewStyle((Ord(ListView1.ViewStyle)+1) mod (Ord(High(TViewStyle))+1));
end;
 
procedure TfrmExplorer.Checkifdirisredundant1Click(Sender: TObject);
begin
if ListView1.ItemIndex = -1 then exit;
 
with TfrmRedundancy.Create(Owner) do
begin
Edit1.Text := CurrentFolder + ListView1.Selected.Caption;
end;
end;
 
function TfrmExplorer.conn: TAdoConnection;
begin
result := frmMain.ADOConnection1;
end;
 
procedure TfrmExplorer.FillListView(sl: TStrings);
var
s: string;
i: Integer;
Icon: TIcon;
Extention : string;
FileInfo : SHFILEINFO;
attr: Cardinal;
begin
ListView1.Clear;
Icon := TIcon.Create;
ImageListSmall.Clear;
ImageListSmall.Width := 16;
ImageListSmall.Height := 16;
ImageListLarge.Clear;
ImageListLarge.Width := 32;
ImageListLarge.Height := 32;
for i := 0 to sl.Count-1 do
begin
s := sl.Strings[i];
with ListView1.Items.Add do
begin
Extention := '*' + ExtractFileExt(s);
 
if Pos('\', s) = 0 then
begin
attr := FILE_ATTRIBUTE_NORMAL;
Caption := s;
Data := Pointer(0);
end
else
begin
attr := FILE_ATTRIBUTE_DIRECTORY;
Caption := Copy(s, 1, Length(s)-1); // remove trailing "\"
Data := Pointer(1);
end;
 
{$REGION 'File extention name'}
SHGetFileInfo(PChar(Extention),
attr,
FileInfo,
SizeOf(FileInfo),
SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES
);
SubItems.Add(FileInfo.szTypeName);
{$ENDREGION}
 
{$REGION 'Small icon'}
SHGetFileInfo(PChar(Extention),
attr,
FileInfo,
SizeOf(FileInfo),
SHGFI_ICON or SHGFI_SMALLICON or
SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES
);
Icon.Handle := FileInfo.hIcon;
AddTransparentIconToImageList(ImageListSmall, Icon, false); // ImageListSmall.AddIcon(Icon);
{$ENDREGION}
 
{$REGION 'Large icon'}
SHGetFileInfo(PChar(Extention),
attr,
FileInfo,
SizeOf(FileInfo),
SHGFI_ICON or SHGFI_LARGEICON or
SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES
);
Icon.Handle := FileInfo.hIcon;
AddTransparentIconToImageList(ImageListLarge, Icon, false); // ImageListLarge.AddIcon(Icon);
{$ENDREGION}
 
ImageIndex := i;
end;
end;
Icon.Free;
end;
 
procedure TfrmExplorer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
 
procedure TfrmExplorer.FormShow(Sender: TObject);
var
ini: TMemIniFile;
begin
ini := frmMain.ini;
// Edit1.Text := ini.ReadString('Explorer', 'DefaultDir', '');
end;
 
procedure TfrmExplorer.ListDevices;
var
q: TADODataSet;
sl: TStringList;
begin
label1.Caption := '*** PLEASE WAIT ***';
Application.ProcessMessages;
 
sl := TStringList.Create;
 
q := conn.GetTable('select distinct left(filename,charindex('':\'',filename,0)) from '+TableName+' where filename not like ''\\%'';');
while not q.Eof do
begin
sl.Add(q.Fields[0].AsString+'\'); // e.g. "C:" or "EHDD:" for ViaThinkSoft
q.Next;
end;
q.Free;
 
q := conn.GetTable('select distinct left(filename,charindex(''\'',filename,3)-1) from '+TableName+' where filename like ''\\%'' and filename not like ''\\?\%'';');
while not q.Eof do
begin
sl.Add(q.Fields[0].AsString+'\'); // e.g. "\\server1"
q.Next;
end;
q.Free;
 
q := conn.GetTable('select distinct left(filename,charindex(''\'',filename,5)-1) from '+TableName+' where filename like ''\\?\%'';');
while not q.Eof do
begin
sl.Add(q.Fields[0].AsString+'\'); // e.g. "\\?\Volume{560e8251-2b6a-4ab7-82fc-d03df4d93538}"
q.Next;
end;
q.Free;
 
FillListView(sl);
CurrentFolder := '';
CurrentDepth := 0;
end;
 
procedure TfrmExplorer.ListView1DblClick(Sender: TObject);
begin
if ListView1.ItemIndex = -1 then exit;
if ListView1.Selected.Data = Pointer(0) then
begin
// Ist eine Datei
ShowMessageFmt('Filename: %s', [ListView1.Selected.Caption]);
end;
if ListView1.Selected.Data = Pointer(1) then
begin
// Ist ein Verzeichnis
OpenFolder(CurrentFolder + ListView1.Selected.Caption + '\');
end;
end;
 
procedure TfrmExplorer.ListView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_BACK then
begin
if SpeedButton1.Enabled then SpeedButton1.Click;
Key := 0;
end;
if Key = VK_RETURN then
begin
ListView1DblClick(ListView1);
Key := 0;
end;
end;
 
procedure TfrmExplorer.OpenFolder(const folder: string);
var
sl: TStringList;
q: TADODataSet;
p: Integer;
DirName: string;
locFolder: string;
relfilepath: string;
folders: TStringList;
begin
label1.Caption := '*** PLEASE WAIT ***';
Application.ProcessMessages;
 
sl := TStringList.Create;
folders := TStringList.Create;
try
//q := conn.GetTable('select filename from '+TableName+' where filename like '+conn.SQLStringEscape(Folder+'%'));
q := conn.GetTable('select distinct left(filename,charindex(''\'',filename+''\'','+inttostr(Length(Folder)+1)+')) from '+TableName+' where filename like '+conn.SQLStringEscape(Folder+'%'));
 
//gauge1.MaxValue := q.RecordCount;
//Gauge1.Progress := 0;
while not q.EOF do
begin
relfilepath := q.Fields[0].AsString;
Delete(relfilepath, 1, Length(Folder));
p := Pos('\', relfilepath);
if p > 0 then
begin
// Ist ein Verzeichnis
DirName := Copy(relfilepath, 1, p);
if folders.IndexOf(DirName) = -1 then folders.Add(DirName);
end
else
begin
sl.Add(ExtractFileName(relfilepath));
end;
q.Next;
//Gauge1.Progress := Gauge1.Progress + 1;
end;
q.Free;
for locFolder in folders do
begin
sl.Add(locFolder);
end;
FillListView(sl);
CurrentFolder := folder;
CurrentDepth := CurrentDepth + 1;
finally
sl.Free;
folders.Free;
end;
end;
 
procedure TfrmExplorer.PrevFolder;
begin
label1.Caption := '*** PLEASE WAIT ***';
Application.ProcessMessages;
 
if CurrentDepth = 1 then
begin
ListDevices;
end
else
begin
OpenFolder(IncludeTrailingPathDelimiter(ExtractFileDir(Copy(CurrentFolder,1,Length(CurrentFolder)-1))));
CurrentDepth := CurrentDepth - 2;
end;
end;
 
procedure TfrmExplorer.ReIndexthisitem1Click(Sender: TObject);
begin
if ListView1.ItemIndex = -1 then exit;
 
with TfrmIndexCreator.Create(Owner) do
begin
LabeledEdit2.Text := CurrentFolder + ListView1.Selected.Caption;
end;
end;
 
procedure TfrmExplorer.SetCurrentDepth(const Value: integer);
begin
SpeedButton1.Visible := Value > 0;
FCurrentDepth := Value;
end;
 
procedure TfrmExplorer.SetCurrentFolder(const Value: string);
begin
Label1.Caption := Value;
FCurrentFolder := Value;
end;
 
procedure TfrmExplorer.SpeedButton1Click(Sender: TObject);
begin
PrevFolder;
end;
 
function TfrmExplorer.TableName: string;
begin
result := frmMain.TableName;
end;
 
procedure TfrmExplorer.Timer1Timer(Sender: TObject);
begin
timer1.Enabled := false;
ListDevices;
end;
 
end.
/trunk/FinderForm.dfm
0,0 → 1,56
object frmFinder: TfrmFinder
Left = 0
Top = 0
Caption = 'Finder'
ClientHeight = 411
ClientWidth = 712
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIChild
OldCreateOrder = False
Visible = True
OnClose = FormClose
OnCloseQuery = FormCloseQuery
OnShow = FormShow
DesignSize = (
712
411)
PixelsPerInch = 96
TextHeight = 13
object Edit1: TEdit
Left = 8
Top = 8
Width = 606
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
ExplicitWidth = 529
end
object Memo1: TMemo
Left = 8
Top = 39
Width = 696
Height = 364
Anchors = [akLeft, akTop, akRight, akBottom]
Lines.Strings = (
'Results')
TabOrder = 1
ExplicitWidth = 619
ExplicitHeight = 253
end
object Button1: TButton
Left = 629
Top = 8
Width = 75
Height = 25
Anchors = [akTop, akRight]
Caption = 'Search'
TabOrder = 2
OnClick = Button1Click
ExplicitLeft = 552
end
end
/trunk/FinderForm.pas
0,0 → 1,89
unit FinderForm;
 
interface
 
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, AdoDb;
 
type
TfrmFinder = class(TForm)
Edit1: TEdit;
Memo1: TMemo;
Button1: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormShow(Sender: TObject);
private
procedure EnableDisableControls(v: boolean);
protected
StopRequest: boolean;
public
function conn: TAdoConnection;
function TableName: string;
end;
 
implementation
 
{$R *.dfm}
 
uses
MainForm, AdoConnHelper, IniFiles;
 
procedure TfrmFinder.Button1Click(Sender: TObject);
var
q: TADODataSet;
begin
memo1.Lines.Clear;
EnableDisableControls(false);
try
q := conn.GetTable('select filename from '+TableName+' where filename like '+conn.SQLStringEscape('%'+edit1.Text+'%')+' order by filename');
while not q.Eof do
begin
memo1.Lines.Add(q.Fields[0].AsString);
if StopRequest then Abort;
q.Next;
end;
finally
EnableDisableControls(true);
end;
end;
 
function TfrmFinder.conn: TAdoConnection;
begin
result := frmMain.ADOConnection1;
end;
 
procedure TfrmFinder.EnableDisableControls(v: boolean);
begin
Memo1.Enabled := v;
Button1.Enabled := v;
Edit1.Enabled := v;
end;
 
procedure TfrmFinder.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
 
procedure TfrmFinder.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
StopRequest := true;
end;
 
procedure TfrmFinder.FormShow(Sender: TObject);
var
ini: TMemIniFile;
begin
ini := frmMain.ini;
Edit1.Text := ini.ReadString('Finder', 'DefaultDir', '');
end;
 
function TfrmFinder.TableName: string;
begin
result := frmMain.TableName;
end;
 
end.
/trunk/IndexCreatorForm.dfm
0,0 → 1,234
object frmIndexCreator: TfrmIndexCreator
Left = 0
Top = 0
Caption = 'ViaThinkSoft Directory Hasher'
ClientHeight = 611
ClientWidth = 877
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIChild
OldCreateOrder = False
Position = poDefault
Visible = True
OnClose = FormClose
OnShow = FormShow
DesignSize = (
877
611)
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 24
Top = 279
Width = 827
Height = 13
Anchors = [akLeft, akTop, akRight]
AutoSize = False
Caption = 'Ready'
ExplicitWidth = 465
end
object Label2: TLabel
Left = 24
Top = 298
Width = 113
Height = 13
Caption = 'Size of processed data:'
end
object Label3: TLabel
Left = 24
Top = 317
Width = 111
Height = 13
Caption = 'Sum of processed files:'
end
object Label4: TLabel
Left = 24
Top = 336
Width = 47
Height = 13
Caption = 'New files:'
end
object Label5: TLabel
Left = 160
Top = 297
Width = 6
Height = 13
Caption = '0'
end
object Label6: TLabel
Left = 160
Top = 316
Width = 6
Height = 13
Caption = '0'
end
object Label7: TLabel
Left = 160
Top = 335
Width = 6
Height = 13
Caption = '0'
end
object Label8: TLabel
Left = 24
Top = 355
Width = 67
Height = 13
Caption = 'Updated files:'
end
object Label9: TLabel
Left = 160
Top = 355
Width = 6
Height = 13
Caption = '0'
end
object Label10: TLabel
Left = 24
Top = 374
Width = 33
Height = 13
Caption = 'Errors:'
end
object Label11: TLabel
Left = 160
Top = 374
Width = 6
Height = 13
Caption = '0'
end
object Label12: TLabel
Left = 160
Top = 393
Width = 6
Height = 13
Caption = '0'
end
object Label13: TLabel
Left = 24
Top = 393
Width = 41
Height = 13
Caption = 'Deleted:'
end
object Label14: TLabel
Left = 584
Top = 8
Width = 53
Height = 13
Caption = 'Process list'
end
object Button1: TButton
Left = 320
Top = 185
Width = 169
Height = 33
Caption = 'Start'
Default = True
TabOrder = 1
OnClick = Button1Click
end
object LabeledEdit2: TLabeledEdit
Left = 24
Top = 56
Width = 273
Height = 21
EditLabel.Width = 113
EditLabel.Height = 13
EditLabel.Caption = 'Drive / Label to analyze'
PopupMenu = PopupMenu1
TabOrder = 0
end
object Button2: TButton
Left = 320
Top = 224
Width = 169
Height = 33
Caption = 'Exit'
TabOrder = 2
OnClick = Button2Click
end
object Memo1: TMemo
Left = 584
Top = 25
Width = 283
Height = 193
Anchors = [akLeft, akTop, akRight]
ScrollBars = ssBoth
TabOrder = 3
WordWrap = False
end
object Button4: TButton
Left = 778
Top = 224
Width = 89
Height = 33
Anchors = [akTop, akRight]
Caption = 'Go'
TabOrder = 4
OnClick = Button4Click
end
object cbNoDelete: TCheckBox
Left = 320
Top = 128
Width = 241
Height = 17
Caption = 'Disable deleting/truncating of vanished data'
TabOrder = 5
end
object Memo2: TMemo
Left = 24
Top = 440
Width = 843
Height = 156
Anchors = [akLeft, akTop, akRight, akBottom]
Lines.Strings = (
'Log messages')
ScrollBars = ssBoth
TabOrder = 6
WordWrap = False
end
object cbVerboseLogs: TCheckBox
Left = 772
Top = 417
Width = 97
Height = 17
Anchors = [akTop, akRight]
Caption = 'Verbose logging'
TabOrder = 7
end
object cbSimulate: TCheckBox
Left = 320
Top = 151
Width = 97
Height = 17
Caption = 'Simulate'
TabOrder = 8
end
object rgModus: TRadioGroup
Left = 320
Top = 9
Width = 185
Height = 105
Caption = 'Mode'
ItemIndex = 0
Items.Strings = (
'Update index'
'Completely re-create index'
'Verify checksums')
TabOrder = 9
OnClick = rgModusClick
end
object PopupMenu1: TPopupMenu
Left = 272
Top = 80
object Copyuniquepathtoclipboard1: TMenuItem
Caption = 'Copy unique path to clipboard'
OnClick = Copyuniquepathtoclipboard1Click
end
end
end
/trunk/IndexCreatorForm.pas
0,0 → 1,858
unit IndexCreatorForm;
 
// TODO: vor einem fehler bitte vorher einen löschvorgang durchführen --> geht nicht?
// TODO: berücksichtigen, wenn datei gesperrt. etc, fehler anschauen
// TODO: warum sind in der db mehr einträge als dateien auf der festplatte sind?!
// TODO: Möglichkeit geben, Dateien und Verzeichnisse auszuschließen
// TODO: should we include flags (readonly, invisible, compressed, encrypted)?
// TODO: search+replace tool, wenn man große verschiebungen vorgenommen hat
// update top (100000) files set filename = replace(filename, '\\?\Volume{560e8251-2b6a-4ab7-82fc-d03df4d93538}\', 'EHDD:\') where filename like '%\\?\%';
// TODO: anzeige, wie viele stunden der prozess schon läuft
// TODO: multithreading
// TODO: diverse tools schreiben, die die datenbank nutzen, z.b. ein tool, das prüft, ob ein verzeichnis vollständig redundant ist
// TODO: Beim Lauf F:\nas\data wurden 1312 Fehler gefunden, aber nicht geloggt! ?! Eine exception im exception handler?!
// => nochmal durchlaufen lassen
// TODO: "Laufwerk" EHDD: soll man auch eingeben dürfen (das ist z.b. wichtig, wenn man Querverknüpfung vom Explorer verwendet)
 
{$DEFINE VIATHINKSOFT}
 
interface
 
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls, DB, ADODB, Menus;
 
const
modusUpdate = 0;
modusRecreate = 1;
modusValidation = 2;
 
type
TfrmIndexCreator = class(TForm)
Button1: TButton;
Label1: TLabel;
LabeledEdit2: TLabeledEdit;
Button2: TButton;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
PopupMenu1: TPopupMenu;
Copyuniquepathtoclipboard1: TMenuItem;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
Label13: TLabel;
Memo1: TMemo;
Button4: TButton;
Label14: TLabel;
cbNoDelete: TCheckBox;
Memo2: TMemo;
cbVerboseLogs: TCheckBox;
cbSimulate: TCheckBox;
rgModus: TRadioGroup;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Copyuniquepathtoclipboard1Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure rgModusClick(Sender: TObject);
private
StopRequest: boolean;
sumsize: int64;
sumfiles: int64;
sumfiles_new: int64;
sumfiles_updated: int64;
sumfiles_error: int64;
sumfiles_deleted: int64;
sumfiles_integrityfail: int64;
function TableName: string;
function conn: TAdoConnection;
procedure Rec(StartDir: string; const FileMask: string);
procedure CheckFile(const originalFileName, uniqueFilename: string);
procedure EnableDisableControls(enabled: boolean);
procedure IndexDrive(initialdir: string);
procedure RedrawStats;
procedure DeleteVanishedFiles(mask: string = '');
class function DriveGuid(const Letter: char): string; static;
class function uniqueFilename(const filename: string): string; static;
class function VtsSpecial(const filename: string): string; static;
procedure DeleteAllFiles(mask: string = '');
end;
 
implementation
 
{$R *.dfm}
 
uses
FileCtrl, DateUtils, inifiles, IdHashMessageDigest, idHash, Math, Clipbrd,
StrUtils, AdoConnHelper, MainForm;
 
const
Win32ImportSuffix = {$IFDEF Unicode}'W'{$ELSE}'A'{$ENDIF};
 
function GetVolumeNameForVolumeMountPointA(lpszVolumeMountPoint: PAnsiChar;
lpszVolumeName: PAnsiChar; cchBufferLength: DWORD): BOOL; stdcall;
external 'kernel32.dll';
function GetVolumeNameForVolumeMountPointW(lpszVolumeMountPoint: PWideChar;
lpszVolumeName: PWideChar; cchBufferLength: DWORD): BOOL; stdcall;
external 'kernel32.dll';
function GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint: PChar;
lpszVolumeName: PChar; cchBufferLength: DWORD): BOOL; stdcall;
external 'kernel32.dll' name 'GetVolumeNameForVolumeMountPoint' +
Win32ImportSuffix;
 
const
ERROR_FIELD_SIZE = 200;
{$IFDEF VIATHINKSOFT}
GUID_EHDD_A = '\\?\Volume{31e044b1-28dc-11e6-9bae-d067e54bf736}\';
GUID_EHDD_B = '\\?\Volume{560e8251-2b6a-4ab7-82fc-d03df4d93538}\';
{$ENDIF}
 
function MD5File(const filename: string): string;
var
IdMD5: TIdHashMessageDigest5;
FS: TFileStream;
begin
IdMD5 := TIdHashMessageDigest5.Create;
FS := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
try
{$IFDEF UNICODE} // I actually do not know at which version of Delphi/Indy, this has changed.
Result := IdMD5.HashStreamAsHex(FS);
{$ELSE}
Result := IdMD5.AsHex(IdMD5.HashValue(FS));
{$ENDIF}
finally
FS.Free;
IdMD5.Free;
end;
end;
 
function FileMTime_UTC(const filename: string): TDateTime;
var
fad: TWin32FileAttributeData;
systime: SYSTEMTIME;
begin
if not GetFileAttributesEx(PChar(filename), GetFileExInfoStandard, @fad) then
RaiseLastOSError;
 
FileTimeToSystemTime(fad.ftLastWriteTime, systime);
 
Result := SystemTimeToDateTime(systime);
end;
 
function FileCTime_UTC(const filename: string): TDateTime;
var
fad: TWin32FileAttributeData;
systime: SYSTEMTIME;
begin
if not GetFileAttributesEx(PChar(filename), GetFileExInfoStandard, @fad) then
RaiseLastOSError;
 
FileTimeToSystemTime(fad.ftCreationTime, systime);
 
Result := SystemTimeToDateTime(systime);
end;
 
function UTCTimeToLocalTime(const aValue: TDateTime): TDateTime;
var
lBias: Integer;
lTZI: TTimeZoneInformation;
begin
lBias := 0;
case GetTimeZoneInformation(lTZI) of
TIME_ZONE_ID_UNKNOWN:
lBias := lTZI.Bias;
TIME_ZONE_ID_DAYLIGHT:
lBias := lTZI.Bias + lTZI.DaylightBias;
TIME_ZONE_ID_STANDARD:
lBias := lTZI.Bias + lTZI.StandardBias;
end;
// UTC = local time + bias
// bias is in number of minutes, TDateTime is in days
Result := aValue - (lBias / (24 * 60));
end;
 
function GetFileSize(const AFileName: String): int64;
var
lFindData: TWin32FindData;
lHandle: Cardinal;
begin
// https://www.delphipraxis.net/24331-dateigroesse-einer-beliebigen-datei-ermitteln.html
lHandle := FindFirstFile(PChar(AFileName), lFindData);
if (lHandle <> INVALID_HANDLE_VALUE) then
begin
Result := lFindData.nFileSizeLow;
PCardinal(Cardinal(@Result) + SizeOf(Cardinal))^ := lFindData.nFileSizeHigh;
Windows.FindClose(lHandle);
end
else
Result := 0;
end;
 
function IntToStr2(i: int64): string;
begin
// https://www.delphipraxis.net/150464-integer-mit-tausender-trennzeichen-ausgeben.html
Result := Format('%.0n', [i / 1]);
end;
 
function ConvertBytes(Bytes: int64): string;
const
Description: Array [0 .. 8] of string = ('Bytes', 'KB', 'MB', 'GB', 'TB',
'PB', 'EB', 'ZB', 'YB');
var
i: Integer;
begin
// https://stackoverflow.com/questions/30548940/correct-way-to-convert-size-in-bytes-to-kb-mb-gb-delphi
i := 0;
 
while Bytes > Power(1024, i + 1) do
Inc(i);
 
Result := FormatFloat('###0.##', Bytes / IntPower(1024, i)) + ' ' +
Description[i];
end;
 
var
DriveGuidCache: TStringList = nil;
 
class function TfrmIndexCreator.DriveGuid(const Letter: char): string;
var
Buffer: array [0 .. 49] of char;
begin
if not Assigned(DriveGuidCache) then
DriveGuidCache := TStringList.Create;
 
Result := DriveGuidCache.Values[Letter];
if Result = '' then
begin
Win32Check(GetVolumeNameForVolumeMountPoint(PChar(Letter + ':\'), Buffer,
Length(Buffer)));
Result := Buffer;
DriveGuidCache.Values[Letter] := Result;
end;
end;
 
class function TfrmIndexCreator.uniqueFilename(const filename: string): string;
var
guid: string;
begin
if Length(filename) < 2 then
exit;
if filename[2] = ':' then
begin
guid := DriveGuid(filename[1]);
 
Result := guid + Copy(filename, 4, Length(filename) - 3);
 
// result := LowerCase(result);
end
else
Result := filename; // z.B. UNC-Pfad
end;
 
class function TfrmIndexCreator.VtsSpecial(const filename: string): string;
begin
Result := filename;
{$IFDEF VIATHINKSOFT}
Result := StringReplace(Result, GUID_EHDD_A, 'EHDD:\', []);
Result := StringReplace(Result, GUID_EHDD_B, 'EHDD:\', []);
{$ENDIF}
end;
 
procedure TfrmIndexCreator.CheckFile(const originalFileName,
uniqueFilename: string);
 
function DateTimeToSQL(dt: TDateTime): string;
begin
if dt = -1 then
Result := 'NULL'
else
Result := conn.SQLStringEscape(DateTimetoStr(dt));
end;
 
type
TExistResult = (erDoesNotExist, erHadError, erChanged, erUnchanged);
 
var
lastCheckedMd5: string;
 
function Exists(const filename: string; size: int64;
const modified: TDateTime): TExistResult;
var
q: TADODataSet;
begin
q := conn.GetTable('select error, size, modified, md5hash from ' + TableName
+ ' where filename = ' + conn.SQLStringEscape
(VtsSpecial(uniqueFilename)));
try
if q.RecordCount = 0 then
Result := erDoesNotExist
else if not q.Fields[0].IsNull then
Result := erHadError
else if (q.Fields[1].AsString <> IntToStr(size)) or
// we are combining strings because of int64
(SecondsBetween(q.Fields[2].AsDateTime, UTCTimeToLocalTime(modified)
) > 2) then
begin
Result := erChanged
end
else
Result := erUnchanged;
lastCheckedMd5 := q.Fields[3].AsString;
finally
FreeAndNil(q);
end;
end;
 
var
created, modified: TDateTime;
size: int64;
md5: string;
begin
Label1.Caption := MinimizeName(originalFileName, Label1.Canvas, Label1.Width);
Application.ProcessMessages;
 
try
if FileExists(uniqueFilename) then
created := FileCTime_UTC(uniqueFilename)
else
created := -1;
 
if FileExists(uniqueFilename) then
modified := FileMTime_UTC(uniqueFilename)
else
modified := -1;
 
size := GetFileSize(uniqueFilename);
Inc(sumsize, size);
Inc(sumfiles);
 
if rgModus.ItemIndex = modusRecreate then
begin
md5 := MD5File(uniqueFilename);
if not cbSimulate.Checked then
begin
conn.ExecSQL('INSERT INTO ' + TableName +
' (filename, size, created, modified, md5hash, error) values (' +
conn.SQLStringEscape(VtsSpecial(uniqueFilename)) + ', ' +
IntToStr(size) + ', ' + DateTimeToSQL(UTCTimeToLocalTime(created)) +
', ' + DateTimeToSQL(UTCTimeToLocalTime(modified)) + ', ' +
conn.SQLStringEscape(LowerCase(md5)) + ', NULL);');
end;
if cbVerboseLogs.Checked then
Memo2.Lines.Add('New: ' + uniqueFilename);
Inc(sumfiles_new);
end
else
begin
case Exists(uniqueFilename, size, modified) of
erDoesNotExist: // File does not exist or has a different hash
begin
if rgModus.ItemIndex <> modusValidation then
md5 := MD5File(uniqueFilename);
if not cbSimulate.Checked and (rgModus.ItemIndex <> modusValidation)
then
begin
conn.ExecSQL('INSERT INTO ' + TableName +
' (filename, size, created, modified, md5hash, error) values ('
+ conn.SQLStringEscape(VtsSpecial(uniqueFilename)) + ', ' +
IntToStr(size) + ', ' +
DateTimeToSQL(UTCTimeToLocalTime(created)) + ', ' +
DateTimeToSQL(UTCTimeToLocalTime(modified)) + ', ' +
conn.SQLStringEscape(LowerCase(md5)) + ', NULL);');
end;
if cbVerboseLogs.Checked then
Memo2.Lines.Add('New: ' + uniqueFilename);
Inc(sumfiles_new);
end;
erHadError, erChanged:
begin
if rgModus.ItemIndex <> modusValidation then
md5 := MD5File(uniqueFilename);
if not cbSimulate.Checked and (rgModus.ItemIndex <> modusValidation)
then
begin
conn.ExecSQL('UPDATE ' + TableName + ' SET size = ' +
IntToStr(size) + ', created = ' +
DateTimeToSQL(UTCTimeToLocalTime(created)) + ', modified = ' +
DateTimeToSQL(UTCTimeToLocalTime(modified)) + ', md5hash = ' +
conn.SQLStringEscape(LowerCase(md5)) +
', error = NULL WHERE filename = ' + conn.SQLStringEscape
(VtsSpecial(uniqueFilename)) + ';');
end;
if cbVerboseLogs.Checked then
Memo2.Lines.Add('Updated: ' + uniqueFilename);
Inc(sumfiles_updated);
end;
erUnchanged: // Date/Time+Size has not changed
begin
if rgModus.ItemIndex = modusValidation then
begin
md5 := MD5File(uniqueFilename);
if not SameText(md5, lastCheckedMd5) then
begin
Memo2.Lines.Add
('!!! HASH HAS CHANGED WHILE DATETIME+SIZE IS THE SAME: ' +
uniqueFilename + ' (' + lastCheckedMd5 + ' became ' +
md5 + ')');
Memo2.Color := clRed;
Inc(sumfiles_integrityfail);
end;
end;
end;
end;
end;
except
on E: Exception do
begin
if E is EAbort then
Abort;
// if AdoConnection1.InTransaction then AdoConnection1.RollbackTrans;
// AdoConnection1.BeginTrans;
try
if not cbSimulate.Checked and (rgModus.ItemIndex <> modusValidation)
then
begin
conn.ExecSQL('DELETE FROM ' + TableName + ' WHERE filename = ' +
conn.SQLStringEscape(VtsSpecial(uniqueFilename)) + ';');
conn.ExecSQL('INSERT INTO ' + TableName +
' (filename, size, created, modified, md5hash, error) values (' +
conn.SQLStringEscape(VtsSpecial(uniqueFilename)) +
', NULL, NULL, NULL, NULL, ' + conn.SQLStringEscape(Copy(E.Message,
1, ERROR_FIELD_SIZE)) + ');');
Memo2.Lines.Add('Error (logged): ' + E.Message + ' at file ' +
VtsSpecial(uniqueFilename));
end
else
begin
Memo2.Lines.Add('Error: ' + E.Message + ' at file ' +
VtsSpecial(uniqueFilename));
end;
// AdoConnection1.CommitTrans;
except
// AdoConnection1.RollbackTrans;
Memo2.Lines.Add('Cannot write error into file database! ' + E.Message +
' at file ' + VtsSpecial(uniqueFilename));
end;
Inc(sumfiles_error);
end;
end;
 
RedrawStats;
Application.ProcessMessages;
end;
 
function TfrmIndexCreator.conn: TAdoConnection;
begin
Result := frmMain.AdoConnection1;
end;
 
procedure TfrmIndexCreator.RedrawStats;
begin
Label5.Caption := ConvertBytes(sumsize);
Label6.Caption := IntToStr2(sumfiles);
Label7.Caption := IntToStr2(sumfiles_new);
Label9.Caption := IntToStr2(sumfiles_updated);
Label11.Caption := IntToStr2(sumfiles_error);
Label12.Caption := IntToStr2(sumfiles_deleted);
// LabelXX.Caption := IntToStr2(sumfiles_integrityfail);
end;
 
procedure TfrmIndexCreator.Copyuniquepathtoclipboard1Click(Sender: TObject);
var
s: string;
begin
s := uniqueFilename(LabeledEdit2.Text);
Clipboard.AsText := s;
{$IFDEF VIATHINKSOFT}
if VtsSpecial(s) <> s then
begin
s := s + #13#10 + VtsSpecial(s);
end;
{$ENDIF}
ShowMessageFmt('Copied to clipboard:' + #13#10#13#10 + '%s', [s]);
end;
 
procedure TfrmIndexCreator.rgModusClick(Sender: TObject);
begin
cbSimulate.enabled := rgModus.ItemIndex <> modusValidation;
cbNoDelete.enabled := rgModus.ItemIndex <> modusValidation;
end;
 
function TfrmIndexCreator.TableName: string;
begin
Result := frmMain.TableName;
end;
 
procedure TfrmIndexCreator.Rec(StartDir: string; const FileMask: string);
var
SR: TSearchRec;
DirList: TStrings;
IsFound: boolean;
i: Integer;
UniqueStartDir: string;
begin
StartDir := IncludeTrailingPathDelimiter(StartDir);
 
i := 0;
conn.BeginTrans;
IsFound := FindFirst(StartDir + FileMask, faAnyFile - faDirectory, SR) = 0;
try
while IsFound do
begin
Inc(i);
if i mod 1000 = 0 then // Only for performance
begin
conn.CommitTrans;
conn.BeginTrans;
end;
Application.ProcessMessages;
if Application.Terminated or StopRequest then
Abort;
 
if UniqueStartDir = '' then
UniqueStartDir := uniqueFilename(StartDir);
CheckFile(StartDir + SR.Name, UniqueStartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end;
finally
FindClose(SR);
conn.CommitTrans;
end;
 
// Build a list of subdirectories
DirList := TStringList.Create;
try
IsFound := FindFirst(StartDir + '*', faDirectory, SR) = 0;
try
while IsFound do
begin
if (SR.Name <> '.') and (SR.Name <> '..') then
begin
Application.ProcessMessages;
if Application.Terminated or StopRequest then
Abort;
 
DirList.Add(StartDir + SR.Name);
end;
IsFound := FindNext(SR) = 0;
end;
finally
FindClose(SR);
end;
 
// Scan the list of subdirectories
for i := 0 to DirList.Count - 1 do
begin
try
Rec(DirList[i], FileMask);
except
on E: Exception do
begin
if E is EAbort then
Abort;
Memo2.Lines.Add('Unexpected error at directory ' + DirList[i] + ': ' +
E.Message);
end;
end;
end;
finally
DirList.Free;
end;
end;
 
procedure TfrmIndexCreator.DeleteAllFiles(mask: string = '');
begin
sumfiles_deleted := conn.GetScalar('select count(*) as cnt from ' + TableName
+ ' where filename like ' + conn.SQLStringEscape(VtsSpecial(mask)));
RedrawStats;
 
if not cbSimulate.Checked and (rgModus.ItemIndex <> modusValidation) then
begin
if (mask = '') or (mask = '%') then
conn.ExecSQL('delete from ' + TableName)
else
conn.ExecSQL('delete from ' + TableName + ' where filename like ' +
conn.SQLStringEscape(VtsSpecial(mask)));
end;
end;
 
procedure TfrmIndexCreator.DeleteVanishedFiles(mask: string = '');
 
{$IFDEF VIATHINKSOFT}
var
cacheAconnected: boolean;
cacheBconnected: boolean;
{$ENDIF}
function AllowFileCheck(AFileName: string): boolean;
var
guid: string;
begin
Result := false;
{$IFDEF VIATHINKSOFT}
if StartsText('EHDD:\', AFileName) then
begin
if not cacheAconnected and SysUtils.DirectoryExists(GUID_EHDD_A) then
begin
cacheAconnected := true;
end;
if not cacheBconnected and SysUtils.DirectoryExists(GUID_EHDD_B) then
begin
cacheBconnected := true;
end;
Result := cacheAconnected or cacheBconnected;
end
else
{$ENDIF}
if StartsText('\\?\Volume', AFileName) then
begin
guid := Copy(AFileName, 1, 49);
if EndsText('\', guid) then // should always happen
begin
// TODO: cache this result somehow, so that DirectoryExists() does not need to be called all the time
if SysUtils.DirectoryExists(guid) then // is drive connected/existing?
begin
Result := true;
end;
end;
end
else
begin
// TODO: Einen Code für Netzlaufwerke machen: Wir dürfen nur Dateien löschen,
// wenn das Netzlaufwerk wirklich da ist.
end;
end;
 
function FileDoesExist(AFileName: string): boolean;
begin
{$IFDEF VIATHINKSOFT}
if StartsText('EHDD:\', AFileName) then
begin
// Attention: AllowFileCheck must be called to initialize cacheAconnected and cacheBconnected
 
if cacheAconnected and FileExists(StringReplace(AFileName, 'EHDD:\',
GUID_EHDD_A, [])) then
exit(true);
 
if cacheBconnected and FileExists(StringReplace(AFileName, 'EHDD:\',
GUID_EHDD_B, [])) then
exit(true);
 
exit(false);
end;
{$ENDIF}
exit(FileExists(AFileName));
end;
 
var
filename: string;
q: TADODataSet;
fFileName: TField;
i: int64;
begin
if mask <> '' then
q := conn.GetTable('select filename from ' + TableName +
' where filename like ' + conn.SQLStringEscape(VtsSpecial(mask)))
else
q := conn.GetTable('select filename from ' + TableName);
try
i := 0;
fFileName := q.FieldByName('filename');
while not q.Eof do
begin
filename := fFileName.AsString;
 
if AllowFileCheck(filename) and not FileDoesExist(filename) then
begin
if not cbSimulate.Checked and (rgModus.ItemIndex <> modusValidation)
then
begin
conn.ExecSQL('delete from ' + TableName + ' where filename = ' +
conn.SQLStringEscape(filename));
end;
Inc(sumfiles_deleted);
if cbVerboseLogs.Checked then
Memo2.Lines.Add('Deleted: ' + filename);
RedrawStats;
end;
 
Inc(i);
if i mod 100 = 0 then
begin
Label1.Caption := MinimizeName(filename, Label1.Canvas, Label1.Width);
Application.ProcessMessages;
if Application.Terminated or StopRequest then
Abort;
end;
 
q.Next;
end;
finally
FreeAndNil(q);
end;
end;
 
procedure TfrmIndexCreator.IndexDrive(initialdir: string);
begin
if not cbNoDelete.Checked and not cbSimulate.Checked and
(rgModus.ItemIndex <> modusValidation) then
begin
if rgModus.ItemIndex = modusRecreate then
begin
DeleteAllFiles(uniqueFilename(IncludeTrailingPathDelimiter
(initialdir)) + '%');
end
else
begin
DeleteVanishedFiles
(uniqueFilename(IncludeTrailingPathDelimiter(initialdir)) + '%');
end;
end;
 
Rec(IncludeTrailingPathDelimiter(initialdir), '*');
end;
 
procedure TfrmIndexCreator.Button1Click(Sender: TObject);
begin
sumsize := 0;
sumfiles := 0;
sumfiles_new := 0;
sumfiles_updated := 0;
sumfiles_error := 0;
sumfiles_deleted := 0;
sumfiles_integrityfail := 0;
 
Label1.Caption := 'Please wait...';
Label5.Caption := '0';
Label6.Caption := '0';
Label7.Caption := '0';
Label9.Caption := '0';
Label11.Caption := '0';
Label12.Caption := '0';
Application.ProcessMessages;
 
EnableDisableControls(false);
try
if not SysUtils.DirectoryExists(LabeledEdit2.Text) then
begin
raise Exception.CreateFmt('Directory %s not found.', [LabeledEdit2.Text]);
end;
 
IndexDrive(LabeledEdit2.Text);
 
(*
if not Application.Terminated or StopRequest then
begin
ShowMessage('Finished');
end;
*)
finally
EnableDisableControls(true);
end;
 
Beep;
Label1.Caption := 'Done.';
Application.ProcessMessages;
end;
 
procedure TfrmIndexCreator.FormClose(Sender: TObject; var Action: TCloseAction);
begin
StopRequest := true;
Action := caFree; // TODO: müssen wir warten bis der prozess angehalten ist?
end;
 
procedure TfrmIndexCreator.FormShow(Sender: TObject);
var
ini: TMemIniFile;
begin
ini := frmMain.ini;
rgModus.ItemIndex := ini.ReadInteger('IndexCreator', 'DefaultMode', modusUpdate);
cbNoDelete.Checked := ini.ReadBool('IndexCreator', 'DefaultCheckVanished', false);
cbVerboseLogs.Checked := ini.ReadBool('IndexCreator', 'DefaultVerboseLogs', false);
cbSimulate.Checked := ini.ReadBool('IndexCreator', 'DefaultSimulate', false);
LabeledEdit2.Text := ini.ReadString('IndexCreator', 'DefaultDir', 'C:\');
end;
 
procedure TfrmIndexCreator.Button2Click(Sender: TObject);
begin
StopRequest := true;
Close;
end;
 
procedure TfrmIndexCreator.Button4Click(Sender: TObject);
var
i: Integer;
s: string;
begin
sumsize := 0;
sumfiles := 0;
sumfiles_new := 0;
sumfiles_updated := 0;
sumfiles_error := 0;
sumfiles_deleted := 0;
 
Label1.Caption := 'Please wait...';
Label5.Caption := '0';
Label6.Caption := '0';
Label7.Caption := '0';
Label9.Caption := '0';
Label11.Caption := '0';
Label12.Caption := '0';
Application.ProcessMessages;
 
EnableDisableControls(false);
try
// if fileexists('tmp') then memo1.lines.LoadFromFile('tmp');
for i := Memo1.Lines.Count - 1 downto 0 do
begin
s := Memo1.Lines.strings[i];
if Trim(s) <> '' then
begin
LabeledEdit2.Text := s;
 
if not SysUtils.DirectoryExists(LabeledEdit2.Text) then
begin
raise Exception.CreateFmt('Directory %s not found.',
[LabeledEdit2.Text]);
end;
 
IndexDrive(LabeledEdit2.Text);
end;
Memo1.Lines.Delete(i);
// memo1.lines.SaveToFile('tmp');
end;
 
(*
if not Application.Terminated or StopRequest then
begin
ShowMessage('Finished');
end;
*)
finally
EnableDisableControls(true);
end;
 
Beep;
Label1.Caption := 'Done.';
Application.ProcessMessages;
end;
 
procedure TfrmIndexCreator.EnableDisableControls(enabled: boolean);
begin
rgModus.enabled := enabled;
cbNoDelete.enabled := enabled and (rgModus.ItemIndex <> modusValidation);
cbVerboseLogs.enabled := enabled;
cbSimulate.enabled := enabled and (rgModus.ItemIndex <> modusValidation);
Button1.enabled := enabled;
LabeledEdit2.enabled := enabled;
Memo1.enabled := enabled;
Button4.enabled := enabled;
end;
 
end.
/trunk/MainForm.dfm
0,0 → 1,46
object frmMain: TfrmMain
Left = 0
Top = 0
Caption = 'ViaThinkSoft Offline File Indexer Suite'
ClientHeight = 300
ClientWidth = 635
Color = clBlack
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIForm
Menu = MainMenu1
OldCreateOrder = False
Position = poScreenCenter
WindowState = wsMaximized
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object MainMenu1: TMainMenu
Left = 112
Top = 88
object IndexCreator1: TMenuItem
Caption = 'Index Creator'
OnClick = IndexCreator1Click
end
object OfflineExplorer1: TMenuItem
Caption = 'Offline Explorer'
OnClick = OfflineExplorer1Click
end
object RedundancyVerifier1: TMenuItem
Caption = 'Redundancy Verifier'
OnClick = RedundancyVerifier1Click
end
object Finder1: TMenuItem
Caption = 'Finder'
OnClick = Finder1Click
end
end
object ADOConnection1: TADOConnection
Left = 264
Top = 88
end
end
/trunk/MainForm.pas
0,0 → 1,111
unit MainForm;
 
// TODO: viele funktionen: (ggf auch per kontextmenü im explorer)
// - öffnen der datei, wenn datenträger online ist
// - anzeigen von eigenschaften
// - schauen ob es die dateiprüfsumme noch woanders gibt
// - welche dateien in A und welche in B?
// - Alle Fehler zeigen
// - Statistik (Anzahl Dateien etc)
 
interface
 
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Menus, Data.DB,
Data.Win.ADODB, IniFiles;
 
type
TfrmMain = class(TForm)
MainMenu1: TMainMenu;
OfflineExplorer1: TMenuItem;
RedundancyVerifier1: TMenuItem;
IndexCreator1: TMenuItem;
ADOConnection1: TADOConnection;
Finder1: TMenuItem;
procedure OfflineExplorer1Click(Sender: TObject);
procedure RedundancyVerifier1Click(Sender: TObject);
procedure IndexCreator1Click(Sender: TObject);
procedure Finder1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FTableName: string;
public
ini: TMemIniFile;
property TableName: string read FTableName;
end;
 
var
frmMain: TfrmMain;
 
implementation
 
{$R *.dfm}
 
uses
ExplorerForm, RedundancyForm, IndexCreatorForm, FinderForm;
 
procedure TfrmMain.FormCreate(Sender: TObject);
var
iniFilename: string;
begin
iniFilename := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'VtsFileIndexerSuite.ini';
if FileExists(iniFilename) then
begin
ini := TMemIniFile.Create(iniFilename);
 
FTableName := ini.ReadString('IndexerSuite', 'TableName', 'files');
Caption := Caption + Format(' [%s]', [FTableName]);
 
ADOConnection1.ConnectionString := ini.ReadString('IndexerSuite', 'ConnectionString', '');
if ADOConnection1.ConnectionString = '' then
begin
ShowMessage('Please define a ConnectionString in the INI file.');
Close;
Exit;
end;
try
ADOConnection1.Connected := true;
except
on E: Exception do
begin
ShowMessage('Cannot connect to the database: ' + E.Message);
Close;
Exit;
end;
end;
end
else
begin
ShowMessageFmt('%s not found', [iniFilename]);
Close;
end;
end;
 
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
FreeAndNil(ini);
end;
 
procedure TfrmMain.IndexCreator1Click(Sender: TObject);
begin
TfrmIndexCreator.Create(self);
end;
 
procedure TfrmMain.OfflineExplorer1Click(Sender: TObject);
begin
TfrmExplorer.Create(Self);
end;
 
procedure TfrmMain.Finder1Click(Sender: TObject);
begin
TfrmFinder.Create(Self);
end;
 
procedure TfrmMain.RedundancyVerifier1Click(Sender: TObject);
begin
TfrmRedundancy.Create(Self);
end;
 
end.
/trunk/RedundancyForm.dfm
0,0 → 1,104
object frmRedundancy: TfrmRedundancy
Left = 0
Top = 0
Caption = 'Redundant Directory Verifier'
ClientHeight = 528
ClientWidth = 613
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIChild
OldCreateOrder = False
Visible = True
OnClose = FormClose
OnCloseQuery = FormCloseQuery
OnShow = FormShow
DesignSize = (
613
528)
PixelsPerInch = 96
TextHeight = 13
object Gauge1: TGauge
Left = 8
Top = 481
Width = 591
Height = 33
Anchors = [akLeft, akRight, akBottom]
Progress = 0
ExplicitTop = 456
ExplicitWidth = 544
end
object Label1: TLabel
Left = 8
Top = 8
Width = 196
Height = 13
Caption = 'Check if following directory is redundant:'
end
object Label2: TLabel
Left = 8
Top = 85
Width = 61
Height = 13
Caption = 'Unique Files:'
end
object Label3: TLabel
Left = 8
Top = 462
Width = 46
Height = 13
Caption = 'Progress:'
end
object Label4: TLabel
Left = 72
Top = 462
Width = 3
Height = 13
end
object Button1: TButton
Left = 462
Top = 51
Width = 137
Height = 33
Anchors = [akTop, akRight]
Caption = 'Check'
Default = True
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 8
Top = 104
Width = 592
Height = 353
Anchors = [akLeft, akTop, akRight, akBottom]
ScrollBars = ssBoth
TabOrder = 1
end
object Edit1: TEdit
Left = 8
Top = 24
Width = 592
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 2
end
object ComboBox1: TComboBox
Left = 8
Top = 51
Width = 329
Height = 21
Style = csDropDownList
ItemIndex = 0
TabOrder = 3
Text = 'Mode 1: Check if entry in index table is unique'
Items.Strings = (
'Mode 1: Check if entry in index table is unique'
'Mode 2: Check if local folder has files which are not in the ind' +
'ex')
end
end
/trunk/RedundancyForm.pas
0,0 → 1,272
unit RedundancyForm;
 
interface
 
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, AdoDb,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Samples.Gauges;
 
type
TfrmRedundancy = class(TForm)
Button1: TButton;
Memo1: TMemo;
Gauge1: TGauge;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
ComboBox1: TComboBox;
Label3: TLabel;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormShow(Sender: TObject);
private
procedure Mode2Rec(StartDir: string; const FileMask: string;
var cntRedundant: integer; var cntUnique: integer);
protected
StopRequest: Boolean;
procedure EnableDisableControls(v: Boolean);
function TableName: string;
function conn: TAdoConnection;
end;
 
implementation
 
{$R *.dfm}
 
uses
DB, AdoConnHelper, IdHashMessageDigest, idHash, MainForm, IniFiles;
 
function MD5File(const FileName: string): string;
var
IdMD5: TIdHashMessageDigest5;
FS: TFileStream;
begin
IdMD5 := TIdHashMessageDigest5.Create;
FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
{$IFDEF UNICODE} // I actually do not know at which version of Delphi/Indy, this has changed.
Result := IdMD5.HashStreamAsHex(FS);
{$ELSE}
Result := IdMD5.AsHex(IdMD5.HashValue(FS));
{$ENDIF}
finally
FS.Free;
IdMD5.Free;
end;
end;
 
procedure TfrmRedundancy.Mode2Rec(StartDir: string; const FileMask: string;
var cntRedundant: integer; var cntUnique: integer);
 
procedure CheckFile(aFilename: string);
var
md5: string;
begin
try
Label4.Caption := aFilename;
md5 := MD5File(aFilename);
if conn.GetScalar('select count(*) from ' + TableName +
' where md5hash = ' + conn.SQLStringEscape(md5)) = 0 then
begin
Memo1.Lines.Add(aFilename);
Inc(cntUnique);
end
else
begin
Inc(cntRedundant);
end;
except
on E: Exception do
begin
Memo1.Lines.Add(Format('Error: Cannot process %s : %s',
[aFilename, E.Message]))
end;
end;
end;
 
var
SR: TSearchRec;
DirList: TStrings;
IsFound: Boolean;
i: integer;
begin
StartDir := IncludeTrailingPathDelimiter(StartDir);
 
i := 0;
IsFound := FindFirst(StartDir + FileMask, faAnyFile - faDirectory, SR) = 0;
try
while IsFound do
begin
Inc(i);
Application.ProcessMessages;
if Application.Terminated or StopRequest then
Abort;
 
CheckFile(StartDir + SR.Name);
IsFound := FindNext(SR) = 0;
end;
finally
FindClose(SR);
end;
 
// Build a list of subdirectories
DirList := TStringList.Create;
try
IsFound := FindFirst(StartDir + '*', faDirectory, SR) = 0;
try
while IsFound do
begin
if (SR.Name <> '.') and (SR.Name <> '..') then
begin
Application.ProcessMessages;
if Application.Terminated or StopRequest then
Abort;
 
DirList.Add(StartDir + SR.Name);
end;
IsFound := FindNext(SR) = 0;
end;
finally
FindClose(SR);
end;
 
// Scan the list of subdirectories
for i := 0 to DirList.Count - 1 do
begin
try
Mode2Rec(DirList[i], FileMask, cntRedundant, cntUnique);
except
on E: Exception do
begin
if E is EAbort then
Abort;
Memo1.Lines.Add('Unexpected error at directory ' + DirList[i] + ': ' +
E.Message);
end;
end;
end;
finally
DirList.Free;
end;
end;
 
function TfrmRedundancy.TableName: string;
begin
result := frmMain.TableName;
end;
 
procedure TfrmRedundancy.Button1Click(Sender: TObject);
var
q: TADODataSet;
fMD5: TField;
fFilename: TField;
dirMask: string;
cntRedundant: integer;
cntUnique: integer;
begin
EnableDisableControls(False);
if ComboBox1.ItemIndex = 1 then
Gauge1.Visible := False;
Memo1.Lines.Clear;
try
{$REGION 'Mode 1'}
if ComboBox1.ItemIndex = 0 then
begin
dirMask := IncludeTrailingPathDelimiter(Edit1.Text) + '%';
q := conn.GetTable
('select filename, md5hash from '+TableName+' where filename like ' +
conn.SQLStringEscape(dirMask) + ' order by filename');
try
Gauge1.MinValue := 0;
Gauge1.MaxValue := q.RecordCount;
Gauge1.Progress := 0;
cntRedundant := 0;
cntUnique := 0;
fMD5 := q.FieldByName('md5hash');
fFilename := q.FieldByName('filename');
while not q.Eof do
begin
if conn.GetScalar('select count(*) from '+TableName+' where md5hash = ' +
conn.SQLStringEscape(fMD5.AsString) + ' and filename not like ' +
conn.SQLStringEscape(dirMask)) = 0 then
begin
Memo1.Lines.Add(fFilename.AsString);
Inc(cntUnique);
end
else
begin
Inc(cntRedundant);
end;
Gauge1.Progress := Gauge1.Progress + 1;
Application.ProcessMessages;
if Application.Terminated then
Abort;
q.Next;
end;
finally
q.Free;
end;
end;
{$ENDREGION}
{$REGION 'Mode 2'}
if ComboBox1.ItemIndex = 1 then
begin
cntRedundant := 0;
cntUnique := 0;
Mode2Rec(Edit1.Text, '*', cntRedundant, cntUnique);
end;
{$ENDREGION}
if (cntRedundant = 0) and (cntUnique = 0) then
raise Exception.Create('No files found. Is the string correct?')
else
ShowMessageFmt('Done. %d files are redundant. %d are unique.',
[cntRedundant, cntUnique]);
 
if ComboBox1.ItemIndex = 0 then
begin
ShowMessage
('Attention: Only check 1 directory at a time, then delete redundant files, then re-index and only then continue with checking the redundancy of the any other directory.');
end;
finally
EnableDisableControls(True);
Gauge1.Progress := 0;
Gauge1.Visible := True;
Label4.Caption := '';
end;
end;
 
function TfrmRedundancy.conn: TAdoConnection;
begin
Result := frmMain.AdoConnection1;
end;
 
procedure TfrmRedundancy.EnableDisableControls(v: Boolean);
begin
Edit1.Enabled := v;
Button1.Enabled := v;
ComboBox1.Enabled := v;
end;
 
procedure TfrmRedundancy.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
 
procedure TfrmRedundancy.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
StopRequest := True;
end;
 
procedure TfrmRedundancy.FormShow(Sender: TObject);
var
ini: TMemIniFile;
begin
ini := frmMain.ini;
Edit1.Text := ini.ReadString('RedundancyFinder', 'DefaultDir', '');
ComboBox1.ItemIndex := ini.ReadInteger('RedundancyFinder', 'DefaultMode', 1)-1;
end;
 
end.
/trunk/VtsFileIndexerSuite.dpr
0,0 → 1,18
program VtsFileIndexerSuite;
 
uses
Vcl.Forms,
MainForm in 'MainForm.pas' {frmMain},
ExplorerForm in 'ExplorerForm.pas' {frmExplorer},
RedundancyForm in 'RedundancyForm.pas' {frmRedundancy},
IndexCreatorForm in 'IndexCreatorForm.pas' {frmIndexCreator},
FinderForm in 'FinderForm.pas' {frmFinder};
 
{$R *.res}
 
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.
/trunk/VtsFileIndexerSuite.dproj
0,0 → 1,585
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{A26E4150-D10E-4979-B0B9-132BCCBF0E92}</ProjectGuid>
<ProjectVersion>18.4</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<MainSource>VtsFileIndexerSuite.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Application</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
<Cfg_2_Win32>true</Cfg_2_Win32>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<DCC_UsePackage>RESTComponents;FireDAC;FireDACSqliteDriver;soaprtl;FireDACIBDriver;soapmidas;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
<SanitizedProjectName>VtsFileIndexerSuite</SanitizedProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;vcltouch;vcldb;bindcompfmx;svn;FireDACPgDriver;inetdb;DbxCommonDriver;fmx;fmxdae;xmlrtl;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;IndyIPClient;bindcompvcl;VCLRESTComponents;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;vcltouch;vcldb;bindcompfmx;FireDACPgDriver;inetdb;DbxCommonDriver;fmx;fmxdae;xmlrtl;fmxobj;vclwinx;rtl;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;IndyIPClient;bindcompvcl;VCLRESTComponents;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppEnableHighDPI>true</AppEnableHighDPI>
<DCC_UnitSearchPath>C:\Users\DELL User\ownCloud\Entwicklung\ADO;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_ExeOutput>.</DCC_ExeOutput>
<DCC_DcuOutput>.</DCC_DcuOutput>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
<AppEnableHighDPI>true</AppEnableHighDPI>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="MainForm.pas">
<Form>frmMain</Form>
<FormType>dfm</FormType>
</DCCReference>
<DCCReference Include="ExplorerForm.pas">
<Form>frmExplorer</Form>
<FormType>dfm</FormType>
</DCCReference>
<DCCReference Include="RedundancyForm.pas">
<Form>frmRedundancy</Form>
<FormType>dfm</FormType>
</DCCReference>
<DCCReference Include="IndexCreatorForm.pas">
<Form>frmIndexCreator</Form>
<FormType>dfm</FormType>
</DCCReference>
<DCCReference Include="FinderForm.pas">
<Form>frmFinder</Form>
<FormType>dfm</FormType>
</DCCReference>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Application</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">VtsFileIndexerSuite.dpr</Source>
</Source>
<Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k250.bpl">Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver</Excluded_Packages>
<Excluded_Packages Name="$(BDSBIN)\dclofficexp250.bpl">Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server</Excluded_Packages>
</Excluded_Packages>
</Delphi.Personality>
<Deployment Version="3">
<DeployFile LocalName="VtsFileIndexerSuite.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>VtsFileIndexerSuite.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClassesDexFile">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidGDBServer">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1024">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch1536">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2048">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch768">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch320">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch640x1136">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceResourceRules">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements">
<Platform Name="iOSDevice32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSInfoPList">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements">
<Platform Name="OSX32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXInfoPList">
<Platform Name="OSX32">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
</Deployment>
<Platforms>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>
/trunk/VtsFileIndexerSuite.ini
0,0 → 1,10
[IndexerSuite]
TableName=files
ConnectionString=Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Indexer;Data Source=DELL;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=DELL;Use Encryption for Data=False;Tag with column collation when possible=False;
 
[IndexCreator]
DefaultDir=I:\
 
[RedundancyFinder]
DefaultDir=EHDD:\
DefaultMode=1
/trunk/VtsFileIndexerSuite.res
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/delwaste.bat
0,0 → 1,6
@echo off
del *.dcu
del *.~*
del *.local
del *.identcache
del *.stat