开放式从C ++ DLL写入控制台

时间:2013-05-11 19:07:22

标签: c++ visual-c++ dll console

在开始我的问题之前作为一个快速说明,我对C ++,特别是DLL很新。

我目前正在编写VS2012中的C ++ DLL,用于程序。请注意,我没有特定程序的源访问权限。 当有问题的程序要求它做某事时,我想从DLL中将一些输出写入一个单独的控制台窗口。

我的问题是,我该如何做这样的事情?为了清楚地说明我想要的东西,我想在DLL连接到程序后立即打开一个单独的控制台窗口,然后让它将输出写入控制台。当DLL与程序分离时,它也应该关闭控制台窗口。

到目前为止,我的猜测是在我的解决方案中创建一个单独的Win32控制台应用程序项目,然后可能在我的DLL中引用它,并让它从它执行某些方法,输出包含在调用的参数中。我不知道如何解决这个问题,特别是因为我希望这个单独的控制台项目包含在同一个DLL中。

感谢您的任何意见。

2 个答案:

答案 0 :(得分:4)

以下课程将帮助您了解您需要做什么。 在构造时,CConsole尝试使用AllocConsole为该过程创建新的控制台。

如果AllocConsole失败,则没有任何更改 - 控制台已经存在,并且该类假定已经在其他地方设置了C-Runtime句柄。

如果AllocConsole成功,则保存当前与stdout和stdin关联的对象,然后将这些对象替换为为新控制台创建的对象。现在,C-Runtime输出函数(如printf)将输出到新控制台。 cout和cin也将使用新的控制台。

RemoveMenu调用将阻止用户关闭控制台窗口,从而终止进程。除此功能外没有必要。

当销毁CConsole(并且AllocConsole成功)时,将恢复stdout和stdin,然后通过调用FreeConsole关闭控制台。

当你希望你的控制台超出创建它的功能时,我发现这个类很不方便 - 你需要获得一个新的CConsole并跟踪它的指针,直到你用删除关闭它。但它的实现规定了您需要在自己的项目中采取的步骤。我从来没有用dll试过这个,但我认为这没有任何理由造成问题。

Console.h:

#pragma once
#include <stdio.h>

class CConsole {
    FILE m_OldStdin, m_OldStdout;
    bool m_OwnConsole;
public:
    CConsole();
    ~CConsole();
};

Console.cpp:

#include <windows.h>
#include <conio.h>
#include <FCNTL.H>
#include <io.h>
#include "Console.h"

static BOOL WINAPI MyConsoleCtrlHandler(DWORD dwCtrlEvent) { return dwCtrlEvent == CTRL_C_EVENT;}

CConsole::CConsole() : m_OwnConsole(false) {
    if(!AllocConsole()) return;

    SetConsoleCtrlHandler(MyConsoleCtrlHandler, TRUE);
    RemoveMenu(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_BYCOMMAND);
    const int in  = _open_osfhandle(INT_PTR(GetStdHandle(STD_INPUT_HANDLE)),  _O_TEXT);
    const int out = _open_osfhandle(INT_PTR(GetStdHandle(STD_OUTPUT_HANDLE)), _O_TEXT);
    m_OldStdin  = *stdin;
    m_OldStdout = *stdout;

    *stdin  = *_fdopen(in,  "r");
    *stdout = *_fdopen(out, "w");

    m_OwnConsole = true;
}

CConsole::~CConsole() {
    if(m_OwnConsole) {
        fclose(stdout);
        fclose(stdin);
        *stdout = m_OldStdout;
        *stdin  = m_OldStdin;
        SetConsoleCtrlHandler(MyConsoleCtrlHandler, FALSE);
        FreeConsole();
    }
}

享受!

答案 1 :(得分:0)

如果您创建一个单独的控制台项目,您将获得一个单独的控制台应用程序,这可能是您想要的,也可能不是。但是,在这种情况下,你可以使它工作,因为你可以避免使用控制台句柄的所有问题,只需使用该应用程序。您可以从dll启动应用程序,从具有多个实例创建互斥锁,并且可以让控制台应用程序通过命名管道实现简单的记录器。你的dll和你的控制台应用程序都打开了同一个命名管道的句柄,你从dll写入管道并从exe中读取,写入stdout。

这些都不一定需要控制台应用程序;您可以通过GUI应用程序轻松完成此操作。就此而言,正如@VoidStar所说,您可以直接从应用程序写入日志。您还可以使用OutputDebugString并使用来自SysInternals的DebugView查看输出。