unit ExifTool; interface uses Classes; var ETout, ETerr: TStringList; //data from ExifTool will be here function ExecuteET(const ETcmd,WorkDir: string): Boolean; implementation uses Windows; function ExecuteET(const ETcmd,WorkDir: string): Boolean; const szBuffer=255; var StartupInfo: TStartupInfo; ProcessInfo: TProcessInformation; PWorkDir: PChar; SecurityAttr: TSecurityAttributes; PipeOutputRead: THandle; PipeOutputWrite: THandle; PipeErrorsRead: THandle; PipeErrorsWrite: THandle; Succeed: Boolean; Buffer: array [0..szBuffer] of Char; BytesRead: DWORD; Stream: TMemoryStream; begin //=== Usual steps to initialize data for CreateProcess: FillChar(Buffer,SizeOf(Buffer),0); FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0); SecurityAttr.nLength := SizeOf(SecurityAttr); SecurityAttr.bInheritHandle := true; SecurityAttr.lpSecurityDescriptor := nil; CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0); CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0); FillChar(StartupInfo, SizeOf(TStartupInfo), 0); StartupInfo.cb:=SizeOf(StartupInfo); with StartupInfo do begin hStdInput:=0; hStdOutput:=PipeOutputWrite; hStdError:=PipeErrorsWrite; wShowWindow:=SW_HIDE; dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; end; if WorkDir='' then PWorkDir:=nil else PWorkDir:=PChar(WorkDir); ETout.Clear; ETerr.Clear; //=== Here is where ExifTool is called: if CreateProcess(nil, PChar(ETcmd), nil, nil, true, CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, PWorkDir, StartupInfo, ProcessInfo) then begin //=ExifTool started successfully: result:=true; CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsWrite); end else begin //=ExifTool not started (because, i.e. not found): result:=false; CloseHandle(PipeOutputRead); CloseHandle(PipeOutputWrite); CloseHandle(PipeErrorsRead); CloseHandle(PipeErrorsWrite); end; if result then begin //= Get output written by ExifTool(tag names/values): Stream:=TMemoryStream.Create; try repeat succeed:=ReadFile(PipeOutputRead,Buffer,szBuffer,BytesRead,nil); if not succeed then break; Stream.Write(Buffer,BytesRead) until (BytesRead=0); Stream.Position:=0; ETout.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeOutputRead); //= Get errors written by ExifTool (if any): Stream:=TMemoryStream.Create; try repeat succeed:=ReadFile(PipeErrorsRead,Buffer,szBuffer,BytesRead,nil); if not succeed then break; Stream.Write(Buffer,BytesRead); until (BytesRead=0); Stream.Position:=0; ETerr.LoadFromStream(Stream); finally Stream.Free; end; CloseHandle(PipeErrorsRead); WaitForSingleObject(ProcessInfo.hProcess,5000); //=5sec CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); end; end; initialization begin ETout:=TStringList.Create; ETerr:=TStringList.Create; end; finalization begin ETerr.Free; ETout.Free; end; end.
unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) LabeledEdit1: TLabeledEdit; Button1: TButton; Memo1: TMemo; Label1: TLabel; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation uses ExifTool; {$R *.dfm} var ETcmd:string; procedure TForm1.Button1Click(Sender: TObject); var i: smallint; begin Memo1.Clear; ETcmd:=LabeledEdit1.Text; if ExecuteET('exiftool '+ETcmd,'') then with Memo1.Lines do begin Append('*** ExifTool output:'); if ETout.Count>0 then for i:=0 to ETout.Count-1 do Append(ETout[i]); Append('*** ExifTool errors:'); if ETerr.Count>0 then for i:=0 to ETerr.Count-1 do Append(ETerr[i]); Append('^^^ END'); end else ShowMessage('exiftool.exe not found!?'); end; end.
In above example, because second ExecuteET parameter (WorkDir) is empty, command must include path to image file which we wish to read or modify. So ExifTool command must look like:
-Exif:all c:\myPhotos\test.jpgor
-Exif:Artist="My name" "c:\Photo album\Family\*.jpg"-here we also needed quotes, because tag value (and path) contains spaces.
However, from our "main" code, we can call ExecuteET function by specifying "working directory". By doing something like:
... var ETcmd, WorkDir: string; ... WorkDir:='c:\Photo album\Family\'; // -no quotes needed now ETcmd:='-Exif:Artist="My name" *.jpg'; // -path not needed now if ExecuteET('exiftool '+ETcmd, WorkDir) then ... ...
Bogdan Hrastnik
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4