Problem converting to Delphi 2009 from Delphi 2006

I am converting large applications from Turbo Delphi 2006 to Delphi 2009 (Unicode full support)
Currently, I am blocked on the function listed below (see code)
It runs fine with TD2006 but not with Delphi 2009
I first commented the line OemToAnsi (will solve that later on)
So it compiles
But when running it, I get an access violation in kernel32.dll on the CreateProcess call
No idea why till now
Can somebody help with this ?
Thanks !
function RunDOSInSL(Command:string;SL:TStringList;Dir:string):boolean;
const
   CUANTOBUFFER = 2000;
var
  Seguridades         : TSecurityAttributes;
  PaLeer,PaEscribir   : THandle;
  start               : TStartUpInfo;
  ProcessInfo         : TProcessInformation;
  Buffer              : Pchar;
  BytesRead           : DWord;
  CuandoSale          : DWord;
  tb                  : PDWord;
  UseDir:string;
  BigString:string;
begin
  SL.Clear;
  BigString := '';
  Result := False;
  with Seguridades do
  begin
    nlength              := SizeOf(TSecurityAttributes);
    binherithandle       := true;
    lpsecuritydescriptor := nil;
  end;
  if CreatePipe (PaLeer, PaEscribir, @Seguridades, 0)
   then begin
    Buffer  := AllocMem(CUANTOBUFFER + 1);
    FillChar(Start,Sizeof(Start),#0);
    start.cb          := SizeOf(start);
    start.hStdOutput  := PaEscribir;
    start.hStdInput   := PaLeer;
    start.dwFlags     := STARTF_USESTDHANDLES +
                         STARTF_USESHOWWINDOW;
    start.wShowWindow := SW_HIDE;
    if CreateProcess(nil,PChar(Command),@Seguridades,@Seguridades,true,
                     NORMAL_PRIORITY_CLASS,nil,PChar(UseDir),start,ProcessInfo)
    then begin
      Result := True;
      new(tb);
      repeat
        CuandoSale := WaitForSingleObject( ProcessInfo.hProcess,100);
        repeat
          BytesRead := 0;
          PeekNamedPipe(PaLeer,nil,0,nil,tb,nil);
          if (tb ^= 0) then Break;
           ReadFile(PaLeer,Buffer[0],CUANTOBUFFER,BytesRead,nil);
          Buffer[BytesRead]:= #0;
          OemToAnsi(Buffer,Buffer);
          BigString := BigString + String(Buffer);
        until (BytesRead < CUANTOBUFFER);
        Application.ProcessMessages;
      until (CuandoSale <> WAIT_TIMEOUT);
      dispose(tb);
    end                                          // CreateProcess
    else raiseLastOSError;
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(PaLeer);
    CloseHandle(PaEscribir);
    SL.Text := BigString;
  end                                            // CreatePipe
  else raiseLastOSError;
end;

Open in new window

LVL 1
LeTayAsked:
Who is Participating?
 
LeTayConnect With a Mentor Author Commented:
I posted again the question ,more precisly on this forum : "Get the result (stdout) of a console application in a string" and got the answer right away
0
 
HypoCommented:
You should set the first parameter in CreateProcess to the path of the exe-file... I know that it is also passed in the Command parameter, and the help says that you can have the first parameter set to nil if the second parameter contains that name, but I've had the same problem as you have, and it was solved by setting the first Parameter to the exe-file path. If I remember correct, then this problem only exists for CreateProcessW and I never saw it with CreateProcessA, which would explain why you din't get it in Delphi2006.

regards
Hypo
0
 
LeTayAuthor Commented:
Excellent Hypo !
It works
I will give you the point
But I have an additional question concerning the resulting buffer coming back from the execution
Do I post another question or is it okay to post it here
In fact, the result of the function is to return the "stdout" of the executable (console application) into a TStringList (via its text property)
Running now a few sample, I get ... unreadable results
I suppose there is some conversion to do on the Buffer variable or before
I tried unicodestring() and things like that but result is still so strange...
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
HypoCommented:
I think the first problem was that your BUFFER variable is PChar (which is a PWideChar in delphi2009) whilst the data read from the pipe is in Ansi format. So first, change OemToAnsi to OemToChar, since OemToAnsi is obsolete and has been replaced by OemToChar... second, create a second targetBuffer, that is a PWideChar (which is PChar in D2009) to which you convert the data in OemToChar. This cfunction would then convert the Ansi data from the pipe into unicode data, that you can then accaumulate in the BigString variable.

The new lines would then be:
var
...
    Buffer : PAnsiChar;
    targetBuffer : PChar;
...
  Buffer[BytesRead] := #0;
  OemToChar(Buffer, targetBuffer);
  BigString := BigString + targetBuffer;
...

regards
Hypo
0
 
LeTayAuthor Commented:
I will test this probably the 10th of June
I keep you informed
Thanks
0
 
LeTayAuthor Commented:
Hello Hypo
Sorry to have tested your solution so lately
It is "almost" perfect
There is still a little thing not working
I debugged to be sure : during the OemToChar conversion of Buffer to targetBuffer, all characters are correctly converted except the hexa 13 and 10 (CR-LF) that separates each line.
In debug mode these characters are show as little squares
How can I fix this and really have the 13 and 10 remaining like that
Thanks
0
 
HypoCommented:
Hi,
I think that the characters #13 and #10 will always be displayed as squares when you look at them in the debugger (as will other control characters as well)... have you tried adding the text to a multiline control? how are the characters represented then?

regards
Hypo
0
 
LeTayAuthor Commented:
Hypo
In debug mode,when I look at the content of Buffer, it shows something like #D#A for these characters
Once "move" to targetBuffer, they are badly converted, that's sure : I tried to locate in debug mode via the expression Pos(chr(13),targetBuffer) but this returns zero
Indeed, the statement to put targetBuffer into the TStringList SL is SL.Text := targetBuffer
0
 
LeTayAuthor Commented:
Hypo,
No final idea to fix this ?
Thanks
0
 
HypoCommented:
Hi,
I've created a small test application, and I've got the same result as you (#13#10 is not converted correctly). Do you know why the original code used the OemToAnsi function? because if you can skip that function then it might solve your problem...

I know i recommended you to change from OemToAnsi to OemToChar, but what if you skip that function compleatley, and just let Delphi convert the strings instead?

Like this:

var
...
  Buffer : PAnsiChar;
...
  if (tb ^= 0) then Break;
    ReadFile(PaLeer,Buffer[0],CUANTOBUFFER,BytesRead,nil);
  Buffer[BytesRead] := #0;
  BigString := BigString + String(Buffer);



does it work then?

/Hypo
0
 
LeTayAuthor Commented:
I will try next week
This is an application I developed at my customer site where I will go one week from now
0
 
LeTayAuthor Commented:
I still have a problem with that famous #13#10 that is badly "converted" whatever conversion function I apply ...
Can somebody help on that ?
0
 
HypoCommented:
So you've got an answer to your addional question now then?  
0
 
LeTayAuthor Commented:
Yes and the solution is so trivial !
0
 
HypoCommented:
Man... I thought I solved your original problem?

"Excellent Hypo !
It works
I will give you the point
But I have an additional question concerning the resulting buffer coming back from the execution
Do I post another question or is it okay to post it here"
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.