Subversion Repositories userdetect2

Compare Revisions

Regard whitespace Rev 84 → Rev 85

/trunk/UserDetect2/UD2_Main.pas
101,7 → 101,7
{$R *.dfm}
 
uses
ShellAPI, Clipbrd, Math, AlphaNumSort, UD2_Utils, UD2_TaskProperties;
ShellAPI, Clipbrd, Math, AlphaNumSort, UD2_Utils, UD2_TaskProperties, UD2_Parsing;
 
type
TUD2ListViewEntry = class(TObject)
212,9 → 212,8
LNG_TASK_NOT_EXISTS = 'The task "%s" does not exist in the INI file.';
LNG_NOTHING_MATCHES = 'No identification string matches to your environment. No application was launched. Please check the Task Definition File.';
var
slCmds: TStringList;
i: integer;
cmd: string;
cmds: TUD2CommandArray;
begin
if not ud2.TaskExists(ShortTaskName) then
begin
224,26 → 223,20
Exit;
end;
 
slCmds := TStringList.Create;
try
ud2.GetCommandList(ShortTaskName, slCmds);
SetLength(cmds, 0);
cmds := ud2.GetCommandList(ShortTaskName);
 
if (slCmds.Count = 0) and ud2.ReadMetatagBool(ShortTaskName, TagWarnIfNothingMatches, DefaultWarnIfNothingMatches) then
if (Length(cmds) = 0) and ud2.ReadMetatagBool(ShortTaskName, TagWarnIfNothingMatches, DefaultWarnIfNothingMatches) then
begin
MessageDlg(LNG_NOTHING_MATCHES, mtWarning, [mbOK], 0);
ExitCode := EXITCODE_TASK_NOTHING_MATCHES;
end;
 
for i := 0 to slCmds.Count-1 do
for i := Low(cmds) to High(cmds) do
begin
cmd := slCmds.Strings[i];
if cmd = '' then continue;
UD2_RunCMD(cmd, SW_NORMAL); // Idea: Let SW_NORMAL be configurable by the user?
UD2_RunCMD(cmds[i]);
end;
finally
slCmds.Free;
end;
end;
 
procedure TUD2MainForm.FormDestroy(Sender: TObject);
var
388,8 → 381,14
end;
 
procedure TUD2MainForm.Button1Click(Sender: TObject);
var
cmd: TUD2Command;
begin
UD2_RunCMD(ud2.IniFileName, SW_NORMAL);
cmd.executable := ud2.IniFileName;
cmd.runAsAdmin := false;
cmd.runInOwnDirectory := false;
cmd.windowMode := SW_NORMAL;
UD2_RunCMD(cmd);
end;
 
procedure TUD2MainForm.Button2Click(Sender: TObject);
402,14 → 401,19
 
procedure TUD2MainForm.URLLabelClick(Sender: TObject);
var
s: string;
cmd: TUD2Command;
begin
s := TLabel(Sender).Caption;
if Pos('@', s) > 0 then
s := 'mailto:' + s
cmd.executable := TLabel(Sender).Caption;
if Pos('@', cmd.executable) > 0 then
cmd.executable := 'mailto:' + cmd.executable
else
s := 'http://' + s;
UD2_RunCMD(s, SW_NORMAL);
cmd.executable := 'http://' + cmd.executable;
 
cmd.runAsAdmin := false;
cmd.runInOwnDirectory := false;
cmd.windowMode := SW_NORMAL;
 
UD2_RunCMD(cmd);
end;
 
procedure TUD2MainForm.TasksPopupMenuPopup(Sender: TObject);
529,7 → 533,10
begin
ExitCode := EXITCODE_OK;
 
if ParamStr(3) <> '' then UD2_RunCMD(ParamStr(3), SW_NORMAL); // Idea: SW_NORMAL changeable via parameter
if ParamStr(3) <> '' then
begin
UD2_RunCMD(UD2P_DecodeCommand(ParamStr(3)));
end;
end
else
begin
570,23 → 577,28
procedure TUD2MainForm.Button5Click(Sender: TObject);
var
idTerm: string;
slCmd: TStrings;
cmds: TUD2CommandArray;
sCmds: string;
i: integer;
begin
// TODO xxx: Auch eine Möglichkeit geben, einfach nur "Testecho(abc)" einzugeben und es kommt was bei raus
 
