przerobienie kodu na unicode

0

próbowałem przerobić następującą funkcję na unicode, ale bez powodzenia, jakieś sugestie ? dziękuję :)

wersja oryginalna (z sieci, działa):

function GetDosOutput(const CommandLine:string): string; 
var 
  SA: TSecurityAttributes; 
  SI: TStartupInfo; 
  PI: TProcessInformation; 
  StdOutPipeRead, StdOutPipeWrite: THandle; 
  WasOK: Boolean; 
  Buffer: array[0..255] of Char; 
  BytesRead: Cardinal; 
  WorkDir, Line: String; 
begin 
  Application.ProcessMessages; 
  with SA do 
  begin 
    nLength := SizeOf(SA); 
    bInheritHandle := True; 
    lpSecurityDescriptor := nil; 
  end; 
  // create pipe for standard output redirection 
  CreatePipe(StdOutPipeRead,  // read handle 
             StdOutPipeWrite, // write handle 
             @SA,             // security attributes 
             0                // number of bytes reserved for pipe - 0 
default 
             ); 
  try 
    // Make child process use StdOutPipeWrite as standard out, 
    // and make sure it does not show on screen. 
    with SI do 
    begin 
      FillChar(SI, SizeOf(SI), 0); 
      cb := SizeOf(SI); 
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; 
      wShowWindow := SW_HIDE; 
      hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect std 
input 
      hStdOutput := StdOutPipeWrite; 
      hStdError := StdOutPipeWrite; 
    end; 


    // launch the command line compiler 
    WorkDir := 'C:\'; 
    WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil, 
PChar(WorkDir), SI, PI); 


    // Now that the handle has been inherited, close write to be safe. 
    // We don't want to read or write to it accidentally. 
    CloseHandle(StdOutPipeWrite); 
    // if process could be created then handle its output 
    if not WasOK then 
      raise Exception.Create('Could not execute command line!') 
    else 
      try 
        // get all output until dos app finishes 
        Line := ''; 
        repeat 
          // read block of characters (might contain carriage returns and 
line feeds) 
          WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); 


          // has anything been read? 
          if BytesRead > 0 then 
          begin 
            // finish buffer to PChar 
            Buffer[BytesRead] := #0; 
            // combine the buffer with the rest of the last run 
            Line := Line + Buffer; 
          end; 
        until not WasOK or (BytesRead = 0); 
        // wait for console app to finish (should be already at this point) 
        WaitForSingleObject(PI.hProcess, INFINITE); 
      finally 
        // Close all remaining handles 
        CloseHandle(PI.hThread); 
        CloseHandle(PI.hProcess); 
      end; 
  finally 
      result:=Line; 
      CloseHandle(StdOutPipeRead); 
  end; 
end; 


end.

wersja zmodyfikowana:
(zmieniłem tylko to co wiedziałem że trzeba, a więc CreateProcess na CreateProcessW i oczywiście string na widestring + pchar na pwidechar)
[EDIT]
może błąd jest w tej linijce ?

 WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);

widechar zajmuje ponoć dwa bajty a nie jeden, ale jak 255 zmieniłem na 510 a potem #0 na widechar(#0) to otrzymuję błąd
[/EDIT]

function GetDosOutput(const CommandLine: widestring; var text: wideString): Boolean;
var
             SA : TSecurityAttributes;
             SI : TStartupInfo;
             PI : TProcessInformation;
StdOutPipeRead,
StdOutPipeWrite : THandle;
          WasOK : Boolean;
         Buffer : array[0..255] of WideChar;
      BytesRead : Cardinal;
           Line : WideString;
begin
   Application.ProcessMessages;
   with SA do
        begin
        nLength := SizeOf(SA);
        bInheritHandle := True;
        lpSecurityDescriptor := nil;
        end;
   // create pipe for standard output redirection
   CreatePipe(StdOutPipeRead, // read handle
              StdOutPipeWrite, // write handle
              @SA, // security attributes
              0 // number of bytes reserved for pipe - 0 default
              );
   try
     // Make child process use StdOutPipeWrite as standard out,
     // and make sure it does not show on screen.
     with SI do
          begin
          FillChar(SI, SizeOf(SI), 0);
          cb := SizeOf(SI);
          dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
          wShowWindow := SW_HIDE;
          hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdinput
          hStdOutput := StdOutPipeWrite;
          hStdError := StdOutPipeWrite;
          end;
     // launch the command line compiler
     result := CreateProcessW(nil,pwidechar(CommandLine),nil,nil,True,0,nil,pwidechar(FWorkDir),SI,PI);
     // Now that the handle has been inherited, close write to be safe.
     // We don't want to read or write to it accidentally.
     CloseHandle(StdOutPipeWrite);
     // if process could be created then handle its output
     if result then
        try
        // get all output until dos app finishes
        Line := '';
        repeat
        // read block of characters (might contain carriage returns and line feeds)
        WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
        // has anything been read?
        if BytesRead > 0 then
           begin
           // finish buffer to pchar
           Buffer[BytesRead] := #0;
           // combine the buffer with the rest of the last run
//tu przechwytuję do tntMemo z czcionką unicode ale dostaję kwadraciki:
           Form1.TntMemo1.Lines.Add(Buffer);
           Line := Line + Buffer;
           end;
        until not WasOK or (BytesRead = 0);
        // wait for console app to finish (should be already at this point)
        WaitForSingleObject(PI.hProcess, INFINITE);
        finally
        // Close all remaining handles
        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);
      end;
   finally
     text := Line;
     CloseHandle(StdOutPipeRead);
   end;
end;
0

konsolowa aplikacja nie wysyła tekstu w postaci Unicode, więc musisz sam konwertować standardowe wyjście - użyj funkcji MultiByteToWideChar.

0
Jojersztajner napisał(a)

konsolowa aplikacja nie wysyła tekstu w postaci Unicode, więc musisz sam konwertować standardowe wyjście - użyj funkcji MultiByteToWideChar.

właśnie zauważyłem że robię pewne rzeczy na wyrost, ale czemu tego nie robią (ani nie przyjmują, ani tym bardziej nie wysyłają) skoro jest do dyspozycji PShellExecuteInfoW, przynajmniej z poziomu delphi, ale wiadomo że to jest windows. jeśli mam mieć pewność że nigdy nie otrzymam unicode to nie mam po co go obsługiwać w tym miejscu.
chyba że Cię źle zrozumiałem ale nie sądzę :)

[EDIT]
wiem to stąd bo sam oprogramowywałem PShellExecuteInfoW po czy ze zdziwieniem stwierdziłem że każdy enkoder audio (do tego mi to było potrzebne) po prostu wyżyguje :) z powrotem wszystki unikodowe pliki jakie mu się wciska, po ludzku pisząc nie obsługuje ich.

1 użytkowników online, w tym zalogowanych: 0, gości: 1