Entwickler-Ecke

Windows API - CreateProcess: Problem mit Parametern


yogo - Sa 19.02.11 16:19
Titel: CreateProcess: Problem mit Parametern
Hallo,

ich habe mit delphi 6 eine anwendung geschrieben, in der ich diese zusammenkopierte funktion benutzt habe:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
function CreateProcessCstm(befehl: string): Longint;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  //Fenster nicht anzeigen
  StartupInfo.dwFlags := StartF_UseShowWindow;

  StartupInfo.wShowWindow := SW_Hide;
  //in delphi 6 ging das hier zB mit Befehl := 'sqlcmd -?'
  //if CreateProcess(nil, PChar(Befehl), nil, nil, False, 0, nil,
  //  PChar(ExtractFilePath(ParamStr(0))), StartupInfo, ProcessInfo) then

  // hier gibts nen zugriffsfehler in der kernel32.dll:
  if CreateProcess(nil, PChar('C:\Windows\System32\calc.exe'), nilnil, False, 0nil,
    nil, StartupInfo, ProcessInfo) then
  //oder:
  if CreateProcess(nil, PChar('calc.exe -bla'), nilnil, False, 0nil,
    nil, StartupInfo, ProcessInfo) then
  //oder: 
  if CreateProcess(PChar('calc.exe'), nilnilnil, False, 0nil,
    nil, StartupInfo, ProcessInfo) then
  //schon allein: 
  if CreateProcess(PChar('C:\Windows\System32\calc'), nilnilnil, False, 0nil,
    nil, StartupInfo, ProcessInfo) then



Nach der Portierung auf Delphi 2010 bekam ich dann allerdings Laufzeitfehler.
Die Hilfe sagt dazu:

Quelltext
1:
The first parameter, lpApplicationName, can be NULL, in which case the executable name must be in the white space-delimited string pointed to by lpCommandLine.                    

Trotzdem muss ich zB CreateProcess(PChar(C:\Windows\System32\calc.exe'), PChar('-bla'), ... ausführen, um einen Fehler zu Vermeiden.
Ich kann weder den Pfad weglassen, noch alles in den zweiten Parameter schreiben.

In meinem Fall (sqlcmd) ist allerdings nicht vorher klar, wo die executable stehen wird.
ShellExecute kommt nicht in Frage, da ich einen Error-Code erwarte.

Ich bin ratlos :nixweiss:
Kann mir jemand von euch sagen, was ich anders machen muss?


jaenicke - Sa 19.02.11 18:08

Das liegt daran, dass der zweite Parameter in der Unicodeversion variabel sein muss. Du übergibst aber Konstanten. Dass das eine Exception auslösen kann, steht doch sogar explizit in der Doku...
MSDN Doku zu CreateProcess [http://msdn.microsoft.com/en-us/library/ms682425(v=vs.85).aspx] hat folgendes geschrieben:
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Also muss das ein variabler Parameter sein. Ein einfacher Workaround:

Delphi-Quelltext
1:
2:
3:
procedure ExecuteFile(const AFileName: string);
begin
  CreateProcess(nil, PChar(AFileName + ''), ...
Durch die Stringkonkatenation wird der String zur Laufzeit neu im Speicher abgelegt und kann verändert werden. Das ist zwar nicht ganz sauber so, aber es funktioniert.

Um es sauber zu machen, müsstest du tatsächlich eine eigene Variable anlegen und die Daten dort hineinkopieren (also nicht nur casten).