if InputQuery('Enter example term', 'Example: Testecho(abc):abc=calc.exe', idTerm) then
begin
slCmd := TStringList.Create;
try
ud2.CheckTerm(idTerm, slCmd);
if slCmd.Count = 0 then
SetLength(cmds, 0);
cmds := ud2.CheckTerm(idTerm);
 
sCmds := '';
for i := Low(cmds) to High(cmds) do
begin
sCmds := sCmds + cmds[i].executable + #13#10;
end;
 
if Length(cmds) = 0 then
ShowMessage('No commands would be executed.')
else
showmessage('Following commands would be executed:' + #13#10#13#10 + slCmd.Text);
finally
slCmd.Free;
showmessage('Following commands would be executed:' + #13#10#13#10 + sCmds);
end;
end;
LoadDetectedIDs;
end;
 
/trunk/UserDetect2/UD2_Obj.pas
10,7 → 10,7
 
uses
Windows, SysUtils, Classes, IniFiles, Contnrs, Dialogs, UD2_PluginIntf,
UD2_PluginStatus, UD2_Utils;
UD2_PluginStatus, UD2_Utils, UD2_Parsing;
 
type
TUD2IdentificationEntry = class;
77,10 → 77,11
property LoadedPlugins: TObjectList{<TUD2Plugin>} read FLoadedPlugins;
property IniFile: TMemIniFile read FIniFile;
procedure GetAllDetectedIDs(outSL: TStrings);
function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean;
procedure CheckTerm(idTermAndCmd: string; commandSLout: TStrings; slIdNames: TStrings=nil);
function FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil): boolean; overload;
function FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean; overload;
function CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil): TUD2CommandArray;
function FindPluginByMethodNameOrGuid(idMethodName: string): TUD2Plugin;
procedure GetCommandList(ShortTaskName: string; outSL: TStrings);
function GetCommandList(ShortTaskName: string): TUD2CommandArray;
procedure HandlePluginDir(APluginDir, AFileMask: string);
procedure GetTaskListing(outSL: TStrings);
constructor Create(AIniFileName: string);
250,18 → 251,18
{ TUD2IdentificationEntry }
 
procedure TUD2IdentificationEntry.GetIdNames(sl: TStrings);
var
cond: TUD2TDFCondition;
begin
if DynamicDataUsed then
begin
sl.Add(Plugin.IdentificationMethodName+'('+DynamicData+'):'+IdentificationString);
sl.Add(Plugin.PluginGUIDString+'('+DynamicData+'):'+IdentificationString);
end
else
begin
sl.Add(Plugin.IdentificationMethodName+':'+IdentificationString);
sl.Add(Plugin.PluginGUIDString+':'+IdentificationString);
cond.idMethodName := Plugin.IdentificationMethodName;
cond.idStr := IdentificationString;
cond.dynamicDataUsed := DynamicDataUsed;
cond.dynamicData := DynamicData;
sl.Add(UD2_CondToStr(cond));
 
cond.idMethodName := Plugin.PluginGUIDString;
sl.Add(UD2_CondToStr(cond));
end;
end;
 
constructor TUD2IdentificationEntry.Create(AIdentificationString: WideString;
APlugin: TUD2Plugin);
442,18 → 443,19
end;
end;
 
function TUD2.FulfilsEverySubterm(conds: TUD2TDFConditionArray; slIdNames: TStrings=nil): boolean;
begin
result := FulfilsEverySubterm(UD2_CondsToStr(conds), slIdNames);
end;
 
function TUD2.FulfilsEverySubterm(idTerm: WideString; slIdNames: TStrings=nil): boolean;
const
CASE_SENSITIVE_FLAG = '$CASESENSITIVE$';
var
x, a, b: TArrayOfString;
i: integer;
p: TUD2Plugin;
idName: WideString;
cleanUpStringList: boolean;
caseSensitive: boolean;
dynamicData: string;
idMethodName: string;
conds: TUD2TDFConditionArray;
cond: TUD2TDFCondition;
idName: string;
begin
cleanUpStringList := slIdNames = nil;
try
463,40 → 465,19
GetAllDetectedIDs(slIdNames);
end;
 
SetLength(x, 0);
if Pos(':', idTerm) = 0 then
begin
// Exclude stuff like "Description"
result := false;
Exit;
end;
x := SplitString('&&', idTerm);
conds := UD2P_ParseConditions(idTerm);
 
result := true;
for i := Low(x) to High(x) do
for i := Low(conds) to High(conds) do
begin
idName := x[i];
cond := conds[i];
 
