Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.05.14;
Скачать: CL | DM;

Вниз

Перенаправленный ввод-вывод   Найти похожие ветки 

 
GanibalLector ©   (2006-01-17 02:36) [0]

Создаю сокет,перенаправляю ввод-вывод на cmd.exe. Захожу клиентом и юзаю cmd.exe из клиента. Так вот,проверяю сие творение на 2 компьютерах. На обном все Ок,а на втором cmd сразу закрывается. В чем может быть дело???
Открыват cmd.exe так :

sHandle := accept(FSocket, nil, nil);
   if sHandle <> INVALID_SOCKET then
    begin
      ZeroMemory(@St, SizeOf(TStartupInfo));
      St.cb := SizeOf(TStartupInfo);
      St.wShowWindow := SW_SHOW;
      St.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
      St.hStdInput  := sHandle;
      St.hStdOutput := sHandle;
      St.hStdError  := sHandle;
      CreateProcess(nil, "cmd.exe", nil, nil, true, 0, nil, nil, St, Pr);


 
Digitman ©   (2006-01-17 08:46) [1]

Из приведенного фрагмента кода нельзя сделать никаких предположений.
Главное (обмен с cmd) осталось за кадром.
Кр.того, почему нет анализа результата вызова CreateProcess ?


 
GanibalLector ©   (2006-01-17 19:56) [2]

2 Digitman
> почему нет анализа результата вызова CreateProcess
ф-ция выполнена успешно.


 
PAVIA ©   (2006-01-17 22:06) [3]

GanibalLector
Какая ОС на компьютерах? А то для этого должна быть поддержка winsock 2.0 или 2.2


 
GanibalLector ©   (2006-01-18 01:44) [4]

2 PAVIA ©   (17.01.06 22:06) [3]
На одном XP SP2 - не работает.
На втором XP Sp1 - работает.

2 Digitman ©   (17.01.06 08:46) [1]
>Главное (обмен с cmd) осталось за кадром.
Не понял. Я могу в принципе и клиента своего выслать.Но ИМХО не стоит. Ибо любой сканер портов заменит моего клиента. Т.е. cmd.exe запустится,а в сканер портов скажет,что мол :Microsoft Windows XP и т.д.


 
Digitman ©   (2006-01-18 08:36) [5]

Причем здесь конкретная функциональность твоего приложения ?
И причем здесь "сканеры" ?
Ты пытаешься управлять вводом-выводом некоего консольного приложения (в дан.случае - cmd.exe) посредством программных каналов. Вот я и хочу выяснить , какие конкретно данные и как ты посылаешь в канал ввода консоли ..


 
GanibalLector ©   (2006-01-18 13:33) [6]

2 Digitman
Да,конечно.Вот клиент(черновой вариант!!!пока без синхронизации) :

unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ComCtrls;

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Start: TButton;
   Stop: TButton;
   Label1: TLabel;
   Edit1: TEdit;
   Exec_Console: TButton;
   procedure StopClick(Sender: TObject);
   procedure StartClick(Sender: TObject);
   procedure Exec_ConsoleClick(Sender: TObject);
 private
   B:Boolean;
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 StopThread,WrCons:Boolean;

const MAX_PACKET_SIZE = $10000;

implementation
 uses WinSock;
{$R *.dfm}

function Dos2Win(const aStr: String): String;
begin
  Result := aStr;
  if Result <> "" then
   OemToChar(PChar(Result),PChar(Result));
end;

function Win2Dos(const aStr: String): String;
begin
Result := aStr;
if Result <> "" then
  CharToOem(PChar(Result),PChar(Result));
end;

procedure Send_(Socket:TSocket;Data:String);
begin
 Data:=Win2Dos(Data);
 Send(Socket,Data[1],Length(Data),0);
end;

function Recv_(Socket:TSocket; var Data:String):Boolean;
 var Len,II:Integer;
     Packet: array[0..MAX_PACKET_SIZE - 1] of Byte;
begin
  Data:="";
  Len:=Recv(Socket,Packet,MAX_PACKET_SIZE,0);
  if Len>0 then
  begin
    for II:=0 to Len-1 do
     Data:=Data+Chr(Packet[II]); // от Лукавого.надо будет переделать
    Data:=Dos2Win(Data);
    Result:=True;
  end else Result:=False;
end;

