C++ CMD异常处理C/C++;

C++ CMD异常处理C/C++;,c++,c,exception-handling,cmd,C++,C,Exception Handling,Cmd,我将在程序中使用一些CMD命令,这些命令可能会引发一些异常。正如您所知,当出现异常时,CMD会在屏幕上写入自己的错误消息。但是,我想写我自己的错误消息 我的问题是:有没有办法阻止CMD消息并只写我自己的错误消息 另外,这不是一个复杂的程序。它使用System()执行CMD命令 例如: 比方说,用户可以重命名和复制程序中的任何文件。如您所知,如果用户没有正确输入文件的路径,屏幕上将显示一条错误消息。我希望这个错误消息永远不会出现在屏幕上。只显示我自己的错误消息 谢谢大家! 一种蛮力方法是通过管道将

我将在程序中使用一些CMD命令,这些命令可能会引发一些异常。正如您所知,当出现异常时,CMD会在屏幕上写入自己的错误消息。但是,我想写我自己的错误消息

我的问题是:有没有办法阻止CMD消息并只写我自己的错误消息

另外,这不是一个复杂的程序。它使用System()执行CMD命令

例如:

比方说,用户可以重命名和复制程序中的任何文件。如您所知,如果用户没有正确输入文件的路径,屏幕上将显示一条错误消息。我希望这个错误消息永远不会出现在屏幕上。只显示我自己的错误消息


谢谢大家!

一种蛮力方法是通过管道将CMD的输出,即
yourCommand>file.txt
传输到一个文件,然后读取文件内容以确定是否存在异常。

您可以使用

#include "Exception.h"

class MyClass
{
public:
    class Error : public Exception { };
    MyClass();
    ~MyClass();
    void myFunction() throw(Error);
}

catch(MyClass::Error&Error)
{

cout这取决于您的平台和您将要使用的命令。顺便说一句,大多数人强烈反对使用for调用控制台命令(对于大多数目的来说,这是一种沉重的方式)。
我建议您使用带有CREATE\u NO\u窗口标志的
CreateProcess()
,并通过调用
WaitForSingleObject()
GetExitCodeProcess()
等待进程退出
这种方法利用了一个事实,即大多数CMD命令都是可执行的,位于
C:/Windows/…
中的某个位置

/*
 * Executes a program and returns it's exit code.
 *
 * TODO: Error checking should be added for
 *   CreateProcess()
 *   WaitForSingleObject()
 *   GetExitCodeProcess()
 */
DWORD ExecCmdLine(TCHAR const* cmdline)
{
    STARTUPINFO si;
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi;
    memset(&pi, 0, sizeof(pi));
    ::CreateProcess(NULL, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
    ::CloseHandle(pi.Thread);
    ::WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD exitcode;
    ::GetExitCodeProcess(pi.hProcess, &exitcode);
    ::CloseHandle(pi.hProcess);
    return exitcode;
}
如果要检索命令的输出,还可以在
STARTUPINFO
结构中提供
hStdOutput
hStdError
,并在
STARTUPINFO.dwFlags
中设置
STARTF\u USESTDHANDLES
。 在命令执行时,你甚至可以在自己的程序中做其他事情(特别是你提到的文件拷贝)。这一个是用C++方式完成的:

/*
 * TODO: Error checking should be added for
 *   CreateProcess()
 *   WaitForSingleObject()
 *   GetExitCodeProcess()
 */
class AsyncCmd
{
public:
    AsyncCmd(std::string const& cmdline)
        : cmdline(cmdline),
          processHandle(NULL)
    {
    }
    ~AsyncCmd()
    {
        if (this->processHandle != NULL)
            ::CloseHandle(this->processHandle);
    }
    // Starts the execution of the commandline.
    void Start(HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE), HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE))
    {
        STARTUPINFO si;
        memset(&si, 0, sizeof(si));
        si.cb = sizeof(si);
        si.dwFlags = STARTF_USESTDHANDLES;
        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
        si.hStdOutput = hOut;
        si.hStdError = hErr;
        PROCESS_INFORMATION pi;
        memset(&pi, 0, sizeof(pi));
        ::CreateProcess(NULL, this->cmdline.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
        ::CloseHandle(pi.hThread);
        this->processHandle = pi.hProcess;
    }
    // Blocks until execution is finished and returns the exit code.
    DWORD ExitCode()
    {
        ::WaitForSingleObject(this->processHandle, INFINITE);
        DWORD exitcode;
        ::GetExitCodeProcess(this->processHandle, &exitcode);
        return exitcode;
    }
private:
    AsyncCmd(AsyncCmd const&);
    AsyncCmd& operator=(AsyncCmd const&);
    std::string cmdline;
    HANDLE processHandle;
}
除了编写的内容之外,我想指出,异常不会跨越进程边界。因此,这里要处理的是已执行程序(和shell)的输出(包括
stderr
stdout
)及其退出代码(如果这提供了任何有用的信息)。这主要是为了让您理解,这并不是您的标题所暗示的异常处理


这意味着您可以在使用
CreateProcess
/
CreateProcessEx
时设置
hStdOutput
hStdError
以使用您控制的管道以及“捕获”的位置在将输出输出到控制台之前,将其替换为您自己的输出。如果您只想替换stderr,也可以这样做。

要重新表述已经说过的内容:

问:您是否能够以某种方式拦截通过“system()”调用的命令引发的错误

答:没有,原因很多

但是您可以重定向由命令行程序编写的文本错误消息:

  • 重定向“stderr”相对容易。“GetStdHandle(STD_ERROR_HANDLE)”是一种方法。重定向到“>:err”是另一种方法

  • 不幸的是,并不是所有的程序都能将错误消息写入“stderr”

    许多人把所有的东西都写在“标准输出”上

在后一种情况下,您必须找出1)实际发生了错误,2)找出如何将文本输入中的“标准输出”部分与“错误文本”部分分开

