View Issue Details

IDProjectCategoryView StatusLast Update
0034158FPCRTLpublic2018-08-20 15:55
ReporterKlaus1Assigned ToMarco van de Voort 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformWindowsOSWindows 64-bitOS Version7
Product Version3.0.4Product Build 
Target VersionFixed in Version3.2.0 
Summary0034158: function ExecuteProcess not working with Unicodestring
DescriptionI have seen that the function only work with Ansistring and when I have umlaut Ü,Ö,Ä in file name the function not work correct.
I have the function adapted and I think is ok.
I think is good in SysUtils and is possible Ansistring and Unicodestring.
   
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files
  • ExecuteProcess.pas (1,781 bytes)
    {adaption from freepascal but with Widestring}
    function fnExecuteProcess(const Path, ComLine: Widestring;
                              Flags:TExecuteFlags=[]):Integer;
    // win specific  function
    var
      SI: TStartupInfoW;
      PI: TProcessInformation;
      Proc : THandle;
      l    : DWord;
      CommandLine :Widestring;
      e    : EOSError;
      ExecInherits : Longbool;
    begin
      FillChar(SI, SizeOf(SI), 0);
      SI.cb:=SizeOf(SI);
      SI.wShowWindow:=1;
      { always surround the name of the application by quotes
        so that long filenames will always be accepted. But don't
        do it if there are already double quotes, since Win32 does not
        like double quotes which are duplicated!
      }
      if pos('"',path)=0 then
        CommandLine:='"'+path+'"'
      else
        CommandLine:=path;
      if ComLine <> '' then
        CommandLine:=Commandline+' '+ComLine+#0
      else
        CommandLine := CommandLine + #0;
    
      ExecInherits := ExecInheritsHandles in Flags;
    
      if not CreateProcessW(nil, PWideChar(CommandLine),
                            nil, nil, ExecInherits,$20, nil, nil, SI, PI) then
        begin
          e:=EOSError.CreateFmt('Failed to execute "%s" Errorcode "%d"',
                                [CommandLine,GetLastError]);
          e.ErrorCode:=GetLastError;
          raise e;
        end;
      Proc:=PI.hProcess;
      if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
        begin
          GetExitCodeProcess(Proc,l);
          CloseHandle(Proc);
          CloseHandle(PI.hThread);
          result:=l;
        end
      else
        begin
          e:=EOSError.CreateFmt('Failed to execute "%S" Errorcode "%d"',
                                [CommandLine,GetLastError]);
          e.ErrorCode:=GetLastError;
          CloseHandle(Proc);
          CloseHandle(PI.hThread);
          raise e;
        end;
    end;
                   
    ExecuteProcess.pas (1,781 bytes)

Activities

Klaus1

2018-08-20 13:33

reporter  

ExecuteProcess.pas (1,781 bytes)
{adaption from freepascal but with Widestring}
function fnExecuteProcess(const Path, ComLine: Widestring;
                          Flags:TExecuteFlags=[]):Integer;
// win specific  function
var
  SI: TStartupInfoW;
  PI: TProcessInformation;
  Proc : THandle;
  l    : DWord;
  CommandLine :Widestring;
  e    : EOSError;
  ExecInherits : Longbool;
begin
  FillChar(SI, SizeOf(SI), 0);
  SI.cb:=SizeOf(SI);
  SI.wShowWindow:=1;
  { always surround the name of the application by quotes
    so that long filenames will always be accepted. But don't
    do it if there are already double quotes, since Win32 does not
    like double quotes which are duplicated!
  }
  if pos('"',path)=0 then
    CommandLine:='"'+path+'"'
  else
    CommandLine:=path;
  if ComLine <> '' then
    CommandLine:=Commandline+' '+ComLine+#0
  else
    CommandLine := CommandLine + #0;

  ExecInherits := ExecInheritsHandles in Flags;

  if not CreateProcessW(nil, PWideChar(CommandLine),
                        nil, nil, ExecInherits,$20, nil, nil, SI, PI) then
    begin
      e:=EOSError.CreateFmt('Failed to execute "%s" Errorcode "%d"',
                            [CommandLine,GetLastError]);
      e.ErrorCode:=GetLastError;
      raise e;
    end;
  Proc:=PI.hProcess;
  if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
    begin
      GetExitCodeProcess(Proc,l);
      CloseHandle(Proc);
      CloseHandle(PI.hThread);
      result:=l;
    end
  else
    begin
      e:=EOSError.CreateFmt('Failed to execute "%S" Errorcode "%d"',
                            [CommandLine,GetLastError]);
      e.ErrorCode:=GetLastError;
      CloseHandle(Proc);
      CloseHandle(PI.hThread);
      raise e;
    end;
end;
               
ExecuteProcess.pas (1,781 bytes)

Klaus1

2018-08-20 13:51

reporter   ~0110166

supplement: the cause is in case of UTF8string with umlaut Ö,Ü,Ä en filename. Lazarus work with UTF8 strings and the declaration for string = UTF8string but a UTF8 string is not a normal Ansistring with 1 byte coding. the function not convert to windows codepage and so the calling of CreateProcessA not work.
On windows is always good use the "W" functions for direct windows routines.

I think a good idea is all the functions calling windows routines with "A" deaktivate and only use the "W" functions. I think that is good for a new version from freepascal.
Regards Klaus

Marco van de Voort

2018-08-20 15:19

manager   ~0110169

Last edited: 2018-08-20 15:20

View 2 revisions

- To use unicode, make sure you craft a unicodestring and pass that to executeprocess. The Ansistring version has no unicode support.
 - no demonstration source of the problem.

Marco van de Voort

2018-08-20 15:55

manager   ~0110170

Fixed in trunk. Forget the above comment, I checked trunk, and everything was ok, but this was not merged back to 3.0.4

Next major version will fix this, and also have a unicode TProcess.

Issue History

Date Modified Username Field Change
2018-08-20 13:33 Klaus1 New Issue
2018-08-20 13:33 Klaus1 File Added: ExecuteProcess.pas
2018-08-20 13:51 Klaus1 Note Added: 0110166
2018-08-20 15:19 Marco van de Voort Note Added: 0110169
2018-08-20 15:19 Marco van de Voort Assigned To => Marco van de Voort
2018-08-20 15:19 Marco van de Voort Status new => feedback
2018-08-20 15:20 Marco van de Voort Note Edited: 0110169 View Revisions
2018-08-20 15:55 Marco van de Voort Note Added: 0110170
2018-08-20 15:55 Marco van de Voort Status feedback => resolved
2018-08-20 15:55 Marco van de Voort Fixed in Version => 3.2.0
2018-08-20 15:55 Marco van de Voort Resolution open => fixed