从非托管的DLL在C#主叫标准输出捕获(Capturing stdout from unmanage

2019-08-01 05:11发布

我有一个C#应用程序通过调用一些C ++ / CLI编组代码的本地C ++ DLL:

C# - > C ++ / CLI - > C ++(无CLR)

我想在DLL后弦更新回调用应用程序在运行时。 目前,非托管的DLL输出写入到标准输出。 基本上我需要捕捉的UI此输出。

在我炮击一个非托管的exe文件,这可以通过简单地从被调用标准输出重定向到绑定到一个文本面板的UI数据的字符串缓冲区来实现其它情况。

我没有使用P /调用或脱壳它作为一个exe,由于互操作层执行非原始类型的基本编组调用DLL的选项。 非托管的DLL没有CLR支持,并且必须保持这种方式。

我不得不使用委托(有限的成功http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.100).aspx ),因为似乎总是地方,托管和非托管世界的碰撞。 取的示例中的链接,从C / CLI传递一个管理委托伪装成本地函数指针到DLL的工作原理,但回调是C ++ / CLI类的范围之外定义,因此不能访问来自传入的一个托管委托主叫层(C#)。

理想我想定义接受非托管字符串,可以将这些转化为管理和回调到UI层,但如果这个类有管理的弦必要的支持,它不能被传递到非托管代码的类。

我可能会丢失与重定向一个简单的一招,将允许标准输出到而不经过层间串被捕获(例如,来自经由委托接收的C / CLI重定向标准输出)。 如果这是不可能的任何人都可以提出一个替代技术?

托管C ++:

using namespace System::Runtime::InteropServices;
using namespace System;

namespace BusinessObjectInterop
{
    typedef void (__stdcall *UnmanagedFP)(std::string);

    //Callback function
    public delegate void SetProgressDelegate(std::string);  


    void SetProgress(std::string s) {
        Console::WriteLine(s);

        //set m_progress - could use managed delegate passed from UI and exposed in static method in CIntermediate?
    }

    public ref class CIntermediate       
    {
    public:

        //Invoked by managed (C#) UI
        void ^ CallBusinessObject(Object ^ data, String ^ progress)
        {
        //Do some data marshalling...
        //...

        m_progress = progress;      

        //Create wrapper for managed delegate
        SetProgressDelegate^ fp = gcnew SetProgressDelegate(SetProgress);
        GCHandle gch = GCHandle::Alloc(fp);
        IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
        UnmanagedFP cb = static_cast<UnmanagedFP>(ip.ToPointer());

        //Call unmanaged DLL
        BusinessObject::DoStuff(cb);
        gch.Free();
        }

    private:
        String ^ m_progress;

    };
}

提前致谢。

Answer 1:

没错,这是行不通的。 一个DLL不拥有标准输出的过程一样。 和过程不创建一个,因为它是GUI应用程序,也不是因为其需要另一种方法可以重定向工作时。

解决方法很简单。 确保你有选择的调试配置。 用鼠标右键单击您的项目,属性, 链接,系统。 更改子系统设置为“控制台(/子系统:控制台)”应用程序选项卡。 改变输出类型设置为“控制台应用程序”。

按F5。 转眼间,现在你已经得到了双方显示从DLL调试输出控制台窗口。 而且你经常GUI。



文章来源: Capturing stdout from unmanaged DLL in C# caller