![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Заново переписал Просьба оценить "корявость кода" v2
AlexeyTG © (2014-12-19 20:25:00)Не стал в тупую копировать куски кода и т.п. как вчера когда быстро нахрапом хотел сделать. Сел почитал, написал заново код. Пожалуйста, гляньте насколько он в данный момент "нормальный"
program Project1;
uses
Vcl.Forms, Winapi.Windows, System.SysUtils;
Var
StartInf: TStartupInfo;
ProcInf: TProcessInformation;
CmdLine: String;
{$R *.res}
function RunApp (const ProgName, ProgParams: String): boolean;
begin
ZeroMemory(@StartInf,sizeof(StartInf));
StartInf.cb:=SizeOf(StartInf);
CmdLine:=Format('"%s" %s', [ProgName, ProgParams]);
Result:=CreateProcess(PChar(ProgName),Pchar(CmdLine),nil,nil,False,NORMAL_PRIORI TY_CLASS,nil,nil,StartInf,ProcInf);
end;
begin
If RunApp('C:\Windows\System32\cmd.exe','/?') then
begin
CloseHandle(ProcInf.hThread);
WaitForSingleObject(ProcInf.hProcess, INFINITE );
CloseHandle(ProcInf.hProcess);
RunApp('C:\Windows\System32\notepad.exe','D:\1.txt');
CloseHandle(ProcInf.hThread);
CloseHandle(ProcInf.hProcess);
Application.Terminate;
end;
end.
AlexeyTG (2014-12-19 22:58:00) [1]Rouse_ОК, спаисбо большое за заве ВРЕМЯ прежде всего :)
___ Постараюсь на основе этого кода переписать свой, т.к. по этому в случае если файл не найдет, то ошибка приложения, а не просто выход :)
Rouse_ (2014-12-19 22:42:00) [2]
> только CloseHandle перенесены в функцию?
Угу.
> и второй вопрос RaiseLastOSError что делает? :)
Поднимает исключение на основе кода последней ошибки
> А Win32Check что такое?
проверяет код возврата и если что-то не так, вызывает RaiseLastOSError.
Усе - убежал, по остальным вопросам читай справку, там все есть :)
AlexeyTG (2014-12-19 22:35:00) [3]Ну и CreateProcess по другому вызывается.
А Win32Check что такое?
AlexeyTG (2014-12-19 22:32:00) [4]Rouse_Да, спасибо ОГРОМНОЕ за Вашу помощь.
Просто уже для общего развития, получается почти тот же код, что я в первом сообщении написал, только CloseHandle перенесены в функцию?
и второй вопрос RaiseLastOSError что делает? :)
Rouse_ (2014-12-19 22:25:00) [5]Ну надеюсь все понятно?
А то хочется уже расслабится в пятницу то :)
Rouse_ (2014-12-19 22:19:00) [6]Ну тогда перепиши код запуска вот так (анализ кода возврата как я понял тебе не нужен):
program Project1;
{$R *.res}
uses
Windows,
SysUtils;
function ExecAndWait(const ExeName, Params: string; out ExitCode: Cardinal; Timeout: Cardinal = MaxInt): boolean;
var
sui: TStartupInfo;
pi: TProcessInformation;
begin
ZeroMemory(@sui, SizeOf(sui));
sui.cb := SizeOf(sui);
Win32Check(CreateProcess(nil, PChar('"' + ExeName + '" ' + Params), nil, nil, False, 0, nil,
nil, sui, pi));
try
CloseHandle(pi.hThread);
Result := WaitForSingleObject(pi.hProcess, Timeout) = WAIT_OBJECT_0;
if Result and (@ExitCode <> nil) then
Win32Check(GetExitCodeProcess(pi.hProcess, ExitCode));
finally
CloseHandle(pi.hProcess);
end;
end;
begin
if not ExecAndWait('C:\Windows\System32\cmd.exe','/?', PCardinal(nil)^) then
RaiseLastOSError;
if not ExecAndWait('C:\Windows\System32\notepad.exe','D:\1.txt', PCardinal(nil)^) then
RaiseLastOSError;
end.
Rouse_ (2014-12-19 22:17:00) [7]Конечно - это же консолька :)
Отключи генерацию консоли в настройках линкера и закоментируй директиву {$APPTYPE CONSOLE}, тогда в случае попытки вывода текста в консоль получишь вот такое исключение:
---------------------------
Debugger Exception Notification
---------------------------
Project Project7.exe raised exception class EInOutError with message 'I/O error 105'.
---------------------------
Break Continue Help
---------------------------
AlexeyTG (2014-12-19 22:16:00) [8]Единственно мне же не нужно консольное приложение. Просто нужен ЕХЕшник запускающий два других. Без собственного окошка и вывода данных :) Как писал здесь
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1418843283&n=18
AlexeyTG (2014-12-19 22:13:00) [9]Сорри, дошло :) поменял cmd на другой ЕХЕшник
AlexeyTG (2014-12-19 22:11:00) [10]Rouse_ © Выстрадал готовый исходник называется :D
Что-то при запуске этого варианта проблемка. Он прям в себе открывает CMD, и после нескольких нажатий клавиши (прокрутка текста справки) в этом же окошке пишет
Специальные символы, которые требуют обязательного заключения в кавычки:
&()[]{}^=;!'+,`~
Wrong exit code: 1
и запускает блокнот
Rouse_ (2014-12-19 22:04:00) [11]Не правильный :)
Делай так:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
SysUtils;
function ExecAndWait(const ExeName, Params: string; out ExitCode: Cardinal; Timeout: Cardinal = MaxInt): boolean;
var
sui: TStartupInfo;
pi: TProcessInformation;
begin
ZeroMemory(@sui, SizeOf(sui));
sui.cb := SizeOf(sui);
Win32Check(CreateProcess(nil, PChar('"' + ExeName + '" ' + Params), nil, nil, False, 0, nil,
nil, sui, pi));
try
CloseHandle(pi.hThread);
Result := WaitForSingleObject(pi.hProcess, Timeout) = WAIT_OBJECT_0;
if Result and (@ExitCode <> nil) then
Win32Check(GetExitCodeProcess(pi.hProcess, ExitCode));
finally
CloseHandle(pi.hProcess);
end;
end;
var
ExitCode: Cardinal;
begin
try
if not ExecAndWait('C:\Windows\System32\cmd.exe','/?', ExitCode) then
RaiseLastOSError;
if ExitCode <> 0 then
Writeln('Wrong exit code: ', ExitCode);
if not ExecAndWait('C:\Windows\System32\notepad.exe','D:\1.txt', ExitCode) then
RaiseLastOSError;
if ExitCode <> 0 then
Writeln('Wrong exit code: ', ExitCode);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
AlexeyTG (2014-12-19 21:56:00) [12]Такой вариант правильный?
AlexeyTG (2014-12-19 21:55:00) [13]
program Project1;
uses
Vcl.Forms, Winapi.Windows, System.SysUtils;
Var
StartInf: TStartupInfo;
ProcInf: TProcessInformation;
CmdLine: String;
Timeout:Cardinal;
{$R *.res}
// Обычный запуск процесса и ожидание его завершения
function ExecAndWait(const ExeName, Params: string; out ExitCode: Cardinal; Timeout: Cardinal = MaxInt): boolean;
var
sui: TStartupInfo;
pi: TProcessInformation;
begin
ZeroMemory(@sui, SizeOf(sui));
sui.cb := SizeOf(sui);
Win32Check(CreateProcess(nil, PChar('"' + ExeName + '" ' + Params), nil, nil, False, 0, nil,
nil, sui, pi));
try
CloseHandle(pi.hThread);
Result := WaitForSingleObject(pi.hProcess, Timeout) = WAIT_OBJECT_0;
if Result and (@ExitCode <> nil) then
Win32Check(GetExitCodeProcess(pi.hProcess, ExitCode));
finally
CloseHandle(pi.hProcess);
end;
end;
begin
If ExecAndWait ('C:\Windows\System32\cmd.exe','/?', Timeout) then
ExecAndWait ('C:\Windows\System32\notepad.exe','D:\1.txt', Timeout) else
Application.Terminate;
end.
AlexeyTG (2014-12-19 21:51:00) [14]
var
ExitCode: Cardinal;
if ExecAndWait('CMD.EXE','/?',ExitCode)then
AlexeyTG (2014-12-19 21:45:00) [15]Прочитал что такое Cardinal :) Не могу разобраться. Можете ткнуть прямые строки кода пример вызова и что дописать :(
Rouse_ (2014-12-19 21:37:00) [16]Ну и ExitCode: Cardinal задекларируй, его и передавай.
AlexeyTG (2014-12-19 21:34:00) [17]if ExecAndWait('C:\Windows\System32\cmd.exe','/?',
а остальные параметры что указать? :(
Rouse_ (2014-12-19 21:21:00) [18]
> Получается так?
Не так - кавычки не там стоят.
> опять же прочитал, что после нее высвобождает ресурсы из
> памяти.
Она и так освободится - не надо настолько грубо управлять работой приложения.
> а как тогда? :(
Возьму любую из приведенных мной функций и используй ее для вызова.
AlexeyTG (2014-12-19 21:15:00) [19]Rouse_ ©
Заключи в кавычки путь к ПО, об этом написано как в MSDN так и с приведенной тобой статье
> Забываем про кавычки или ставим лишние. Кавычки нужны в
> командной строке (второй параметр CreateProcess) и не нужны
> в имени модуля (первый параметр).
If RunApp('C:\Windows\System32\cmd.exe',' "/? "') then
RunApp('C:\Windows\System32\notepad.exe',' "D:\1.txt "');
Получается так?
Да и вообще убери Application.Terminate - зачем он тут тебе? -> опять же прочитал, что после нее высвобождает ресурсы из памяти.
> > так нормально будет? :)
>
> Нет, конечно :)
а как тогда? :(
Rouse_ (2014-12-19 21:11:00) [20]Лови три варианта запуска, покури над ними:
// Обычный запуск процесса и ожидание его завершения
function ExecAndWait(const ExeName, Params: string; out ExitCode: Cardinal; Timeout: Cardinal = MaxInt): boolean;
var
sui: TStartupInfo;
pi: TProcessInformation;
begin
ZeroMemory(@sui, SizeOf(sui));
sui.cb := SizeOf(sui);
Win32Check(CreateProcess(nil, PChar('"' + ExeName + '" ' + Params), nil, nil, False, 0, nil,
nil, sui, pi));
try
CloseHandle(pi.hThread);
Result := WaitForSingleObject(pi.hProcess, Timeout) = WAIT_OBJECT_0;
if Result and (@ExitCode <> nil) then
Win32Check(GetExitCodeProcess(pi.hProcess, ExitCode));
finally
CloseHandle(pi.hProcess);
end;
end;
// Запуск и ожидание с поддержкой процессов с админским манифестом
function ExecAndWaitElevate(const ExeName, Params: string; out ExitCode: Cardinal; Timeout: Cardinal = MaxInt): boolean;
var
SEI: TShellExecuteInfo;
begin
ZeroMemory(@SEI, SizeOf(TShellExecuteInfo));
SEI.cbSize := SizeOf(TShellExecuteInfo);
SEI.lpFile := PChar(ExeName);
SEI.lpParameters := PChar(Params);
SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
SEI.nShow := SW_SHOWNORMAL;
Win32Check(ShellExecuteEx(@SEI));
try
Result := WaitForSingleObject(SEI.hProcess, Timeout) = WAIT_OBJECT_0;
if Result and (@ExitCode <> nil) then
Win32Check(GetExitCodeProcess(SEI.hProcess, ExitCode));
finally
CloseHandle(SEI.hProcess);
end;
end;
// Запуск процесса с поднятием прав до админа
function ExecAndWaitElevate2(const ExeName, Params: string; out ExitCode: Cardinal; Timeout: Cardinal = MaxInt): boolean;
var
SEI: TShellExecuteInfo;
begin
ZeroMemory(@SEI, SizeOf(TShellExecuteInfo));
SEI.cbSize := SizeOf(TShellExecuteInfo);
SEI.lpFile := PChar(ExeName);
SEI.lpDirectory := PChar(ExtractFilePath(ExeName));
SEI.lpParameters := PChar(Params);
SEI.lpVerb := PChar('runas');
SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
SEI.nShow := SW_SHOWNORMAL;
Win32Check(ShellExecuteEx(@SEI));
try
Result := WaitForSingleObject(SEI.hProcess, Timeout) = WAIT_OBJECT_0;
if Result and (@ExitCode <> nil) then
Win32Check(GetExitCodeProcess(SEI.hProcess, ExitCode));
finally
CloseHandle(SEI.hProcess);
end;
end;