Именованные каналы между Winforms и Service могут подключаться только один раз - PullRequest
0 голосов
/ 13 декабря 2018

Я делаю простое приложение, чтобы опробовать именованные каналы для приложения, которое я делаю.Сначала я могу подключиться к каналу и записать в файл, указанный службой, которая прослушивает входные данные.Если я перезапускаю свое приложение winforms и пытаюсь подключиться к каналу, оно просто зависает в методе .Connect ().Если я перезапущу свой сервис, я смогу снова подключиться к своему приложению winforms ... но только один раз (пока я не перезапущу сервис снова)

Вот мой NamedPipeServerStream в моей службе Windows.

protected override void OnStart(string[] args)
{
    StartPipe();
}

protected override void OnStop()
{
}

public void StartPipe()
{
    FileStream fs = new FileStream(@"C:\Users\Nate\Desktop\PipeService.txt", FileMode.OpenOrCreate, FileAccess.Write);
    Task.Run(() =>
    {
        var server = new NamedPipeServerStream("PipeService3");
        server.WaitForConnection();
        StreamReader reader = new StreamReader(server);
        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            StreamWriter writer = new StreamWriter(fs);
            writer.WriteLine(line);
            writer.Flush();
        }
    });
}

Это мой раздел NamePipeClientStream из моего приложения Winforms

public StreamWriter writer;
public NamedPipeClientStream client;

public Form1()
{
    InitializeComponent();

    client = new NamedPipeClientStream("PipeService3");
    client.Connect();

    writer = new StreamWriter(client);
}

private void sendButton_Click(object sender, EventArgs e)
{
    string line = textBox1.Text;
    writer.WriteLine(line);
    writer.Flush();
}

это был мой обходной путь, но я чувствую, чтоесть законный способ сделать это, а не останавливать и запускать службу каждый раз, когда кто-то открывает приложение winforms.

try
{
    client.Connect(1000);
}
catch
{
    var serviceController = ServiceController.GetServices();
    var pipeService = serviceController.Where(s => s.DisplayName == "PipeService").FirstOrDefault();
    pipeService.Stop();
    pipeService.WaitForStatus(ServiceControllerStatus.Stopped);
    pipeService.Start();
    pipeService.WaitForStatus(ServiceControllerStatus.Running);
    client.Connect();
}

1 Ответ

0 голосов
/ 17 декабря 2018

Я смог решить эту проблему, установив канал как рекурсивный, поэтому каждый раз, когда клиент отключается (в моем случае это будет только один клиент), именованный канал удаляется, а новый канал с тем же каналомпо имени.(также включено, что позволяет моему приложению winforms, не являющемуся администратором, по-прежнему подключаться к каналу, который был запущен со службой с повышенными разрешениями)

  public void StartPipe()
    {
        System.Threading.Tasks.Task.Run(() =>
        {
            RecursivePipe();
        });
    }
    public void RecursivePipe()
    {
        PipeSecurity pipeSecurity = new PipeSecurity();
        pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));
        pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), PipeAccessRights.FullControl, AccessControlType.Allow));

        var server = new NamedPipeServerStream("PipeService7", PipeDirection.InOut, 10, PipeTransmissionMode.Message, PipeOptions.WriteThrough, 1024, 1024, pipeSecurity);

        server.WaitForConnection();
        StreamReader reader = new StreamReader(server);
        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            var lineArray = line.Split('$');
            if (lineArray.Length == 4)
            {
                SetkeyValue(lineArray);
            }
            else if (lineArray.Length == 5)
            {
                setStartupStrat(lineArray);
            }
            else
            {
                DeleteKeyValue(lineArray);
            }


        }
        server.Dispose();
        server.Close();
        RecursivePipe();
    }
...