使用 C# 中的 HBITMAP 句柄检索远程位图

发布于 2024-09-18 12:39:06 字数 1751 浏览 10 评论 0原文

我有一个 MarshalByRefObject ,需要对其进行序列化和存储(在数据库中),以便稍后可以反序列化并引用它。我选择了不同的方法:现在我正在运行一个 Windows 服务,它只是使 MarshalByRefObjects 保持“活动状态”(请注意,RemoteObject 实际上是第 3 方对象,我自己不创建):

// This is the object which extends the MarshalByRefObject class
RemoteObject myRemoteObject = new RemoteObject;

TcpServerChannel channel = new TcpServerChannel(6789);
ChannelServices.RegisterChannel(channel, true);

ObjRef objRef = RemotingServices.Marshal((System.MarshalByRefObject)myRemoteObject, id);

在另一个 AppDomain 中,我只需连接并检索对象;一切正常:

RemoteObject myLocalObject = (FCEngine.IFCVerificationSession)Activator.GetObject(
                           typeof(FCEngine.IFCVerificationSession),"tcp://localhost:6789/" + id);

现在的问题是 RemoteObject 包含一个属性,该属性只是一个转换为 long 类型的 HBITMAP 句柄。我可以轻松地取回手柄。通常(本地)我会这样做:

IntPtr hbitmap = (IntPtr)myLocalObject.ContextImage;
System.Drawing.Bitmap bmp = System.Drawing.Image.FromHbitmap(hbitmap);

这在当前情况下不起作用。我得到一个 System.Runtime.InteropServices.ExternalException 我猜问题是 hbitmap 是本地 AppDomain 中不存在的某些内存的句柄,但在Windows 服务应用程序域。我的问题是我的选择是什么:

  • RemoteObject 非常复杂,它就像一棵树,您可以通过调用其函数来遍历节点。第三方强制我只能遍历该对象一次。因此,在服务端遍历它,将位图存储在数据库中,然后再次远程遍历它是行不通的。
  • 理想的情况是能够调用 Windows 服务中的函数,并将 hbitmap 句柄作为参数传递,返回实际的位图。这在 Windows 服务中是不可能的。
  • 我可以将句柄存储在数据库中,并让 Windows 服务轮询数据库来查找它。然后它可以检索位图并将其存储在同一个数据库中。然后我可以再次远程检索该位图。这非常难看,因为我立即需要位图。

基本上我想知道您是否有建议不必执行像第三个选项这样的丑陋黑客......我的选择是什么?

已解决 现在,我通过创建一个在服务端扩展 MarshalByRefObject 的自定义对象来解决这个问题。该对象有一个通过传递句柄来检索和保存位图的方法。我只是远程接近该对象,就像接近我的第 3 方对象一样。尽管一位同事必须指出,但解决方案太简单了。

I have a MarshalByRefObject which I needed to serialize and store (in a database), so I could deserialize and reference it later. I have chosen to approach this differently: right now I am running a Windows Service which simply keeps the MarshalByRefObjects "alive" (please note that the RemoteObject is actually a 3rd party object, which I do not create myself):

// This is the object which extends the MarshalByRefObject class
RemoteObject myRemoteObject = new RemoteObject;

TcpServerChannel channel = new TcpServerChannel(6789);
ChannelServices.RegisterChannel(channel, true);

ObjRef objRef = RemotingServices.Marshal((System.MarshalByRefObject)myRemoteObject, id);

In another AppDomain I simply connect and retrieve the object; all works fine:

RemoteObject myLocalObject = (FCEngine.IFCVerificationSession)Activator.GetObject(
                           typeof(FCEngine.IFCVerificationSession),"tcp://localhost:6789/" + id);

Now the problem is that the RemoteObject contains a property which is simply an HBITMAP handle casted to the long type. I can retrieve the handle easily. Normally (locally) I would do:

IntPtr hbitmap = (IntPtr)myLocalObject.ContextImage;
System.Drawing.Bitmap bmp = System.Drawing.Image.FromHbitmap(hbitmap);

This doesn't work in the current case. I get a System.Runtime.InteropServices.ExternalException I guess the problem is that hbitmap is a handle to some memory which doesn't exist in the local AppDomain, but in the Windows Service AppDomain. My question is what my options are:

  • The RemoteObject is pretty complex, it's like a tree in which you traverse the nodes by calling its functions. The 3rd party imposes that I can only traverse the object once. So traversing it Service-side, storing bitmaps in a database, and traversing it remotely again won't work.
  • Ideal would be to be able to call a function in the Windows Service, and pass the hbitmap handle as an argument, returning the actual bitmap. This is not possible in Windows Services.
  • I could store the handle in a database and make the Windows Service poll the database for it. It could then retrieve the bitmap and store it in that same DB for me. I could then again retrieve that bitmap remotely. This is very ugly, since I need the bitmap immediately.

Basically I'd like to know if you have suggestions to not have to perform ugly hacks like the 3rd option...What are my options?

SOLVED
Right now I solved the problem by creating a custom object which extends MarshalByRefObject on the service side. This object has a method to retrieve and save a bitmap by passing the handle. I simply approach the object remotely, in the same way I approach my 3rd party object. Too simple of a solution, although a colleague had to point it out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

扛起拖把扫天下 2024-09-25 12:39:06

HBitmap 是一个句柄,序列化非托管句柄是没有意义的。您需要序列化位图内容,在远程端重新创建它(位图),然后重新分配新创建的 hbitmap。

PS 物理上句柄是一个指向指针的指针,它的值仅适用于创建地址空间的情况。

恕我直言。

HBitmap is a handle, it has no sense to serialize unmanaged handles. You need to serialize the bitmap content, recreate it (bitmap) on a remote side, and then re-assign newly created hbitmap.

P.S. Physically handle is a pointer to pointer, its value is applicable only an the address space is was created.

IMHO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文