草庐IT

windows - 当我从 CreateProcess 运行 NETSH 时得到 "The system cannot find the file specified"但它在命令提示符下工作正常?

coder 2023-11-11 原文

我有一个调用用 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 将返回错误:

The system cannot find the file specified

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

奇怪的是,我记得它在 2003 服务器上的第一次尝试中工作,但在那之后,无论我尝试了多少次,它都失败了。在其中一次尝试中,我还尝试将以管理员用户身份登录分配给该服务,但无济于事。摆弄文件安全性也无济于事。

我没有 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

Invalid interface LocalArea Connection specified.

如果我将拼写错误“LocalArea”更正为“Local Area”,则会返回以下内容。 netsh接口(interface)ip删除地址“本地连接”10.40.201.65

The system cannot find the file specified.

我必须再次强调,如果我通过命令提示符而不是从我的应用程序发出相同的命令,它会工作得很好。

最佳答案

你试过吗?

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 可能不会反射(reflect)正确的错误代码,因为您将创建实际 netsh.exe 进程委托(delegate)给 cmd

关于windows - 当我从 CreateProcess 运行 NETSH 时得到 "The system cannot find the file specified"但它在命令提示符下工作正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8166840/

有关windows - 当我从 CreateProcess 运行 NETSH 时得到 "The system cannot find the file specified"但它在命令提示符下工作正常?的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  4. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  5. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  6. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  7. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  8. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  9. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  10. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

随机推荐