Solved

Problem converting to Delphi 2009 from Delphi 2006

Posted on 2009-05-20
15
1,306 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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

744 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

10 Experts available now in Live!

Get 1:1 Help Now