Solved

Problem converting to Delphi 2009 from Delphi 2006

Posted on 2009-05-20
15
1,309 Views
Last Modified: 2012-05-07
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

0
Comment
Question by:LeTay
  • 9
  • 6
15 Comments
 
LVL 12

Expert Comment

by:Hypo
ID: 24431350
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
 

Author Comment

by:LeTay
ID: 24431725
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
 
LVL 12

Expert Comment

by:Hypo
ID: 24431912
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
 

Author Comment

by:LeTay
ID: 24448521
I will test this probably the 10th of June
I keep you informed
Thanks
0
 

Author Comment

by:LeTay
ID: 24801991
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
 
LVL 12

Expert Comment

by:Hypo
ID: 24802582
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
 

Author Comment

by:LeTay
ID: 24802795
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:LeTay
ID: 25334779
Hypo,
No final idea to fix this ?
Thanks
0
 
LVL 12

Expert Comment

by:Hypo
ID: 25335033
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
 

Author Comment

by:LeTay
ID: 25335298
I will try next week
This is an application I developed at my customer site where I will go one week from now
0
 

Author Comment

by:LeTay
ID: 25533499
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
 

Accepted Solution

by:
LeTay earned 0 total points
ID: 25940905
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
 
LVL 12

Expert Comment

by:Hypo
ID: 25941021
So you've got an answer to your addional question now then?  
0
 

Author Comment

by:LeTay
ID: 25941032
Yes and the solution is so trivial !
0
 
LVL 12

Expert Comment

by:Hypo
ID: 25941109
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

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now