2009-11-18 78 views
1

我正在尝试编写一个例程,该程序将从Delphi 2010应用程序中执行DOS批处理程序。我在Delphi 6中运行的旧例程不断给我提示错误信息: -如何从Delphi 2010应用程序中调用MS-DOS批处理程序

“Project1.exe引发异常类EAccessViolation,消息'模块'kernel32.dll'中的地址7C82F29C处出现访问冲突,写入地址004A3B82”。

这里是我的老套路,在德尔福工作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; 

请让我知道我做错了或有更好的方法去这个... 非常感谢。

+0

在StackOverflow上搜索“[delphi] ShellExecute”或“[delphi] ShellExecuteEx”会给你一些选择。 – mghie 2009-11-18 08:32:35

回答

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; 
+0

非常感谢... UniqueString确实发挥了魔力。 – Snackmoore 2009-11-18 09:32:55

+1

+1为了链接到CreateProcess声明文章,请留下您的反应/投票,以便我们对Jedi Apilib进行更改! – Remko 2009-11-18 18:33:33

0

我在Delphi 6中做了类似的事情,使用了很多你的代码,但稍有不同,我不知道它是否适合你?

function WinExecAndWait32(FileName: String; Visibility: integer): integer; 
var 
    zAppName: array[0..512] of char; 
    zCurDir: array[0..255] of char; 
    WorkDir: String; 
    StartupInfo: TStartupInfo; 
    ProcessInfo: TProcessInformation; 
    Res: UINT; 
begin 
    StrPCopy(zAppName, FileName); 
    GetDir(0, WorkDir); 
    StrPCopy(zCurDir, WorkDir); 
    FillChar(StartupInfo, Sizeof(StartupInfo), #0); 
    StartupInfo.cb := Sizeof(StartupInfo); 
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW; 
    StartupInfo.wShowWindow := Visibility; 

    if not (CreateProcess(nil, 
     zAppName,    { pointer to command line string } 
     nil,     { pointer to process security attributes} 
     nil,     { pointer to thread security attributes } 
     false,    { handle inheritance flag } 
     CREATE_NEW_CONSOLE or { creation flags } 
     NORMAL_PRIORITY_CLASS, 
     nil,     { pointer to new environment block } 
     nil,     { pointer to current directory name } 
     StartupInfo,   { pointer to STARTUPINFO } 
     ProcessInfo)) then  { pointer to PROCESS_INF } 
     Result := -1 
    else 
    begin 
      WaitforSingleObject(ProcessInfo.hProcess, INFINITE); 
      GetExitCodeProcess(ProcessInfo.hProcess, Res); 
      {Added v2.4.4 (JS)} 
      CloseHandle(ProcessInfo.hProcess); 
      CloseHandle(ProcessInfo.hThread); 
      Result := Res; 
    end; 
end; 

要使用:

WinExecAndWait32(sExtractProgramName, SW_SHOWNORMAL); 
6

你的函数德尔福2010年失败,但在Delphi 6工作的原因是CreateProcessW()不能以只读lpCommandLine参数来调用。引用MSDN文档:

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

,它的工作原理与德尔福6的原因是,所有的Windows功能更宽字符串内部,并在ANSI版本做什么,但字符串转换参数为宽字符串对应,然后调用宽版。您可以使用常量调用该函数,并使用Delphi 6 Windows为您创建一个可写缓冲区。随着德尔福2010年你体验AV。

请注意,你的程序有另一个bug,如文档也确实状态:

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

+0

感谢提到commandLine,否则我将再次遇到砖墙。 – Snackmoore 2009-11-18 09:33:32

相关问题