/// --- Start Dynamic Extension
 
// xxxxxx ( xxxxx ): xxxxxxxxxxxx
// xxxxx ( xx:xx ): xxxxx:xxx(x)
// xxxxxxxxxxxx : xxxxx(xxx)xx
 
SetLength(a, 0);
a := SplitString('(', idName);
if (Length(a) >= 2) and (Pos(':', a[0]) = 0) then
if cond.dynamicDataUsed then
begin
SetLength(b, 0);
b := SplitString('):', a[1]);
if Length(b) >= 2 then
begin
dynamicData := b[0];
idMethodName := a[0];
 
p := FindPluginByMethodNameOrGuid(idMethodName);
p := FindPluginByMethodNameOrGuid(cond.idMethodName);
if Assigned(p) then
begin
if p.InvokeDynamicCheck(dynamicData) then
if p.InvokeDynamicCheck(cond.dynamicData) then
begin
// Reload the identifications
slIdNames.Clear;
504,23 → 485,12
end;
end;
end;
end;
 
/// --- End Dynamic Extension
idName := UD2_CondToStr(cond);
 
if Pos(CASE_SENSITIVE_FLAG, idName) >= 1 then
if (not cond.caseSensitive and (slIdNames.IndexOf(idName) = -1)) or
(cond.caseSensitive and (IndexOf_CS(slIdNames, idName) = -1)) then
begin
idName := StringReplace(idName, CASE_SENSITIVE_FLAG, '', [rfReplaceAll]);
caseSensitive := true;
end
else
begin
caseSensitive := false;
end;
 
if (not caseSensitive and (slIdNames.IndexOf(idName) = -1)) or
(caseSensitive and (IndexOf_CS(slIdNames, idName) = -1)) then
begin
result := false;
break;
end;
549,11 → 519,15
end;
end;
 
procedure TUD2.GetCommandList(ShortTaskName: string; outSL: TStrings);
function TUD2.GetCommandList(ShortTaskName: string): TUD2CommandArray;
var
i: integer;
i, j, l: integer;
slSV, slIdNames: TStrings;
tmpCmds: TUD2CommandArray;
begin
SetLength(result, 0);
SetLength(tmpCmds, 0);
 
slIdNames := TStringList.Create;
try
GetAllDetectedIDs(slIdNames);
563,8 → 537,14
FIniFile.ReadSectionValues(ShortTaskName, slSV);
for i := 0 to slSV.Count-1 do
begin
CheckTerm(slSV.Strings[i], outSL, slIdNames);
tmpCmds := CheckTerm(slSV.Strings[i], slIdNames);
for j := Low(tmpCmds) to High(tmpCmds) do
begin
l := Length(result);
SetLength(result, l+1);
result[l] := tmpCmds[j];
end;
end;
finally
slSV.Free;
end;
573,12 → 553,13
end;
end;
 
procedure TUD2.CheckTerm(idTermAndCmd: string; commandSLout: TStrings; slIdNames: TStrings=nil);
function TUD2.CheckTerm(idTermAndCmd: string; slIdNames: TStrings=nil): TUD2CommandArray;
var
nameVal: TArrayOfString;
idTerm, cmd: string;
slIdNamesCreated: boolean;
ent: TUD2TDFEntry;
begin
SetLength(result, 0);
 
slIdNamesCreated := false;
try
if not Assigned(slIdNames) then
588,18 → 569,11
GetAllDetectedIDs(slIdNames);
end;
 
SetLength(nameVal, 0);
 
// We are doing the interpretation of the line ourselves, because
// TStringList.Values[] would not allow multiple command lines with the
// same key (idTerm)
// TODO xxx: big problem when we want to check environment variables, since our idTerm would contain '=' !
nameVal := SplitString('=', idTermAndCmd);
if Length(nameVal) < 2 then exit;
idTerm := nameVal[0];
cmd := nameVal[1];
 
if FulfilsEverySubterm(idTerm, slIdNames) then commandSLout.Add(cmd);
if not UD2P_ParseTdfLine(idTermAndCmd, ent) then Exit;
if FulfilsEverySubterm(ent.ids, slIdNames) then
begin
result := ent.commands;
end;
finally
if slIdNamesCreated then slIdNames.Free;
end;
/trunk/UserDetect2/UD2_Parsing.pas
7,6 → 7,13
 
// TODO: use this for better object oriented programming
 
