@@ -44,21 +44,23 @@ private bool TryConnect(int timeout, CancellationToken cancellationToken)
44
44
access |= Interop . Kernel32 . GenericOperations . GENERIC_WRITE ;
45
45
}
46
46
47
- // Let's try to connect first
48
- SafePipeHandle handle = Interop . Kernel32 . CreateNamedPipeClient ( _normalizedPipePath ,
49
- access , // read and write access
50
- 0 , // sharing: none
51
- ref secAttrs , // security attributes
52
- FileMode . Open , // open existing
53
- _pipeFlags , // impersonation flags
54
- IntPtr . Zero ) ; // template file: null
47
+ SafePipeHandle handle = CreateNamedPipeClient ( _normalizedPipePath , ref secAttrs , _pipeFlags , access ) ;
55
48
56
49
if ( handle . IsInvalid )
57
50
{
58
51
int errorCode = Marshal . GetLastPInvokeError ( ) ;
59
52
60
- if ( errorCode != Interop . Errors . ERROR_PIPE_BUSY &&
61
- errorCode != Interop . Errors . ERROR_FILE_NOT_FOUND )
53
+ // CreateFileW: "If the CreateNamedPipe function was not successfully called on the server prior to this operation,
54
+ // a pipe will not exist and CreateFile will fail with ERROR_FILE_NOT_FOUND"
55
+ // WaitNamedPipeW: "If no instances of the specified named pipe exist,
56
+ // the WaitNamedPipe function returns immediately, regardless of the time-out value."
57
+ // We know that no instances exist, so we just quit without calling WaitNamedPipeW.
58
+ if ( errorCode == Interop . Errors . ERROR_FILE_NOT_FOUND )
59
+ {
60
+ return false ;
61
+ }
62
+
63
+ if ( errorCode != Interop . Errors . ERROR_PIPE_BUSY )
62
64
{
63
65
throw Win32Marshal . GetExceptionForWin32Error ( errorCode ) ;
64
66
}
@@ -67,8 +69,7 @@ private bool TryConnect(int timeout, CancellationToken cancellationToken)
67
69
{
68
70
errorCode = Marshal . GetLastPInvokeError ( ) ;
69
71
70
- // Server is not yet created or a timeout occurred before a pipe instance was available.
71
- if ( errorCode == Interop . Errors . ERROR_FILE_NOT_FOUND ||
72
+ if ( errorCode == Interop . Errors . ERROR_FILE_NOT_FOUND || // server has been closed
72
73
errorCode == Interop . Errors . ERROR_SEM_TIMEOUT )
73
74
{
74
75
return false ;
@@ -77,22 +78,17 @@ private bool TryConnect(int timeout, CancellationToken cancellationToken)
77
78
throw Win32Marshal . GetExceptionForWin32Error ( errorCode ) ;
78
79
}
79
80
80
- // Pipe server should be free. Let's try to connect to it.
81
- handle = Interop . Kernel32 . CreateNamedPipeClient ( _normalizedPipePath ,
82
- access , // read and write access
83
- 0 , // sharing: none
84
- ref secAttrs , // security attributes
85
- FileMode . Open , // open existing
86
- _pipeFlags , // impersonation flags
87
- IntPtr . Zero ) ; // template file: null
81
+ // Pipe server should be free. Let's try to connect to it.
82
+ handle = CreateNamedPipeClient ( _normalizedPipePath , ref secAttrs , _pipeFlags , access ) ;
88
83
89
84
if ( handle . IsInvalid )
90
85
{
91
86
errorCode = Marshal . GetLastPInvokeError ( ) ;
92
87
93
- // Handle the possible race condition of someone else connecting to the server
94
- // between our calls to WaitNamedPipe & CreateFile.
95
- if ( errorCode == Interop . Errors . ERROR_PIPE_BUSY )
88
+ // WaitNamedPipe: "A subsequent CreateFile call to the pipe can fail,
89
+ // because the instance was closed by the server or opened by another client."
90
+ if ( errorCode == Interop . Errors . ERROR_PIPE_BUSY || // opened by another client
91
+ errorCode == Interop . Errors . ERROR_FILE_NOT_FOUND ) // server has been closed
96
92
{
97
93
return false ;
98
94
}
@@ -106,6 +102,9 @@ private bool TryConnect(int timeout, CancellationToken cancellationToken)
106
102
State = PipeState . Connected ;
107
103
ValidateRemotePipeUser ( ) ;
108
104
return true ;
105
+
106
+ static SafePipeHandle CreateNamedPipeClient ( string ? path , ref Interop . Kernel32 . SECURITY_ATTRIBUTES secAttrs , int pipeFlags , int access )
107
+ => Interop . Kernel32 . CreateNamedPipeClient ( path , access , FileShare . None , ref secAttrs , FileMode . Open , pipeFlags , hTemplateFile : IntPtr . Zero ) ;
109
108
}
110
109
111
110
[ SupportedOSPlatform ( "windows" ) ]
0 commit comments