代码之家  ›  专栏  ›  技术社区  ›  Wildhorn

C#字符串到长指针

  •  2
  • Wildhorn  · 技术社区  · 16 年前

    我正在使用C语言中的一个应用程序,它需要向C++应用程序发送消息。

    [DllImport("user32.dll")]
            public static extern IntPtr SendMessage(
                  int hWnd,      // handle to destination window
                  uint Msg,       // message
                  IntPtr wParam,  // first message parameter
                  IntPtr lParam   // second message parameter
                  );
    

    但现在,我的问题是 . 我尝试了不安全的代码,但字符串似乎不像其他变量那样工作。我怎样才能做到这一点?谢谢。

    3 回复  |  直到 16 年前
        1
  •  11
  •   Hans Passant    16 年前

    有一个复杂的问题,因为你试图发送字符串。目标窗口是否启用Unicode有什么关系。SendMessage有两个版本,SendMessageA()和SendMessageW()。如果程序有日期并且使用8位字符串而不是UTF-16编码字符串,则需要使用前者。

    你可以使用Spy++来发现。使用finder工具选择应用程序的窗口。在常规属性选项卡中,您将看到“windowproc”。如果窗口已启用Unicode,则会显示(Unicode)。如果你看不到它,那么字符串必须被翻译成8位字符。

    要生成需要传递的字符串指针,可以使用Marshal.StringToHGlobalAnsi或StringToHGlobalUni(分别为8位和Unicode)。但是,您可以玩一个技巧,让P/Invoke marshaller为您翻译字符串。省去了通话后释放字符串的麻烦。对于Ansi版本,可以这样声明API函数:

        [DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
        private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
    

    Unicode版本如下:

        [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
        private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
    

    最后一点注意:如果该窗口属于另一个应用程序,则无法正常工作,您将使其崩溃。您传递的指针值仅在您自己的进程中有效,而不是在C++进程中有效。要解决这个问题,必须在目标进程中分配内存,以便指针有效。这需要OpenProcess获取进程的句柄,VirtualAllocEx()在目标进程中分配内存,足够大以存储字符串,WriteProcessMemory写入字符串。现在可以调用SendMessage(),使用用IntPtr声明的wParam和lParam参数的版本,传递从VirtualAllocEx获得的值。接下来使用VirtualFreeEx()释放内存,并使用CloseHandle进行清理。如果你经常这样做的话,也可以把记忆留到下次。

    很多人在那里犯了错误。更不用说安全问题,WriteProcessMemory需要管理员权限,需要UAC提升。

        2
  •  0
  •   Daniel    16 年前

    通过 字符串的任何部分都会涉及不安全的代码,

        3
  •  -2
  •   Wildhorn    16 年前

    我们最终用“WmCpyDta\u d.dll”来处理所有这些。