Click here to Skip to main content
15,893,814 members
Articles / Desktop Programming / Windows Forms

Windows Services Made Simple

Rate me:
Please Sign up or sign in to vote.
4.62/5 (10 votes)
27 Jun 2007CPOL10 min read 94.5K   6.9K   69  
Describes how to build a Windows Service using the Pegasus Library.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;

using Pegasus.Diagnostics;
using Pegasus.Runtime.Serialization;

namespace Pegasus.Runtime.Remoting.Messaging
{
	/// <summary>
	/// Internal class for passing messages as part of the remoting sinks.
	/// </summary>
	[Serializable]
	internal class PegasusMethodCall : IMethodCallMessage, IMethodReturnMessage, ISerializable
	{
		// Local Instance Values
		private IDictionary m_properties;
		
		private object[] m_inArgs = new object[ 0 ];
		private string[] m_inArgsNames = new string[ 0 ];
		private object[] m_args = new object[ 0 ];
		private string[] m_argsNames = new string[ 0 ];
		private object[] m_outArgs = new object[ 0 ];
		private string[] m_outArgsNames = new string[ 0 ];

		private bool m_hasVarArgs = false;
		private LogicalCallContext m_logicalCallContext = null;
		private string m_methodUri = null;
		private object m_returnValue = null;
		private Exception m_exception = null;

		private MethodInfo m_methodInfo = null;
		
		// Local Static Values
		private static ObjectSerializationBinder s_binder = new ObjectSerializationBinder();

