Перейти к содержимому

Фотография

Работа С Командной Строкой


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 12

#1 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 12 сентября 2007 - 12:27

Использую TectComplete 5.12.454.7
Тестируемая программа написана на java
язык скрипта Delphi

Тут возникла необходимость получить данные которые выводяться в командню строку, кто нить знает как это сделать???
Я пытался сделать кодом Delphi который нашел в инете:


procedure com;
var ProcInfo: TProcessInformation;
StartupInfo: TStartupInfo;
SecAtrtrs: TSecurityAttributes;
hOut: THandle;
begin
with SecAtrtrs do
begin
nLength := SizeOf(TSecurityAttributes);
lpSecurityDescriptor := nil;
bInheritHandle := true; // ВОТ ОНО !!! Наша рукоятка будет НАСЛЕДУЕМОЙ
end;

// Создаем файл в который и будем переназначать StdOut
// Например, с такими настройками, вы можете их изменить под свои нужды
hOut := CreateFile('c:\MyStdOut.txt', GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hOut = INVALID_HANDLE_VALUE) then RaiseLastWin32Error;

GetStartupInfo(StartupInfo);
with StartupInfo do
begin
wShowWindow := SW_HIDE; // не показывать окно
dwFlags := dwFlags or STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
hStdOutput := hOutDup; // присваиваем рукоятку на свой файл
end;

// для примера будем запускать [c:\program files\Borland\Delphi5\Bin]grep.exe с ключом '?'
// Вызов CreateProcess с флагом bInheritHandles = TRUE !!!
Win32Check(CreateProcess(nil, 'ipconfig /all', nil, nil, TRUE, CREATE_NEW_CONSOLE, nil, nil, StartupInfo, ProcInfo));

// ждем пока наш процесс отработает
WaitForSingleObject(ProcInfo.hProcess, INFINITE);

Win32Check(CloseHandle(ProcInfo.hProcess));

//если вы больше ничего не хотите делать с файлом, в который перенаправили StdOut, то закроем его
Win32Check(CloseHandle(hOut));
end;


но testcomplet при компиляции даёт ошибку, хотя в редакторе ошибки не идентифицируются
Если кто делал что нить подобное напишите пожалуста
  • 0

#2 pitlord

pitlord

    Новый участник

  • Members
  • Pip
  • 9 сообщений
  • ФИО:Зенин Петр Алексеевич

Отправлено 12 сентября 2007 - 15:33

А не проще работать с файлом после вывода?

с помощью добавления к консоли ">имяф_файла" - вывод будет направлен в файл.
Хотя скорее всего я просто не до конца вник в текст
  • 0

#3 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 12 сентября 2007 - 18:44

Здравствуйте.



Можете использовать ClrBridge, чтобы сделать это через .NET. Вот так:

procedure Test;
var
  p, output;
begin
  p := dotNET.System_Diagnostics.Process.zctor();
  p.StartInfo.FileName := 'c:\Windows\System32\cmd.exe';
  p.StartInfo.Arguments := '/c ipconfig';
  p.StartInfo.UseShellExecute := False;
  p.StartInfo.RedirectStandardOutput := True;
  p.Start;
  
  while not p.HasExited do Delay(100);
  output := p.StandardOutput.ReadToEnd();
  Log.Message(output);
end;



Чтобы этот код заработал, надо добавить ассемблю System.dll в ваш проект TestComplete'а. Для этого дважды щёлкните на имени проекта в Project Explorer, откройте страницу Properties редактора проекта и в опциях 'CLR Bridge' нажмите 'Browse GAC...'.
  • 0
С уважением,
Дмитрий

#4 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 13 сентября 2007 - 05:26

А не проще работать с файлом после вывода?

с помощью добавления к консоли ">имяф_файла" - вывод будет направлен в файл.
Хотя скорее всего я просто не до конца вник в текст


Не проще т.к. команды пишу unuix серверу а он их не поймёт
  • 0

#5 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 13 сентября 2007 - 05:33

Здравствуйте.



Можете использовать ClrBridge, чтобы сделать это через .NET. Вот так:

procedure Test;
var
  p, output;
begin
  p := dotNET.System_Diagnostics.Process.zctor();
  p.StartInfo.FileName := 'c:\Windows\System32\cmd.exe';
  p.StartInfo.Arguments := '/c ipconfig';
  p.StartInfo.UseShellExecute := False;
  p.StartInfo.RedirectStandardOutput := True;
  p.Start;
  
  while not p.HasExited do Delay(100);
  output := p.StandardOutput.ReadToEnd();
  Log.Message(output);
end;



Чтобы этот код заработал, надо добавить ассемблю System.dll в ваш проект TestComplete'а. Для этого дважды щёлкните на имени проекта в Project Explorer, откройте страницу Properties редактора проекта и в опциях 'CLR Bridge' нажмите 'Browse GAC...'.


Спасибо большое за ответ.
Но у меня правда чего не получается:
Поставил себе .NET Framework 3.0
Сделал переконфигурацию testcomplete
потом всё так как вы написали , но он ругается что не знает такого "System_Diagnostics" до этого ругался на "dotNET", я уже внёс в список всё dll какие только были, значиться у меня её нет? как можно её найти?
Подскажите пожалуста
  • 0

#6 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 13 сентября 2007 - 05:44

я тут нашёл ещё...
так не пойдёт заменить ту строку??
p := dotNET.System.System_Diagnostics_Process.ctor();
  • 0

#7 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 13 сентября 2007 - 06:13

