C#内存映射文件,应用程序挂起。怎么了?

时间:2017-05-18 21:18:28

标签: c# winforms ipc memory-mapped-files

我正在尝试使用内存映射文件为IPC编写简单的发送器/接收器类。 我的代码中存在问题,但我不明白我在这里做错了什么:

[Serializable]
public struct MessageData
{
    public int PID;
    public IntPtr HWND;
    public string ProcessName;
    public string ProcessTitle;
}

....

public static class MMF
{
    private const int MMF_MAX_SIZE = 4096;  // allocated memory for this memory mapped file (bytes)
    private const int MMF_VIEW_SIZE = 4096; // how many bytes of the allocated memory can this process access

    public static void Write()
    {
        var security = new MemoryMappedFileSecurity();
        // Create a SecurityIdentifier object for "everyone".
        SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
        security.AddAccessRule(new AccessRule<MemoryMappedFileRights>(everyoneSid, MemoryMappedFileRights.FullControl, AccessControlType.Allow));

        using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("Global\\mmf1", MMF_MAX_SIZE, MemoryMappedFileAccess.ReadWrite))
        {
            using (MemoryMappedViewStream mStream = mmf.CreateViewStream(0, MMF_VIEW_SIZE))
            {

                var p = Process.GetCurrentProcess();
                MessageData msgData = new MessageData();
                msgData.HWND = p.MainWindowHandle;
                msgData.PID = p.Id;
                msgData.ProcessName = p.ProcessName;
                msgData.ProcessTitle = p.MainWindowTitle;

                // serialize the msgData and write it to the memory mapped file
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(mStream, msgData);
                mStream.Flush();
                mStream.Seek(0, SeekOrigin.Begin); // sets the current position back to the beginning of the stream

                //MessageBox.Show("Done");
            }
        }
    }
}

现在我尝试从主应用程序表单测试此代码:

    ...
    private void button1_Click(object sender, EventArgs e)
    {
        MMF.Write();
    }

Visual Studio 2015社区中的流程依然存在。进程运行,但表单界面没有响应。我只能暂停或停止进程。这是using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("Global\\mmf1", ...字符串停止的。

我假设应用无法创建文件,但没有任何例外。

因此,如果我将地图名称更改为“mmf1”(没有“全局”前缀),一切正常,应用程序正常。但据我所知,this answerMSDN

  

使用“Global \”前缀文件映射对象名称允许进程相互通信,即使它们位于不同的终端服务器会话中。

如果我理解正确,则需要使用前缀“Global \”来将我的内存映射文件与任何应用程序进行交互,无论它们运行的​​权限如何。

特别是因为我正在尝试为“所有人”设置文件访问权限。

UPD。此代码在Win 7 / Win 8.1 x64上进行了测试。结果是一样的。

1 个答案:

答案 0 :(得分:1)

您必须以管理员身份运行Visual Studio才能使用“Global \”前缀创建内存映射文件。