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

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

WriteConsoleInput [D7, WinXP]


Страницы:   1 2

Logo ©   (2005-05-31 08:47:00) 

Использую WriteConsoleInput.
Но почему то передается не буква "n", а буква "N".
И еще какой-то пробел после нее. Вместо Энтера знак равно.
Что может быть не так?
Еще не могу по русски писать в консоль.


Logo   (2005-06-23 14:07:00) [1]

Реально работает.
Единственное я немного подправил, чтобы ID можно было вводить русское.
Спасибо, alpet!


alpet   (2005-06-23 13:20:00) [2]

CreateFile и прочие закомментированные элементы можно удалить.


alpet   (2005-06-23 13:19:00) [3]

Блин, а задача интересной оказалось. Но как всегда помогло внимательное чтение справки. Вот держи и разбирай рабочий код, хотя я бы поискал для задачи исходники программы rsa.exe:
program redir;

{$APPTYPE CONSOLE}
uses Windows, Types, SysUtils;
var
SI: TStartupInfo;
PI: TProcessInformation;

function ChToOem (const s: string): string;
var p: array [0..255] of char;
begin
CharToOemBuff (PChar (s), p, Length (s) + 1);
result := p;
end;

procedure SendInputStr (const s: string);
var
 r: TInputRecord;
 n, num: dword;
 ss, ls: string;
 hstdi, hFile: THandle;
begin
ss := ChToOem (s);
ls := LowerCase (ss);
r.EventType := KEY_EVENT;
hFile := CreateFile ('con', GENERIC_WRITE, FILE_SHARE_WRITE, nil,
                        OPEN_ALWAYS, 0, 0);
//hstdi := GetStdHandle (STD_INPUT_HANDLE);
for n := 1 to Length (ss) do
with r.event do
begin
 if (ls [n] = ss [n]) then
    KeyEvent.dwControlKeyState := 0
 else
    KeyEvent.dwControlKeyState := SHIFT_PRESSED;
 KeyEvent.AsciiChar := ss [n];
 KeyEvent.UnicodeChar := WideChar (ss [n]);
 KeyEvent.wRepeatCount := 0;
  case ss [n] of
    #13, #10: KeyEvent.wVirtualKeyCode := VK_RETURN;
    #$30..#$39: KeyEvent.wVirtualKeyCode := ord (ss [n]);
    else KeyEvent.wVirtualKeyCode := ord (UpCase (ss [n]));
  end;
 KeyEvent.wVirtualScanCode := MapVirtualKey (KeyEvent.wVirtualKeyCode, 0);
 KeyEvent.bKeyDown := true;
 //WriteFile (hFile, ss [n], 1, num, nil);
 WriteConsoleInput (Si.hStdInput, r, 1, num);
 r.Event.KeyEvent.bKeyDown := false;
 WriteConsoleInput (Si.hStdInput, r, 1, num);
end;
CloseHandle (hFile);
end;

