簡體   English   中英

當我從CreateProcess運行NETSH時,“系統找不到指定的文件”,但它在命令提示符下運行正常嗎?

[英]Got “The system cannot find the file specified” when I run NETSH from CreateProcess but it works ok on Command Prompt?

我有一個調用Delphi 7編寫的控制台程序的NT服務,讓我們稱之為failover.exe ,然后使用我發現的程序調用NETSH

procedure ExecConsoleApp(CommandLine: ansistring; Output, Errors: TStringList); 

注意:ExecConsoleApp使用CreateProcess,請參閱以下鏈接以獲取完整代碼: http//www.delphisources.ru/pages/faq/base/createprocess_console.html

我會在調用ExecConsoleApp之前將以下內容傳遞給CommandLine:

cmd.exe /c "C:\Windows\system32\netsh.exe interface delete address "Wireless Network Connection" 192.168.0.36" 

ExecConsoleApp將返回錯誤:

該系統找不到指定的文件

但是,如果我在命令提示符下運行它,它運行完美。

奇怪的是,我記得它在2003 Server上的第一次嘗試工作,但在那之后,無論我嘗試多少次都失敗了。 在其中一次嘗試中,我還嘗試將登錄作為管理員用戶分配給服務,但無濟於事。 也沒有擺弄文件安全幫助。

我沒有Win 2003服務器在辦公室進行測試,但我已經在XP和Win7上測試過,而且ExecConsoleApp工作得很好,雖然在XP上,我不得不修改ExecConsoleAppsystem32\\wbem執行以便它工作:

 Res := CreateProcess(nil, PChar(CommandLine), nil, nil, True,
  // **** Attention: Amended by to point current directory to system32\wbem, this is to solve an error returned by netsh.exe if not done otherwise.
 //   CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, @env, nil, si, pi);
   CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, @env, pchar(GetSystemPath(WindRoot) + 'system32\wbem'), si, pi);

我研究了一天,但沒有線索,希望有人可以提供幫助。 謝謝。

補充評論 -

  1. 服務器是32位Win2k3。

  2. 嘗試過域管理員,不起作用。

  3. 代碼片段:

     Procedure ExecConsoleApp(CommandLine: ansistring; Output, Errors: TStringList); var sa: TSECURITYATTRIBUTES; si: TSTARTUPINFO; pi: TPROCESSINFORMATION; hPipeOutputRead: THANDLE; hPipeOutputWrite: THANDLE; hPipeErrorsRead: THANDLE; hPipeErrorsWrite: THANDLE; Res, bTest: boolean; env: array[0..100] of char; szBuffer: array[0..256] of char; dwNumberOfBytesRead: DWORD; Stream: TMemoryStream; begin sa.nLength := sizeof(sa); sa.bInheritHandle := True; sa.lpSecurityDescriptor := nil; CreatePipe(hPipeOutputRead, hPipeOutputWrite, @sa, 0); CreatePipe(hPipeErrorsRead, hPipeErrorsWrite, @sa, 0); ZeroMemory(@env, SizeOf(env)); ZeroMemory(@si, SizeOf(si)); ZeroMemory(@pi, SizeOf(pi)); si.cb := SizeOf(si); si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; si.wShowWindow := SW_HIDE; si.hStdInput := 0; si.hStdOutput := hPipeOutputWrite; si.hStdError := hPipeErrorsWrite; (* Remember that if you want to execute an app with no parameters you nil the second parameter and use the first, you can also leave it as is with no problems. *) Res := CreateProcess(nil, PChar(CommandLine), nil, nil, True, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, @env, nil, si, pi); // Procedure will exit if CreateProcess fail if not Res then begin CloseHandle(hPipeOutputRead); CloseHandle(hPipeOutputWrite); CloseHandle(hPipeErrorsRead); CloseHandle(hPipeErrorsWrite); Exit; end; CloseHandle(hPipeOutputWrite); CloseHandle(hPipeErrorsWrite); //Read output pipe Stream := TMemoryStream.Create; try while True do begin bTest := ReadFile(hPipeOutputRead, szBuffer, 256, dwNumberOfBytesRead, nil); if not bTest then begin break; end; OemToAnsi(szBuffer, szBuffer); Stream.Write(szBuffer, dwNumberOfBytesRead); end; Stream.Position := 0; Output.LoadFromStream(Stream); finally Stream.Free; end; //Read error pipe Stream := TMemoryStream.Create; try while True do begin bTest := ReadFile(hPipeErrorsRead, szBuffer, 256, dwNumberOfBytesRead, nil); if not bTest then begin break; end; OemToAnsi(szBuffer, szBuffer); Stream.Write(szBuffer, dwNumberOfBytesRead); end; Stream.Position := 0; Errors.LoadFromStream(Stream); finally Stream.Free; end; WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(hPipeOutputRead); CloseHandle(hPipeErrorsRead); end; cmdstring := 'cmd.exe /c "' + GetSystemPath(WindRoot) + 'system32\\netsh.exe interface ' + ip + ' delete address "' + NetworkInterfaceName + '" ' + VirtualFailoverIPAddress + '"'; logstr('cmdstring: ' + cmdstring); ExecConsoleApp(cmdstring, OutP, ErrorP); if OutP.Text <> '' then begin logstr('Delete IP Result: ' + OutP.Text); end else begin logstr('Delete IP Error: ' + ErrorP.Text); end; 
  4. 嘗試直接運行netsh.exe而不是“cmd.exe / c C:\\ Windows \\ system32 \\ netsh.exe ...”,並得到相同的“系統找不到指定的文件”。 錯誤。 我還意外地發現,如果我發出錯誤的netsh命令,netsh實際上會返回錯誤,例如

netsh interface ip delete address“LocalArea Connection”10.40.201.65

指定的接口LocalArea連接無效。

如果我將拼寫錯誤“LocalArea”更正為“Local Area”,則返回以下內容。 netsh interface ip delete address“Local Area Connection”10.40.201.65

該系統找不到指定的文件。

同樣,我必須重復,如果我通過命令提示符而不是從我的應用程序發出它,相同的命令工作得很好。

你試過這個嗎?

if not CreateProcess(PChar('C:\Windows\system32\netsh.exe'), PChar(Arguments), ...) then
begin
  // Do somehting with `GetLastError`
end;

當然,最好在運行時檢測C:\\Windows\\system32的路徑,因為這可能在另一個驅動程序或另一個目錄中。

以這種方式運行時,您可以在CreateProcess之后立即使用GetLastError調用從Windows獲取錯誤消息。

ExecConsoleApp過程存在缺陷,因為它不會返回GetLastError ,甚至不會返回CreateProcess失敗的任何跡象。

你應該先解決這個問題。 也許在Exit代碼之前添加raise EExecConsoleAppCreateProcessFailed.Create(SysErrorMessage(GetLastError))

您不應該使用cmd.exe /c作為前綴。 這是多余的,它使錯誤診斷更加困難。 GetLastError可能無法反映正確的錯誤代碼,因為您將創建的acutal netsh.exe進程委派給cmd

如果可執行文件所需的隱式加載的DLL不可用,則也可能出現“找不到指定的文件”錯誤。 在這種情況下,這是最可能的原因 - 當netsh.exe在非交互式上下文中運行時,找不到某些必需的DLL。

使用Process Monitor(可從Microsoft網站下載)記錄嘗試期間發生的文件系統操作。 在服務進程的上下文中或在netsh.exe進程的上下文中查找文件未找到的錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM