[C++] popen maar dan in Borland C Builder (win32)

Pagina: 1
Acties:

  • JokerLash
  • Registratie: Februari 2002
  • Laatst online: 03-04 07:27
Ik probeer dus een DOS exe uit te voeren binnen men programma en wil hiervan de uitvoer die normaal in het dosvenster komt opslaan in een string.

Hiervoor heb ik wel al een linux variant kunnen vinden "popen" maar dit werkt niet in windows of ik doe iets fout.

Tevens heb ik al gezocht op GoT maar kan niet echt een concrete oplossing vinden, naast system("command") en shellexecute die niet doen wat ik wil!

Wie helpt me verder :?

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 21-04 20:42

Tomatoman

Fulltime prutser

Is het echt een MS-DOS executable? Ik gok van niet en denk dat je een Windows consoleapplicatie hebt - zie hier voor het verschil. Dit verschil maakt wel wat uit voor de oplossing van je probleem.

Ik weet dat de oplossing voor console apps een keer in P&W is voorbijgekomen, maar ik kan het topic niet meer terugvinden :|

Een goede grap mag vrienden kosten.


Verwijderd

Ik vermoed dat je een Win32 console applicatie probeert uit te voeren en niet een echt DOS programma, dat verschilt namelijk nogal. ;) (EDIT: geninja'd door tomatoman :) )

Hoe dan ook, je moet gebruik maken van CreateProcess, je kunt dan in de STARTUPINFO die je meegeeft handles doorgeven naar pipes die verbonden worden aan de standard input/output/error.

Zie hier voor een voorbeeld.

[ Voor 8% gewijzigd door Verwijderd op 16-12-2005 01:15 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 21-04 20:42

Tomatoman

Fulltime prutser

Verwijderd schreef op vrijdag 16 december 2005 @ 01:13:
Ik vermoed dat je een Win32 console applicatie probeert uit te voeren en niet een echt DOS programma, dat verschilt namelijk nogal. ;) (EDIT: geninja'd door tomatoman :) )
Woei, een hele minuut sneller dan jij :P. De oplossing waar jij naar verwijst komt me in ieder geval bekend voor, volgens mij is dat dezelfde als die in het bewuste topic werd genoemd :).

Een goede grap mag vrienden kosten.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 21-04 13:55
De MSVCRT library heeft ook een popen-wannabe. Is een heel stuk makkelijker dan die Win32 API-ellende. Gebruik Borland C Builder ook dezelfde runtime library?

  • JokerLash
  • Registratie: Februari 2002
  • Laatst online: 03-04 07:27
Ik wil jullie bedanken voor jullie aanwijzingen ik ben met behulp van een example van borland zelf tot de volgende functie gekomen!

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
AnsiString CCO(const AnsiString sCommand){
  AnsiString sReturn = "";
  Application->ProcessMessages();
  int FBreak;

  // If NT do security stuff
  SECURITY_DESCRIPTOR sd;
  SECURITY_ATTRIBUTES sa;
  LPSECURITY_ATTRIBUTES lpsa = NULL;

  if (IsWindowsNT()) {
    InitializeSecurityDescriptor(&sd,
    SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, true, NULL, false);
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = true;
    sa.lpSecurityDescriptor = &sd;
    lpsa = &sa;
  }

  // Create the Pipe and get r/w handles
  HANDLE hReadPipe;
  HANDLE hWritePipe;
  assert(CreatePipe(&hReadPipe, &hWritePipe, lpsa, 2500000));

  // initialize STARTUPINFO struct
  STARTUPINFO si;
  memset(&si, 0, sizeof(STARTUPINFO));
  si.cb = sizeof(STARTUPINFO);
  si.dwFlags = STARTF_USESHOWWINDOW |STARTF_USESTDHANDLES;
  si.wShowWindow = SW_HIDE;
  si.hStdOutput = hWritePipe;
  si.hStdError = hWritePipe;
  PROCESS_INFORMATION pi;
  assert(hWritePipe);

  // Run the cmdLine tool
  Application->ProcessMessages();

  if(  CreateProcess(NULL, sCommand.c_str(), NULL, NULL, TRUE, 0, 0, 0, &si, &pi) ) {
    CloseHandle(pi.hThread);
    WaitForSingleObject(pi.hProcess, 90000);

    // read from the pipe and put in ansistring
    assert(hReadPipe);
    DWORD BytesRead; //unsigned long
    char dest[4000];
    bool RdLoopDone = false;

    FBreak = 1;
    if (ExitCode) Screen->Cursor = crDefault;
    while (!RdLoopDone) {
      memset(dest, 0, 4000);
      assert(ReadFile(hReadPipe, &dest, sizeof(dest), &BytesRead, NULL));
      // deze regel aan de ansistring plakken
      sReturn = sReturn + String(dest);
      if (BytesRead < 4000) RdLoopDone = true;
      if (FBreak > 150) RdLoopDone = true;
      FBreak++;
    }
  }
  // klaar met lezen
  CloseHandle(hReadPipe);
  CloseHandle(hWritePipe);
  CloseHandle(pi.hProcess);

  return sReturn;
}

int IsWindowsNT(){
    OSVERSIONINFO osv;
  osv.dwOSVersionInfoSize = sizeof(osv);
  GetVersionEx(&osv);
  return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}


Hij doet wat ik wil >:)

