Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2006.05.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.009 c
2-1145943531
barakuda
2006-04-25 09:38
2006.05.14
ВЗЯТЬ ПО МОДУЛЮ


4-1140414579
Виталий Ульянов
2006-02-20 08:49
2006.05.14
Работа с портами


15-1143015202
WhiteBarin
2006-03-22 11:13
2006.05.14
Установка FIBScript


9-1129754635
Ricks
2005-10-20 00:43
2006.05.14
Элементарный поиск пути


2-1145876145
accinctus
2006-04-24 14:55
2006.05.14
свойства файлов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский