6

NTDelphi 7で記述されたコンソールプログラムを呼び出すサービスがあります。それを呼び出して、見つけたプロシージャを使用してfailover.exe呼び出します。NETSH

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

注:ExecConsoleAppはCreateProcessを使用します。完全なコードについては、次のリンクを参照してください:http: //www.delphisources.ru/pages/faq/base/createprocess_console.html

呼び出す前に、コマンドラインに以下を渡しますExecConsoleApp

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

ExecConsoleAppエラーを返します:

システムは、指定されたファイルを見つけることができません

しかし、コマンドプロンプトで実行すると、完全に実行されます。

奇妙なことに、その2003 Serverでの最初の試行で動作したことを思い出しましたが、その後は、試行回数に関係なく失敗しました。その試みの1つとして、管理者ユーザーとしてログオンをサービスに割り当てようとしましたが、役に立ちませんでした。また、ファイルセキュリティの助けをいじることもありません。

オフィスでテストするWin2003サーバーはありませんが、XPとWin7でテストしてExecConsoleApp完全に動作しますが、XPでは、動作させるためにExecConsoleAppから実行するように修正する必要がありました。system32\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日研究しましたが、手がかりはありません。誰かが助けてくれることを願っています。ありがとう。

追記-

  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. 「cmd.exe/cC:\ Windows \ system32 \ netsh.exe ...」の代わりにnetsh.exeを直接実行しようとしましたが、同じ「システムは指定されたファイルを見つけることができません」を取得しました。エラー。また、間違ったnetshコマンドを発行した場合、netshが実際にエラーを返すことも偶然発見しました。

netsh interface ip delete address "LocalArea Connection" 10.40.201.65

無効なインターフェイスLocalArea接続が指定されました。

タイプミス「LocalArea」を「LocalArea」に修正すると、次のようになります。netsh interface ip delete address "Local Area Connection" 10.40.201.65

システムは、指定されたファイルを見つけることができません。

繰り返しますが、アプリケーションからではなくコマンドプロンプトを介して発行した場合、同じコマンドが完全に正常に機能することを繰り返す必要があります。

4

2 に答える 2

2

これを試しましたか?

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

もちろん、C:\Windows\system32これは別のドライバーまたは別のディレクトリにある可能性があるため、実行時にパスを検出することをお勧めします。

この方法で実行すると、GetLastErrorCreateProcess の直後の呼び出しを使用して、Windows からエラー メッセージを取得できます。

この手順には欠陥があり、失敗したことを示すものも何もExecConsoleApp返さないからです。GetLastErrorCreateProcess

これを最初に修正する必要があります。コードのraise EExecConsoleAppCreateProcessFailed.Create(SysErrorMessage(GetLastError))前に追加するかもしれません。Exit

cmd.exe /cプレフィックスとして使用しないでください。これは冗長であり、エラーの診断がより困難になります。実際のプロセスGetLastErrorの作成を に委任しているため、正しいエラー コードが反映されない可能性があります。netsh.execmd

于 2011-11-17T13:01:05.597 に答える
0

「指定されたファイルが見つかりません」というエラーは、実行可能ファイルに必要な暗黙的に読み込まれた DLL が利用できない場合にも発生することがあります。この状況では、これが最も可能性の高い原因です。netsh.exe が非対話型コンテキストで実行されているときに、重要な DLL が見つからないことがあります。

Process Monitor (Microsoft の Web サイトからダウンロード可能) を使用して、試行中に行われるファイル システム操作を記録します。サービス プロセスのコンテキストまたは netsh.exe プロセスのコンテキストで、ファイルが見つからないというエラーを探します。

于 2011-11-19T05:14:17.700 に答える