Tôi có một dịch vụ NT
mà các cuộc gọi một chương trình điều khiển được viết bằng Delphi 7, chúng ta hãy gọi nó failover.exe
mà lần lượt gọi NETSH
sử dụng một thủ tục tôi thấy:Có "Hệ thống không thể tìm thấy tệp được chỉ định" khi tôi chạy NETSH từ CreateProcess nhưng nó hoạt động tốt trên Command Prompt?
procedure ExecConsoleApp(CommandLine: ansistring; Output, Errors: TStringList);
Lưu ý: ExecConsoleApp sử dụng CreateProcess, xem liên kết sau cho mã đầy đủ: http://www.delphisources.ru/pages/faq/base/createprocess_console.html
tôi sẽ vượt qua sau để commandline trước khi gọi ExecConsoleApp
:
cmd.exe /c "C:\Windows\system32\netsh.exe interface delete address "Wireless Network Connection" 192.168.0.36"
ExecConsoleApp
sẽ trả về một lỗi:
The system cannot find the file specified
Nhưng nếu tôi được chạy nó trong Command Prompt, nó chạy một cách hoàn hảo.
Điều lạ lẫm là tôi nhớ nó hoạt động trong lần thử đầu tiên trên Máy chủ 2003 đó, nhưng sau đó, nó không thành công bất kể số lần tôi thử. Trong một lần thử, tôi cũng đã thử gán đăng nhập là người dùng quản trị viên cho dịch vụ nhưng không có kết quả. Cũng không quan tâm đến trợ giúp bảo mật tệp.
Tôi không có một máy chủ Win 2003 để thử nghiệm với trong văn phòng, nhưng tôi đã thử nghiệm nó trên XP và Win7 và ExecConsoleApp
tác phẩm hoàn hảo, mặc dù trên XP, tôi đã phải sửa đổi ExecConsoleApp
để thực hiện từ system32\wbem
để cho nó công việc làm việc:
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);
Tôi đã nghiên cứu một ngày nhưng không có manh mối, hy vọng ai đó có thể trợ giúp. Cảm ơn.
nhận xét bổ sung -
Server là 32 bit Win2k3.
Quản trị viên miền đã cố gắng, không hoạt động.
đoạn Code:
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;
Cố gắng chạy netsh.exe trực tiếp thay vì "cmd.exe/c C: \ Windows \ system32 \ netsh.exe ...", và đã cùng " Hệ thống không thể tìm thấy các tập tin được chỉ định." lỗi. Tôi cũng vô tình phát hiện ra rằng nếu tôi đưa ra lệnh netsh sai, netsh sẽ thực sự trả về lỗi, ví dụ:
netsh interface ip xóa địa chỉ "LocalArea Connection" 10.40.201.65
Invalid interface LocalArea Connection specified.
Sau đây là trả lại nếu tôi sửa lỗi đánh máy "LocalArea" thành "Local Area". netsh interface ip xóa địa chỉ "Local Area Connection" 10.40.201.65
The system cannot find the file specified.
Một lần nữa, tôi phải lặp lại rằng lệnh cùng làm việc hoàn toàn tốt đẹp nếu tôi phát hành nó thông qua Command Prompt thay vì từ ứng dụng của tôi.
Nếu đây là hệ thống 64 bit, c: \ windows \ syswow64 \ netsh.exe có tồn tại không? –
@Harry: Điểm tốt, nếu ứng dụng OPs là 32-bit, nó sẽ bị chuyển hướng WOW64. –
@Harry: Đó là 32 bit, Win2k3, một máy cũ. Tôi sẽ cố gắng mà không có tiền tố cmd.exe/c như Jens đã đề xuất trên máy chủ win2k3 của máy khách. – Joshua