Hallo Leute,
ich habe mal ein bisschen ggegoogelt und gelesen, aber nicht wirklich eine Lösung für mein Problem gefunden.
ZUm Programm:
Ich bin gerade dabei ein Programm zu schreiben, welches nacheinander verschiedene Befehle ausführen soll, ähnlich wie eine Batchdatei.
Dabei sollen allerdings die Ereignise, die in dem cmd-Fenster erscheinen auch in ein Memo geschrieben werden als Logbuch.
Nun habe ich das Problem, das bei einer Abfolge von Befehlen ein Fehler kommt:
Code:
Systemfehler. Code:6.
Das
Handle ist ungültig.
Der Fehler tritt in folgendem Code auf:
Delphi-Quellcode:
function Tfmain.installcwm:Boolean;
begin
fmain.RunCaptured(ExtractFilePath(Application.Exename), 'adb', 'reboot bootloader');
Delay(500);
flog.log.Lines.Add('reboot into bootloader');
flog.log.Free;
Delay(500);
fmain.RunCaptured(ExtractFilePath(Application.Exename), 'fastboot', 'flash recovery cwm.img');
flog.log.Lines.Add('install CWM recovery');
flog.log.Free;
Delay(1000); //<-------------------- hier wird der Fehler angezeigt
fmain.RunCaptured(ExtractFilePath(Application.Exename), 'fastboot', 'reboot');
Delay(500);
result := true;
end;
Die Funktion wird durch den Klick eines Buttons aufgerufen:
Delphi-Quellcode:
procedure Tfmain.Button3Click(Sender: TObject);
begin
if installcwm() = true then
begin
showmessage('CWM installed successfully!');
end
else
begin
showmessage('Ann error occur. Please show log and see at your phone.');
end;
end;
Als Funktion zum ausführen der cmd-Befehle verwende ich den Code, den ich irgendwo hier gefunden habe, ich weiß bloß nicht mehr wo
Delphi-Quellcode:
function Tfmain.RunCaptured(const _dirName, _exeName, _cmdLine: string): Boolean;
var
start: TStartupInfo;
procInfo: TProcessInformation;
tmpName: string;
tmp: Windows.THandle;
tmpSec: TSecurityAttributes;
res: TStringList;
return: Cardinal;
i,i2:integer;
begin
Result := False;
try
{ Setze ein Temporäres File }
{ Set a temporary file }
tmpName := 'marvel.tmp';
FillChar(tmpSec, SizeOf(tmpSec), #0);
tmpSec.nLength := SizeOf(tmpSec);
tmpSec.bInheritHandle := True;
tmp := Windows.CreateFile(PChar(tmpName),
Generic_Write, File_Share_Write,
@tmpSec, Create_Always, File_Attribute_Normal, 0);
try
FillChar(start, SizeOf(start), #0);
start.cb := SizeOf(start);
start.hStdOutput := tmp;
start.dwFlags := StartF_UseStdHandles or StartF_UseShowWindow;
start.wShowWindow := SW_Minimize;
{ Starte das Programm }
if CreateProcess(nil, PChar(_exeName + ' ' + _cmdLine), nil, nil, True,
0, nil, PChar(_dirName), start, procInfo) then
begin
SetPriorityClass(procInfo.hProcess, Idle_Priority_Class);
WaitForSingleObject(procInfo.hProcess, Infinite);
GetExitCodeProcess(procInfo.hProcess, return);
Result := (return = 0);
CloseHandle(procInfo.hThread);
CloseHandle(procInfo.hProcess);
Windows.CloseHandle(tmp);
{ Die Ausgaben hinzufügen }
if KillProcess(GetProcessID('adb.exe')) = true then
begin
res := TStringList.Create;
output:='';
try
res.LoadFromFile(tmpName);
for i:= 0 to res.Count-2 do
begin
if res.Strings[i] = '* daemon not running. starting it now *' then
res.Delete(i);
end;
for i:= 0 to res.Count-2 do
begin
if res.Strings[i] = '* daemon started successfully *' then
res.Delete(i);
end;
i:=0;
IF res.Count <> 0 then begin
For i := res.Count - 1 downto 0 do
begin
IF res.Strings[i] = '' then
res.Delete(i);
end;
end;
flog.log.Lines.AddStrings(res);
output:=res.Text;
finally
res.Free;
end;
end;
Windows.DeleteFile(PChar(tmpName));
end
else
begin
Application.MessageBox(PChar(SysErrorMessage(GetLastError())),
'RunCaptured Error', MB_OK);
end;
except
Windows.CloseHandle(tmp);
Windows.DeleteFile(PChar(tmpName));
raise;
end;
finally
end;
end;
Da die adb.exe als Service gestartet wird, muss ich vorher den Prozess beenden, bevor ich wieder Zugriff auf die marvel.tmp habe. Dazu verwende ich folgenden Code:
Delphi-Quellcode:
function tfmain.KillProcess(dwProcID: DWORD):Boolean;
var
hProcess : Cardinal;
dw : DWORD;
begin
{ open the process and store the process-handle }
hProcess := OpenProcess(SYNCHRONIZE
or PROCESS_TERMINATE, False, dwProcID);
{ kill it }
TerminateProcess(hProcess, 0);
{ TerminateProcess returns immediately, so wie have to verify the result via
WaitfForSingleObject }
dw := WaitForSingleObject(hProcess, 5000);
case dw
of
WAIT_OBJECT_0: result:=true;
{ process could not be terminated after 5 seconds }
WAIT_TIMEOUT:
begin
Messagebox(Application.Handle, '
Prozess konnte nicht innerhalb von 5 Sekunden beendet werden.',
'
Prozess beenden', MB_ICONSTOP);
result:=false;
CloseHandle(hProcess);
exit;
end;
{ error in calling WaitForSingleObject }
WAIT_FAILED:
begin
RaiseLastOSError;
CloseHandle(hProcess);
exit;
end;
end;
CloseHandle(hProcess);
end;
Nun weiß ich nicht wirklich wo denn der Fehler ist. Laut meiner Auffassung müsste es gehen. Hat von euch noch jemand Lösungsansätze?
Danke schon mal im voraus.