ShellExecute i parametry wiersza poleceń

dział ogólny

ShellExecute i parametry wiersza poleceń

Nowy postprzez banita » sobota, 27 wrzeÅ›nia 2008, 18:05

muszę napisać bardzo proste, podstawowe GUI dla programu Grep(przeportowanego z linuxa na winde).
mam problem z funkcją ShellExecute, otóż:
Kod: Zaznacz cały
ShellExecute(Form1->Handle, NULL , "grep.exe", "-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt", "", SW_HIDE);


w miejscu lpParameters podaje:
-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt

i wszystko cacy tylko że wyniki przekazywane są na standardowe wyjście a nie do pliku d:\\log.txt jak określiłem w parametrze.
przy ręcznym odpaleniu programu Grep w konsoli to wyniki są ładnie kierowane do pliku. jakiś pomysł jak to wykonać w funkcji ShellExecute?
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez Cyfrowy Baron » sobota, 27 wrzeÅ›nia 2008, 19:13

Funkcja ShellExecute służy tylko do uruchomienia programu z jednym argumentem, ta funkcja nie analizuje argumentu przekazywanego z linii komend tylko go przekazuje do programu. Teoretycznie program GREP powinien sam przeanalizować parametr i coś z nim zrobić, ale to tak nie działa.
Programy pobierają standardowo zawsze jeden parametr ParamStr(0) i jest to zawsze ścieżka dostępu do programu wraz z pełną nazwą pliku, tak już jest w Windows, kolejne argumenty to są ParamStr(1), ParamStr(2) i tak dalej, te dodatkowe argumenty są odbierane przez program tylko jeżeli program jest nastawiony na ich odbieranie, a ten Tój program GREP najwyraźniej oczekuje więcej niż jeden taki argument. Problem polega jednak na tym, że do programu należy przekazywać argumenty pojedynczo, a nie jako ciąg znaków, czyli nie tak:

"-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt"

lecz tak:

"\"-i vector\" \"d:\\TEST___\\SLT1.cpp\" \"d:\\TEST___\\STL2.cpp > d:\\log.txt\""

nie jestem pewien tej składni, chodzi jednak o to, że jeżeli program oczekuje kilki parametrów jeden po drugim to tak należy je przekazywać, jako kilka parametrów a wszystkie w jednym.



Lepszym rozwiązaniem jest funkcja CreateProcess i dla Twoich potrzeb mogła by wyglądać tak:

Kod: Zaznacz cały
//--------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   AnsiString Grep = "c:\\grep.exe";
   Grep = Grep + " " + "\"-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt\"";

    STARTUPINFO StartupInfo;
    ;ZeroMemory( &StartupInfo, sizeof(STARTUPINFO));
    StartupInfo.cb = sizeof(STARTUPINFO);

    PROCESS_INFORMATION ProcessInfo;

    if(CreateProcess(NULL,
        Grep.c_str(),
        NULL,
        NULL,
        TRUE,
        NORMAL_PRIORITY_CLASS,
        NULL,
        NULL,
        &StartupInfo,
        &ProcessInfo))
    {
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    }

}
//--------------------------------


Przy takim zapisie: "-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt" przekazujesz do programu parametr w takiej postaci:

-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt

Zauważ, że brakuje cudzysłowów, podczas gdy przy takim zapisie: "\"-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt\"" uzyskasz:

"-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt"

czyli przekazywany parametr zawiera cudzysłowie. Być może problem z ShellExecute sprowadza się tak naprawdę tylko do tych cudzysłowó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
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez banita » niedziela, 28 wrzeÅ›nia 2008, 16:46

niestety zapis tych parametrów (cudzysłowia) jest niepoprawny. szukałem informacji na ten temat ale wszędzie piszą jak przekazać jeden parametr.

EDIT:
tak sobie teraz pomyślałem że chyba wszystko jest w porządku:D
uruchamiam program w ten sposób:
grep -i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt

ta część:
-i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp

wykonuje się poprawnie, a są tu cztery parametry: ignorowanie wielkości liter, szukany ciąg i dwa pliku do przeszukania.
natomiast
> d:\\log.txt

już się nie wykonuje, ale to przecież nie jest parametr tylko przekierowanie wyjścia programu do pliku. dlatego nie powstaję ten plik z wynikami... tak mi się wydaje.

w takiej sytuacje pytanie brzmi: jak uruchomić program i równocześnie przekierować jego wyjście do pliku a nie na sterownik konsoli.
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez Cyfrowy Baron » niedziela, 28 wrzeÅ›nia 2008, 17:54

już się nie wykonuje, ale to przecież nie jest parametr tylko przekierowanie wyjścia programu do pliku. dlatego nie powstaję ten plik z wynikami... tak mi się wydaje.

w takiej sytuacje pytanie brzmi: jak uruchomić program i równocześnie przekierować jego wyjście do pliku a nie na sterownik konsoli.


i tutaj masz rację. Rozwiązaniem jest wykorzystanie PIPE, opis w serwisie Cyfrowy Baron ostatnia aktualizacja, porada Wyświetlanie zawartości konsoli CMD.exe w Memo - wg. pomysłu kinio w dziale: porady > różne 2
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
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez kinio » niedziela, 28 wrzeÅ›nia 2008, 18:27

