在.NET下的remoting使用里面,很多的書上都是使用了客戶和服務器端都是使用一樣共享成員或接口的示例來做說明。而且在實際的使用中有不小的問題。
[共享代碼] share.vb Imports System.windows.forms
Public Interface Iconnect '客戶端和服務器端同時共享使用一個接口 Function getName() As String End Interface
Public Class app Public Shared ReadOnly Property appPath() As String '提供一些應用程序常用路徑將會在服務安裝的 Get '過程中被使用 Return Application.StartupPath End Get End Property
Public Shared ReadOnly Property winPath() As String Get Return System.Environment.GetEnvironmentVariable("windir") End Get End Property End Class
[服務器端] '共倆個文件,第一個是服務文件,第二個是服務調用的功能實現文件 service1.vb '引用了System.Runtime.Remoting.dll文件,這是服務 Imports System.ServiceProcess Imports System.Runtime Imports System.Runtime.Remoting Imports System.Runtime.Remoting.Channels
Public Class Service1 Inherits System.ServiceProcess.ServiceBase
#Region " 組件設計器生成的代碼 "
Public Sub New() MyBase.New()
' 該調用是組件設計器所必需的。 InitializeComponent()
' 在 InitializeComponent() 調用之后添加任何初始化
End Sub
'UserService 重寫 dispose 以清理組件列表。 Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub
' 進程的主入口點 <MTAThread()> _ Shared Sub Main() Dim ServicesToRun() As System.ServiceProcess.ServiceBase
' 在同一進程中可以運行不止一個 NT 服務。若要將 ' 另一個服務添加到此進程,請更改下行以 ' 創建另一個服務對象。例如, ' ' ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService} ' ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1}
System.ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub
'組件設計器所必需的 Private components As System.ComponentModel.IContainer
'注意: 以下過程是組件設計器所必需的 ' 可以使用組件設計器修改此過程。 ' 不要使用代碼編輯器修改它。 <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() ' 'Service1 ' Me.ServiceName = "Server"
End Sub
#End Region
Protected Overrides Sub OnStart(ByVal args() As String) ' 在此處添加啟動服務的代碼。此方法應設置具體的操作 ' 以便服務可以執行它的工作。 Try Dim ch As New Tcp.TcpChannel(8212) '監聽端口是在8212,你可以修改該端口 ChannelServices.RegisterChannel(ch) '注冊端口 Remoting.RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("serviceShare.serviceShare,serviceShare", True, True), "server", WellKnownObjectMode.Singleton)
'Type.GetType中的String是需要引用的服務所在的位置,"serviceShare.serviceShare,serviceShare" 中前面倆個serviceShare是指服務所在的程序集中的要做服務的類。逗號后面的serviceShare是指該程序集位于的文件。后面的第三個參數:True就是表示要搜索該文件時不區分大小寫。"server"表示服務的名稱。 Catch ex As Exception EventLog.WriteEntry("日志 " & ex.Message) End Try
End Sub
Protected Overrides Sub OnStop() ' 在此處添加代碼以執行停止服務所需的關閉操作。 Try Dim ch As New Tcp.TcpChannel(8212) ChannelServices.UnregisterChannel(ch) Catch ex As Exception EventLog.WriteEntry("日志 " & ex.Message) End Try End Sub
End Class
serviceShare.vb '該文件為接口的實現文件,可以修改這個文件獲得自己需要的服務,可以在這里引用 '其他DLL中的方法 Public Class serviceShare Inherits MarshalByRefObject Implements share.Iconnect Private shared i As Int32 = 0
Public Function getName() As String Implements share.Iconnect.getName i = i + 1 Return "from Server " & i End Function End Class
[客戶端] form1.vb Imports System Imports System.Runtime Imports System.Runtime.Remoting Imports System.Runtime.Remoting.Channels
Public Class Form1 Inherits System.Windows.Forms.Form Private ch As Tcp.TcpChannel
#Region " Windows 窗體設計器生成的代碼 "
Public Sub New() MyBase.New()
'該調用是 Windows 窗體設計器所必需的。 InitializeComponent()
'在 InitializeComponent() 調用之后添加任何初始化
End Sub
'窗體重寫 dispose 以清理組件列表。 Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub
'Windows 窗體設計器所必需的 Private components As System.ComponentModel.IContainer
'注意: 以下過程是 Windows 窗體設計器所必需的 '可以使用 Windows 窗體設計器修改此過程。 '不要使用代碼編輯器修改它。 Friend WithEvents Label1 As System.Windows.Forms.Label Friend WithEvents Button1 As System.Windows.Forms.Button <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.Label1 = New System.Windows.Forms.Label Me.Button1 = New System.Windows.Forms.Button Me.SuspendLayout() ' 'Label1 ' Me.Label1.Location = New System.Drawing.Point(80, 50) Me.Label1.Name = "Label1" Me.Label1.Size = New System.Drawing.Size(125, 25) Me.Label1.TabIndex = 0 Me.Label1.Text = "Label1" ' 'Button1 ' Me.Button1.Location = New System.Drawing.Point(105, 195) Me.Button1.Name = "Button1" Me.Button1.Size = New System.Drawing.Size(75, 25) Me.Button1.TabIndex = 1 Me.Button1.Text = "Button1" ' 'Form1 ' Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14) Me.ClientSize = New System.Drawing.Size(292, 273) Me.Controls.Add(Me.Button1) Me.Controls.Add(Me.Label1) Me.Name = "Form1" Me.Text = "Form1" Me.ResumeLayout(False)
End Sub
#End Region
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim serverName As String Dim aa As share.Iconnect serverName = "tcp://127.0.0.1:8212/server" aa = CType(Activator.GetObject(Type.GetType("share.Iconnect,share", True, True), serverName), share.Iconnect) '注意這個地方 Label1.Text = aa.getName() End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ch = New Tcp.TcpChannel '客戶端可以不注冊端口 ChannelServices.RegisterChannel(ch) End Sub End Class
[服務安裝] Strart.vb '服務安裝 Module Strart Sub Main(ByVal arg() As String) On Error Resume Next #If DEBUG Then If IO.File.Exists("setup.bat") Then '批處理附后面 Shell("setup.bat", , True) End If #End If If (IO.File.Exists("testService.exe")) Then Shell(share.app.winPath & "\Microsoft.NET\Framework\v1.1.4322\InstallUtil.exe " _ & share.app.appPath & "\testService.exe /LogFile", AppWinStyle.Hide, True) Dim Sc2 As New System.ServiceProcess.ServiceController("server") If Sc2.Status = ServiceProcess.ServiceControllerStatus.Stopped Then Sc2.Start() End If End If End Sub End Module
[服務卸載] UnSetup.vb Module strart Sub Main() On Error Resume Next If (IO.File.Exists("testservice.exe")) Then Dim Sc1 As New System.ServiceProcess.ServiceController("server") If Sc1.Status = ServiceProcess.ServiceControllerStatus.Running Then Sc1.Stop()
End If Shell(share.app.winPath & "\Microsoft.NET\Framework\v1.1.4322\InstallUtil.exe /u " _ & share.app.appPath & "\testservice.exe /LogFile", AppWinStyle.Hide, True) End If End Sub End Module
[批處理] copy ..\..\serviceShare\bin\serviceShare.dll .\serviceShare.dll copy ..\..\test\bin\test.exe .\test.exe copy ..\..\shared\bin\share.dll .\share.dll copy ..\..\UnSetup\bin\UnSetup.exe .\UnSetup.exe copy ..\..\testService\bin\testService.exe .\testService.exe
這樣能方便的擴展自己的功能,因為很多書上的代碼,使用都是抄微軟的,如果程序是分開獨立制作,只公布接口的話,安微軟的做法就很難成功。
示例雖然是在一個程序中實現的,但在倆個程序里面也不會有問題,大家可以自己試。
點擊下載所需代碼
|