附言:


“system()”的另一个API是“popen()”

你能说得更具体一点吗?我假设你正在编写一个控制台应用程序?通过CMD你指的是Windows命令行?错误通常写入到stderr/cerr,用你自己的流替换该流(如何替换取决于你使用的操作系统)或将所有内容重定向到一个文件(你将解析)。这与处理从cmd.exe打印到stdout的错误消息无关。我认为应该补充一点,管道是
hStdOutput
hStdError
的良好“死胡同”,因为s(he)想抑制执行程序的输出。哇!这很酷,但是对我来说有点先进…所以,我想知道你能建议一个教程还是一个C++主题,这是必须学习的,这使得代码对我来说是可以理解的?我真的很想提高我的C++技能和能力。但是,对于C++,我通常都喜欢,特别是面向对象编程部分。我有C++的一般知识,没有问题。但是,我不能理解你写的代码行……我想,只有了解它们的方法才能学习Windows API,对吗?真的不必“学习”它,但您可以检查MSDN中您不知道的API调用:,实际上,只有当且仅当命令行中显式使用
cmd.exe
作为shell时,这才有效,因为您尝试在此处使用shell重定向。此外,
2>
还可以用于重定向
stderr
,而不仅仅是
stdout
NUL
可以类似于unixoid系统上的
/dev/null
来抑制输出。为了完整性,您可以通过在命令前面加上
%COMSPEC%/c
cmd.exe
来强制使用
cmd.exe
支持,而不仅仅是
stdin
stdout
stderr
。我将把这一点保留下来,只是为了历史记录,但是@yourmt的答案显然是最好的。用他的。
/*
 * Executes a program and returns it's exit code.
 *
 * TODO: Error checking should be added for
 *   CreateProcess()
 *   WaitForSingleObject()
 *   GetExitCodeProcess()
 */
DWORD ExecCmdLine(TCHAR const* cmdline)
{
    STARTUPINFO si;
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi;
    memset(&pi, 0, sizeof(pi));
    ::CreateProcess(NULL, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
    ::CloseHandle(pi.Thread);
    ::WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD exitcode;
    ::GetExitCodeProcess(pi.hProcess, &exitcode);
    ::CloseHandle(pi.hProcess);
    return exitcode;
}
/*
 * TODO: Error checking should be added for
 *   CreateProcess()
 *   WaitForSingleObject()
 *   GetExitCodeProcess()
 */
class AsyncCmd
{
public:
    AsyncCmd(std::string const& cmdline)
        : cmdline(cmdline),
          processHandle(NULL)
    {
    }
    ~AsyncCmd()
    {
        if (this->processHandle != NULL)
            ::CloseHandle(this->processHandle);
    }
    // Starts the execution of the commandline.
    void Start(HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE), HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE))
    {
        STARTUPINFO si;
        memset(&si, 0, sizeof(si));
        si.cb = sizeof(si);
        si.dwFlags = STARTF_USESTDHANDLES;
        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
        si.hStdOutput = hOut;
        si.hStdError = hErr;
        PROCESS_INFORMATION pi;
        memset(&pi, 0, sizeof(pi));
        ::CreateProcess(NULL, this->cmdline.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
        ::CloseHandle(pi.hThread);
        this->processHandle = pi.hProcess;
    }
    // Blocks until execution is finished and returns the exit code.
    DWORD ExitCode()
    {
        ::WaitForSingleObject(this->processHandle, INFINITE);
        DWORD exitcode;
        ::GetExitCodeProcess(this->processHandle, &exitcode);
        return exitcode;
    }
private:
    AsyncCmd(AsyncCmd const&);
    AsyncCmd& operator=(AsyncCmd const&);
    std::string cmdline;
    HANDLE processHandle;
}