		/// <summary>
		/// Initializes a new instance of the <see cref="PegasusMethodCall"/> class.
		/// </summary>
		/// <param name="message">The message.</param>
		public PegasusMethodCall( IMessage message )
		{
			// Check Parameters
			ParamCode.AssertNotNull( message, "message" );

			// Get references to all the values of the message object
			IDictionary properties = message.Properties;
			m_properties = new Hashtable();
			foreach( object key in properties.Keys )
			{
				m_properties.Add( key, properties[ key ] );
			}

			if( message is IMethodMessage )
			{
				IMethodMessage methodMessage = (IMethodMessage) message;

				m_args = methodMessage.Args;
				int count = m_args.Length;
				m_argsNames = new string[ count ];
				for( int x = 0; x < count; x++ )
				{
					m_argsNames[ x ] = methodMessage.GetArgName( x );
				}

				m_hasVarArgs = methodMessage.HasVarArgs;
				m_logicalCallContext = methodMessage.LogicalCallContext;
				m_methodUri = methodMessage.Uri;

				m_methodInfo = (MethodInfo) methodMessage.MethodBase;

				if( message is IMethodCallMessage )
				{
					IMethodCallMessage methodCall = (IMethodCallMessage) message;

					m_inArgs = methodCall.InArgs;
					count = m_inArgs.Length;
					m_inArgsNames = new string[ count ];
					for( int x = 0; x < count; x++ )
					{
						m_inArgsNames[ x ] = methodCall.GetInArgName( x );
					}
				}

				if( message is IMethodReturnMessage )
				{
					IMethodReturnMessage returnMessage = (IMethodReturnMessage) message;

					m_outArgs = returnMessage.OutArgs;
					count = m_outArgs.Length;
					m_outArgsNames = new string[ count ];
					for( int x = 0; x < count; x++ )
					{
						m_outArgsNames[ x ] = returnMessage.GetOutArgName( x );
					}

					m_returnValue = returnMessage.ReturnValue;
					m_exception = returnMessage.Exception;
				}
			}
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="PegasusMethodCall"/> class.
		/// </summary>
		/// <param name="info">The info.</param>
		/// <param name="context">The context.</param>
		public PegasusMethodCall( SerializationInfo info, StreamingContext context )
		{
			// Check Parameters
			ParamCode.AssertNotNull( info, "info" );
			ParamCode.AssertNotNull( context, "context" );

			m_properties = (IDictionary) info.GetValue( "m_properties", typeof( IDictionary ) );

			m_args = (object[]) info.GetValue( "m_args", typeof( object[] ) );
			m_argsNames = (string[]) info.GetValue( "m_argsNames", typeof( string[] ) );
			m_hasVarArgs = info.GetBoolean( "m_hasVarArgs" );
			m_inArgs = (object[]) info.GetValue( "m_inArgs", typeof( object[] ) );
			m_inArgsNames = (string[]) info.GetValue( "m_inArgsNames", typeof( string[] ) );
			m_outArgs = (object[]) info.GetValue( "m_outArgs", typeof( object[] ) );
			m_outArgsNames = (string[]) info.GetValue( "m_outArgsNames", typeof( string[] ) );

			m_returnValue = info.GetValue( "m_returnValue", typeof( object ) );
			m_exception = (Exception) info.GetValue( "m_exception", typeof( Exception ) );

			m_logicalCallContext = (LogicalCallContext) info.GetValue( "m_logicalCallContext", typeof( LogicalCallContext ) );
			m_methodUri = info.GetString( "m_methodUri" );

			string methodName = info.GetString( "MethodName" );
			string typeName = info.GetString( "TypeName" );
			string assemblyName = info.GetString( "AssemblyName" );

			// Find the method info object using the version independant binder
			Type methodType = s_binder.BindToType( assemblyName, typeName );
			if( methodType == null )
			{
				throw new SerializationException( string.Format( "Unable to find type {0} or assembly {1}", typeName, assemblyName ) );
			}

			m_methodInfo = methodType.GetMethod( methodName );
			if( m_methodInfo == null )
			{
				throw new SerializationException( string.Format( "Unable to find method {0} in type {1}", methodName, typeName ) );
			}
		}

		/// <summary>
		/// Gets an <see cref="T:System.Collections.IDictionary"></see> that represents a collection of the message's properties.
		/// </summary>
		/// <value></value>
		/// <returns>A dictionary that represents a collection of the message's properties.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public IDictionary Properties
		{
			get
			{
				return m_properties;
			}
		}

		/// <summary>
		/// Gets the number of arguments in the call that are not marked as out parameters.
		/// </summary>
		/// <value></value>
		/// <returns>The number of arguments in the call that are not marked as out parameters.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public int InArgCount
		{
			get
			{
				return m_inArgs.Length;
			}
		}

		/// <summary>
		/// Gets an array of arguments that are not marked as out parameters.
		/// </summary>
		/// <value></value>
		/// <returns>An array of arguments that are not marked as out parameters.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public object[] InArgs
		{
			get
			{
				return m_inArgs;
			}
		}

		/// <summary>
		/// Gets the number of arguments passed to the method.
		/// </summary>
		/// <value></value>
		/// <returns>The number of arguments passed to the method.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public int ArgCount
		{
			get
			{
				return m_args.Length;
			}
		}

		/// <summary>
		/// Gets an array of arguments passed to the method.
		/// </summary>
		/// <value></value>
		/// <returns>An <see cref="T:System.Object"></see> array containing the arguments passed to the method.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public object[] Args
		{
			get
			{
				return m_args;
			}
		}

		/// <summary>
		/// Gets a value indicating whether the message has variable arguments.
		/// </summary>
		/// <value></value>
		/// <returns>true if the method can accept a variable number of arguments; otherwise, false.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public bool HasVarArgs
		{
			get
			{
				return m_hasVarArgs;
			}
		}

		/// <summary>
		/// Gets the <see cref="T:System.Runtime.Remoting.Messaging.LogicalCallContext"></see> for the current method call.
		/// </summary>
		/// <value></value>
		/// <returns>Gets the <see cref="T:System.Runtime.Remoting.Messaging.LogicalCallContext"></see> for the current method call.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public LogicalCallContext LogicalCallContext
		{
			get
			{
				return m_logicalCallContext;
			}
		}

		/// <summary>
		/// Gets the <see cref="T:System.Reflection.MethodBase"></see> of the called method.
		/// </summary>
		/// <value></value>
		/// <returns>The <see cref="T:System.Reflection.MethodBase"></see> of the called method.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public MethodBase MethodBase
		{
			get
			{
				return m_methodInfo;
			}
		}

		/// <summary>
		/// Gets the name of the invoked method.
		/// </summary>
		/// <value></value>
		/// <returns>The name of the invoked method.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public string MethodName
		{
			get
			{
				return m_methodInfo.Name;
			}
		}

		/// <summary>
		/// Gets an object containing the method signature.
		/// </summary>
		/// <value></value>
		/// <returns>An object containing the method signature.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public object MethodSignature
		{
			get
			{
				ParameterInfo[] paramArray = m_methodInfo.GetParameters();
				int count = paramArray.Length;
				Type[] types = new Type[ count ];
				for( int x = 0; x < count; x++ )
				{
					types[ x ] = paramArray[ x ].ParameterType;
				}

				return types;
			}
		}

			/// <summary>
			/// Gets the full <see cref="T:System.Type"></see> name of the specific object that the call is destined for.
			/// </summary>
			/// <value></value>
			/// <returns>The full <see cref="T:System.Type"></see> name of the specific object that the call is destined for.</returns>
			/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
			/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
			public string TypeName
		{
			get
			{
				return m_methodInfo.DeclaringType.FullName;
			}
		}

		/// <summary>
		/// Gets the URI of the specific object that the call is destined for.
		/// </summary>
		/// <value></value>
		/// <returns>The URI of the remote object that contains the invoked method.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public string Uri
		{
			get
			{
				return m_methodUri;
			}
		}

		/// <summary>
		/// Gets the number of arguments in the method call marked as ref or out parameters.
		/// </summary>
		/// <value></value>
		/// <returns>The number of arguments in the method call marked as ref or out parameters.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public int OutArgCount
		{
			get
			{
				return m_outArgs.Length;
			}
		}

		/// <summary>
		/// Returns the specified argument marked as a ref or an out parameter.
		/// </summary>
		/// <value></value>
		/// <returns>The specified argument marked as a ref or an out parameter.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public object[] OutArgs
		{
			get
			{
				return m_outArgs;
			}
		}

		/// <summary>
		/// Gets the return value of the method call.
		/// </summary>
		/// <value></value>
		/// <returns>The return value of the method call.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public object ReturnValue
		{
			get
			{
				return m_returnValue;
			}
		}

		/// <summary>
		/// Gets the exception thrown during the method call.
		/// </summary>
		/// <value></value>
		/// <returns>The exception object for the method call, or null if the method did not throw an exception.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		/// <PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Infrastructure"/></PermissionSet>
		public Exception Exception
		{
			get
			{
				return m_exception;
			}
		}

		/// <summary>
		/// Returns the specified argument that is not marked as an out parameter.
		/// </summary>
		/// <param name="argNum">The number of the requested in argument.</param>
		/// <returns>
		/// The requested argument that is not marked as an out parameter.
		/// </returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		public object GetInArg( int argNum )
		{
			// Check Parameters
			ParamCode.AssertRange( argNum, 0, m_inArgs.Length - 1, "argNum" );

			return m_inArgs[ argNum ];
		}

		/// <summary>
		/// Returns the name of the specified argument that is not marked as an out parameter.
		/// </summary>
		/// <param name="index">The number of the requested in argument.</param>
		/// <returns>
		/// The name of a specific argument that is not marked as an out parameter.
		/// </returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		public string GetInArgName( int index )
		{
			// Check Parameters
			ParamCode.AssertRange( index, 0, m_inArgsNames.Length - 1, "index" );

			return m_inArgsNames[ index ];
		}

		/// <summary>
		/// Gets a specific argument as an <see cref="T:System.Object"></see>.
		/// </summary>
		/// <param name="argNum">The number of the requested argument.</param>
		/// <returns>The argument passed to the method.</returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		public object GetArg( int argNum )
		{
			// Check Parameters
			ParamCode.AssertRange( argNum, 0, m_args.Length - 1, "argNum" );

			return m_args[ argNum ];
		}

		/// <summary>
		/// Gets the name of the argument passed to the method.
		/// </summary>
		/// <param name="index">The number of the requested argument.</param>
		/// <returns>
		/// The name of the specified argument passed to the method, or null if the current method is not implemented.
		/// </returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		public string GetArgName( int index )
		{
			// Check Parameters
			ParamCode.AssertRange( index, 0, m_argsNames.Length - 1, "index" );

			return m_argsNames[ index ];
		}

		/// <summary>
		/// Returns the specified argument marked as a ref or an out parameter.
		/// </summary>
		/// <param name="argNum">The number of the requested argument.</param>
		/// <returns>
		/// The specified argument marked as a ref or an out parameter.
		/// </returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		public object GetOutArg( int argNum )
		{
			// Check Parameters
			ParamCode.AssertRange( argNum, 0, m_outArgs.Length - 1, "argNum" );

			return m_outArgs[ argNum ];
		}

		/// <summary>
		/// Returns the name of the specified argument marked as a ref or an out parameter.
		/// </summary>
		/// <param name="index">The number of the requested argument name.</param>
		/// <returns>
		/// The argument name, or null if the current method is not implemented.
		/// </returns>
		/// <exception cref="T:System.Security.SecurityException">The immediate caller makes the call through a reference to the interface and does not have infrastructure permission. </exception>
		public string GetOutArgName( int index )
		{
			// Check Parameters
			ParamCode.AssertRange( index, 0, m_outArgsNames.Length - 1, "index" );

			return m_outArgsNames[ index ];
		}

		/// <summary>
		/// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> with the data needed to serialize the target object.
		/// </summary>
		/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> to populate with data.</param>
		/// <param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"></see>) for this serialization.</param>
		/// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
		public void GetObjectData( SerializationInfo info, StreamingContext context )
		{
			// Check Parameters
			ParamCode.AssertNotNull( info, "info" );
			ParamCode.AssertNotNull( context, "context" );

			info.AddValue( "m_properties", m_properties );

			info.AddValue( "m_args", m_args );
			info.AddValue( "m_argsNames", m_argsNames );
			info.AddValue( "m_hasVarArgs", m_hasVarArgs );
			info.AddValue( "m_inArgs", m_inArgs );
			info.AddValue( "m_inArgsNames", m_inArgsNames );
			info.AddValue( "m_outArgs", m_outArgs );
			info.AddValue( "m_outArgsNames", m_outArgsNames );

			info.AddValue( "m_returnValue", m_returnValue );
			info.AddValue( "m_exception", m_exception );

			info.AddValue( "m_logicalCallContext", m_logicalCallContext );
			info.AddValue( "m_methodUri", m_methodUri );

			// Save the method info data 
			info.AddValue( "MethodName", m_methodInfo.Name );
			info.AddValue( "TypeName", m_methodInfo.DeclaringType.FullName );
			info.AddValue( "AssemblyName", m_methodInfo.DeclaringType.Assembly.FullName );
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions