来自WCF服务的响应抛出CommunicationException

时间:2015-10-14 22:00:52

标签: c# wcf

首先,请允许我发布有问题的代码!!! ...

/// <summary>
/// Represents the implementation of the Remote Launch Service.
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
[KnownType(typeof(RemoteProcessHandle))]
[KnownType(typeof(RemoteLaunchServiceResult<RemoteProcessHandle>))]
[KnownType(typeof(RemoteLaunchServiceResult<bool>))]
public sealed class RemoteLaunchService : IRemoteLaunchService
{
    /// <summary>
    /// Handles the event in which a process is started by the Remote Launch Service.
    /// </summary>
    /// <param name="sender">the object that raised the event.</param>
    /// <param name="startInfo">the <see cref="RemoteProcessStartInfo"/> object containing information about the process that was started.</param>
    /// <param name="handle">the <see cref="RemoteProcessHandle"/> for the resulting process.</param>
    public delegate void ProcessStartedEventHandler(
        object sender, RemoteProcessStartInfo startInfo, RemoteProcessHandle handle);

    /// <summary>
    /// Handles the event in which an attempt to close the main window of a process is made by the Remote Launch Service.
    /// </summary>
    /// <param name="sender">the object that raised the event.</param>
    /// <param name="handle">the <see cref="RemoteProcessHandle"/> corresponding to the process.</param>
    /// <param name="successful">true if the operation was successful, otherwise false.</param>
    public delegate void ProcessMainWindowClosedEventHandler(
        object sender, RemoteProcessHandle handle, bool successful);

    /// <summary>
    /// Handles the event in which a process is killed by the Remote Launch Service.
    /// </summary>
    /// <param name="sender">the object that raised the event.</param>
    /// <param name="handle">the <see cref="RemoteProcessHandle"/> corresponding to the process.</param>
    public delegate void ProcessKilledEventHandler(
        object sender, RemoteProcessHandle handle);

    /// <summary>
    /// Handles the event in which an exception is thrown by the Remote Launch Service.
    /// </summary>
    /// <param name="sender">the object that raised the event.</param>
    /// <param name="exception">the exception that was thrown.</param>
    public delegate void ExceptionThrownEventHandler(
        object sender, Exception exception);

    /// <summary>
    /// Handles the event in which a process is started by the Remote Launch Service.
    /// </summary>
    public event ProcessStartedEventHandler ProcessStarted;

    /// <summary>
    /// Handles the event in which an attempt to close the main window of a process is made by the Remote Launch Service.
    /// </summary>
    public event ProcessMainWindowClosedEventHandler ProcessMainWindowClosed;

    /// <summary>
    /// Handles the event in which a process is killed by the Remote Launch Service.
    /// </summary>
    public event ProcessKilledEventHandler ProcessKilled;

    /// <summary>
    /// Handles the event in which an exception is thrown by the Remote Launch Service.
    /// </summary>
    public event ExceptionThrownEventHandler ExceptionThrown;

    /// <summary>
    /// Starts a remote process via the Remote Launch Service, using information within the specified <see cref="RemoteProcessStartInfo"/>.
    /// </summary>
    /// <param name="startInfo">the <see cref="RemoteProcessStartInfo"/> object containing information about the process to start.</param>
    /// <returns>a <see cref="RemoteLaunchServiceResult{RemoteProcessHandle}"/> containing a <see cref="RemoteProcessHandle"/> for the process.</returns>
    public RemoteLaunchServiceResult<RemoteProcessHandle> Start(
        RemoteProcessStartInfo startInfo)
    {
        try
        {
            // Start the process and retrieve the handle.
            RemoteProcessHandle handle = new RemoteProcessHandle(Process.Start(startInfo.LocalProcessStartInfo));

            // If there are any handlers registered to the appropriate event, raise it.
            if (ProcessStarted != null) ProcessStarted(this, startInfo, handle);

            // Return the result containing the handle.
            return new RemoteLaunchServiceResult<RemoteProcessHandle>(handle, null);
        }
        catch (Exception exception)
        {
            // If an exception is thrown, raise the appropriate event (if any handlers are registered to it), and return the result containing the exception.
            if (ExceptionThrown != null) ExceptionThrown(this, exception);
            return new RemoteLaunchServiceResult<RemoteProcessHandle>(null, exception.Message);
        }
    }

