First off im a student, but this is Not an assignment, it's the end of degree project!.. so im kinda freakin out a bit.
i dont want a handout, just a point in the right direction.
Ive built this application, like a floorplan viewer that has network devices on the map, works great, but now my business client wants to make it distributed, and run it as a service.
i have used a previous chatroom that i built to use for a test case, to see if i could host a remoting server in a service. the chatroom works fine its very simple, which is why i thought it would be a good test for using remoting in a service. for the test case (and confidentialy) ive decided its better to post this chatroom that i converted to a service instead of the real app.
The problem is the same with both the chatroom and the floorplan app,
1. the service starts fine, creates proxy, a successful event log is written.
2. start the client, proxy created, then on the first proxy method call i get this error...
************** Exception Text **************
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'ClientGUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'ClientGUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.Reflection.MemberInfoSerializationHolder..ctor(SerializationInfo info, StreamingContext context)
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: DisplayName = ClientGUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/chat/MyService/bin/Release/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/chat/MyService/bin/Release/ClientGUI.DLL.
LOG: Attempting download of new URL file:///C:/chat/MyService/bin/Release/ClientGUI/ClientGUI.DLL.
LOG: Attempting download of new URL file:///C:/chat/MyService/bin/Release/ClientGUI.EXE.
LOG: Attempting download of new URL file:///C:/chat/MyService/bin/Release/ClientGUI/ClientGUI.EXE.
--- End of inner exception stack trace ---
Server stack trace:
at System.RuntimeMethodHandle._SerializationInvoke(Object target, SignatureStruct& declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.RuntimeMethodHandle.SerializationInvoke(Object target, SignatureStruct declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.Reflection.RuntimeConstructorInfo.SerializationInvoke(Object target, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel)
at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at SharedClasses.IServer.Connect(Parcel msgDel, Parcel usrDel, String userName)
at ClientGUI.ClientForm.btnConnect_Click(Object sender, EventArgs e) in C:\chat\ClientGUI\ClientForm.vb:line 41
at System.Windows.Forms.Control.onclick(EventArgs e)
at System.Windows.Forms.Button.onclick(EventArgs e)
at System.Windows.Forms.Button.onmouseup(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativewindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativewindow.WndProc(Message& m)
at System.Windows.Forms.Nativewindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
************** Loaded Assemblies **************
mscorlib
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
ClientGUI
Assembly Version: 1.0.0.0
Win32 Version: 1.0.0.0
CodeBase: file:///C:/chat/ClientGUI/bin/Release/ClientGUI.exe
----------------------------------------
Microsoft.VisualBasic
Assembly Version: 8.0.0.0
Win32 Version: 8.0.50727.42 (RTM.050727-4200)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/Microsoft.VisualBasic/8.0.0.0__b03f5f7f11d50a3a/Microsoft.VisualBasic.dll
----------------------------------------
System
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Windows.Forms
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Configuration
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Xml
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
System.Runtime.Remoting
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.832 (QFE.050727-8300)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Runtime.Remoting/2.0.0.0__b77a5c561934e089/System.Runtime.Remoting.dll
----------------------------------------
SharedClasses
Assembly Version: 1.0.0.0
Win32 Version: 1.0.0.0
CodeBase: file:///C:/chat/ClientGUI/bin/Release/SharedClasses.DLL
----------------------------------------
the questions i guess i have are...
How do i tell it where to find the assembly?,
why does this not happen when it is not run as a service.. it works fine. i got good marks for it!
i really havent dealt with assemblys and namespaces (conciously) and this stuff, but keen as to figure this out.
Can anyone point me in the right direction?
Many thanks
red
Code for Service:
Imports System.Runtime.Remoting
Imports MyServer
Imports SharedClasses
Public Class MyService
Private proxy As Server
Protected Overrides Sub onstart(ByVal args() As String)
RemotingConfiguration.Configure("C:\chat\MyService\bin\Release\ServerForm.config", False)
proxy = CType(Activator.GetObject(Type.GetType("SharedClasses.IServer, SharedClasses"), "tcp://localhost:8085/yakkityYak"), SharedClasses.IServer)
Dim objEventLog As New EventLog()
objEventLog.Source = "MyService"
objEventLog.WriteEntry("proxy created")
'StartTimer()
' Add code here to start your service. This method should set things
' in motion so your service can do its work.
End Sub
Protected Overrides Sub onstop()
' Add code here to perform any tear-down necessary to stop your service.
End Sub
End Class
Code for Server:
Imports SharedClasses
Public Class Server
Inherits MarshalByRefObject
Implements IServer
Private htMsgDel As New Hashtable
Private htUsrDel As New Hashtable
Public msgDel As IServer.msgCallBack
Public usrDel As IServer.usrCallBack
Public Function Connect(ByVal msgParcel As Parcel, ByVal usrParcel As Parcel, ByVal userName As String) As Boolean Implements IServer.Connect
SyncLock GetType(Server)
Dim connected As Boolean
If Not htUsrDel.ContainsKey(userName) Then
htMsgDel.Add(userName, msgParcel.msgDel())
htUsrDel.Add(userName, usrParcel.usrDel())
BroadcastUsers(userName)
connected = True
Else
MsgBox("The username " & userName & " is not available.")
End If
Return connected
End SyncLock
End Function
Public Sub disConnect(ByVal userName As String) Implements SharedClasses.IServer.disConnect
SyncLock GetType(Server)
htMsgDel.Remove(userName)
htUsrDel.Remove(userName)
BroadcastUsers(userName)
End SyncLock
End Sub
Public Sub BroadcastUsers(ByVal senderName As String) Implements IServer.BroadcastUsers
Dim alUsers As New ArrayList
For Each userName As String In htUsrDel.Keys
If Not userName = "server" Then
alUsers.Add(userName)
End If
Next
For Each userName As String In htUsrDel.Keys
If Not userName = senderName Then
usrDel = htUsrDel.Item(userName)
usrDel(alUsers)
End If
Next
End Sub
Public Sub Message(ByVal msg As String, ByVal userName As String) Implements IServer.Message
SyncLock GetType(Server)
For Each user As String In htMsgDel.Keys
If Not user = userName Then
msgDel = htMsgDel.Item(user)
msgDel(userName & ": " & msg & vbCrLf, userName)
End If
Next
End SyncLock
End Sub
Public Function getUsers() As ArrayList Implements IServer.getUsers
Dim alUsers As New ArrayList
For Each userName As String In htMsgDel.Keys
alUsers.Add(userName)
Next
Return alUsers
End Function
Public Sub TickMessage(ByVal msg As String) Implements IServer.TickMessage
SyncLock GetType(Server)
For Each user As String In htMsgDel.Keys
If Not user = "server" Then
msgDel = htMsgDel.Item(user)
msgDel(msg & vbCrLf, user)
End If
Next
End SyncLock
End Sub
End Class
Code for Server config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.runtime.remoting> <application> <channels> <channel ref="tcp" port="8085"> <serverProviders> <provider ref="wsdl" /> <formatter ref="soap" typeFilterLevel="Full" /> <formatter ref="binary" typeFilterLevel="Full" /> </serverProviders> <clientProviders> <formatter ref="binary" /> </clientProviders> </channel> </channels> <service> <wellknown type="MyServer.Server, MyServer" objectUri="yakkityYak" mode="Singleton" /> </service> <!-- <lifetime leaseTime="10S" sponsorshipTimeOut="10S" renewOnCallTime="5S"/> --> </application> </system.runtime.remoting> </configuration>
Code for Client:
Imports System.Runtime.Remoting.Channels.ChannelServices
Imports System.Runtime.Remoting.Channels.TCP
Imports SharedClasses
Public Class ClientForm
Private IPAddress As String
Private userName As String
Private proxy As IServer
Public msgDel As IServer.msgCallBack
Public usrDel As IServer.usrCallBack
Private myConfiguration As Configuration
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn.Click
If txtUserName.Text = "" Then
MsgBox("enter a user name please")
txtUserName.Focus()
ElseIf Not txtUserName.Text.Length <= 13 Then
MsgBox("user name must be 13 characters or less")
txtUserName.Focus()
Else
Dim chan As TcpChannel
chan = New TcpChannel(0)
RegisterChannel(chan, False)
proxy = Activator.GetObject(Type.GetType("SharedClasses.IServer, SharedClasses"), "tcp://localhost:8085/yakkityYak")
' Send message delegate
msgDel = AddressOf msgCallBack
Dim msgParcel As Parcel = New Parcel(msgDel)
usrDel = AddressOf usrCallBack
Dim usrParcel As Parcel = New Parcel(usrDel)
userName = txtUserName.Text
Try
Dim connected As Boolean = proxy.Connect(msgParcel, usrParcel, userName)
If connected Then
btn.Enabled = False
btnSend.Enabled = True
txtUserName.Enabled = False
Me.Text = "Client : " & txtUserName.Text
ToolStripConnect.Text = "Connected"
For Each user As String In proxy.getUsers()
If Not user = "server" Then
lstUserNames.Items.Add(user)
End If
Next
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End If
End Sub
Private Sub ClientForm_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
If Not proxy Is Nothing Then
proxy.disConnect(userName)
End If
End Sub
Public Sub usrCallBack(ByVal userNames As ArrayList)
lstUserNames.Items.Clear()
For Each user As String In userNames
lstUserNames.Items.Add(user)
Next
End Sub
Public Sub msgCallBack(ByVal msg As String, ByVal userName As String)
rtbMessages.AppendText(msg)
End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
If Not txtMessage.Text = "" Then
proxy.Message(txtMessage.Text, userName)
msgCallBack(userName & ": " & txtMessage.Text & vbCrLf, userName)
txtMessage.Text = ""
txtMessage.Focus()
End If
End Sub
Private Sub ClientForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
btnSend.Enabled = False
IPAddress = "localhost"
End Sub
Private Sub contextUser_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles contextUser.Opening
If Not lstUserNames.SelectedIndex = -1 Then
MsgBox(lstUserNames.SelectedItem.ToString)
End If
End Sub
Private Sub mnuConfiguration_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuConfiguration.Click
If myConfiguration Is Nothing Then
myConfiguration = New Configuration
End If
myConfiguration.Show()
End Sub
End Class
Code for serializable object
<Serializable()> Public Class Parcel Private msgDelegate As IServer.msgCallBack Private usrDelegate As IServer.usrCallBack Public Sub New(ByVal del As IServer.msgCallBack) msgDelegate = del End Sub Public Sub New(ByVal del As IServer.usrCallBack) usrDelegate = del End Sub Public ReadOnly Property msgDel() As IServer.msgCallBack Get Return msgDelegate End Get End Property Public ReadOnly Property usrDel() As IServer.usrCallBack Get Return usrDelegate End Get End Property End Class
code for interface to server
Public Interface IServer Delegate Sub msgCallBack(ByVal s As String, ByVal userName As String) Delegate Sub usrCallBack(ByVal userNames As ArrayList) Function Connect(ByVal msgDel As Parcel, ByVal usrDel As Parcel, ByVal userName As String) As Boolean Sub disConnect(ByVal userName As String) Sub Message(ByVal msg As String, ByVal userName As String) Sub TickMessage(ByVal msg As String) Sub BroadcastUsers(ByVal senderName As String) Function getUsers() As ArrayList End Interface
code for the server Gui ***** not used anymore, this is what the service is replacing... hopefully...
Imports System.Runtime.Remoting
Imports MyServer
Imports SharedClasses
Public Class ServerForm
Private proxy As New Server
Public msgDel As IServer.msgCallBack
Public usrDel As IServer.usrCallBack
Private Sub ServerForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
mnuShutdown.Enabled = False
Timer1.Enabled = True
End Sub
Private Sub StartServerToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuStart.Click
'configure server
RemotingConfiguration.Configure("ServerForm.config", False)
proxy = CType(Activator.GetObject(Type.GetType("SharedClasses.IServer, SharedClasses"), "tcp://localhost:8085/yakkityYak"), IServer)
'setup delegates
msgDel = AddressOf MsgCallBack
Dim msgParcel As Parcel = New Parcel(msgDel)
usrDel = AddressOf usrCallBack
Dim usrParcel As Parcel = New Parcel(usrDel)
'connect to proxy
Dim connected As Boolean = proxy.Connect(msgParcel, usrParcel, "server")
mnuStart.Enabled = False
mnuShutdown.Enabled = True
toolStripConnect.Text = "Server Started"
End Sub
Public Sub MsgCallBack(ByVal msg As String, ByVal userName As String)
rtbMessages.AppendText(msg)
End Sub
Public Sub usrCallBack(ByVal userNames As ArrayList)
lstUserNames.Items.Clear()
For Each user As String In userNames
lstUserNames.Items.Add(user)
Next
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
proxy.TickMessage("sss")
MsgBox("x")
End Sub
End Class
thanks for your time

Reply





MultiQuote




|