接下来,我们看看开发一个Windows CE的应用程序如何做;作为.NET Framework 的一个子集,.NET Compact Framework只提供了.NET Framework的一部分功能 ,所以特别的Mutex的对象的功能已经完全被弱化.; NET Compact Framework 并不支持这个所谓的互斥体,但幸运的是 Windows CE通过这个coredll.dll动态链接库中的几个函数可以实现这一功能; 有人就问啦,为什么是coredll.dll,而不是其他动态链接库呢?好问题,是因为Windows CE下大部分的API存在于coredll.dll里面,同时DllImport不仅仅支持Win32 API,他可以支持任何native 的DLL的引入。于是有人又要问啦,啥叫”native的DLL的引入?”..呵呵…自己查资料,网上一大堆..
在操作系统创建这个Mutex是必须带有一个特别的命名,这个在文章开头已经讲的比较清楚,就是唯一的暂住证(哈哈..真的有点象..大家好好体会这个”暂住证”..);有了这个暂住证呢,这个Mutex的实际功能才能真正体现;如果你想再冒名创建同样的名字,对不起,系统就警告你;
基本上来讲,如果你创建一个带特别命名的Mutex应用程序,就能确保这个应用程序能唯一地运行在操作系统中;
作为.NET Framework 的一个子集,.NET Compact Framework只提供了.NET Framework的一部分功能,因此有时在实现一些功能时不得不借助于Windows CE API。另外还存在一些第三方的组件或资源,或以动态链接库形式提供,或者已经是COM组件。相对于.NET Compact Framework,它们都属于非托管资源。我们需要一种功能,实现由托管环境访问这些非托管资源。和.NET Framework 一样,平台调用P/Invoke(Platform Invocation Services)提供托管代码调用驻留于 DLL 中的非托管函数的功能。下面是一张平台调用的原理图(From MSDN)。
.NET Compact Framework下,如何做平台调用呢?
下面使用DllImport特征导入Windows CE的API函数MessageBoxW的定义。现举例说明:
<DllImport("coredll.dll", SetLastError := true)> _
public static extern Private Shared function MessageBoxW(ByVal hWnd as IntPtr, ByVal text as String, ByVal caption as String caption, byVal type as uint) as Integer
End Function
End Class
然后可以对它进行调用;
Private sub button1_Click(ByVal sender as object, ByVal e as EventArgs )
Dim Zero as intPtr
APIHelper.MessageBoxW(Zero, "测试MessageBoxW函数",
"API调用", 0)
End sub
然后可以对它进行调用;
Dim Zero as intPtr
APIHelper.MessageBoxW(Zero, "测试MessageBoxW函数",
"API调用", 0)
End sub
可以看到,使用P/Invoke包括声明和调用两个过程,另外还有一个错误处理的过程。通过声明来指定要调用的非托管函数,.NET Compact Framework也是使用DllImport特性来进行声明,包括模块名、函数名及调用约定。与.NET Framework完整版的DllImport特性不同,.NET Compact Framework的一共包括五个公共字段:CallingConvention,CharSet,EntryPoint,PreserveSig和SetLastError。具体各字段的说明可以参考MSDN。
有了上述的内容打底,我们就要用平台调用这样的概念来实现,Windows CE下,这个应用程序单独运行这样的用户需求;下面我创建了一个类,就叫SingleInstance Application;
Imports System.Windows.Forms
‘记得要引用InteropServices这个类
Imports System.Runtime.InteropServices
Imports System.Reflection
Public Class SingleInstanceApplication
<DllImport("coredll.dll", SetLastError:=True)> _
Private Shared Function CreateMutex(ByVal Attr As IntPtr, ByVal Own As Boolean, ByVal Name As String) As Integer
End Function
<DllImport("coredll.dll", SetLastError:=True)> _
Private Shared Function ReleaseMutex(ByVal hMutex As IntPtr) As Boolean
End Function
Const ERROR_ALREADY_EXISTS As Long = 183
Public Sub Run(ByVal frm As Form)
Dim name As String = Assembly.GetExecutingAssembly().GetName().Name
Dim mutexHandle As IntPtr = CreateMutex(IntPtr.Zero, True, name)
Dim xError As Long = Marshal.GetLastWin32Error()
If xError <> ERROR_ALREADY_EXISTS Then
Application.Run(frm)
Else
MsgBox("This Application already running now!")
frm.Close()
End If
ReleaseMutex(mutexHandle)
End Sub
End Class
这个类导入了两个native 的函数,一个是创建Mutex,那另一个就是释放Mutex;还有一个简单的公用函数;