Verwijderd

Oei oei oei! Zet nooit code met side effects in een assert!

Assert is bedoelt puur en alleen voor het debuggen, en de meeste compilers zullen de assert calls verwijderen als je in Release configuratie compileert. De code die je daarin uitvoert is dan ook weg. De assert(CreatePipe(...)) verdwijnt compleet en er wordt dus opeens geen pipe meer gemaakt. In zo'n situatie zou je normaal gesproken twee statements moeten gebruiken, dus BOOL result = CreatePipe(...); assert(result);. Dan wordt de CreatePipe ook uitgevoerd als de preprocessor de assert weghaalt.

Maar ook dat is hier niet de goede oplossing, want assert moet je alleen gebruiken voor het controleren van situaties die in correcte code nooit voor kunnen komen, wederom omdat het controles zijn die niet worden uitgevoerd in de Release build, en dat is wat je eindgebruikers gaan gebruiken. Een ReadFile die mislukt kan ook in correcte code voorkomen (schijffout of wat dan ook), dit controleer je dus niet met assert maar met andere, eventueel zelf geschreven, error handling routines. Je wil immers dat die controles ook gedaan worden in release builds, niet alleen in debug builds.

  • JokerLash
  • Registratie: Februari 2002
  • Laatst online: 03-04 07:27
Verwijderd schreef op vrijdag 16 december 2005 @ 02:26:
Oei oei oei! Zet nooit code met side effects in een assert!

Assert is bedoelt puur en alleen voor het debuggen, en de meeste compilers zullen de assert calls verwijderen als je in Release configuratie compileert. De code die je daarin uitvoert is dan ook weg. De assert(CreatePipe(...)) verdwijnt compleet en er wordt dus opeens geen pipe meer gemaakt. In zo'n situatie zou je normaal gesproken twee statements moeten gebruiken, dus BOOL result = CreatePipe(...); assert(result);. Dan wordt de CreatePipe ook uitgevoerd als de preprocessor de assert weghaalt.

Maar ook dat is hier niet de goede oplossing, want assert moet je alleen gebruiken voor het controleren van situaties die in correcte code nooit voor kunnen komen, wederom omdat het controles zijn die niet worden uitgevoerd in de Release build, en dat is wat je eindgebruikers gaan gebruiken. Een ReadFile die mislukt kan ook in correcte code voorkomen (schijffout of wat dan ook), dit controleer je dus niet met assert maar met andere, eventueel zelf geschreven, error handling routines. Je wil immers dat die controles ook gedaan worden in release builds, niet alleen in debug builds.
Bedankt voor je reactie maar zoals ik al zei komt dit stukje code rechtstreeks uit een voorbeeld van borland zelf. Hier stond nog meer omheen maar de niet nuttige dingen hebben ik eruit gehaald.

Graag zou ik weten hoe dit GOED op te lossen dus zonder de assert.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21-04 01:08

.oisyn

Moderator Devschuur®

Demotivational Speaker

Door de assert weg te halen maar de call naar CreatePipe te laten staan natuurlijk. Welke errors op kunnen treden kun je wel in de documentatie lezen :) (hetzelfde voor ReadFile een stukje verderop)

[ Voor 14% gewijzigd door .oisyn op 16-12-2005 11:11 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1