Ввод данных в другое приложение
Вопросик.
Есть готовый ехе-шник DOS приложения (1) и разрабатываемое WIN приложение (2) на Builder. Приложение 2 запускает приложение 1. Приложение (1) DOS ожидает ввода данных (допустим scanf). Вопрос. Как приложением 2 (WIN) ввести данные в DOS приложение.
Есть идеи?
Всем привет.
Вопросик.
Есть готовый ехе-шник DOS приложения (1) и разрабатываемое WIN приложение (2) на Builder. Приложение 2 запускает приложение 1. Приложение (1) DOS ожидает ввода данных (допустим scanf). Вопрос. Как приложением 2 (WIN) ввести данные в DOS приложение.
Есть идеи?
Идея, не уверен, что для DOS-приложения сработает: есть в виндах функция емуляции нажатий клавиш на клавиатуре. keybdevent или keybd_event, что-то около того. Вызывать для окна ДОС-приложения.
Идея, не уверен, что для DOS-приложения сработает: есть в виндах функция емуляции нажатий клавиш на клавиатуре. keybdevent или keybd_event, что-то около того. Вызывать для окна ДОС-приложения.
Не сработает.
Моё приложение открывает bat файл в скрытом режиме (нафик надо чтобы в виндовом приложении мелькало DOS окно, а тем более постоянно запрашивало пароль). Файл bat настраивается пользователем. Вот из файла bat и будет запускаться DOS приложение. Если не ошибаюсь это окно будет не активным. Пробовал fprintf(stdin,...,...); не помогает.
Помогите. Ну срочно надо.
Всем привет.
Вопросик.
Есть готовый ехе-шник DOS приложения (1) и разрабатываемое WIN приложение (2) на Builder. Приложение 2 запускает приложение 1. Приложение (1) DOS ожидает ввода данных (допустим scanf). Вопрос. Как приложением 2 (WIN) ввести данные в DOS приложение.
Есть идеи?
Привет, мне, ноаборот, нужно было передать данные(имя файла) из приложения DOS в моё приложение на Builder. Я создала базу данных и работала с её единственной строкой, в которую записывала это имя, и потом брала его оттуда.
Привет, мне, ноаборот, нужно было передать данные(имя файла) из приложения DOS в моё приложение на Builder. Я создала базу данных и работала с её единственной строкой, в которую записывала это имя, и потом брала его оттуда.
Ну эта задача попроще. Я так понял, что DOS приложение тоже твоё. Тогда просто куча способов передать строку: через временный файл, командной строкой... можно ещё придумать. Не стоит из за такой мелочи пользоваться БД.
Сейчас попробую по ссылке ILS . Должно пойти.
посмотри на
http://www.codenet.ru/progr/bcb/pipes.php
(Если поможет - скажешь :-) - сам не пробовал)
Совсем не пойму, как хотябы *.bat файл запустить CreateProcess -ом.
Так работает,
// spawnle(SW_HIDE, "c:\\command.com","d:\\programs\\CVS_\\tmp.bat", NULL, NULL);
и так работает,// ShellExecute(NULL,"open","d:\\programs\\CVS_\\tmp.bat",NULL,NULL,SW_SHOW);
а так вообще не запускается (и вообще все комбинации поменял)
CreateProcess("c:\\command.com", // No module name (use command line).
"d:\\programs\\CVS_\\tmp.bat", // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
true, // Set handle inheritance to FALSE.
CREATE_NEW_CONSOLE, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
NULL, // Pointer to STARTUPINFO structure.
NULL );// Pointer to PROCESS_INFORMATION structure.
Кто нить сообразит.
CreateProcess("c:\\command.com", // No module name (use command line).
"d:\\programs\\CVS_\\tmp.bat", // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
true, // Set handle inheritance to FALSE.
CREATE_NEW_CONSOLE, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
NULL, // Pointer to STARTUPINFO structure.
NULL );// Pointer to PROCESS_INFORMATION structure.
Кто нить сообразит.
вместо 2-х последних нулевых указателей нужно вставит реальные указатели на реальные структуры (пусть даже в них все по нулям)
У меня это работает примерно так:
if(!OpenDialog1->Execute()) return;
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));
if(CreateProcess(NULL,
OpenDialog1->FileName.c_str(),
NULL,//security
NULL,// security
false,//inherits handles
0,
0,
0,
&si,
&pi)
) CloseHandle(pi.hThread);
else er=GetLastError();
if (strComSpec.IsEmpty()) {
strComSpec = AnsiString(getenv("WINDIR")) + AnsiString("\\command.com");
}
AnsiString strCmd(strComSpec + " /c " + strCommandLine);
hProcess = NULL;
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(sa));
if (IsWinNT()) {
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
sa.lpSecurityDescriptor = &sd;
}
sa.nLength = sizeof(sa);
sa.bInheritHandle = true;
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if (!CreateProcess(NULL, strCmd.c_str(),
NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi )) {
throw Exception("Cannot create process");
}
Bat файл я запустил: путь к command.com в запускаемом файле, а путь к *.bat в командной строке. Но запустить, это не основная цель. Пробовал через пайпы - нет никакой реакции.
Чтой-то я не врубаюсь - а при чем здесь bat?
В предложенном примере пайп строиться между запускающим процессом (в твоем случае Win) и запускаемым/порождаемым (в твоем случае д.б. Dos приложение). А ты, насколько я понял, запускаешь/порождаешь вовсе не свое проиложение(в ктр и нужно вводить данные)...
Чтой-то я не врубаюсь - а при чем здесь bat?
В предложенном примере пайп строиться между запускающим процессом (в твоем случае Win) и запускаемым/порождаемым (в твоем случае д.б. Dos приложение). А ты, насколько я понял, запускаешь/порождаешь вовсе не свое проиложение(в ктр и нужно вводить данные)...
Что то я затупил. Написал, неподумав, а потом озарило. ВСЁ ЗАРАБОТАЛО, УРА!!!!! СПАСИБО ВСЕМ.
ILS если есть желание, могу выложить текст подпрограмки.
если есть желание, могу выложить текст подпрограмки.
желание-то оно всегда есть ;-) - не хватает возможностей...
Всё работает нормально, но при запуске с одной из вариаций командной строки, нажатия "Y", не происходит, и она зацикливается.
Задумано:
Path - запускаемое приложение (консольное)
ComStr - командная строка
vvod - при -1 вывод окна приложения на монитор и ввод данных в ручную, при 1 - подтверждение "Y" или "N", при 10 - ввод пароля, при 11-ввод пароля и подтверждение.
out - так, просто( что консоль хочет ответить).
void __fastcall TForm1::Password(AnsiString Path,AnsiString ComStr,int vvod,char *out)
{
int i,j;
char buf[1024]; //буфер ввода/вывода
AnsiString vivod=0;
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd; //структура security для пайпов
PROCESS_INFORMATION pi;
HANDLE newstdin,newstdout,read_stdout,write_stdin; //дескрипторы
// пайпов
if (IsWinNT()) //инициализация security для Windows NT
{
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; //разрешаем наследование дескрипторов
if (!CreatePipe(&newstdin,&write_stdin,&sa,0)) //создаем пайп
// для stdin
{
ErrorMessage("CreatePipe");
getch();
return;
}
if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //создаем пайп
// для stdout
{
ErrorMessage("CreatePipe");
getch();
CloseHandle(newstdin);
CloseHandle(write_stdin);
return;
}
GetStartupInfo(&si); //создаем startupinfo для
// дочернего процесса
/*
Параметр dwFlags сообщает функции CreateProcess
как именно надо создать процесс.
STARTF_USESTDHANDLES управляет полями hStd*.
STARTF_USESHOWWINDOW управляет полем wShowWindow.
*/
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = /*(vvod<0)? */SW_NORMAL/*:SW_HIDE*/;
si.hStdOutput = newstdout;
si.hStdError = newstdout; //подменяем дескрипторы для
si.hStdInput = newstdin; // дочернего процесса
chdir(PathDirDan.c_str());
//создаем дочерний процесс
if (!CreateProcess(Path.c_str(),ComStr.c_str(),NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
NULL,NULL,&si,&pi))
{
ErrorMessage("CreateProcess");
getch();
CloseHandle(newstdin);
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
return;
}
unsigned long exit=0; //код завершения процесса
unsigned long bread; //кол-во прочитанных байт
unsigned long avail; //кол-во доступных байт
bzero(buf);
for(;;) //основной цикл программы
{
GetExitCodeProcess(pi.hProcess,&exit); //пока дочерний процесс
// не закрыт
if (exit != STILL_ACTIVE)
{
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); //читаем из
// пайпа stdout
sprintf(out,"%s\0",buf);
bzero(buf);
}
}
else {
ReadFile(read_stdout,buf,1023,&bread,NULL);
sprintf(out,"%s\0",buf);
}
if(vvod>=0)OutStrToBox(out);// Вывод из stdout в ListBox1
}
break;
}
if(vvod>0)
{
for(i=0;i<Pass.Length() && vvod>=10;i++) //проверяем, есть ли пароль, есои есть вводим
{
bzero(buf);
*buf = *(Pass.c_str()+i);
//printf("%c",*buf);
WriteFile(write_stdin,buf,1,&bread,NULL); //отправляем это
// в stdin
}
if (vvod>0 && vvod<10)// если подтверждение (Y/N) вводим его
{
bzero(buf);
*buf = 'Y';
// printf("%c",*buf);
WriteFile(write_stdin,buf,1,&bread,NULL);
}
if (vvod>0)// если чтото вводилось (пароль или подтверждение), то Enter
{
bzero(buf);
vvod=vvod-vvod/10*10;
*buf =13;
// printf("%c",*buf);
WriteFile(write_stdin,buf,1,&bread,NULL); //формирум конец
//строки, если нужно
}
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(newstdin); //небольшая уборка за собой
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
return ;
}
Опять клинит.
Всё работает нормально, но при запуске с одной из вариаций командной строки, нажатия "Y", не происходит, и она зацикливается.
Собственно говоря, я вобще не вижу в приведенном коде выхода из твоего цикла...
Иежду тем в первоисточнике было:
for(;;) //основной цикл программы
{
...
if (exit != STILL_ACTIVE)
break;
....
}
Он конечно, списывать нужно творчески, но не настолько же :-)
if (exit != STILL_ACTIVE)
{
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); //читаем из
// пайпа stdout
sprintf(out,"%s\0",buf);
bzero(buf);
}
}
else {
ReadFile(read_stdout,buf,1023,&bread,NULL);
sprintf(out,"%s\0",buf);
}
if(vvod>=0)OutStrToBox(out);// Вывод из stdout в ListBox1
}
break;
}
Если консоль закрыта, чтение из буфера stdout, занесение подпрограммкой в ListBox1, и выход.
В остальных случаях работает. Ума не дам.