Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Заново переписал Просьба оценить "корявость кода" v2


Страницы:   1 2

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;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо