2009-11-18 80 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

相關問題