Форум: "Начинающим";
Текущий архив: 2017.01.15;
Скачать: [xml.tar.bz2];
ВнизЗаново переписал Просьба оценить "корявость кода" v2 Найти похожие ветки
← →
AlexeyTG (2014-12-19 20:25) [0]Не стал в тупую копировать куски кода и т.п. как вчера когда быстро нахрапом хотел сделать. Сел почитал, написал заново код. Пожалуйста, гляньте насколько он в данный момент "нормальный"
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.
← →
кгшзх © (2014-12-19 20:34) [1]убрать глобальные переменные
и сделать их праметрами.
← →
Rouse_ © (2014-12-19 20:48) [2]1. Первый параметр, передаваемый CreateProcess избыточен.
2. Это все не сработает на экзешниках от сетаперов от InstallShield, т.е. ты дождешся только завершения работы экзешника, а не того кода, который он запустит далее на исполнение.
3.Если файл, который ты хочешь запустить будет не найден, то CloseHandle под отладчиком сгенерирует ошибку (штатоное поведение на невалидный хэндл в процессе отладки).
4. Как я понял коды возврата будет анализировать Пушкин?
← →
AlexeyTG (2014-12-19 20:55) [3]1. По первому парметру прочитал здесь http://www.gunsmoker.ru/2009/07/createprocess.html
Application := "C:\Program Files\MySoft\MyApp.exe";
Так ошибок не будет никогда (обратите внимание на расстановку кавычек и пробелов). А если вы его не укажете - у вашей программы могут быть серьёзные проблемы с безопасностью. Особенно, если вы не используете кавычки.
Params := "-n:6 /p5 "C:\Program Files\MySoft\Data.bin"";
CmdLine := Format(""%s" %s", [Application, Params]);
CreateProcess(PChar(Application), PChar(CmdLine), ...);
И на другом ресурсе где обсуждали.
2. экзешник не сетапер, простое приложение, именно для него пишется лаунчер, на нем работает вроде нормально.
3, 4 beginIf 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 else Application.Terminate
так нормально будет? :)
← →
AlexeyTG (2014-12-19 20:57) [4]кгшзх вот тут вы меня в тупик поставиили, если их параметрами делать, то какие значения им передавать при вызове функции.
← →
Rouse_ © (2014-12-19 21:04) [5]
> Так ошибок не будет никогда (обратите внимание на расстановку
> кавычек и пробелов). А если вы его не укажете - у вашей
> программы могут быть серьёзные проблемы с безопасностью.
> Особенно, если вы не используете кавычки.
Заключи в кавычки путь к ПО, об этом написано как в MSDN так и с приведенной тобой статье.
> так нормально будет? :)
Нет, конечно :)
Да и вообще убери Application.Terminate - зачем он тут тебе?
← →
Rouse_ © (2014-12-19 21:11) [6]Лови три варианта запуска, покури над ними:
// Обычный запуск процесса и ожидание его завершения
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;
← →
AlexeyTG (2014-12-19 21:15) [7]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:21) [8]
> Получается так?
Не так - кавычки не там стоят.
> опять же прочитал, что после нее высвобождает ресурсы из
> памяти.
Она и так освободится - не надо настолько грубо управлять работой приложения.
> а как тогда? :(
Возьму любую из приведенных мной функций и используй ее для вызова.
← →
AlexeyTG (2014-12-19 21:34) [9]if ExecAndWait("C:\Windows\System32\cmd.exe","/?",
а остальные параметры что указать? :(
← →
Rouse_ © (2014-12-19 21:37) [10]Ну и ExitCode: Cardinal задекларируй, его и передавай.
← →
AlexeyTG (2014-12-19 21:45) [11]Прочитал что такое Cardinal :) Не могу разобраться. Можете ткнуть прямые строки кода пример вызова и что дописать :(
← →
AlexeyTG (2014-12-19 21:51) [12]
var
ExitCode: Cardinal;
if ExecAndWait("CMD.EXE","/?",ExitCode)then
← →
AlexeyTG (2014-12-19 21:55) [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:56) [14]Такой вариант правильный?
← →
Rouse_ © (2014-12-19 22:04) [15]Не правильный :)
Делай так: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 22:11) [16]Rouse_ © Выстрадал готовый исходник называется :D
Что-то при запуске этого варианта проблемка. Он прям в себе открывает CMD, и после нескольких нажатий клавиши (прокрутка текста справки) в этом же окошке пишетСпециальные символы, которые требуют обязательного заключения в кавычки:
<пробел>
&()[]{}^=;!"+,`~
Wrong exit code: 1
и запускает блокнот
← →
AlexeyTG (2014-12-19 22:13) [17]Сорри, дошло :) поменял cmd на другой ЕХЕшник
← →
AlexeyTG (2014-12-19 22:16) [18]Единственно мне же не нужно консольное приложение. Просто нужен ЕХЕшник запускающий два других. Без собственного окошка и вывода данных :) Как писал здесь
http://delphimaster.net/view/2-1418843283/
← →
Rouse_ © (2014-12-19 22:17) [19]Конечно - это же консолька :)
Отключи генерацию консоли в настройках линкера и закоментируй директиву {$APPTYPE CONSOLE}, тогда в случае попытки вывода текста в консоль получишь вот такое исключение:---------------------------
Debugger Exception Notification
---------------------------
Project Project7.exe raised exception class EInOutError with message "I/O error 105".
---------------------------
Break Continue Help
---------------------------
← →
Rouse_ © (2014-12-19 22:19) [20]Ну тогда перепиши код запуска вот так (анализ кода возврата как я понял тебе не нужен):
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:25) [21]Ну надеюсь все понятно?
А то хочется уже расслабится в пятницу то :)
← →
AlexeyTG (2014-12-19 22:32) [22]Rouse_ Да, спасибо ОГРОМНОЕ за Вашу помощь.
Просто уже для общего развития, получается почти тот же код, что я в первом сообщении написал, только CloseHandle перенесены в функцию?
и второй вопрос RaiseLastOSError что делает? :)
← →
AlexeyTG (2014-12-19 22:35) [23]Ну и CreateProcess по другому вызывается.
А Win32Check что такое?
← →
Rouse_ © (2014-12-19 22:42) [24]
> только CloseHandle перенесены в функцию?
Угу.
> и второй вопрос RaiseLastOSError что делает? :)
Поднимает исключение на основе кода последней ошибки
> А Win32Check что такое?
проверяет код возврата и если что-то не так, вызывает RaiseLastOSError.
Усе - убежал, по остальным вопросам читай справку, там все есть :)
← →
AlexeyTG (2014-12-19 22:58) [25]Rouse_ ОК, спаисбо большое за заве ВРЕМЯ прежде всего :)
___ Постараюсь на основе этого кода переписать свой, т.к. по этому в случае если файл не найдет, то ошибка приложения, а не просто выход :)
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2017.01.15;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.049 c