C# DllImport 意外崩溃

C# DllImport crashes unexpectedly

我有一个带有 C++ 组件的 C# 应用程序。我在模块之间与 DllImport 通信。该应用程序可以正常工作很多天,有时会意外崩溃。

[DllImport("recorder", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr start_recording();

是否可以 运行 受保护容器中的 C++ 部分,以免整个应用程序崩溃?

事件查看器

Application Error

Faulting application name: Recorder.exe, version: 1.0.0.0, time stamp: 0x59eef7cb
Faulting module name: avformat-57.dll, version: 57.71.100.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x00000000000d7e7f
Faulting process id: 0x186c
Faulting application start time: 0x01d3620b7e41ef96
Faulting application path: C:\Test\Recorder.exe
Faulting module path: C:\Test\avformat-57.dll
Report Id: 3fde49fc-d2ed-11e7-bf5c-002590abb7d4

.NET Runtime

Application: Recorder.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: exception code c0000005, exception address 000007FEEA407E7F

一般来说,有一些情况总是会导致进程退出,而你与它无关。

虽然您可以通过捕获异常、设置信号处理程序或只是修复错误来处理一些错误,但这只会修复特定情况,不会为您提供通用解决方案,而且您可能不这样做完全控制模块。

这种情况下的常见解决方案是将模块分离到不同的代理进程中,该代理进程将与您自己的应用程序进行通信。

在这里您可以找到 Interprocess Communications

的更多信息

我决定使用 NamedPipes 非常快,我可以双向通信。

C++ 示例

cout << "Connecting to pipe..." << endl;

// Open the named pipe
// Most of these parameters aren't very relevant for pipes.
HANDLE pipe = CreateFile(
    L"\\.\pipe\MyServerPipe",
    GENERIC_READ, // only need read access
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    //NULL,
    NULL
);

if (pipe == INVALID_HANDLE_VALUE) {
    cout << "Failed to connect to pipe." << endl;
    // look up error code here using GetLastError()
    system("pause");
    return 1;
}

cout << "Reading data from pipe..." << endl;


// The read operation will block until there is data to read
char buffer[128];
DWORD numBytesRead = 0;
BOOL result = ReadFile(
    pipe,
    buffer, // the data from the pipe will be put here
    127 * sizeof(char), // number of bytes allocated
    &numBytesRead, // this will store number of bytes actually read
    NULL // not using overlapped IO
);

if (result) {
    buffer[numBytesRead / sizeof(char)] = '[=10=]'; // null terminate the string
    cout << "Number of bytes read: " << numBytesRead << endl;
    //wcout << "Message: " << buffer << endl;

    //wstring ws(buffer);
    //string str(ws.begin(), ws.end());
    cout << "Test:" << buffer << endl;

}
else {
    wcout << "Failed to read data from the pipe." << endl;
}

// Close our pipe handle
CloseHandle(pipe);

//wcout << "Done." << endl;

system("pause");
return 0;

C#获取所有可用的管道

var listOfPipes = System.IO.Directory.GetFiles(@"\.\pipe\")

C# 示例

using (var pipeServer = new NamedPipeServerStream("MyServerPipe", PipeDirection.InOut))
{
    Console.WriteLine("NamedPipeServerStream object created.");

    // Wait for a client to connect
    Console.Write("Waiting for client connection...");
    pipeServer.WaitForConnection();

    Console.WriteLine("Client connected.");
    try
    {
        using (var bw = new BinaryWriter(pipeServer))
        {
            var data = Encoding.ASCII.GetBytes("SendInformation data1 data2 data3");
            //var data = Encoding.ASCII.GetBytes("Start\r\n");
            bw.Write(data);
        }
    }
    // Catch the IOException that is raised if the pipe is broken
    // or disconnected.
    catch (IOException e)
    {
        Console.WriteLine("ERROR: {0}", e.Message);
    }
}