2012-10-05 34 views
2

我有一个C#应用程序调用经由一些C++/CLI编组码的本地C++ DLL:从非托管的DLL的stdout捕捉在C#呼叫者

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层,但如果此类对托管字符串有必要的支持,则不能将其传递给非托管代码。

我可能会错过一个简单的重定向技巧,它可以在不传递层间字符串的情况下捕获stdout(例如,通过委托接收的从C++/CLI重定向stdout)。如果这是不可能的,任何人都可以提出一种替代技术?

托管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; 

    }; 
} 

预先感谢。

回答

7

对,这是行不通的。一个DLL不拥有标准输出,一个过程。而且由于它是GUI应用程序,您的过程不会创建一个,因为这需要另一个过程,所以也不能重定向。

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

按F5。 Presto,现在你已经有了一个控制台窗口,显示DLL的调试输出。而你的常规GUI。

+0

该设置将用于C++/CLI应用程序,不是吗?问题说应用程序(它调用C++/CLI DLL)是用C#编写的。或者即使您将其设置在C++/CLI DLL项目中,它也可以工作吗? – svick

+0

确实,更正了。谢谢! –

+0

感谢您的回复。有没有一种方法可以将stdout从控制台重定向回主应用程序,只要使用上述架构,即不使用.Net ShelledProcess类或类似的东西?理想情况下,我希望能够在UI中显示之前对stdout进行后处理,以删除不必要的文本并添加各种标记和其他格式。 – pdm2011