// TODO : WideStrings idName: WideString; ???
 
const
// Prefixes for UD2_RunCmd()
UD2_RUN_IN_OWN_DIRECTORY_PREFIX = '$RIOD$';
UD2_RUN_AS_ADMIN = '$ADMIN$';
 
type
TUD2Command = record
executable: string;
31,55 → 38,157
end;
TUD2TDFEntryArray = array of TUD2TDFEntry;
 
// Split
function UD2P_ParseConditions(idTerm: string): TUD2TDFConditionArray;
function UD2P_ParseTdfLine(idTermAndCmd: string; var entry: TUD2TDFEntry): boolean;
function UD2P_DecodeCommand(line: string): TUD2Command;
function UD2P_DecodeCondition(idName: string; var cond: TUD2TDFCondition): boolean;
 
// Merge
function UD2_CondToStr(cond: TUD2TDFCondition): string;
function UD2_CondsToStr(conds: TUD2TDFConditionArray): string;
 
implementation
 
uses
UD2_Utils;
 
function ParseTdfLine(line: string; var entry: TUD2TDFEntry): boolean;
function UD2_CondsToStr(conds: TUD2TDFConditionArray): string;
var
i: integer;
begin
// TODO: xxxxx
result := '';
for i := Low(conds) to High(conds) do
begin
if result <> '' then result := result + '&&';
result := result + UD2_CondToStr(conds[i]);
end;
end;
 
(*
entry.idName: string;
entry.idValue: string;
entry.dynamicDataUsed: Boolean;
entry.dynamicData: string;
entry.caseSensitive: boolean;
entry.commands: TUD2CommandArray;
*)
function UD2_CondToStr(cond: TUD2TDFCondition): string;
begin
if cond.dynamicDataUsed then
begin
result := cond.idMethodName+'('+cond.dynamicData+'):'+cond.idStr;
end
else
begin
result := cond.idMethodName+':'+cond.idStr;
end;
end;
 
// ReadSectionValues
function UD2P_DecodeCommand(line: string): TUD2Command;
begin
result.runAsAdmin := Pos(UD2_RUN_AS_ADMIN, line) >= 1;
if result.runAsAdmin then
begin
line := StringReplace(line, UD2_RUN_AS_ADMIN, '', [rfReplaceAll]);
end;
 
result.runInOwnDirectory := Pos(UD2_RUN_IN_OWN_DIRECTORY_PREFIX, line) >= 1;
if result.runInOwnDirectory then
begin
line := StringReplace(line, UD2_RUN_IN_OWN_DIRECTORY_PREFIX, '', [rfReplaceAll]);
end;
 
(*
nameVal := SplitString('=', idTermAndCmd);
if Length(nameVal) < 2 then exit;
idTerm := nameVal[0];
cmd := nameVal[1];
*)
result.executable := line;
result.WindowMode := SW_NORMAL; // TODO (future): make it configurable
end;
 
function ParseCommandLine(line: string; var cmd: TUD2Command): boolean;
function UD2P_DecodeCondition(idName: string; var cond: TUD2TDFCondition): boolean;
const
CASE_SENSITIVE_FLAG = '$CASESENSITIVE$';
var
a, b: TArrayOfString;
begin
if Pos(UD2_RUN_AS_ADMIN, line) >= 1 then
result := false;
 
cond.caseSensitive := Pos(CASE_SENSITIVE_FLAG, idName) >= 1;
if cond.caseSensitive then
begin
line := StringReplace(line, UD2_RUN_AS_ADMIN, '', [rfReplaceAll]);
cmd.runAsAdmin := true;
end
else cmd.runAsAdmin := false;
idName := StringReplace(idName, CASE_SENSITIVE_FLAG, '', [rfReplaceAll]);
end;
 
if Pos(UD2_RUN_IN_OWN_DIRECTORY_PREFIX, line) >= 1 then
/// --- Start Dynamic Extension
// xxxxxx ( xxxxx ): xxxxxxxxxxxx
// xxxxx ( xx:xx ): xxxxx:xxx(x)
// xxxxxxxxxxxx : xxxxx(xxx)xx
 
