CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Pobieranie wyników działania skryptu *nixowego do Memo1

Pobieranie wyników działania skryptu *nixowego do Memo1

dział ogólny

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez nvdante » poniedziałek, 7 lutego 2011, 19:42

Powiem Ci Baronie, że coś szwankuje obsługa błędów. Na dole wyjaśnię dlaczego.
Kod obecnie jest taki:
KOD cpp:     UKRYJ  
void ErrorExit(String lpFun)
{ /* funkcja obsługujaca błędy */
   LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;

    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
                (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen(lpFun.c_str())+40)*sizeof(TCHAR));
    wsprintf((LPTSTR)lpDisplayBuf,
        TEXT("%s failed with error %d: %s"),
                lpFun, dw, lpMsgBuf);
        MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
        ExitProcess(dw);
}
//---------------------------------------------------------------------------
BOOL ProcessExists(String ProcesName, HANDLE &hProcess)
{ /* funkcja sprawdzająca czy proces istnieje */
 DWORD ExitCode;
 HANDLE Snap;
 PROCESSENTRY32 proces;

 Snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 proces.dwSize = sizeof(PROCESSENTRY32);

 if(Process32First(Snap, &proces))
 {
  do
  {
   if(proces.szExeFile[0] != '[')
   {
    if(SameText(proces.szExeFile, ProcesName))
    {
      TOKEN_PRIVILEGES tPriv;
      LUID luid;

      HANDLE hWndTok;
      if(!OpenProcessToken(GetCurrentProcess(),
         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hWndTok))
          { ErrorExit("OpenProcessToken: "); }

      if(!LookupPrivilegeValue(NULL, "SeDebugPrivilege", &luid ))
          { ErrorExit("LookupPrivilegeValue: "); }

      tPriv.PrivilegeCount = 1;
      tPriv.Privileges[0].Luid = luid;
      tPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

      if(!AdjustTokenPrivileges(hWndTok, false, &tPriv, sizeof(TOKEN_PRIVILEGES),
          (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
          { ErrorExit("AdjustTokenPrivileges: "); }


      hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, proces.th32ProcessID);
      if(GetLastError() > 0) { ErrorExit("OpenProcess: "); }

     CloseHandle(Snap);
     return true;
    }
   }
  }while(Process32Next(Snap , &proces));
 }
 CloseHandle(Snap);
 return false;
}

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
SpeedButton1->Caption="Proszę czekać!";
SpeedButton1->Refresh();

 WinExec(("C:\\program.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt " + Edit5->Text + " > dane\"").c_str(), SW_SHOW);

 HANDLE hProcess;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program.exe", hProcess)) break;
 }

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 WinExec(("C:\\program2.exe /console " + Edit1->Text + ":" + Edit2->Text + "@ip /command \"get dane c:\\\" \"exit\"").c_str(), SW_SHOW);

  HANDLE hProcess1;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program2.exe", hProcess1)) break;
 }

 WaitForSingleObject(hProcess1, INFINITE);
 CloseHandle(hProcess1);

 Memo1->Lines->LoadFromFile("C:\\dane");
 DeleteFile("c:\\dane");

SpeedButton1->Caption="Zaloguj na serwer i odczytaj dane";
SpeedButton1->Refresh();

String mText = Memo1->Lines->Strings[6];
int p = mText.Pos(":");
Edit5->Text = mText.SubString(p + 1, mText.Length()).Trim();        
}

Twierdzę tak dlaczego, że odpalenie tego kodu spowoduje odpalenie program1, poczekanie na zamknięcie, a później zawieszenie aplikacji i to w taki sposób, że trzeba ubijać proces bcb, bo inaczej nie można przerwać działania.
Próbowałem z pojedynczym uchwytem, jedynie przy pierwszej funkcji i wtedy, po zastosowaniu sleep'a działa bardzo dobrze. Problem jednak w tym, że muszę zastosować więcej niż 1 uchwyt i nie chcę sleepów.
Masz może jakiś pomysł?
Liberae sunt nostrae cogitationes
Avatar użytkownika
nvdante
Intelektryk
Intelektryk
 
