/// <summary>
        /// 보안 특성 구하기
        /// </summary>
        /// <returns>보안 특성</returns>
        private static SECURITY_ATTRIBUTE GetSecurityAttribute()
        {
            RawSecurityDescriptor descriptor = new RawSecurityDescriptor(ControlFlags.DiscretionaryAclPresent, null, null, null, null);

            SECURITY_ATTRIBUTE securityAttribute = new SECURITY_ATTRIBUTE();

            securityAttribute.Length        = (uint)Marshal.SizeOf(typeof(SECURITY_ATTRIBUTE));
            securityAttribute.InheritHandle = false;

            byte[] byteArray = new byte[descriptor.BinaryLength];

            descriptor.GetBinaryForm(byteArray, 0);

            securityAttribute.SecurityDescriptor = Marshal.AllocHGlobal(byteArray.Length);

            Marshal.Copy(byteArray, 0, securityAttribute.SecurityDescriptor, byteArray.Length);

            return(securityAttribute);
        }
 private static extern SafeFileHandle CreateNamedPipe(string pipeName, uint openMode, uint pipeMode, uint maximumInstanceCount, uint outBufferSize, uint inBufferSize, uint defaultTimeOut, ref SECURITY_ATTRIBUTE securityAttribute);
        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 연결 대기하기 - WaitForConnection()

        /// <summary>
        /// 연결 대기하기
        /// </summary>
        /// <returns>자식 파이프</returns>
        public NamedPipe WaitForConnection()
        {
            if (string.IsNullOrEmpty(this.pipeName) == true || this.exitEventHandle == null)
            {
                Trace.WriteLine("파이프 서비스 종료");

                return(null);
            }

            NamedPipe clientPipe = new NamedPipe();

            clientPipe.pipeName      = this.pipeName;
            clientPipe.pipeDirection = this.pipeDirection;

            SECURITY_ATTRIBUTE securityAttribute = GetSecurityAttribute();

            clientPipe.pipeHandle = CreateNamedPipe
                                    (
                clientPipe.pipeName,
                (uint)(this.pipeDirection | PipeDirection.FILE_FLAG_OVERLAPPED),
                PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
                255,
                BUFFER_SIZE,
                BUFFER_SIZE,
                0,
                ref securityAttribute
                                    );

            Marshal.FreeHGlobal(securityAttribute.SecurityDescriptor);

            if (clientPipe.pipeHandle.IsInvalid)
            {
                Trace.WriteLine("무효한 파이프 연결");

                clientPipe.Dispose();

                return(null);
            }

            NativeOverlapped nativeOverlapped = new NativeOverlapped();

            SecurityIdentifier securityIdentifier = new SecurityIdentifier(WellKnownSidType.WorldSid, null);

            EventWaitHandleSecurity eventHandleSecurity = new EventWaitHandleSecurity();

            bool created;

            eventHandleSecurity.AddAccessRule(new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.FullControl, AccessControlType.Allow));
            eventHandleSecurity.AddAccessRule(new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.ChangePermissions, AccessControlType.Deny));

            using (EventWaitHandle eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, null, out created, eventHandleSecurity))
            {
                nativeOverlapped.EventHandle = eventHandle.SafeWaitHandle.DangerousGetHandle();

                ConnectNamedPipe(clientPipe.pipeHandle, ref nativeOverlapped);

                int lastError = Marshal.GetLastWin32Error();

                if (lastError == 997)
                {
                    int completeCode = 0;

                    IntPtr[] waitHandleArray = new IntPtr[]
                    {
                        eventHandle.SafeWaitHandle.DangerousGetHandle(),
                        this.exitEventHandle.SafeWaitHandle.DangerousGetHandle()
                    };

                    completeCode = WaitForMultipleObjects(waitHandleArray.Length, waitHandleArray, false, -1);

                    if (completeCode == 0)
                    {
                    }
                    else if (completeCode == 1)
                    {
                        Trace.WriteLine("파이프 서비스 종료 (리소스 해제)");

                        clientPipe.Dispose();

                        return(null);
                    }
                }
                else if (lastError != 535)
                {
                    Trace.WriteLine("파이프 연결 에러 : " + lastError);

                    clientPipe.Dispose();

                    return(null);
                }
                else
                {
                    Debug.WriteLine("연결되었습니다.");
                }
            }

            clientPipe.needToDisconnect = true;

            FileAccess fileAccess = GetFileAccess(clientPipe.pipeDirection);

            clientPipe.pipeStream = new FileStream(clientPipe.pipeHandle, fileAccess, (int)BUFFER_SIZE, true);

            if (clientPipe.pipeStream == null)
            {
                Trace.WriteLine("파이프 파일 스트림이 null 입니다.");

                clientPipe.Dispose();

                return(null);
            }

            return(clientPipe);
        }