SetLength(a, 0);
a := SplitString('(', idName);
if (Length(a) >= 2) and (Pos(':', a[0]) = 0) then
begin
line := StringReplace(line, UD2_RUN_IN_OWN_DIRECTORY_PREFIX, '', [rfReplaceAll]);
cmd.runInOwnDirectory := true;
end
else cmd.runInOwnDirectory := false;
SetLength(b, 0);
b := SplitString('):', a[1]);
if Length(b) >= 2 then
begin
cond.idMethodName := a[0];
cond.idStr := b[1];
cond.dynamicDataUsed := true;
cond.dynamicData := b[0];
result := true;
Exit;
end;
end;
/// --- End Dynamic Extension
 
cmd.executable := line;
if not result then
begin
a := SplitString(':', idName);
if Length(a) >= 2 then
begin
cond.idMethodName := a[0];
cond.idStr := a[1];
cond.dynamicDataUsed := false;
cond.dynamicData := '';
result := true;
Exit;
end;
end;
end;
 
cmd.windowMode := SW_NORMAL; // TODO (future): make it configurable
function UD2P_ParseConditions(idTerm: string): TUD2TDFConditionArray;
var
cond: TUD2TDFCondition;
x: TArrayOfString;
i, l: integer;
idName: string;
begin
SetLength(x, 0);
x := SplitString('&&', idTerm);
SetLength(result, 0);
for i := Low(x) to High(x) do
begin
idName := x[i];
if UD2P_DecodeCondition(idName, cond) then
begin
l := Length(result);
SetLength(result, l+1);
result[l] := cond;
end;
end;
end;
 
function UD2P_ParseTdfLine(idTermAndCmd: string; var entry: TUD2TDFEntry): boolean;
var
nameVal: TArrayOfString;
idTerm, cmd: string;
begin
result := false;
 
// Split conditions and command
nameVal := SplitString('=', idTermAndCmd); // TODO: problem... "=" could be inside dynamicData...
if Length(nameVal) < 2 then exit;
idTerm := nameVal[0];
cmd := nameVal[1];
 
// Decode conditions
entry.ids := UD2P_ParseConditions(idTerm);
 
// Decode command
SetLength(entry.commands, 1);
entry.commands[0] := UD2P_DecodeCommand(cmd);
 
result := true;
end;
 
/trunk/UserDetect2/UD2_TaskProperties.pas
37,7 → 37,7
{$R *.dfm}
 
uses
UD2_Utils, UD2_Main, ShellAPI;
UD2_Utils, UD2_Main, UD2_Parsing, ShellAPI;
 
procedure TUD2TaskPropertiesForm.LoadExecutableFilesList;
resourcestring
44,31 → 44,30
LNG_RIOD = 'Run in own directory';
LNG_ADMIN = 'Run as admin';
var
sl: TStringList;
i: integer;
cmdLine, flags: string;
flags: string;
cmds: TUD2CommandArray;
cmd: TUD2Command;
begin
//fud2.GetCommandList(AShortTaskName, ListBox1.Items);
ListBox1.Clear;
sl := TStringList.Create;
try
fud2.GetCommandList(FShortTaskName, sl);
for i := 0 to sl.Count-1 do
cmds := fud2.GetCommandList(FShortTaskName);
 
for i := Low(cmds) to High(cmds) do
begin
cmdLine := sl.Strings[i];
cmd := cmds[i];
 
flags := '';
 
if Pos(UD2_RUN_AS_ADMIN, cmdLine) >= 1 then
if cmd.runAsAdmin then
begin
cmdLine := StringReplace(cmdLine, UD2_RUN_AS_ADMIN, '', [rfReplaceAll]);
if flags <> '' then flags := flags + ', ';
flags := flags + LNG_ADMIN;
end;
 
if Pos(UD2_RUN_IN_OWN_DIRECTORY_PREFIX, cmdLine) >= 1 then
if cmd.runInOwnDirectory then
begin
cmdLine := StringReplace(cmdLine, UD2_RUN_IN_OWN_DIRECTORY_PREFIX, '', [rfReplaceAll]);
if flags <> '' then flags := flags + ', ';
flags := flags + LNG_RIOD;
end;
78,12 → 77,9
flags := ' [' + flags + ']';
end;
 
ListBox1.Items.Add(cmdLine + flags);
ListBox1.Items.Add(cmd.executable + flags);
end;
finally
sl.Free;
end;
end;
 
procedure TUD2TaskPropertiesForm.LoadIcon;
var
134,8 → 130,14
end;
 