function potok(Param:Pointer):DWord;
 var
   Sock:TSocket;
   Addr:TSockAddr;
   Data_:TWSAData;
   Data:String;
   FDSet:TFDSet;
   Tm:TTimeVal;
   ServStoped:Boolean;
begin
 StopThread:=True;
 WrCons:=False;
 ServStoped:=True;
 Result:=0;
 if WSAStartup($101,Data_)=0 then
 begin
   Sock:=Socket(AF_INET, SOCK_STREAM,0);
   if Sock<>INVALID_SOCKET then
   begin
     Addr.sin_family:=AF_Inet;
     Addr.sin_port:=HToNS(801);
     Addr.sin_addr.S_addr:=Inet_Addr("192.168.1.6");
     FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0);
     if Connect(Sock,Addr,SizeOf(TSockAddr))<>SOCKET_ERROR then
     begin
       Form1.Memo1.Lines.Add("Нить запущена!");
       repeat
         FD_Zero(FDSet);    
         FD_Set(Sock,FDSet);
         Tm.tv_sec:=0;
         Tm.tv_usec:=10000;
         if Select(0,@FDSet,nil,nil,@Tm)<>0 then
         begin
           if FD_IsSet(Sock,FDSet) then
           begin
             if Recv_(Sock,Data) then
               Form1.Memo1.Lines.Add(Data)
               // выводим все полученное в Memo
               else
               ServStoped:=False; // сервер упал.выходим
           end;
         end;

         if WrCons then
         begin  // посылаем в консоль
           Send_(Sock,Form1.Edit1.Text+#13#10);
           WrCons:=False;
         end;

       until (not StopThread) or (not ServStoped);
       if not StopThread then
        Form1.Memo1.Lines.Add("Прервано пользователем") else
        Form1.Memo1.Lines.Add("Обрыв на сервере");
       CloseSocket(Sock);
       WSACleanup;
     end else
     begin  //
       Result:=WSAGetLastError;
       CloseSocket(Sock);
       WSACleanup;
     end;
   end else
   begin   //Socket
     Result:=WSAGetLastError;
     WSACleanup;
   end;
 end else Result:=WSAGetLastError; //WSAStartup
end;

procedure TForm1.StopClick(Sender: TObject);
begin
 StopThread:=False; // "убиваем" нить
 // для "убийства" можно использовать и CloseSocket
 // пока не определился какой вариант лучше
end;

procedure MsgWaitForSingleObject(Handle: THandle);
begin
repeat
  if MsgWaitForMultipleObjects(1, Handle, False, INFINITE, QS_ALLINPUT) = WAIT_OBJECT_0 + 1 then
   Application.ProcessMessages else
   Break;
until True = False;
end;

procedure TForm1.StartClick(Sender: TObject);
 var hThread:HWND;
   ThreadID,ECode:DWord;
begin
 if not(B) then
 begin
   B:=True;
   hThread:=BeginThread(nil,0,@potok,nil,0,ThreadID);
   MsgWaitForSingleObject(hThread);
   GetExitCodeThread(hThread,ECode);
   CloseHandle(hThread);
   if ECode<>0 then
     MessageDlg("Ошибка :"+SysErrorMessage(ECode),MtError,[MbOk],0);
   B:=False;
 end else
 MessageDlg("Нить УЖЕ работает!!! Хватит",MtError,[MbOk],0);
end;

procedure TForm1.Exec_ConsoleClick(Sender: TObject);
begin
 if Length(Edit1.Text)=0 then Exit;
 WrCons:=True;
end;

end.


Данный код у меня работает с разных Ос(98,ХР).Повторюсь сервер запускается на ХР SP1.
При коннекте клиентом на сервере запускается и "висит" cmd.exe до тех пор пока я не разорвусь клиентом.

З.Ы.При запуске сервера на SP2 (и дальнейшем коннекте клиентом) cmd.exe запускается и сразу же закрывается.Я все же  думаю,что беда в сервере. Вот,примерное такое происходит на сервере:


procedure TForm1.Button1Click(Sender: TObject);
 var
  St: TStartupInfo;
  Pr: TProcessInformation;
begin
  ZeroMemory(@St, SizeOf(TStartupInfo));
  St.cb := SizeOf(TStartupInfo);
  St.wShowWindow := SW_SHOW;
  St.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  St.hStdInput  := 0;  // это я специально,дабы показать
  St.hStdOutput := 0;
  St.hStdError  := 0;
  if not (CreateProcess(nil, "cmd.exe", nil, nil, True, 0, nil, nil, St, Pr)) then
  MessageDlg("Ошибка:"+SysErrorMessage(GetLastError),MtError,[MbOk],0); // ошибки не будет
  CloseHandle(Pr.hProcess);
  CloseHandle(Pr.hThread);
end;


 
Digitman ©   (2006-01-18 16:14) [7]

Отложи на время свои "беды с неожиданным закрытием CMD", у тебя серьезные проблемы еще ДО этого.

Обращаться к визуальным VCL-контролам  в контексте доп.потока НЕдопустимо.


 
GanibalLector ©   (2006-01-18 21:45) [8]

2 Digitman ©   (18.01.06 16:14) [7]
>Обращаться к визуальным VCL-контролам  в контексте доп.потока НЕдопустимо.

Я знаю. Сказал же в [6],что черновой вариант. На самом деле должно быть так :

var CS:TRTLCriticalSection;

procedure MemoOutput(Value:String);
begin
 EnterCriticalSection(CS);
 Form1.Memo1.Lines.Add(Value);
 LeaveCriticalSection(CS);
end;

// вызов MemoOutput("Нить запущена");

initialization
 InitializeCriticalSection(CS);
finalization
 DeleteCriticalSection(CS);

Тоже и для переменной WrCons надо сделать.

Но только и это НЕ решает моей проблемы!!!
P.S. Вот даже земляк GuAV говорит,что все работает. А у меня чЁто никак :(


 
GanibalLector ©   (2006-01-18 21:45) [9]

2 Digitman ©   (18.01.06 16:14) [7]
>Обращаться к визуальным VCL-контролам  в контексте доп.потока НЕдопустимо.

Я знаю. Сказал же в [6],что черновой вариант. На самом деле должно быть так :

var CS:TRTLCriticalSection;

procedure MemoOutput(Value:String);
begin
 EnterCriticalSection(CS);
 Form1.Memo1.Lines.Add(Value);
 LeaveCriticalSection(CS);
end;

// вызов MemoOutput("Нить запущена");

initialization
 InitializeCriticalSection(CS);
finalization
 DeleteCriticalSection(CS);

Тоже и для переменной WrCons надо сделать.

Но только и это НЕ решает моей проблемы!!!
P.S. Вот даже земляк GuAV говорит,что все работает. А у меня чЁто никак :(


 
GanibalLector ©   (2006-01-19 01:10) [10]

И вот еще : http://headnet.net.ru/dir6/p1370.htm тоже не работает. Тут видать проблема не в коде,а в чем-то другом. :(


 
Digitman ©   (2006-01-19 10:51) [11]


> На самом деле должно быть так


Нет, не так.

А хотя бы вот так :

procedure MemoOutput(Value:String);
begin
 SendMessage(хэндл_формы, WM_MYMESSAGE, WParam(PChar(Value)), 0);
end;

procedure TMyForm.MyMessageHandler(var Message: TMessage); //обработчик WM_MYMESSAGE
begin
  Memo1.Lines.Add(String(PChar(Message.WParam)));
end;

Если поставить и поймать брейкпойнт на

CloseHandle(Pr.hProcess);

cmd-консоль и в этом случае закрывается ?


 
GanibalLector ©   (2006-01-19 19:29) [12]

2 Digitman ©   (19.01.06 10:51) [11]
>А хотя бы вот так
Спасибо.Понял.

>Если поставить и поймать брейкпойнт на  CloseHandle(Pr.hProcess);
Да,УЖЕ закрыта.


 
Digitman ©   (2006-01-20 08:38) [13]


> Да,УЖЕ закрыта


при этом система что-то пишет в Application Events Log ? И/или другие логи ?


 
GanibalLector ©   (2006-01-20 09:59) [14]

Нет,ничего не пишет


 
umbra ©   (2006-01-20 12:29) [15]

похоже на супер-пупер файервол ХР СП2


 
Digitman ©   (2006-01-20 13:20) [16]


> похоже на супер-пупер файервол ХР СП2


с чего бы "супер-пупер файерволу" снимать cmd-процесс, если ему еще ни одна команда по каналу ввода не поступила ?

непонятно ..


 
Digitman ©   (2006-01-20 13:21) [17]

вот если только cmd.exe заражен-загажен (лезет в сеть, едва стартовав) - тогда еще понятно ..


 
umbra ©   (2006-01-20 13:47) [18]

мое предположение - cmd закрывается потому, что подсоединившийся клиент отрубается файерволом.


 
umbra ©   (2006-01-20 13:53) [19]

и неплохо бы и серверу и клиенту вести подробный лог при работе.


 
Digitman ©   (2006-01-20 13:59) [20]


> umbra ©   (20.01.06 13:47) [18]


Какой такой "клиент" ?

Клиентский Socket же активируется автором в совершенно другом процессе, и этот самый процесс как раз и должен сниматься файрволом с выполнения, но никак не cmd ...


 
umbra ©   (2006-01-20 15:18) [21]

2 Digitman ©   (20.01.06 13:59) [20]


> GanibalLector ©   (18.01.06 13:33) [6]
> При коннекте клиентом на сервере запускается и "висит" cmd.
> exe до тех пор пока я не разорвусь клиентом.
>


 
Digitman ©   (2006-01-20 15:29) [22]


> umbra ©   (20.01.06 15:18) [21]



> до тех пор пока я не разорвусь клиентом


до "разрыва" и дело не доходит.

Как утверждает автор, процесс-сервер, с которым успешно соединился процесс-клиент, средствами CreateProcess успешно выполнил запуск процесса cmd.exe и остановил свое выполнение на брейкпойнте на операторе, следующем СРАЗУ за CreateProcess. При этом, как опять же утверждает автор, процесс cmd.exe едва стартовав тут же снимается с выполнения... В этот момент при такой ситуации состояние клиента серверу абсолютно безразлично - процесс сервера отладчик приостановил на брейкпойнте.


 
umbra ©   (2006-01-20 16:16) [23]


>
>   if not (CreateProcess(nil, "cmd.exe", nil, nil,
>     True, 0, nil, nil, St, Pr)) then
>   MessageDlg("Ошибка:"+SysErrorMessage(GetLastError),MtError,
>       [MbOk],0); // ошибки не будет
>   CloseHandle(Pr.hProcess);
>   CloseHandle(Pr.hThread);


может,я чего-то недопонимаю, но по-моему в этом фрагменте написано, что если процесс успешно создан, то его надо сразу же закрыть. или я не прав?


 
Digitman ©   (2006-01-20 16:27) [24]


> или я не прав?


Не прав.

Закрытие хендла в дан.случае не означает уничтожение созданного объекта-процесса, теряется лишь доступ тек.процесса к этому объекту.

А даже если ты и был бы прав, то - вникни еще раз в [12] - автор утверждает, что строчка CloseHandle(Pr.hProcess) еще не выполнена (отладчик поймал брейкпойнт на ней и приостановил текущий процесс), а процессу cmd.exe уже приключился кирдык


 
GanibalLector ©   (2006-01-20 19:54) [25]

Да,фаеврол стоит.При тестах я его закрывал или делал Allow All.
Вирусов вроде нет ;) Неделю назад проверял Касперским.
Даже поставил все update-ты последние в надежде на счастье. Но увы :(

В общем,я свою проблему разрешил.Сделал так : при получении сервером от клиента определенной команды запускаю "cmd.exe /c тут_комманда" и перенаправляю ввод-вывод на файл или pipe.Жду завершения процесса,накапливаю все в буфере,а потом отвечаю клиенту этим буфером.Работает за исключением пары комманд(find и еще что-то). От Лукавого конечно,но работает ;)

А на работе,все работает и так(т.е. через перенаправление cmd на сокет).

Вот такие чудеса !

З.Ы. Спасибо! Персонально Digitman ©   (19.01.06 10:51) [11]. Принял на вооружение ;)


 
Лорд Байрон ©   (2006-01-22 12:00) [26]

В какой из инет магазинов лучше регистрироваться чтобы больше покупали и какие проги надо продавать.
Помогите плизззззззззз...
P.S.
Прога создающая стерео изображение годится?



Страницы: 1 вся ветка

Текущий архив: 2006.05.14;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.058 c
2-1145693535
Ell
2006-04-22 12:12
2006.05.14
int64 в цикле


15-1145537828
fast2
2006-04-20 16:57
2006.05.14
Где взять маленькие рисунки всяких стрелочек, галочек и т.д.


2-1145784517
Mark86
2006-04-23 13:28
2006.05.14
как забить массив значений в Combobox?


2-1145588748
Tans
2006-04-21 07:05
2006.05.14
Help!


3-1143008249
abhtr
2006-03-22 09:17
2006.05.14
Последующий поиск