На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Результат выполнения командной строки , Получить результат от cmd процесса
    Уважаемые программисты! Есть такая беда: я выполняю функцией WinExec() (понимаю, что можно через Pipe, но как? <_< ) некоторые команды командной строки Windows XP, например:
    WinExec('cmd /c SystemInfo', 1);
    В результате данная командная строка выводит кучу полезных даных о компе.

    Как получить эти данные в своей программе и поместить их, например, в Мемо?
      Цитата Jetus @
      что можно через Pipe, но как?

      Переопределением stdin,stdout.

      Добавлено
      Использование anonymous pipes для перехвата StdIn/StdOut дочернего процесса

      Как получить содержимое DOS окна?

      Добавлено
      Цитата Jetus @
      В результате данная командная строка выводит кучу полезных даных о компе

      Эти данные можно получить и другими способами.
        То, что надо переопределять stdout, то это ясно.
        Я имел в виду, что ищу НОРМАЛЬНО РАБОТОСПОСОБНЫЙ пример на ДЕЛЬФИ, как это все осуществить.

        Есть такой вот пример:

        ExpandedWrap disabled
          Function GetDosOutput( const CommandLine, WorkDir: String; var
          ResultCode: Cardinal ): String;
          var StdOutPipeRead, StdOutPipeWrite: THandle;
             SA                             : TSecurityAttributes;
             SI                             : TStartupInfo;
             PI                             : TProcessInformation;
             WasOK                          : Boolean;
             Buffer                         : array[0..255] of Char;
             BytesRead                      : Cardinal;
             Line                           : String;
          Begin
             //Application.ProcessMessages;
             With SA do
             Begin
                nLength := SizeOf( SA );
                bInheritHandle := True;
                lpSecurityDescriptor := nil;
             end;
             // создаём пайп для перенаправления стандартного вывода
             CreatePipe( StdOutPipeRead,  // дескриптор чтения
                         StdOutPipeWrite, // дескриптор записи
                         @SA,              // аттрибуты безопасности
                         0                // количество байт принятых для пайпа - 0 по умолчанию
                        );
             try
              // Создаём дочерний процесс, используя StdOutPipeWrite в качестве стандартного вывода,
              // а так же проверяем, чтобы он не показывался на экране.
              with SI do
              Begin
                 FillChar( SI, SizeOf( SI ), 0 );
                 cb := SizeOf( SI );
                 dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
                 wShowWindow := SW_HIDE;
                 hStdInput := GetStdHandle( STD_INPUT_HANDLE ); // стандартный ввод не перенаправляем
                 hStdOutput := StdOutPipeWrite;
                 hStdError := StdOutPipeWrite;
              end;
           
              //Запускаем компилятор из командной строки
              //WorkDir := ExtractFilePath(CommandLine);
              WasOK := CreateProcess( nil,
                                      PChar( CommandLine ),
                                      nil,
                                      nil,
                                      True,
                                      0,
                                      nil,
                                      PChar( WorkDir ),
                                      SI,
                                      PI );
              // Теперь, когда дескриптор получен, для безопасности закрываем запись.
              // Нам не нужно, чтобы произошло случайное чтение или запись.
              CloseHandle( StdOutPipeWrite );
              // если процесс может быть создан, то дескриптор, это его вывод
              if not WasOK then
               raise Exception.Create( 'Ошибка выполнения или компиляции: ' +
                      Chr( 10 ) + Chr( 13 ) + CommandLine )
              else
                try
                  // получаем весь вывод до тех пор, пока DOS-приложение не будет завершено
                  Line := '';
                  Repeat
                     // читаем блок символов (могут содержать возвраты каретки и переводы строки)
                     WasOK := ReadFile( StdOutPipeRead, Buffer, 255, BytesRead, nil );
                     // есть ли что-нибудь ещё для чтения?
                     if BytesRead > 0 then
                     Begin
                        // завершаем буфер PChar-ом
                        Buffer[BytesRead] := #0;
                        // добавляем буфер в общий вывод
                        Line := Line + Buffer;
                     end;
                     //Application.ProcessMessages;
                  Until not WasOK or ( BytesRead = 0 );
                  // ждём, пока завершится консольное приложение
                  WaitForSingleObject( PI.hProcess, INFINITE );
                  ResultCode := 0;
                  GetExitCodeProcess( PI.hProcess, ResultCode );
                finally
                  // Закрываем все оставшиеся дескрипторы
                  CloseHandle( PI.hThread );
                  CloseHandle( PI.hProcess );
                end;
             finally
               Result := Line;
               CloseHandle( StdOutPipeRead );
           end;
          end;


        Использовать так:

        ExpandedWrap disabled
          Memo1.Lines.Text := GetDosOutput( 'del c:\*.*', 'c:\', Rc );


        Код, к сожалению, выдает ошибку в строке:

        ExpandedWrap disabled
          if not WasOK then
               raise Exception.Create( 'Ошибка выполнения или компиляции: ' +
                      Chr( 10 ) + Chr( 13 ) + CommandLine )
          Цитата Jetus @
          WinExec('cmd /c SystemInfo', 1);

          выполняй то же самое тем же WinExec(), если хочется, но напиши команду вот так:
          ExpandedWrap disabled
            cmd /c SystemInfo > C:\123.txt

          и полюбуйся на содержимое файла C:\123.txt - будет тебе счастье (в DOS-кодировке)
            Mischka, я не настолько тупой, как ты думаешь! <_<

            cmd /c SystemInfo > C:\123.txt - это давно всем известно, а вот как обойтись без файла, создаваемого на винчестере?
              Цитата Jetus @
              Mischka, я не настолько тупой, как ты думаешь!

              я и не считаю тебя тупым. Но в задаче не было сказано, что нужно обойтись без файла ;) Да и чем тебе не нравится временный файл?
                Вот именно этот пример у меня нормально абсолютно отработал.
                А ошибка простая - не правильно передаешь параметры в функцию.
                К примеру вот правильный вариант:
                ExpandedWrap disabled
                  procedure TForm1.Button1Click(Sender: TObject);
                  var
                    RC: Cardinal;
                  begin
                    Memo1.Lines.Text := GetDosOutput( 'cmd /c SystemInfo', 'c:\', Rc );
                  end;

                а вот вариант с ошибкой:
                ExpandedWrap disabled
                  procedure TForm1.Button1Click(Sender: TObject);
                  var
                    RC: Cardinal;
                  begin
                    Memo1.Lines.Text := GetDosOutput( 'cmd /c SystemInfo', '', Rc );
                  end;
                  Огромное спасибо, Rouse! Теперь все тип-топ! ;)

                  Тебе, Mischka, тоже спасибо!
                    Мужики, а я попробовал, но у меня все исполняется, но консоль создается, разворачивается на весь экран и пофигу ей SW_HIDE :blink:
                      Короче, если поставить вот такие параметры то стопроцентно все пучком:

                      ExpandedWrap disabled
                            with SI do
                        ...
                                 wShowWindow := SW_HIDE or SW_SHOWMINNOACTIVE;
                        ...
                            end;
                        А у тебя какая опреационная система стоит? Потому что я на ХР Pro пробовал и там все "пряталось" :)
                        И ещё. Кому єта тема ещё интересна. Есть еще такой вот вариант выполнить ту же задачу:

                        ExpandedWrap disabled
                          const
                            H_IN_READ = 1;
                            H_IN_WRITE = 2;
                            H_OUT_READ = 3;
                            H_OUT_WRITE = 4;
                            H_ERR_READ = 5;
                            H_ERR_WRITE = 6;
                           
                          type
                            TPipeHandles = array [1..6] of THandle;
                          var
                            hPipes: TPipeHandles;
                            ProcessInfo: TProcessInformation;
                            Form1: TForm1;
                           
                          . . . . .
                           
                          (************CREATE HIDDEN CONSOLE PROCESS************)
                          function CreateHiddenConsoleProcess(szChildName: string;
                                   ProcPriority: DWORD; ThreadPriority: integer): Boolean;
                          label
                            error;
                          var
                            fCreated: Boolean;
                            si: TStartupInfo;
                            sa: TSecurityAttributes;
                          begin
                            // Initialize handles
                            hPipes[ H_IN_READ ] := INVALID_HANDLE_VALUE;
                            hPipes[ H_IN_WRITE ] := INVALID_HANDLE_VALUE;
                            hPipes[ H_OUT_READ ] := INVALID_HANDLE_VALUE;
                            hPipes[ H_OUT_WRITE ] := INVALID_HANDLE_VALUE;
                            hPipes[ H_ERR_READ ] := INVALID_HANDLE_VALUE;
                            hPipes[ H_ERR_WRITE ] := INVALID_HANDLE_VALUE;
                            ProcessInfo.hProcess := INVALID_HANDLE_VALUE;
                            ProcessInfo.hThread := INVALID_HANDLE_VALUE;
                            // Create pipes
                            // initialize security attributes for handle inheritance (for WinNT)
                            sa.nLength := sizeof(sa);
                            sa.bInheritHandle := TRUE;
                            sa.lpSecurityDescriptor := nil;
                            // create STDIN pipe
                            if not CreatePipe( hPipes[ H_IN_READ ], hPipes[ H_IN_WRITE ], @sa, 0 ) then
                              goto error;
                            // create STDOUT pipe
                            if not CreatePipe( hPipes[ H_OUT_READ ], hPipes[ H_OUT_WRITE ], @sa, 0 ) then
                              goto error;
                            // create STDERR pipe
                            if not CreatePipe( hPipes[ H_ERR_READ ], hPipes[ H_ERR_WRITE ], @sa, 0 ) then
                              goto error;
                            // process startup information
                            ZeroMemory(Pointer(@si), sizeof(si));
                            si.cb := sizeof(si);
                            si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
                            si.wShowWindow := SW_SHOW;
                            // assign "other" sides of pipes
                            si.hStdInput := hPipes[ H_IN_READ ];
                            si.hStdOutput := hPipes[ H_OUT_WRITE ];
                            si.hStdError := hPipes[ H_ERR_WRITE ];
                            // Create a child process
                            try
                              fCreated := CreateProcess( nil, PChar(szChildName), nil, nil, True,
                              ProcPriority, // CREATE_SUSPENDED,
                              nil, nil, si, ProcessInfo );
                            except
                              fCreated := False;
                            end;
                           
                            if not fCreated then
                              goto error;
                           
                            Result := True;
                            CloseHandle(hPipes[ H_OUT_WRITE ]);
                            CloseHandle(hPipes[ H_ERR_WRITE ]);
                            // ResumeThread( pi.hThread );
                            SetThreadPriority(ProcessInfo.hThread, ThreadPriority);
                            CloseHandle( ProcessInfo.hThread );
                            Exit;
                            //-----------------------------------------------------
                            error:
                              //ClosePipes( hPipes );
                              CloseHandle( ProcessInfo.hProcess );
                              CloseHandle( ProcessInfo.hThread );
                              ProcessInfo.hProcess := INVALID_HANDLE_VALUE;
                              ProcessInfo.hThread := INVALID_HANDLE_VALUE;
                              Result := False;
                          end;


                        А вот как запускать:

                        ExpandedWrap disabled
                          procedure TForm1.Button1Click(Sender: TObject);
                          var
                            OutputStr: TFileStream;
                            OutText  : TStringList;
                          begin
                            CreateHiddenConsoleProcess('cmd /c systeminfo', NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS);
                            Sleep(8000);
                            OutputStr := TFileStream.Create(hPipes[H_OUT_READ]);
                            OutText := TStringList.Create;
                            OutText.LoadFromStream(OutputStr);
                            OutputStr.Free;
                            Memo1.Lines := OutText;
                          end;


                        Понимаю, что испольовать вот так Sleep(8000) - это очень плохой тон, но мне было просто лень дорабатывать программу :whistle:
                          Цитата Jetus @

                          Newbie
                          Профиль · PM



                          А у тебя какая опреационная система стоит?


                          Дык ХР... Видимо просто где-то есть какие-то настройки по запуску консолей, ну типа фулскрин, цвета, размеры буфферов и т.д.


                          По примеру. Ну, а как, например, в консоль, передать строку каку-нить? Например, консоль спрашивает пароль...

                          ЗЫ Вообщем, это мне надо, но раз уж ты разобрался может мне ленивому кинешь примерчик? :rolleyes:

                          Добавлено
                          Все, не надо :)
                            Короче, если кому-то надо. Примерчик с проходом авторизации, если консоль спрашивает пароль:

                            ExpandedWrap disabled
                              Function GetDosOutput( CommandLine, Pass: String; var
                              ResultCode: Cardinal ): String;
                              var StdOutPipeRead, StdOutPipeWrite, StdInPipeRead, StdInPipeWrite: THandle;
                                 SA                             : TSecurityAttributes;
                                 SI                             : TStartupInfo;
                                 PI                             : TProcessInformation;
                                 WasOK                          : Boolean;
                                 Buffer                         : array[0..255] of Char;
                                 PassA                          : array[0..255] of Char;
                                 BytesRead                      : Cardinal;
                                 Line                           : String;
                                 Written                        : DWORD;
                                 Passed                         : boolean;
                              Begin
                                 //Application.ProcessMessages;
                                 With SA do
                                 Begin
                                    nLength := SizeOf( SA );
                                    bInheritHandle := True;
                                    lpSecurityDescriptor := nil;
                                 end;
                                 // создаём пайп для перенаправления стандартного вывода
                                 CreatePipe( StdOutPipeRead,  // дескриптор чтения
                                             StdOutPipeWrite, // дескриптор записи
                                             @SA,              // аттрибуты безопасности
                                             0                // количество байт принятых для пайпа - 0 по умолчанию
                                            );
                                 // создаём пайп для перенаправления стандартного ввода
                                 CreatePipe( StdInPipeRead,  // дескриптор чтения
                                             StdInPipeWrite, // дескриптор записи
                                             @SA,              // аттрибуты безопасности
                                             0                // количество байт принятых для пайпа - 0 по умолчанию
                                            );
                               
                                 try
                                  // Создаём дочерний процесс, используя StdOutPipeWrite в качестве стандартного вывода,
                                  // а так же проверяем, чтобы он не показывался на экране.
                                  with SI do
                                  Begin
                                     FillChar( SI, SizeOf( SI ), 0 );
                                     cb := SizeOf( SI );
                                     dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
                                     wShowWindow := SW_HIDE or SW_SHOWMINNOACTIVE;
                                     hStdInput := StdInPipeRead; //GetStdHandle(STD_INPUT_HANDLE);
                                     hStdOutput := StdOutPipeWrite;
                                     hStdError := StdOutPipeWrite;
                                  end;
                                  Passed := false;
                               
                                  //Запускаем компилятор из командной строки
                                  //WorkDir := ExtractFilePath(CommandLine);
                                  WasOK := CreateProcess( nil,
                                                          PChar( CommandLine ),
                                                          nil,
                                                          nil,
                                                          True,
                                                          0,
                                                          nil,
                                                          nil,
                                                          SI,
                                                          PI );
                               
                                  // если процесс может быть создан, то дескриптор, это его вывод
                                  CloseHandle( StdOutPipeWrite );
                                  if not WasOK then
                                   raise Exception.Create( 'Ошибка выполнения или компиляции: ' +
                                          Chr( 10 ) + Chr( 13 ) + CommandLine )
                                  else
                                    try
                                      // получаем весь вывод до тех пор, пока DOS-приложение не будет завершено
                                      Line := '';
                                      Repeat
                                         // читаем блок символов (могут содержать возвраты каретки и переводы строки)
                                         WasOK := ReadFile( StdOutPipeRead, Buffer, 255, BytesRead, nil );
                                         // есть ли что-нибудь ещё для чтения?
                                         if BytesRead > 0 then
                                         Begin
                                            // завершаем буфер PChar-ом
                                            Buffer[BytesRead] := #0;
                                            // добавляем буфер в общий вывод
                                            Line := Line + Buffer;
                                         end;
                                        If not Passed AND
                                           (Pos('PASSWORD',AnsiUpperCase(Line)) > 0) then
                                          begin
                                            Pass := Pass + #13#10; //добавляем ввод
                                            WasOk := WriteFile(StdinPipeWrite,Pass[1],length(Pass),Written,nil);
                                            Passed := true; //прошли авторизацию
                                          end;
                                         //Application.ProcessMessages;
                                      Until not WasOK or ( BytesRead = 0 );
                                      // ждём, пока завершится консольное приложение
                                      WaitForSingleObject( pi.hProcess, INFINITE );
                                      ResultCode := 0;
                                      GetExitCodeProcess( pi.hProcess, ResultCode );
                                    finally
                                      // Закрываем все оставшиеся дескрипторы
                                      CloseHandle( PI.hThread );
                                      CloseHandle( pi.hProcess );
                                    end;
                                 finally
                                   Result := Line;
                                   CloseHandle( StdOutPipeRead );
                                   CloseHandle( StdInPipeRead );
                                   CloseHandle( StdInPipeWrite );
                               end;
                              end;
                               
                               
                              procedure TForm1.Button1Click(Sender: TObject);
                              Var RC: cardinal;
                              begin
                                Memo1.Text := GetDosOutPut('commandline','password', Rc);
                              end;

                              Как функция поведет себя если надо ввести 2 параметра , ответить на вопросы Y/N и в зависимости от них еще несколько параметров или чегото еще?
                              Например архиватор спрашивает - создать папку,файл уже есть удалить добавить , нет места на диске.....
                              Я не вижу тут диалога , куда выводяться сообщения dos окна?
                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,0546 ]   [ 16 queries used ]   [ Generated: 29.06.25, 14:13 GMT ]