Posty: 188
Dołączył(a): piątek, 12 czerwca 2009, 16:58
Lokalizacja: Dom
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Windows 7
Kompilator: VS 2015
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez Cyfrowy Baron » poniedziałek, 7 lutego 2011, 21:07

A co do ponownego uchwytu to jesteś pewny? Bo jak deklaruje pod jednym Button1 to dostaję info:


Masz błąd bo deklarujesz uchwyt dwukrotnie a wystarczy raz.



Zawieszenie powoduje pętla while. gdyż działa tak długo jak długo nie odnajdzie zadanego programu.
Przeprowadziłem taki test i u mnie program działa bez zarzutu:

KOD cpp:     UKRYJ  
 WinExec("c:\\program1.exe", SW_SHOW);

 HANDLE hProcess;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program1.exe", hProcess)) break;
 }

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 WinExec("c:\\program2.exe", SW_SHOW);

 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program2.exe", hProcess)) break;
 }

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 ShowMessage("Zakończono wszystkie procesy");


Jak widzisz jest tylko jeden uchwyt.



Zawieszenie programu u Ciebie powstaje prawdopodobnie tutaj:

KOD cpp:     UKRYJ  
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program2.exe", hProcess1)) break;
 }


Program nie odnajduje procesu program2.exe, więc pętla cały czas działa poszukując tego procesu i program pozostaje zblokowany. Przeprowadź test z kodem wyłączającym pętlę, gdy wykona określoną liczbę cykli, np:

KOD cpp:     UKRYJ  
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
SpeedButton1->Caption="Proszę czekać!";
SpeedButton1->Refresh();

 WinExec(("C:\\program.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt " + Edit5->Text + " > dane\"").c_str(), SW_SHOW);

 HANDLE hProcess;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program.exe", hProcess)) break;
 }

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 WinExec(("C:\\program2.exe /console " + Edit1->Text + ":" + Edit2->Text + "@ip /command \"get dane c:\\\" \"exit\"").c_str(), SW_SHOW);

 ShowMessage("Zakończono pierwszy proces. Szukam drugiego procesu");

 int cycle = 0;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program2.exe", hProcess)) break;
  cycle++;

  if(cycle >= 100000) break;
 }

 WaitForSingleObject(hProcess1, INFINITE);
 CloseHandle(hProcess1);

 Memo1->Lines->LoadFromFile("C:\\dane");
 DeleteFile("c:\\dane");

SpeedButton1->Caption="Zaloguj na serwer i odczytaj dane";
SpeedButton1->Refresh();

String mText = Memo1->Lines->Strings[6];
int p = mText.Pos(":");
Edit5->Text = mText.SubString(p + 1, mText.Length()).Trim();        
}


Zobaczysz, że teraz program się odwiesi po tym jak pętla wykona 100000 cykli. Z jakiegoś powodu program nie jest w stanie odnaleźć procesu program2. Dodatkowo dodałem komunikat, który wyświetla się po zakończeniu pierwszego procesu.
Czy kod odpala program2.exe, bo jeżeli go nie uruchomi, to pętla nie przestanie działać. Jeżeli program nie jest w stanie uruchomić procesu program2.exe, to tutaj szukaj przyczyny błędu, gdyż u mnie kod działa prawidłowo.




Sprawdź czy sam ten kod działa, czyli czy uruchamia program2.exe:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 WinExec(("C:\\program2.exe /console " + Edit1->Text + ":" + Edit2->Text + "@ip /command \"get dane c:\\\" \"exit\"").c_str(), SW_SHOW);
}
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez nvdante » wtorek, 8 lutego 2011, 13:36

Cyfrowy Baron napisał(a):Jak widzisz jest tylko jeden uchwyt.


Faktycznie, już poprawiłem i uruchomiłem 2-3 razy. Na razie bez zawieszenia.

Program nie odnajduje procesu program2.exe, więc pętla cały czas działa poszukując tego procesu i program pozostaje zblokowany.


Hmmm ... jestem pewny, że program się odpala. Tym bardziej, że poprawienie ilości uchwytów pomogło, o ile nic się nie zmieni.
Spróbuję dokończyć program, dam znać.
Liberae sunt nostrae cogitationes
Avatar użytkownika
nvdante
Intelektryk
Intelektryk
 