var n: dword;
begin
ZeroMemory(@SI, SizeOf(SI));
si.cb := sizeof (si);
si.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
// SetConsoleMode (si.hStdInput, ENABLE_PROCESSED_OUTPUT);
chdir ('C:\temp\rsa\');
CreateProcess(Nil, 'C:\temp\rsa\RSAKEYS.EXE -kg 512 << con', Nil, Nil, True, 0, Nil, Nil, SI, PI);
// CreateProcess(Nil, 'C:\Windows\system32\cmd.exe', Nil, Nil, True, 0, Nil, Nil, SI, PI);
Sleep (1000);
SendInputStr ('AfxName1234'#13);
Sleep (200);
FlushConsoleInputBuffer (si.hStdInput);
SendInputStr ('PWDUNIVERSAL'#13);
Sleep (200);
FlushConsoleInputBuffer (si.hStdInput);
SendInputStr ('PWDUNIVERSAL'#13);
Sleep (200);
FlushConsoleInputBuffer (si.hStdInput);
n := 0;
while (WaitForSingleObject (pi.hProcess, random (200) + 10) = WAIT_TIMEOUT) and
        (n < 10)  do
 begin
  SendInputStr ('QWERTY');
  inc (n);
 end;
 CloseHandle (pi.hProcess);
// WaitForSingleObject (pi.hProcess, INFINITE);
///TerminateProcess (pi.hProcess, 0); // not wait process
// FreeConsole;
// readln (input);
end.


Logo   (2005-06-23 06:55:00) [4]

Вот код. Он запускает прогу и выводит вместо 12345 пять букв A.

{$APPTYPE CONSOLE}
uses SysUtils, Windows;
var
 SI: TStartupInfo;
 PI: TProcessInformation;

function ChToOem (const s: string): string;
var p: array [0..255] of char;
begin
CharToOemBuff (PChar (s), p, Length (s) + 1);
result := p;
end;

procedure SendInputStr (const s: string);
var
  r: TInputRecord;
  n, num: dword;
  ss: string;
  hstdi: THandle;
begin
ss := ChToOem (s);
r.EventType := KEY_EVENT;
//hstdi := GetStdHandle (STD_INPUT_HANDLE);
for n := 1 to Length (ss) do
with r.event do
begin
 KeyEvent.bKeyDown := true;
 KeyEvent.AsciiChar := ss [n];
 KeyEvent.wRepeatCount := 0;
 KeyEvent.wVirtualKeyCode := 0;
 KeyEvent.wVirtualScanCode := 0;
 WriteConsoleInput (Si.hStdInput, r, 1, num);
 r.Event.KeyEvent.bKeyDown := false;
 WriteConsoleInput (Si.hStdInput, r, 1, num);
end;
end;

begin
ZeroMemory(@SI, SizeOf(SI));
si.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
AllocConsole;
CreateProcess(Nil, 'C:\temp\rsa\RSAKEYS.EXE -kg 512', Nil, Nil, True, 0, Nil, Nil, SI, PI);
Sleep(1000);
SendInputStr ('12345');

Sleep(1000);
//  CloseHandle(PI.hThread);
//  CloseHandle(PI.hProcess);
//  FreeConsole;
end.


alpet   (2005-06-22 10:32:00) [5]

Код представь пожайлуста весь.


Logo   (2005-06-22 07:51:00) [6]

будете смеяться, но не могу добиться передачи login и password через delphi приложение. Передаются не те символы которые посылаются.


alpet   (2005-06-15 11:43:00) [7]

C нажатиями клавиш через файл нечего передавать не удается, видимо используются функции для проверки соостояния клавы (kbhit ???) которые не обманываются с помощью перехвата ввода (можно попробывать SetKeyboardStatus, внедрив dll в пространство ntdvm процесса).

Вот какое содержимое файла 1.txt программа воспринимает в качестве логина и пары паролей.

login

password
password


Logo   (2005-06-15 11:23:00) [8]

Попробовал создал в том же дельфи консольное приложение которое readln-ом получает данные. подставил вместо rsakeys.exe и все замечательно работает!
где копать? может сама прога что-то криво воспринимает?


Logo   (2005-06-15 06:22:00) [9]

Будешь смеяться, но я не могу корректно даже логин ей передать через WriteConsoleInput().

Через перенаправление ввода логин и первый пароль в нее попадают, второй тоже попадает но получаю сообщение о несовпадении пар паролей :( хотя в файле 1.txt они явно одинаковые

Одна из функций - объединение ключей после которого и надо нажимать лишь кнопку 'N'. После этого случайные символы не нужны но эффект тот же - зависон консоли.
Спасибо, что пытаешься помочь. Это редко бывает в наше время ;)


alpet   (2005-06-14 15:32:00) [10]

1. С этого надо было начинать.
2. Программа нормально получает логин и пару паролей, но затыкается когда дело доходит до произвольного текста. Собственно надо понять что она использует для оценки нажатия клавиши, возможно и не stdinput.

Попробуй после ввода логина и паролей отправлять символы, чередуя их с случайной задержкой:

for n := 1 to 100 do
begin
 WriteConsoleInput (...); // some char
 Sleep (random (100) + 100);
end;


Logo   (2005-06-14 15:20:00) [11]

Прога здесь - http://botchallenge.com/u/RSAKEYS.EXE
Это что-то наподобие PGP.
Например, комманда: RSAKEYS.EXE -KG 512, котрую я вызываю.
потом запрашивает ID Пользователя. Надо ввести, например, Пупкин.
Затем пароль два раза одинаковый, затем нажатия произвольных кнопок. После чего должны появиться два файла pubkeys и seckeys.

Когда делаю перенаправлением ввода консоль виснет.


alpet   (2005-06-14 14:09:00) [12]

Хм... А пример того что в консоли получается можно увидеть? И как та же программа (proga.exe) работает через echo или < перенаправления?

Пример файл 1.txt

echo start
dir
cd c:\windows

Если запустить cmd.exe < 1.txt он будет выполнять комманды файла так как если бы их вводил пользователь.


Logo   (2005-06-14 13:43:00) [13]

2 alpet Help!
Твой пример действительно работает. Вызывается консоль и в ней пишется то, что туда засылается. Но вот когда вместо консоли подсовываю свою DOS программку, в нее начинает выводится какой то бред.

вот кусок вставленного кода в твой пример.
==== BEG ====
var
 SI: TStartupInfo;
 PI: TProcessInformation;

begin
 ZeroMemory(@SI, SizeOf(SI));
 si.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
 AllocConsole;
 CreateProcess(Nil, 'proga.EXE', Nil, Nil, True, 0, Nil, Nil, SI, PI);
 Sleep(1000);
 SendInputStr ('Test ');
end.
==== END ====


alpet   (2005-05-31 14:48:00) [14]

VMcL ©   (31.05.05 14:16) [12]
1. Абсолютно с вами согласен. Быстрее на целых 0.2%
2. И тут верно, функция моя пригодна лишь только для ShortString переменных, длиной не более 255 символов.


VMcL   (2005-05-31 14:16:00) [15]

>> alpet ©   (31.05.05 13:15) [10]

Если интересует быстродействие, то самый рулез приводить не к PChar, а к Pointer.

>> alpet ©   (31.05.05 10:50) [5]

Строк длинее 255 символов не бывает?

function StringToOEM(const S: AnsiString): AnsiString;
var
 Len: Integer;
begin
 Len := Length(S);
 SetLength(Result, Len);
 if Len > 0 then
   Win32Check(CharToOEM(PChar(S), PChar(Result)));
end;


Digitman   (2005-05-31 13:47:00) [16]


> alpet ©   (31.05.05 13:15) [10]


о производительности речи не идет.


alpet   (2005-05-31 13:15:00) [17]

Компилятору не фиолетово. При использовании приведении типа, код генерируется несколько другой, хотя разницы в результате и не наблюдается (только что 30% разница в быстродействии - приведение меньше времени занимает, но кому сейчас это интересно).


Digitman   (2005-05-31 11:34:00) [18]


> alpet ©   (31.05.05 11:12) [8]
> работать будет, только выглядит криво


да почему криво ?

на вкус и цвет, как известно, товарищей нет - кому удобней воспринимать PChar(AnsiStrVar), а кому и @AnsiStrVar[1] ..  компилятору же фиолетово)


alpet   (2005-05-31 11:12:00) [19]

2 Digitman
Ну да работать будет, только выглядит криво...


alpet   (2005-05-31 11:10:00) [20]

Пример консольного приложения в котором это все работает:

{$APPTYPE CONSOLE}
uses SysUtils, Windows;
function ChToOem (const s: string): string;
var p: array [0..255] of char;
begin
CharToOemBuff (PChar (s), p, Length (s) + 1); // + \0
result := p;
end;
procedure SendInputStr (const s: string);
var
   r: TInputRecord;
   n, num: dword;
   ss: string;
   hstdi: THandle;
begin
ss := ChToOem (s);
r.EventType := KEY_EVENT;
hstdi := GetStdHandle (STD_INPUT_HANDLE);
for n := 1 to Length (ss) do
with r.event do
 begin
  KeyEvent.bKeyDown := true;
  KeyEvent.AsciiChar := ss [n];
  KeyEvent.wRepeatCount := 0;
  KeyEvent.wVirtualKeyCode := 0;
  KeyEvent.wVirtualScanCode := 0;
  WriteConsoleInput (hstdi, r, 1, num);
  r.Event.KeyEvent.bKeyDown := false;
  WriteConsoleInput (hstdi, r, 1, num);
 end;
end;

begin
SendInputStr ('Test ');
SendInputStr ('Тест');
readln;
end.


Страницы:   1 2

Наверх

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