    /// <summary>
    /// Attempts to close the main window of the process corresponding to the specified <see cref="RemoteProcessHandle"/>.
    /// </summary>
    /// <param name="handle">the <see cref="RemoteProcessHandle"/> corresponding to the process.</param>
    /// <returns>a <see cref="RemoteLaunchServiceResult{bool}"/> containing whether the operation was successful or not.</returns>
    public RemoteLaunchServiceResult<bool> CloseMainWindow(
        RemoteProcessHandle handle)
    {
        try
        {
            // Attempt to close the main window of the process and retrieve whether this was successful.
            bool successful = handle.LocalProcess.CloseMainWindow();

            // If there are any handlers registered to the appropriate event, raise it.
            if (ProcessMainWindowClosed != null) ProcessMainWindowClosed(this, handle, successful);

            // Return the result containing whether the operation was successful or not.
            return new RemoteLaunchServiceResult<bool>(successful, null);
        }
        catch (Exception exception)
        {
            // If an exception is thrown, raise the event (if any handlers are registered to it), and return the result containing the exception.
            if (ExceptionThrown != null) ExceptionThrown(this, exception);
            return new RemoteLaunchServiceResult<bool>(false, exception.Message);
        }
    }

    /// <summary>
    /// Kills the process corresponding to the specified <see cref="RemoteProcessHandle"/>.
    /// </summary>
    /// <param name="handle">the <see cref="RemoteProcessHandle"/> corresponding to the process.</param>
    /// <returns>a <see cref="RemoteLaunchServiceResult{bool}"/> containing whether an exception was thrown or not.</returns>
    public RemoteLaunchServiceResult<bool> Kill(
        RemoteProcessHandle handle)
    {
        try
        {
            handle.LocalProcess.Kill();

            // If there are any handlers registered to the appropriate event, raise it.
            if (ProcessKilled != null) ProcessKilled(this, handle);

            // Return the result indicating that no exception was thrown.
            return new RemoteLaunchServiceResult<bool>(true, null);
        }
        catch (Exception exception)
        {
            // If an exception is thrown, raise the event (if any handlers are registered to it), and return the result containing the exception.
            if (ExceptionThrown != null) ExceptionThrown(this, exception);
            return new RemoteLaunchServiceResult<bool>(false, exception.Message);
        }
    }

    /// <summary>
    /// The default port number used by the Remote Launch Service.
    /// </summary>
    public const int DefaultPort = 2185;

    /// <summary>
    /// Gets the address of the Remote Launch Service running on the specified machine, using the specified port number.
    /// </summary>
    /// <param name="machineName">the name of the machine.</param>
    /// <param name="port">the port number.</param>
    /// <returns>a <see cref="string"/> containing the address.</returns>
    public static string GetAddress(
        string machineName, int port)
    {
        // The machine name and port number must be valid.
        if (machineName == null) throw new ArgumentNullException(nameof(machineName));
        if ((port < IPEndPoint.MinPort) || (port > IPEndPoint.MaxPort)) throw new ArgumentOutOfRangeException(nameof(port));

        // Derive and return the address.
        return string.Format(@"net.tcp://{0}:{1}/RemoteLaunchService", machineName, port);
    }

    /// <summary>
    /// Gets the address of the Remote Launch Service running on this machine, using the specified port number.
    /// </summary>
    /// <param name="port">the port number.</param>
    /// <returns>a <see cref="string"/> containing the address.</returns>
    public static string GetAddress(
        int port)
    {
        return GetAddress(Dns.GetHostName(), port);
    }
}

我通过ChannelFactory课程访问该服务,一切顺利,直到我点击Start()方法中的return语句...

    /// <summary>
    /// Starts a remote process via the Remote Launch Service, using information within the specified <see cref="RemoteProcessStartInfo"/>.
    /// </summary>
    /// <param name="startInfo">the <see cref="RemoteProcessStartInfo"/> object containing information about the process to start.</param>
    /// <returns>a <see cref="RemoteLaunchServiceResult{RemoteProcessHandle}"/> containing a <see cref="RemoteProcessHandle"/> for the process.</returns>
    public RemoteLaunchServiceResult<RemoteProcessHandle> Start(
        RemoteProcessStartInfo startInfo)
    {
        try
        {
            // Start the process and retrieve the handle.
            RemoteProcessHandle handle = new RemoteProcessHandle(Process.Start(startInfo.LocalProcessStartInfo));

            // If there are any handlers registered to the appropriate event, raise it.
            if (ProcessStarted != null) ProcessStarted(this, startInfo, handle);

            // Return the result containing the handle.
            return new RemoteLaunchServiceResult<RemoteProcessHandle>(handle, null);
        }
        catch (Exception exception)
        {
            // If an exception is thrown, raise the appropriate event (if any handlers are registered to it), and return the result containing the exception.
            if (ExceptionThrown != null) ExceptionThrown(this, exception);
            return new RemoteLaunchServiceResult<RemoteProcessHandle>(null, exception.Message);
        }
    }