Cześć

Tak, mam tutaj dla Ciebie poprawioną wersję biblioteki, bo w tamtej nie dało sie uruchomić procesu z parametrami.
No i jeszcze przykładową aplikację, która pokazuje jak jej użyć.
Wszystko w załączniku.

pozdr!
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
If a machine is expected to be infallible, it cannot also be intelligent.
-- A.Turing
Avatar użytkownika
kinio
Homos antropiczny
Homos antropiczny
 
Posty: 67
Dołączył(a): poniedziałek, 14 lipca 2008, 08:51
PodziÄ™kowaÅ‚ : 0
OtrzymaÅ‚ podziÄ™kowaÅ„: 0
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez banita » niedziela, 28 wrzeÅ›nia 2008, 19:52

w zasadzie ten sam efekt uzyskam poprzez:
Kod: Zaznacz cały
system("grep.exe -i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt");

tyle że jest to bardzo nieładne i słabe rozwiązanie.

innym rozwiązaniem które przyszło mi do głowy to utworzenie pliku *.bat z zawartością:
grep.exe -i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt

i w funkcji ShellExecute odpalić ten plik *.bat, przy zmianie parametrów po prostu modyfikować zawartość pliku.

biblioteka kinio jest w porządku ale zastanawiam się czy jest sens zaprzęgać taki mechanizm dla stosunkowo małych potrzeb.
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 29 wrzeÅ›nia 2008, 09:01

i w funkcji ShellExecute odpalić ten plik *.bat, przy zmianie parametrów po prostu modyfikować zawartość pliku.

biblioteka kinio jest w porządku ale zastanawiam się czy jest sens zaprzęgać taki mechanizm dla stosunkowo małych potrzeb.


Używając pliku *.BAT właśnie stosujesz ten mechanizm, z tą różnicą, że Twój program uruchamia plik wsadowy, a API systemu robi resztę.

Użycie biblioteki kinio do tak prostej operacji, może rzeczywiście wydawać się tutaj zbyt... nie wiem jakiego wyrażenia użyć...

Można by to trochę uprościć, aczkolwiek nie wiem czy to zadziała:

Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
  AnsiString fileP = "c:\\grep.exe -i vector d:\\TEST___\\SLT1.cpp d:\\TEST___\\STL2.cpp > d:\\log.txt";

  SECURITY_ATTRIBUTES sa;
  ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  sa.bInheritHandle = true;
  sa.lpSecurityDescriptor = NULL;
  HANDLE ReadPipeHandle;
  HANDLE WritePipeHandle;
  if(!CreatePipe(&ReadPipeHandle, &WritePipeHandle, &sa, 0))
        RaiseLastWin32Error();

  STARTUPINFO si;
  ZeroMemory(&si, sizeof(STARTUPINFO));
  si.cb=sizeof(STARTUPINFO);
  si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = WritePipeHandle;
  si.hStdError = WritePipeHandle;

  PROCESS_INFORMATION pi;
  ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  if(!CreateProcess(fileP.c_str(), NULL, NULL, NULL, true, 0,
               NULL, NULL, &si, &pi))
      RaiseLastWin32Error();

  char Data[1024];
  for (;;)
  {
    DWORD BytesRead;
   DWORD TotalBytes;
    DWORD BytesLeft;


   if(!PeekNamedPipe(ReadPipeHandle, Data, sizeof(Data), &BytesRead,
      &TotalBytes, &BytesLeft))RaiseLastWin32Error();

    if(BytesRead)
    {
     if(!ReadFile(ReadPipeHandle, Data, sizeof(Data)-1, &BytesRead, NULL))
          RaiseLastWin32Error();
     Data[BytesRead] = '\0';
      Memo1->Lines->Add(AnsiString(Data));

    }
    else
   {
    if(WaitForSingleObject(pi.hProcess,0) == WAIT_OBJECT_0) break;
    }
  }
  CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
  CloseHandle(ReadPipeHandle);
  CloseHandle(WritePipeHandle);
}
//---------------------------------------------------------------------------


Oczywiście, jeżeli nie potrzebujesz to możesz zrezygnować z tego fragmentu kodu, w którym następuje wyświetlanie operacji w Memo1.
Daj znać, czy to zadziałało, gdyż nie mam tego programu grep.exe i sam nie mogę sprawdzić.
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
    NieznanyNieznana

Re: ShellExecute i parametry wiersza poleceń

Nowy postprzez banita » poniedziaÅ‚ek, 29 wrzeÅ›nia 2008, 15:27

niestety dziejÄ… siÄ™ jakieÅ› cyrki:)

Kod: Zaznacz cały
  if(!CreateProcess(fileP.c_str(), NULL, NULL, NULL, true, 0,
               NULL, NULL, &si, &pi))
      RaiseLastWin32Error();


funkcja RaiseLastWin32Error(); rzuca jakimś wyjątkiem (błędny katalog bądź nazwa woluminu). oczywiście ścieżkę do programu ustawiłem poprawną.

wygląda na to że najprościej będzie z tym plikiem *.bat, i będę mógł ukryć uruchomienie tego programu odpowiednim parametrem w ShellExecute
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

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 20 gości

cron