如何从delphi 2010应用程序调用MS-DOS批处理程序

Sna*_*ore 1 delphi batch-file

我正在尝试编写一个例程,它将在Delphi 2010应用程序中执行DOS批处理程序.我在Delphi 6中运行的旧例程不断给我错误信息: -

"Project1.exe引发异常类EAccessViolation,并在模块'kernel32.dll'中的地址7C82F29C处发出访问冲突'.写入地址004A3B82".

这是我在Delphi 6中运行的旧例程: -

Procedure TForm1.BatchProgramCall;  
var  
    StartInfo: TStartUpInfo;  
    ProcInfo: TProcessInformation;  
    createOK: Boolean;  
begin  
     FillChar(StartInfo, SizeOf(TStartUpInfo), #0);  
     FillChar(ProcInfo, SizeOf(TProcessInformation), #0);  
     StartInfo.cb := SizeOf(TStartUpInfo);  
     StartInfo.dwFlags := STARTF_USESHOWWINDOW;  
     StartInfo.wShowWindow := SW_SHOWMINIMIZED;  

     createOK := CreateProcess(Nil,PCHAR('SOMEBATCHPROGRAM.BAT'),Nil, Nil, false,
                               CREATE_NEW_PROCESS_GROUP+HIGH_PRIORITY_CLASS,
                               NIL, NIL, STARTINFO, PROCINFO);
     if createOK then
        waitForSingleObject(PROCINFO.HPROCESS, Infinite);
end;
Run Code Online (Sandbox Code Playgroud)

请让我知道我做错了什么或有更好的方法来解决这个问题...非常感谢.

RRU*_*RUZ 10

您可以阅读有关CreateProcess和unicode问题的这些文章.

此函数的Unicode版本CreateProcessW可以修改此字符串的内容.因此,此参数不能是只读内存的指针(例如const变量或文字字符串).如果此参数是常量字符串,则该函数可能会导致访问冲突.

您可以使用UniqueString函数作为解决方法来解决问题.

Procedure TForm1.BatchProgramCall;  
var
    StartInfo: TStartUpInfo;
    ProcInfo: TProcessInformation;
    createOK: Boolean;
    sMyBat: string;

begin
     FillChar(StartInfo, SizeOf(TStartUpInfo), #0);
     FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
     StartInfo.cb := SizeOf(TStartUpInfo);
     StartInfo.dwFlags      := STARTF_USESHOWWINDOW;
     StartInfo.wShowWindow := SW_SHOWMINIMIZED;

     sMyBat  :='SOMEBATCHPROGRAM.BAT';
     UniqueString(sMyBat); //this make the magic.
     createOK := CreateProcess(Nil,pchar(sMyBat),Nil, Nil, false,
                               CREATE_NEW_PROCESS_GROUP+HIGH_PRIORITY_CLASS,
                               NIL, NIL, STARTINFO, PROCINFO);
     if createOK then
        waitForSingleObject(PROCINFO.HPROCESS, Infinite);
end;
Run Code Online (Sandbox Code Playgroud)


mgh*_*hie 6

您的函数在Delphi 2010中失败但在Delphi 6中工作的原因是CreateProcessW()不能使用只读lpCommandLine参数调用它.引用MSDN文档:

此函数的Unicode版本CreateProcessW可以修改此字符串的内容.因此,此参数不能是只读内存的指针(例如const变量或文字字符串).如果此参数是常量字符串,则该函数可能会导致访问冲突.

它与Delphi 6一起使用的原因是所有的Windows函数都是内部的宽字符串,而Ansi版本除了将字符串参数转换为宽字符串对应,然后调用宽版本之外什么都不做.使用常量调用函数,使用Delphi 6 Windows在内部为您创建可写缓冲区.使用Delphi 2010,您将体验AV.

请注意,您的程序还有另一个错误,因为文档也说明了:

要运行批处理文件,必须启动命令解释程序; 将lpApplicationName设置为cmd.exe并将lpCommandLine设置为以下参数:/ c加上批处理文件的名称.