代码在不进入catch块的情况下正确执行了该过程,但是一旦我返回CommunicationException就会抛出RemoteLaunchServiceResult。有趣的是,如果我改变......

            return new RemoteLaunchServiceResult<RemoteProcessHandle>(handle, null);

...到...

            return new RemoteLaunchServiceResult<RemoteProcessHandle>(null, null);

...没有抛出任何异常,让我觉得它可能是RemoteProcessHandle类的问题。这是这个班级的列表...

/// <summary>
/// Represents the information required to access a remote process after it has been started by the Remote Launch Service.
/// </summary>
[Serializable]
public sealed class RemoteProcessHandle : ISerializable
{
    /// <summary>
    /// Initializes a new instance of the <see cref="RemoteProcessHandle"/> class.
    /// </summary>
    /// <param name="process">the <see cref="Process"/> object to derive the handle from.</param>
    public RemoteProcessHandle(
        Process process)
    {
        if (process == null) return;

        try { this.processID = process.Id; } catch { }
        try { this.machineName = process.MachineName; } catch { }
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="RemoteProcessHandle"/> class from data contained within a <see cref="SerializationInfo"/> object.
    /// </summary>
    /// <param name="info">the <see cref="SerializationInfo"/> containing the information required to deserialize this <see cref="RemoteProcessHandle"/>.</param>
    /// <param name="context">the <see cref="StreamingContext"/> containing the source of the serialized stream associated with this <see cref="RemoteProcessHandle"/>.</param>
    public RemoteProcessHandle(
        SerializationInfo info, StreamingContext context) : this(null)
    {
        try { this.processID = (int?)info.GetValue(nameof(this.processID), typeof(int?)); } catch { }
        try { this.machineName = (string)info.GetValue(nameof(this.machineName), typeof(string)); } catch { }
    }

    // Instance variables.
    private int? processID = null;
    private string machineName = null;

    /// <summary>
    /// Gets the ID of the process that this <see cref="RemoteProcessHandle"/> represents.
    /// </summary>
    public int? ProcessID
    {
        get { return this.processID; }
    }

    /// <summary>
    /// Gets the name of the machine running the process that this <see cref="RemoteProcessHandle"/> represents.
    /// </summary>
    public string MachineName
    {
        get { return this.machineName; }
    }

    /// <summary>
    /// Gets the local <see cref="Process"/> corresponding to this <see cref="RemoteProcessHandle"/>.
    /// </summary>
    public Process LocalProcess
    {
        get
        {
            // The machine name within this information has got to match this machine, and the process ID mustn't be null.
            if (!Dns.GetHostName().Equals(this.MachineName, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException();
            if (this.ProcessID == null) throw new InvalidOperationException();

            // Get and return the process.
            return Process.GetProcessById(this.ProcessID.Value);
        }
    }


    /// <summary>
    /// Gets the address of the Remote Launch Service, using the specified port number, running the process that this <see cref="RemoteProcessHandle"/> represents.
    /// </summary>
    /// <param name="port">the port number.</param>
    /// <returns>a <see cref="string"/> containing the address.</returns>
    public string GetRemoteLaunchServiceAddress(
        int port)
    {
        return RemoteLaunchService.GetAddress(this.MachineName, port);
    }

    /// <summary>
    /// Populates a <see cref="SerializationInfo"/> object with data required to serialize this <see cref="RemoteProcessHandle"/>.
    /// </summary>
    /// <param name="info">the <see cref="SerializationInfo"/> to contain the information required to serialize this <see cref="RemoteProcessHandle"/>.</param>
    /// <param name="context">the <see cref="StreamingContext"/> containing the destination of the serialized stream associated with this <see cref="RemoteProcessHandle"/>.</param>
    public void GetObjectData(
        SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(this.processID), this.processID, typeof(int?));
        info.AddValue(nameof(this.machineName), this.machineName, typeof(string));
    }
}

请有人可以提出任何可能引起此异常的建议吗?

1 个答案:

答案 0 :(得分:1)

我已设法修复此错误!...

[Serializable]
[KnownType(typeof(RemoteProcessHandle))]
public sealed class RemoteLaunchServiceResult<T>
{
    // I solved the problem by adding the "KnownType" attribute. I thought
    // it would have worked having it in the "RemoteLaunchService" class,
    // but I was wrong!
}

感谢您输入的人!!!