i had problem with application messaging, ...after some question and answer, i went to use Remoting namespace, under System.Runtime namespace...
it worked perfectly, but the matter is when application terminate with exception... if server stop in not manner, the channel i register will stay registered, ...
i dont have much knowledge over remoting or other related matter... but i checked some of things, and non didnt worked...
the article i went through done registering this way, and didnt unregister the application, and i use it in service, and seem service application host dont close just with service beign stopped...
here's my client class which is used in service applciation...
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace Remoting
{
public class Client
{
private RemotableObject remoteObject;
/// <summary>
/// Configure Client Class
/// </summary>
/// <param name="url">Something like: tcp://localhost:8080/HelloWorld</param>
public Client(string url)
{
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
remoteObject = (RemotableObject)Activator.GetObject(typeof(RemotableObject), url);
}
public void SetMessage(string message)
{
remoteObject.SetMessage(message);
}
}
}
as i noticed, the article give no information to the channel, so i'm wonder for unregistering it how should i find it.....
in the server APP, the article done givin host post at last
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace Remoting
{
public abstract class Server:IObserver
{
private RemotableObject remotableObject;
/// <summary>
/// Configure Server Class
/// </summary>
/// <param name="port">port number like: 8080</param>
/// <param name="url">Object url like: HelloWorld</param>
public Server(int port, string url)
{
remotableObject = new RemotableObject();
TcpChannel channel = new TcpChannel(port);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotableObject), url, WellKnownObjectMode.Singleton);
Cache.Attach(this);
}
public abstract void Notify(string message);
}
}
but, even know think i launch my application over a server that run an app with same port number, i do not want to un-register other application channels... what should i do?
BTW most issue is about the client that register a channel, with no information... how do i detect it? and unregister it, before service try to do that, and terminate with exception?
if it help, this is the error i already recieve:
Event Type: Error
Event Source: Event Reader Service
Event Category: None
Event ID: 0
Date: 8/20/2012
Time: 5:23:14 PM
User: N/A
Computer: HF-SERVER-PC
Description:
Service cannot be started. System.Runtime.Remoting.RemotingException: The channel 'tcp' is already registered. at System.Runtime.Remoting.Channels.ChannelServices.RegisterChannelInternal(IChannel chnl, Boolean ensureSecurity) at System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(IChannel chnl) at Remoting.Client..ctor(String url) at FileEventReaderService.Services.Logger.EventLogger..ctor(String source, String logName, String url) at FileEventReaderService.EventReader..ctor(String sqlServer, String instance, String integratedSecurityType, String username, String password, String dataBase) at FileEventReaderService.EventReaderService.OnStart(String[] args) at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)For more information, see Help and Support Center at go.microsoft.com/fwlink/….
In my case the problem were with multiple registering the tcp channel, in same instance, so i made a singleton class, and just set client once, and all other time i just called that instance....
using Remoting;
namespace FileEventReaderService.Services.Remotable
{
class SingletonClient
{
private static SingletonClient _instance = new SingletonClient();
private Client _client = null;
public static SingletonClient GetSingletonClient()
{
return _instance;
}
public Client GetClient()
{
return _client;
}
public void SetClientConfiguration(string url)
{
_client=new Client(url);
}
}
}
BTW, if any one need to find the process... he can use this article: http://www.timvw.be/2007/09/09/build-your-own-netstatexe-with-c/ download the demo source and use it...
i also edit it in my own way, you can use it: (i did not changed 2 main class 'TcpTable' and 'IpHelper')
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation;
using System.Net;
using System.Diagnostics;
using System.Collections;
using System.IO;
namespace FileEventReaderUI.Services.Network
{
class NetworkInformation
{
public ListenerProcessInformation GetListenerProcessInformationByPort(int port)
{
string fileName;
List<string> processModules=new List<string>();
foreach (TcpRow tcpRow in ManagedIpHelper.GetExtendedTcpTable(true))
{
if (tcpRow.LocalEndPoint.Port.ToString(CultureInfo.InvariantCulture).Equals(
port.ToString(CultureInfo.InvariantCulture))
&& tcpRow.State==TcpState.Listen)
{
Process process = Process.GetProcessById(tcpRow.ProcessId);
if (process.ProcessName != "System")
{
foreach (ProcessModule processModule in process.Modules)
{
processModules.Add(processModule.FileName);
}
fileName = Path.GetFileName(process.MainModule.FileName);
}
else
{
//Console.WriteLine(" -- unknown component(s) --"); ProcessModules count=0
//Console.WriteLine(" [{0}]", "System");
fileName = "[System]";
}
return new ListenerProcessInformation(fileName
, processModules.ToArray()
, new IPEndPoint(tcpRow.LocalEndPoint.Address,
tcpRow.LocalEndPoint.Port)
, new IPEndPoint(tcpRow.RemoteEndPoint.Address,
tcpRow.RemoteEndPoint.Port)
, tcpRow.ProcessId
, tcpRow.State);
}
}
return null;
}
}
#region Managed IP Helper API
public class TcpTable : IEnumerable<TcpRow>
{
#region Private Fields
private IEnumerable<TcpRow> tcpRows;
#endregion
#region Constructors
public TcpTable(IEnumerable<TcpRow> tcpRows)
{
this.tcpRows = tcpRows;
}
#endregion
#region Public Properties
public IEnumerable<TcpRow> Rows
{
get { return this.tcpRows; }
}
#endregion
#region IEnumerable<TcpRow> Members
public IEnumerator<TcpRow> GetEnumerator()
{
return this.tcpRows.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return this.tcpRows.GetEnumerator();
}
#endregion
}
public class TcpRow
{
#region Private Fields
private IPEndPoint localEndPoint;
private IPEndPoint remoteEndPoint;
private TcpState state;
private int processId;
#endregion
#region Constructors
public TcpRow(IpHelper.TcpRow tcpRow)
{
this.state = tcpRow.state;
this.processId = tcpRow.owningPid;
int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
long localAddress = tcpRow.localAddr;
this.localEndPoint = new IPEndPoint(localAddress, localPort);
int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
long remoteAddress = tcpRow.remoteAddr;
this.remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
}
#endregion
#region Public Properties
public IPEndPoint LocalEndPoint
{
get { return this.localEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return this.remoteEndPoint; }
}
public TcpState State
{
get { return this.state; }
}
public int ProcessId
{
get { return this.processId; }
}
#endregion
}
public static class ManagedIpHelper
{
#region Public Methods
public static TcpTable GetExtendedTcpTable(bool sorted)
{
List<TcpRow> tcpRows = new List<TcpRow>();
IntPtr tcpTable = IntPtr.Zero;
int tcpTableLength = 0;
if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) != 0)
{
try
{
tcpTable = Marshal.AllocHGlobal(tcpTableLength);
if (IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidAll, 0) == 0)
{
IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.length));
for (int i = 0; i < table.length; ++i)
{
tcpRows.Add(new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow))));
rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
}
}
}
finally
{
if (tcpTable != IntPtr.Zero)
{
Marshal.FreeHGlobal(tcpTable);
}
}
}
return new TcpTable(tcpRows);
}
#endregion
}
#endregion
#region P/Invoke IP Helper API
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366073.aspx"/>
/// </summary>
public static class IpHelper
{
#region Public Fields
public const string DllName = "iphlpapi.dll";
public const int AfInet = 2;
#endregion
#region Public Methods
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
/// </summary>
[DllImport(IpHelper.DllName, SetLastError = true)]
public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TcpTableType tcpTableType, int reserved);
#endregion
#region Public Enums
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366386.aspx"/>
/// </summary>
public enum TcpTableType
{
BasicListener,
BasicConnections,
BasicAll,
OwnerPidListener,
OwnerPidConnections,
OwnerPidAll,
OwnerModuleListener,
OwnerModuleConnections,
OwnerModuleAll,
}
#endregion
#region Public Structs
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TcpTable
{
public uint length;
public TcpRow row;
}
/// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TcpRow
{
public TcpState state;
public uint localAddr;
public byte localPort1;
public byte localPort2;
public byte localPort3;
public byte localPort4;
public uint remoteAddr;
public byte remotePort1;
public byte remotePort2;
public byte remotePort3;
public byte remotePort4;
public int owningPid;
}
#endregion
}
#endregion
}
and the Entity class i use to fill ...
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
namespace FileEventReaderUI.Services.Network
{
class ListenerProcessInformation
{
private string _fileName;
private string[] _processModules;
private IPEndPoint _localEndPoint;
private IPEndPoint _remoteEndPoint;
private int _processId;
private TcpState _state;
public ListenerProcessInformation(string fileName, string[] processModules, IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, int processId, TcpState state)
{
_fileName = fileName;
_processModules = processModules;
_localEndPoint = localEndPoint;
_remoteEndPoint = remoteEndPoint;
_processId = processId;
_state = state;
}
public string FileName
{
get { return _fileName; }
}
public string[] ProcessModules
{
get { return _processModules; }
}
public IPEndPoint LocalEndPoint
{
get { return _localEndPoint; }
}
public IPEndPoint RemoteEndPoint
{
get { return _remoteEndPoint; }
}
public int ProcessId
{
get { return _processId; }
}
public TcpState State
{
get { return _state; }
}
}
}