【问题标题】:ShellExecute() not working with .bat fileShellExecute() 不适用于 .bat 文件
【发布时间】:2013-05-18 07:42:24
【问题描述】:

我尝试使用 win32 api 在 c++ 中执行以下 bat 文件。以下是执行代码。

  //#include "Shellapi.h"
    #include "Windows.h"
    int _tmain(int argc, _TCHAR* argv[])
    {
        ShellExecute(GetDesktopWindow(), "sa.bat","", NULL, NULL, SW_SHOWNORMAL);
        DWORD LastError = GetLastError();
        return 0;
    }

但它不起作用。

以下是内容“sa.bat”

C:\windows\system32\wusa /uninstall /kb:2718695 /quiet /forcerestart

但最后一个错误返回 1155。

【问题讨论】:

  • 你弄错了参数,“sa.bat”应该作为第三个参数传递。
  • @HansPassant 不,它不是 :-(。我觉得批处理命令出了点问题。你是这样吗??请问我的新问题。

标签: c++ winapi


【解决方案1】:

试试这个:

//#include "Shellapi.h"
#include "Windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
  HINSTANCE hReturnCode=ShellExecute(NULL, _T("open"), _T("cmd.exe"), _T("/C sa.bat"), NULL, SW_SHOWNORMAL);
  DWORD LastError = GetLastError();
  return 0;
}

[已编辑] 这个可行的建议来自 Chris:

    //#include "Shellapi.h"
    #include "Windows.h"
    int _tmain(int argc, _TCHAR* argv[])
    {
      HINSTANCE hReturnCode=ShellExecute(NULL, _T("open"), _T("sa.bat"), NULL, NULL, SW_SHOWNORMAL);
      DWORD LastError = GetLastError();
      return 0;
    }

【讨论】:

  • 批处理文件应该作为第三个参数,不是吗?我在其他地方用它们代替了可执行文件。
  • 好吧,我刚刚测试了它,它确实运行我的批处理文件而不通过 cmd 路由。
  • 在这种情况下,我会将您的建议作为答案发布 - 我的支持已经让您:)
  • 这已经是您答案的一部分。我所暗示的只是需要“打开”并将批处理文件移动到下一个参数。当我测试它们时,这两种方法都有效。
【解决方案2】:

.BAT 文件不是可执行的二进制文件,因此单独的批处理文件不会起飞,而是使用命令解释器 (CMD.EXE) 启动。在ShellExecute 上,您可以直接使用CMD /C 启动它,也可以利用注册表关联,它以“打开”动词开头的.BAT 文件。

见:

你显然没有尝试启动 CMD.EXE,所以关联。

您得到的错误代码是ERROR_NO_ASSOCIATION“没有应用程序与此操作的指定文件关联。”它指的是ShellExecute API,而不是批处理文件的内容。

SE_ERR_NOASSOC

没有与给定文件扩展名关联的应用程序。如果您尝试打印不可打印的文件,也会返回此错误。

这意味着ShellExecute 无法理解您的论点。该文件应该是第三个,而不是第二个,然后第二个参数将是“open”或 NULL(动词)。将动词应用于.BAT 文件将使.BAT 文件“运行”。

【讨论】:

  • .bat 文件本身可能不是二进制可执行文件,但它们可以通过 ShellExecute/Ex() 直接执行,因为它们与注册表中的 cmd.exe 相关联。您链接到的两篇文章都使用 cmd.exe,因为它们利用了需要它的额外功能。
  • @RemyLebeau:我澄清了这一点。
【解决方案3】:

这也可以:

#include <windows.h>
#include <stdio.h>
int main()
{
   STARTUPINFO si;
   PROCESS_INFORMATION pi;

   ZeroMemory( &si, sizeof(si) );
   si.cb = sizeof(si);
   ZeroMemory( &pi, sizeof(pi) );
   if( !CreateProcess( NULL, "cmd /C  sa.bat", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)  )
   {
     printf( "CreateProcess failed (%d)\n", GetLastError() );
     return FALSE;
   }
   WaitForSingleObject( pi.hProcess, INFINITE );
   CloseHandle( pi.hProcess );
   CloseHandle( pi.hThread );
   return 0;
}

【讨论】:

    【解决方案4】:

    ShellExecute() 通过自己的返回值报告错误,而不是通过GetLastError()。您还需要在lpFile 参数中传递文件名,而不是lpOperation 参数。

    试试这个:

    //#include "Shellapi.h"
    #include "Windows.h"
    int _tmain(int argc, _TCHAR* argv[])
    {
        int nErrorCode = (int) ShellExecute(NULL, NULL, "sa.bat", NULL, NULL, SW_SHOWNORMAL);
        if (nErrorCode <= 32)
          // an error occurred...
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-03
      • 2016-07-27
      • 2017-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多