Posty: 188
Dołączył(a): piątek, 12 czerwca 2009, 16:58
Lokalizacja: Dom
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Windows 7
Kompilator: VS 2015
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez Cyfrowy Baron » wtorek, 8 lutego 2011, 14:26

Hmmm ... jestem pewny, że program się odpala. Tym bardziej, że poprawienie ilości uchwytów pomogło, o ile nic się nie zmieni.


To było tylko wyjaśnienie w jakiej sytuacji program może pozostać w zawieszenie. Jeżeli proces nie zostanie uruchomiony, to pętla while będzie działać w nieskończoność. Powinieneś się zabezpieczyć przed taką sytuacją, może tak jak podałem ze zmienną cycle w pętli while. Poza tym błąd może pojawić się w sytuacji gdy uchwyt będzie NULL, więc przed tym również powinieneś się zabezpieczyć:

KOD cpp:     UKRYJ  
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
 SpeedButton1->Caption="Proszę czekać!";
 SpeedButton1->Enabled = false; /* by nie można było kliknąć na przycisk */
 SpeedButton1->Refresh(); /* to jest chyba zbędne */

 WinExec(("C:\\program.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt " + Edit5->Text + " > dane\"").c_str(), SW_SHOW);

 HANDLE hProcess;
 int cycle = 0;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program.exe", hProcess)) break;
   cycle++;
   if(cycle >= 3000) return; /* przerwanie wykonywania kodu po 5 minutach, jeżeli nie odnaleziono procesu */
   Sleep(10);
 }

 if(hProcess == NULL) return;

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 WinExec(("C:\\program2.exe /console " + Edit1->Text + ":" + Edit2->Text + "@ip /command \"get dane c:\\\" \"exit\"").c_str(), SW_SHOW);

 ShowMessage("Zakończono pierwszy proces. Szukam drugiego procesu");

 cycle = 0;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program2.exe", hProcess)) break;
   cycle++;
   if(cycle >= 3000) return; /* przerwanie wykonywania kodu po 5 minutach, jeżeli nie odnaleziono procesu */
   Sleep(10);
 }

  if(hProcess == NULL) return;

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 Memo1->Lines->LoadFromFile("C:\\dane");
 DeleteFile("c:\\dane");

 SpeedButton1->Caption = "Zaloguj na serwer i odczytaj dane";
 SpeedButton1->Enabled = true; /* by można było kliknąć na przycisk */
 SpeedButton1->Refresh(); /* to jest chyba zbędne */

 String mText = Memo1->Lines->Strings[6];
 int p = mText.Pos(":");
 Edit5->Text = mText.SubString(p + 1, mText.Length()).Trim();        
}
 
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez nvdante » piątek, 11 lutego 2011, 14:47

Pozwolę sobie jeszcze na chwilę wrócić do tego wątku.
Macie może pomysł dlaczego taki zapis nie działa:
KOD cpp:     UKRYJ  
 WinExec(("C:\\program1.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt " + Edit5->Text + " dzis > /logowanie\"").c_str(), SW_HIDE);

 cycle = 0;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program1.exe", hProcess)) break;
   cycle++;
   if(cycle >= 3000) return;
   Sleep(10);
 }

 if(hProcess == NULL) return;

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 WinExec(("C:\\program2.exe /console " + Edit1->Text + ":" + Edit2->Text + "@ip /command \"get /logowanie c:\\\" \"exit\"").c_str(), SW_HIDE);

 cycle = 0;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program2.exe", hProcess)) break;
   cycle++;
   if(cycle >= 3000) return;
   Sleep(10);
 }

 if(hProcess == NULL) return;

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 WinExec(("C:\\program1.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"rm logowanie\"").c_str(), SW_SHOW);

 cycle = 0;
 while(1) /* oczekiwanie na uruchomienie procesu */
 {
  if(ProcessExists("program1.exe", hProcess)) break;
   cycle++;
   if(cycle >= 3000) return;
   Sleep(10);
 }

 if(hProcess == NULL) return;

 WaitForSingleObject(hProcess, INFINITE);
 CloseHandle(hProcess);

 Memo2->Lines->LoadFromFile("C:\\logowanie");
 DeleteFile("c:\\logowanie");


