检查WCF(namedpipes)主机是否可用?

时间:2011-09-26 08:29:58

标签: wcf exception-handling named-pipes

您好,

我们有一个winform应用程序只能作为singelton执行,如果第二个实例尝试启动这个新实例将连接到当前并通过namedpipes传输参数。

问题是,在启动第一个实例时,将尝试连接到现有主机。如果主机不存在(如本例所示),则抛出异常。处理此异常没有问题,但我们的开发人员经常使用“Break on Exception”,这意味着每次启动应用程序时,开发人员都会得到两个(在这种情况下)中断异常。每次开始时,Thay必须两次击中F5。

如果没有抛出异常,有没有办法检查服务是否可用?

BestRegards

编辑1:

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenFileMapping(uint dwDesiredAccess, bool bInheritHandle, string lpName);

以下代码说明:错误152无法将类型'System.IntPtr'隐式转换为'Orbit.Client.Main.Classes.Controllers.MyClientController.SafeFileMappingHandle'

using (SafeFileMappingHandle fileMappingHandle
                = OpenFileMapping(FILE_MAP_READ, false, sharedMemoryName))
            {

3 个答案:

答案 0 :(得分:3)

如果已经有一个WCF服务器正在侦听命名管道端点,则会创建一个共享内存对象,服务器通过该对象发布管道的实际名称。 See here for details of this

如果没有服务器正在运行,您可以使用以下代码检查此共享内存对象是否存在,该代码不会抛出,只返回false。 (我从我已经工作的代码中提取了这个,然后编辑它来做你想要的 - 但是没有测试编辑的版本,所以如果你必须修复程序集/命名空间引用等以使其运行,那么道歉。)< / p>

public static class ServiceInstanceChecker
{

    public static bool DoesAServerExistAlready(string hostName, string path)
    {
        return IsNetNamedPipeSharedMemoryMetaDataPublished(DeriveSharedMemoryName(hostName, path));
    }


    private static string DeriveSharedMemoryName(string hostName, string path)
    {
        StringBuilder builder = new StringBuilder();
        builder.Append(Uri.UriSchemeNetPipe);
        builder.Append("://");
        builder.Append(hostName.ToUpperInvariant());
        builder.Append(path);
        byte[] uriBytes = Encoding.UTF8.GetBytes(builder.ToString());

        string encodedNameRoot;
        if (uriBytes.Length >= 0x80)
        {
            using (HashAlgorithm algorithm = new SHA1Managed())
            {
                encodedNameRoot = ":H" + Convert.ToBase64String(algorithm.ComputeHash(uriBytes));
            }
        }
        else
        {
            encodedNameRoot = ":E" + Convert.ToBase64String(uriBytes);
        }
        return Uri.UriSchemeNetPipe + encodedNameRoot;
    }

    private static bool IsNetNamePipeSharedMemoryMetaDataPublished(string sharedMemoryName)
    {
        const uint FILE_MAP_READ = 0x00000004;
        const int ERROR_FILE_NOT_FOUND = 2;
        using (SafeFileMappingHandle fileMappingHandle 
            = OpenFileMapping(FILE_MAP_READ, false, sharedMemoryName))
        {
            if (fileMappingHandle.IsInvalid)
            {
                int errorCode = Marshal.GetLastWin32Error();
                if (ERROR_FILE_NOT_FOUND == errorCode) return false; 
                throw new Win32Exception(errorCode); // The name matched, but something went wrong opening it
            }
            return true;
        }
    }

    private class SafeFileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        public SafeFileMappingHandle() : base(true) { }
        public SafeFileMappingHandle(IntPtr handle) : base(true) { base.SetHandle(handle); }

        protected override bool ReleaseHandle()
        {
            return CloseHandle(base.handle);
        }
    }

}

您传入的主机名和路径是从WCF服务网址派生的。主机名是特定主机名(例如localhost)或+*,具体取决于HostNameComparisonMode的设置。

编辑:你还需要为Win API函数提供一些P / Invoke声明:

[DllImport("kernel32.dll", SetLastError = true)] 
static extern bool CloseHandle(IntPtr hObject); 

[DllImport("kernel32.dll", SetLastError = true)] 
static extern SafeFileMappingHandle OpenFileMapping(
  uint dwDesiredAccess,
  bool inheritHandle,
  string name
);

EDIT2:我们需要调整DeriveSharedMemoryName的返回值以指定本地内核命名空间,假设您的应用程序未使用提升的权限运行。将此函数的最后一行更改为:

return @"Local\" + Uri.UriSchemeNetPipe + encodedNameRoot;

您还需要正确指定hostname参数以匹配绑定中使用的hostNameComparisonMode设置。据我所知,这默认为NetNamedPipeBinding中的StrongWildcard匹配,因此您可能需要传递"+"而不是"localhost"

答案 1 :(得分:0)

您可以尝试使用

列出可用的命名管道吗?

String[] listOfPipes = System.IO.Directory.GetFiles(@"\.\pipe\");

然后确定你的命名管道是否在其中?

答案 2 :(得分:-1)

我的解决方案如下:

if (Debugger.IsAttached) 
return true;

这将确保在调试期间永远不会运行用于检查服务的代码。

<强> BestRegards

相关问题