Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите с anonymous pipes, Оболочка для консольного приложения 
:(
    Опции темы
dbondar
Дата 18.6.2006, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 18.6.2006

Репутация: нет
Всего: нет



Доброго времени суток!

Дано: программа cmd.exe к примеру, необходимо написать оболочку к ней на C++ Builder, чтобы ст.вывод выводить в Мемо, а ст.ввод брать из Edit.
Написал класс, приведенный ниже (точнее переделал взятый с форума). После нажатия кнопки СТАРТ произходит запуск дочернего процесса Pipes::Start(); и запуск 1 секундного таймера, по истечению которого производится Pipes::Read; и занесение в Мемо.
Также имеется Edit. При вводе в него текста производится передача его по трубе к cmd.exe (Pipes::Write("command");).

Собственно проблема: при запуске приложения и при старте дочернего процесса производится занесение информации в Мемо, затем в Edit пишу ping localhost [Enter] - крастоа! Работает! Еще раз пишу ту же строку - вот теперь выводиться в Мемо надпись "Продолжить?" и все. Если еще что нибуть отправить дочернему процессу, то он закроется.

Помогите найти ошибку, уважаемые коллеги. Буду всем очень благодарен!

Pipes.cpp:
Код

#define bzero(a) memset(a,0,sizeof(a))

Pipes::Pipes()
{
    Started = false;
}

void Pipes::Start(String Param)
{
  try
  {
    if (this->IsWinNT())
    {
      InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
      SetSecurityDescriptorDacl(&sd, true, NULL, false);
      sa.lpSecurityDescriptor = &sd;
    } else sa.lpSecurityDescriptor = NULL;

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = true;

    // Ñîçäàåì òðóáó STDIN
    if (!CreatePipe(&newstdin,&write_stdin,&sa,0))
    throw Exception("Íå óäàëîñü ñîçäàòü òðóáó STDIN");

    // Ñîçäàåì òðóáó STDOUT
    if (!CreatePipe(&read_stdout,&newstdout,&sa,0))
    {
      CloseHandle(newstdin);
      CloseHandle(write_stdin);
      throw Exception("Íå óäàëîñü ñîçäàòü òðóáó STDOUT");
    }

    GetStartupInfo(&si);
    si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    si.hStdOutput = newstdout;
    si.hStdError = newstdout;
    si.hStdInput = newstdin;

    char *app_spawn = "c:\\windows\\system32\\cmd.exe";

    //ñîçäàåì äî÷åðíèé ïðîöåññ
    if (!CreateProcess(NULL,app_spawn,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
    {
      CloseHandle(newstdin);
      CloseHandle(newstdout);
      CloseHandle(read_stdout);
      CloseHandle(write_stdin);
      throw Exception("Íå óäàëîñü ñîçäàòü äî÷åðíèé ïðîöåññ " + (String) app_spawn);
    }

    exit = 0;
    bzero(buf);
    MainForm->RefreshTimer->Enabled = true;
    Started = true;
  }
  catch(Exception &E)
  {
    Started = false;
    MainForm->RefreshTimer->Enabled = false;
    ShowMessage(E.Message);
  }
}

bool Pipes::IsWinNT()
{
  OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  GetVersionEx(&osv);
  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}


bool Pipes::Write(String Data)
{
  try
  {
    if(Data.IsEmpty()) return 1;
    bzero(buf);
    StrCopy(buf, (Data+"\r\n").c_str());
    WriteFile(write_stdin,buf,sizeof(buf),&bread,NULL);
    return 1;
  }
  catch(...)
  {
    return 0;
  }
}

String Pipes::Read()
{
  try
  {
    if(!Started) throw Exception("Server is NOT STARTED");
    String Line;
    GetExitCodeProcess(pi.hProcess, &exit);
    if (exit != STILL_ACTIVE) throw Exception("Server is DEAD");
    PeekNamedPipe(read_stdout, buf, 1023, &bread, &avail, NULL);

    //Ïðîâåðÿåì, åñòü ëè äàííûå äëÿ ÷òåíèÿ â stdout
    if (bread != 0)
    {
      bzero(buf);
      if (avail > 1023)
      {
        while (bread >= 1023)
        {
          ReadFile(read_stdout,buf,1023,&bread,NULL);
          OemToAnsi(buf, buf);
          Line = buf;
          bzero(buf);
        }
      }
      else
      {
        ReadFile(read_stdout,buf,1023,&bread,NULL);
        OemToAnsi(buf, buf);
        Line = buf;
      }
    // Ýòî òàê âûðàâíèâàåì êîíåö ñòðîêè è âîçâðàò êîðåòêè (äëÿ ðàçíûõ ïðèëîæåíèé)
    Line = AnsiReplaceStr(Line, "\r\n", "\n");
    Line = AnsiReplaceStr(Line, "\n", "\r\n");
    return Line;
    }
  }
  catch(Exception &E)
  {
    this->Stop();
    MainForm->RefreshTimer->Enabled = false;
    ShowMessage("READ: " + E.Message);
  }
}

void Pipes::Stop()
{
  this->Write("exit");
  WaitForSingleObject(pi.hProcess, INFINITE);
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(newstdin);
  CloseHandle(newstdout);
  CloseHandle(read_stdout);
  CloseHandle(write_stdin);
  MainForm->RefreshTimer->Enabled=false;
}
//---------------------------------------------------------------------------


Pipes.hpp:
Код

class Pipes {
    public:
        Pipes();
        void Start(String Param);
        void Stop();
        bool Write(String Data);
        String Read();
    private:
        bool Started;
        bool IsWinNT();
        unsigned long exit;
        unsigned long bread;
        unsigned long avail;
        char buf[1024];
        HANDLE newstdin,newstdout,read_stdout,write_stdin;
        STARTUPINFO si;
        SECURITY_ATTRIBUTES sa;
        SECURITY_DESCRIPTOR sd;
        PROCESS_INFORMATION pi;
};
 
PM MAIL   Вверх
dumb
Дата 18.6.2006, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



    WriteFile(write_stdin,buf,strlen(buf),&bread,NULL);
 
PM MAIL   Вверх
dbondar
Дата 18.6.2006, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 18.6.2006

Репутация: нет
Всего: нет



Сапсибо, с Вашей помощью нашел ошибку! Действительно. У меня же массив из 1024 символов!!! smile 
Вот так всегда. Зациклишься на одном месте и все тут.

Возникла очередная проблема:
С cmd.exe все в порядке, а вот приложение, для которого пренадназначалась оболочка работать отказывается! Дело в том, что это консольное приложение генерит свой курсор и постоянную строку вверху консоли. У меня не получается передать консоли нужные мне команды. Консольное приложение их просто игнорирует. Как быть, не подскажите? 
PM MAIL   Вверх
dumb
Дата 19.6.2006, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



узнать как именно работает с консолью управляемое приложение. 
PM MAIL   Вверх
dbondar
Дата 19.6.2006, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 18.6.2006

Репутация: нет
Всего: нет



Значит обнаружилось следующее:
В обычном консольном приложении (cmd.exe) при нажатии клавиши производится немедленный вывод символа и затем автоповтор пока не отпустишь.
В консольном приложении, под которое пишу оболочку несколько иначе. Нажимаешь клавишу - символ не выводится сколько бы эту клавишу не держать, а вот после отпускания он выводится на экран.
Думаю, что из-за того, что в этом консольном приложении раз в секунду производится вывод информации в верхнюю строку консоли (которую я своей программой не ловлю почемуто), то и опрос клавиатуры сделан каим-то особым способом.
Попутный вопрос: как можно запустить дочерний процесс (как в коде выше) так, чтобы его окно небыло скрыто, а отображалось одновременно с моей оболочкой. Это решит ряд вопросов.
Спасибо. 
PM MAIL   Вверх
dumb
Дата 19.6.2006, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



похоже, твое приложение работает не с stdin/stdout, а напрямую, через консольные функции. простым перенаправлением, соответственно, не отделаешься. чем "отделываться" я не подскажу - не в теме, сорри. 
PM MAIL   Вверх
dbondar
Дата 19.6.2006, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 18.6.2006

Репутация: нет
Всего: нет



dumb, большое Вам спасибо. Проверьте пожалуйста почту. 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0778 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.