procedure TUD2TaskPropertiesForm.Button1Click(Sender: TObject);
var
cmd: TUD2Command;
begin
UD2_RunCMD(fud2.IniFileName, SW_NORMAL);
cmd.executable := fud2.IniFileName;
cmd.runAsAdmin := false;
cmd.runInOwnDirectory := false;
cmd.windowMode := SW_NORMAL;
UD2_RunCMD(cmd);
end;
 
end.
/trunk/UserDetect2/UD2_Utils.pas
9,7 → 9,7
{$INCLUDE 'UserDetect2.inc'}
 
uses
Windows, SysUtils, Dialogs, ShellAPI, Classes;
Windows, SysUtils, Dialogs, ShellAPI, Classes, UD2_Parsing;
 
const
EXITCODE_OK = 0;
28,16 → 28,11
IconIndex: integer;
end;
 
const
// Prefixes for UD2_RunCmd()
UD2_RUN_IN_OWN_DIRECTORY_PREFIX = '$RIOD$';
UD2_RUN_AS_ADMIN = '$ADMIN$';
 
function SplitString(const aSeparator, aString: string; aMax: Integer = 0): TArrayOfString;
function BetterInterpreteBool(str: string): boolean;
function GetOwnCmdName: string;
function ExpandEnvStr(const szInput: string): string;
procedure UD2_RunCMD(cmdLine: string; WindowMode: integer=SW_NORMAL);
procedure UD2_RunCMD(cmd: TUD2Command);
function SplitIconString(IconString: string): TIconFileIdx;
// function GetHTML(AUrl: string): string;
procedure VTS_CheckUpdates(VTSID, CurVer: string);
198,7 → 193,7
end;
end;
 
procedure UD2_RunCMD(cmdLine: string; WindowMode: integer=SW_NORMAL);
procedure UD2_RunCMD(cmd: TUD2Command);
// Discussion: http://stackoverflow.com/questions/32802679/acceptable-replacement-for-winexec/32804669#32804669
// Version 1: http://pastebin.com/xQjDmyVe
// --> CreateProcess + ShellExecuteEx
217,6 → 212,7
cmdFile, cmdArgs, cmdDir: string;
p: integer;
sei: TShellExecuteInfo;
cmdLine: string;
begin
// We need a function which does following:
// 1. Replace the Environment strings, e.g. %SystemRoot%
226,7 → 222,7
// 5. Runs non-EXE files (e.g. "Letter.doc")
// 6. Commands with white spaces (e.g. "C:\Program Files\xyz.exe") must be enclosed in quotes.
 
cmdLine := ExpandEnvStr(cmdLine);
cmdLine := ExpandEnvStr(cmd.executable);
 
// Split command line from argument list
if Copy(cmdLine, 1, 1) = '"' then
262,17 → 258,13
 
ZeroMemory(@sei, SizeOf(sei));
 
if Pos(UD2_RUN_AS_ADMIN, cmdLine) >= 1 then
if cmd.runAsAdmin then
begin
cmdLine := StringReplace(cmdLine, UD2_RUN_AS_ADMIN, '', [rfReplaceAll]);
 
sei.lpVerb := 'runas';
end;
 
if Pos(UD2_RUN_IN_OWN_DIRECTORY_PREFIX, cmdLine) >= 1 then
if cmd.runInOwnDirectory then
begin
cmdLine := StringReplace(cmdLine, UD2_RUN_IN_OWN_DIRECTORY_PREFIX, '', [rfReplaceAll]);
 
cmdFile := ExtractFileName(cmdLine);
cmdDir := ExtractFilePath(cmdLine);
end
289,7 → 281,7
{$ENDIF}
if cmdArgs <> '' then sei.lpParameters := PChar(cmdArgs);
if cmdDir <> '' then sei.lpDirectory := PChar(cmdDir);
sei.nShow := WindowMode;
sei.nShow := cmd.windowMode;
if ShellExecuteEx(@sei) then Exit;
{$IFNDEF PREFER_SHELLEXECUTEEX_MESSAGES}
if not CheckLastOSCall(false) then ExitCode := EXITCODE_RUN_FAILURE;
474,16 → 466,18
end;
 
function IndexOf_CS(aStrings: TStrings; aToken: String): Integer;
// Source: http://www.delphipraxis.net/888928-post15.html
var
i : Integer;
begin
Result := -1;
for i := 0 to aStrings.Count do
if aStrings[i]=aToken then begin
for i := 0 to aStrings.Count-1 do
begin
if aStrings[i] = aToken then
begin
Result := i;
Break;
end;
end;
end;
 
end.