Заменил в коде строку p := dotNET.System_Diagnostics.Process.zctor(); на p := dotNET.System.System_Diagnostics_Process.ctor();
и вроде всё заработало только вот я не пойму как организовать такое действие:
Я запускаю cmd через testcomplete и данные тоже ввожу только им а вот полученыы результат уже и выводить
мне надо не одну не две команды написать , нужно организовать целую серию запросов-ответов
  • 0

#8 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 13 сентября 2007 - 11:31

Здравствуйте.

Можно послать несколько запросов, а потом, когда приложение закроется, прочитать все ответы сразу.

procedure Test;
var
  p, input, output;
begin
  p := dotNET.System_Diagnostics.Process.zctor();
  p.StartInfo.FileName := 'c:\Windows\System32\cmd.exe';
  p.StartInfo.UseShellExecute := False;
  p.StartInfo.RedirectStandardOutput := True;
  p.StartInfo.RedirectStandardInput := True;
  p.Start;

  input := p.StandardInput;
  output := p.StandardOutput;
  input.WriteLine('ver');
  input.WriteLine('dir');
  input.WriteLine('ipconfig');
  input.WriteLine('quit');
  
	
  while not p.HasExited do Delay(100);
  while not output.EndOfStream do
	Log.Message(output.ReadLine());
end;



Конечно, хотелось бы, чтобы ответы читались сразу после запросов. Однако, если запросить у потока StandardOutput строку, в которой производится запрос на ввод (например, командная строка), то методы чтения потока "подвиснут", пока приложение не напишет что-либо в поток. А оно не напишет, пока не пошлёшь строку в StandardInput. Это можно разрулить подписавшишь на соответствующее событие или запустив чтение и запись в разных нитях (threads), однако ни то ни другое нельзя сделать из скрипта.

Как вариант, можно читать из потока StandardOutput по символу, пока не увидите приглашение коммандной строки (по умолчанию '>', но можно изменить коммандой prompt).
  • 0
С уважением,
Дмитрий

#9 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 17 сентября 2007 - 04:21

Dmitry N, начал пытаться реализовать вашу процедуру, так у меня при компиляции ругается на input.WriteLine('ver'); пишет что происходит несовпадение типов, а там ведь и правда не получиться так сделать.
Кстати интересный факт теперь у меня ваша строка p := dotNET.System_Diagnostics.Process.zctor();, работает, а моя(которая ещё в пятницу отрабатывала) p := dotNET.System.System_Diagnostics_Process.ctor(); не хотит :)
  • 0

#10 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 17 сентября 2007 - 05:23

Заменил WriteLine на WriteLine_11 нормально заработало, но возникла другая проблема: мне ведь надо работать с telnet , и если просто ручками вызываешь cmd а потом телнет то сеанс нормально работает но testcomplete видимо воспринимает телнет как другой процесс и не передаёт ему команды которые я пишу , пробовал заменять p.StartInfo.FileName := 'c:\Windows\System32\cmd.exe'; на p.StartInfo.FileName := 'c:\Windows\System32\telnet.exe'; но тогда вообще логи пустые, мелькнёт окошко и всё
Как можно это обойти? или телнету нельзя так же команты передавать и читать как cmd ?
  • 0

#11 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 17 сентября 2007 - 10:20

Здравствуйте.



Разные имена у функций могут быть из-за того, что не используете плагин 'TestComplete 3 Compatibility' (он у меня был включен, когда я пример делал).



Что касается telnet, я думаю разницы быть не должно. Убедитесь, что вы перенаправили и поток ввода и поток вывода перед запуском процесса:

  p.StartInfo.UseShellExecute := False;
  p.StartInfo.RedirectStandardOutput := True;
  p.StartInfo.RedirectStandardInput := True;
  • 0
С уважением,
Дмитрий

#12 Rumata

Rumata

    Новый участник

  • Members
  • Pip
  • 66 сообщений
  • Город:Астана

Отправлено 17 сентября 2007 - 10:46

Вспомнил я ведь правда убрал "TestComplete 3 Compatibility"
Вот код процедуры всё также

procedure com;
var
p, input, output;
begin
p := dotNET.System_Diagnostics.Process.zctor();
p.StartInfo.FileName := 'C:\WINDOWS\system32\telnet.exe';
p.StartInfo.UseShellExecute := False;
p.StartInfo.RedirectStandardOutput := True;
p.StartInfo.RedirectStandardInput := True;
p.Start;
input := p.StandardInput;
output := p.StandardOutput;
input.WriteLine_11('?');
while not p.HasExited do
Delay(100);
while not output.EndOfStream do
Log.Message(output.ReadLine());

end;


окошко мелькает и исчезает, хотя cmd хотя бы на экране остаётся, поучается что запуск идёт неправильно может дело в dll System_Diagnostics ведь у нёё название содержит смысл "Диагностика" что как то с telnet -ом не вяжется???
вообщем я завяз и думаю может написать на Delphi элементарнейший клиент и из него уже таскать данные???
  • 0

#13 Dmitry N

Dmitry N

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 742 сообщений
  • ФИО:Николаев Дмитрий
  • Город:Где-то в России

Отправлено 17 сентября 2007 - 13:04

Здравствуйте.



У меня тоже telnet так себя ведёт. Я посмотрел -- у него Exit Code равен '-1'. Это не нормальный код, нормальный это '0'. Не могу сказать, что именно это значит. Возможно, какие-то настйроки безопасности системы не дают запустить telnet с параметром UseShellExecute = false или с перенаправлением потоков.



В данном случае могу предложить посылать команды в окно telnet используя Wnd.Keys, а читать их через буфер обмена. Другой вариант -- написать простую программу, как вы сами предложили.
  • 0
С уважением,
Дмитрий


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных