问题
GotDotNet论坛,用户问"有没有办法支持一个"ddeexec'的功能在vb.net应用程序的文件关联,所以当应用程序已经在运行,一个文件双击从Windows资源管理器,应用程序可以处理呢?"。 DDE有没有被推荐的很长一段时间,。NET中不支持它。一个解决方案
就个人而言,我可能永远不会被人打扰得到DDE工作。相反,我用从旧vbAccelerator站点: 名称与具体到您的应用程序创建一个互斥; &
#160; 如果互斥不存在,你的应用程序没有运行:
启动应用程序;&
#160; 标记与属性,以使容易辨认(SetProp)的主要形式;
60; 子类的主要形式,并等待WM_COPYDATA消息。数据将包含从一个新的实例的命令行;
60; 如果互斥已经存在,你的应用程序已经运行:
160; 枚举所有的窗口,找到一个与你的财产(GetProp);
如果你没有找到它,进行第2步; 如果你找到它,它发送WM_COPYDATA消息,从这个实例的命令行;
;
这可能看起来非常复杂,但App.PrevInstance财产并不总是可靠的,并没有提供任何方式将数据传输到其他实例。。NET
当我第一次看这个问题,我认为必须有一个更好的解决方案。NET中 - 这是很常见的一种应用,我是肯定的功能,将内置的。其中一些 - 如互斥锁 - 是。在System.Diagnostics类有些看起来非常有前途的的,但似乎并没有工作。举例来说,似乎没有一种方式从Process.MainWindowHandle NativeWindow对象 - FromHandle方法返回Nothing。有一个COPYDATASTRUCT System.Windows.Forms的,但尽管对象浏览器认为它是公共的,编译器认为它是私有的,所以不能使用。
最后,我不得不求助于我在VB6中使用了很多相同的Win32 API调用。子类是容易得多,VB.NET,和互斥对象的帮助,但我不能看到一个纯粹的托管代码解决这个问题。加端,Marshal类提供了一个非常简单的方法来管理对象和联合国的托管API之间的数据传输,虽然有些调用VB6的程序员可能并不明显。对象序列化也使人们有可能通过以及进程之间的对象。使用代码
要使用自己的代码,你将需要添加mMain.vb的文件添加到项目。设置启动对象,在本模块主要小组,并改变引用frmMain的,以反映您的应用程序的主要形式。您需要使您的主要形式实施mMain.SingleInstance.ISingleInstanceForm,使用下面的代码为例:
VB.NET和指针
//
// frmMain.vb
//
...
Public Event WndProc2(ByVal m As System.Windows.Forms.Message, _
ByRef Cancel As Boolean) _
Implements mMain.SingleInstance.ISingleInstanceForm.WndProc
'//Subclassing the form - so much easier than VB6! :)
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Dim bCancel As Boolean = False
RaiseEvent WndProc2(m, bCancel)
'If this message wasn't handled (i.e. WM_COPYDATA), pass it on
If Not bCancel Then MyBase.WndProc(m)
End Sub
'//The reference to the handle is required for SetProp
Public ReadOnly Property hWnd() As System.IntPtr _
Implements mMain.SingleInstance.ISingleInstanceForm.Handle
Get
Return Handle
End Get
End Property
'//This is where the string passed in the COPYDATASTRUCT is handled
'//In this case, we have a Base64 serialization of the CmdArgs() array
Public Sub HandleCommand(ByVal strCmd As String) _
Implements mMain.SingleInstance.ISingleInstanceForm.HandleCommand
Dim arrCmd() As String
Try
arrCmd = SerialHelper.DeserializeFromBase64String(strCmd)
HandleCommand(arrCmd)
Catch ex As Exception
MsgBox(ex.ToString)
HandleCommand(New String() {strCmd})
Finally
Erase arrCmd
End Try
End Sub
'//This is where we handle the command-line arguments
'//In this sample, I simply add them to the list-box
'//You would probably want to open the files, etc.
Public Sub HandleCommand(ByVal strArgs() As String)
Dim strCmd As String
For Each strCmd In strArgs
lstEvents.Items.Add("CMD: " & strCmd)
Next
End Sub
...
///
这个代码的一个有趣的事情 - 我已经发现了如何处理与联合国管理的指针。例如,COPYDATASTRUC结构包含的lpData成员,这是一个字节数组的指针。如果成员是定义为一个IntPtr,结构不能被传递给一个API,所以它声明为一个整数。
有两个操作 - 设置lpData成员指向一个字符串,并从中检索一个String。在VB6中,你会使用VarPtr和RtlMoveMemory API(又名CopyMemory)做到这一点。在。NET,VarPtr不再存在,但Marshal类提供了更好的替代品。
要设置指针到一个字符串值:{C}
要检索一个String指针:完成了!
如果有人发现一个更好的办法做到这一点,或一种方式来获得Process.MainWindowHandle NativeWindow对象,请让我知道!积分
SerialHelper类是"借用"从。