Kod ma za zadanie utworzyć plik, skopiować, skasować, a skopiowany odczytać.
Ręczne wywołanie skryptu wygląda tak:
Kod: Zaznacz cały
./skrypt opcje dzis

gdzie opcje są zmienne, a dziś to data.
Problem w tym, że jak wywołuje go ręcznie to działa, a przez program już nie.
Okazuje się, że samo wywołanie skryptu przebiega pomyślnie, bo jego użycie loguje się do pliku, więc teoretycznie program działa ok, ale plik o nazwie logowanie się nie tworzy. Próbowałem także dodać do skryptu opcję tworzenia pliku, ale to nic nie daje :-(
Liberae sunt nostrae cogitationes
Avatar użytkownika
nvdante
Intelektryk
Intelektryk
 
Posty: 188
Dołączył(a): piątek, 12 czerwca 2009, 16:58
Lokalizacja: Dom
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Windows 7
Kompilator: VS 2015
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez Cyfrowy Baron » piątek, 11 lutego 2011, 14:55

Jak rozumiem nie działa już pierwsze wywołanie WinExec?! Może polecenie ./skrypt opcje dzis daj bez cudzysłowów, czyli:

KOD cpp:     UKRYJ  
WinExec(("C:\\program1.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  ./skrypt " + Edit5->Text + " dzis > /logowanie").c_str(), SW_HIDE);


Problem niewątpliwie dotyczy sposobu przekazywania argumentów do programu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez nvdante » piątek, 11 lutego 2011, 15:03

Niestety to także nie powoduje powstania pliku.
Dodam, jeszcze takie kody:

KOD cpp:     UKRYJ  
WinExec(("C:\\program1.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt " + Edit5->Text + " > /dane\"").c_str(), SW_HIDE);


KOD cpp:     UKRYJ  
WinExec(("C:\\program1.exe " + Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt2 " + Edit5->Text + " dzis > dane2\"").c_str(), SW_HIDE);


Oba obsługują inne skryptu, ale pierwszy działa, drugi nie.
Dodając, że ręcznie działa pierwszy i drugi skrypt to wskazuje na problem z przekazywaniem danych PROGRAM <-> SKRYPT.
Liberae sunt nostrae cogitationes
Avatar użytkownika
nvdante
Intelektryk
Intelektryk
 
Posty: 188
Dołączył(a): piątek, 12 czerwca 2009, 16:58
Lokalizacja: Dom
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Windows 7
Kompilator: VS 2015
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez Cyfrowy Baron » piątek, 11 lutego 2011, 15:09

Zamiast WinExec spróbuj ShellExecute:

KOD cpp:     UKRYJ  
 ShellExecuteA( NULL, "open", "C:\\program1.exe",
                (Edit1->Text + "@ip -pw " + Edit2->Text + "  \"./skrypt " +
                 Edit5->Text + " > /dane\"").c_str(),
                 NULL, SW_SHOWNORMAL);
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez nvdante » piątek, 11 lutego 2011, 15:18

Jest mała zmiana, bo plik logowanie się tworzy, ale jest pusty.
Wygląda to tak, jakby przekazywanie danych działało prawidłowo, bo mniej więcej widzę co leci z aplikacji do skryptu, ale gdy skrypt się wywoła z podanymi opcjami to program nie odbiera wszystkiego tylko część danych w postaci na przykład utworzenia pliku ( pustego ).
Liberae sunt nostrae cogitationes
Avatar użytkownika
nvdante
Intelektryk
Intelektryk
 
Posty: 188
Dołączył(a): piątek, 12 czerwca 2009, 16:58
Lokalizacja: Dom
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Windows 7
Kompilator: VS 2015
Gadu Gadu: 0
    Windows XPFirefox

Re: Pobieranie wyników działania skryptu *nixowego do Memo1

Nowy postprzez Cyfrowy Baron » piątek, 11 lutego 2011, 15:50

Nie mam już pomysłów.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Poprzednia strona

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 38 gości

cron