convert Pilz.IO to C# & Add EmbeddedFilesContainer

This commit is contained in:
2020-04-28 13:59:46 +02:00
parent b86e392ac2
commit 9a98cbce02
26 changed files with 1342 additions and 462 deletions

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Pilz.IO
{
/// <summary>
/// stellt den Erben "Server" und "Client" 2 verschiedene
/// Message-Events zur Verfügung, und ein Event-Raisendes Dispose
/// </summary>
public abstract class ManagedPipe : IDisposable
{
public delegate void EventHandlerWithOneArgument<T0>(T0 Sender);
/// <summary>
/// Zur Ausgabe chat-verwaltungstechnischer Status-Informationen
/// </summary>
public event EventHandler<DataEventArgs> StatusMessage;
/// <summary>Zur Ausgabe von Chat-Messages</summary>
public event EventHandler<DataEventArgs> RetriveData;
public event EventHandlerWithOneArgument<ManagedPipe> Disposed;
private bool _IsDisposed = false;
protected abstract void Dispose(bool disposing);
public abstract void Send(byte[] bytes);
public abstract Task SendAsnyc(byte[] bytes);
protected void OnStatusMessage(DataEventArgs e)
{
StatusMessage?.Invoke(this, e);
}
protected void OnRetriveData(DataEventArgs e)
{
RetriveData?.Invoke(this, e);
}
public void RemoveFrom<T>(ICollection<T> Coll) where T : ManagedPipe
{
Coll.Remove((T)this);
}
public bool IsDisposed
{
get
{
return _IsDisposed;
}
}
public void AddTo<T>(ICollection<T> Coll) where T : ManagedPipe
{
Coll.Add((T)this);
}
public void Dispose()
{
if (_IsDisposed)
return;
_IsDisposed = true;
Dispose(true); // rufe die erzwungenen Überschreibungen von Sub Dispose(Boolean)
Disposed?.Invoke(this);
GC.SuppressFinalize(this);
}
}
}

View File

@@ -1,53 +0,0 @@
''' <summary>
''' stellt den Erben "Server" und "Client" 2 verschiedene
''' Message-Events zur Verfügung, und ein Event-Raisendes Dispose
''' </summary>
Public MustInherit Class ManagedPipe : Implements IDisposable
Public Delegate Sub EventHandlerWithOneArgument(Of T0)(Sender As T0)
''' <summary>
''' Zur Ausgabe chat-verwaltungstechnischer Status-Informationen
''' </summary>
Public Event StatusMessage As EventHandler(Of DataEventArgs)
''' <summary>Zur Ausgabe von Chat-Messages</summary>
Public Event RetriveData As EventHandler(Of DataEventArgs)
Public Event Disposed As EventHandlerWithOneArgument(Of ManagedPipe)
Private _IsDisposed As Boolean = False
Protected MustOverride Sub Dispose(disposing As Boolean)
Public MustOverride Sub Send(bytes As Byte())
Public MustOverride Function SendAsnyc(bytes As Byte()) As Task
Protected Sub OnStatusMessage(ByVal e As DataEventArgs)
RaiseEvent StatusMessage(Me, e)
End Sub
Protected Sub OnRetriveData(ByVal e As DataEventArgs)
RaiseEvent RetriveData(Me, e)
End Sub
Public Sub RemoveFrom(Of T As ManagedPipe)(ByVal Coll As ICollection(Of T))
Coll.Remove(DirectCast(Me, T))
End Sub
Public ReadOnly Property IsDisposed() As Boolean
Get
Return _IsDisposed
End Get
End Property
Public Sub AddTo(Of T As ManagedPipe)(ByVal Coll As ICollection(Of T))
Coll.Add(Me)
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
If _IsDisposed Then Return
_IsDisposed = True
Dispose(True) ' rufe die erzwungenen Überschreibungen von Sub Dispose(Boolean)
RaiseEvent Disposed(Me)
GC.SuppressFinalize(Me)
End Sub
End Class

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using global::System.IO.Pipes;
using System.Threading.Tasks;
using global::Pilz.Threading;
namespace Pilz.IO
{
public class ManagedPipeClient : ManagedPipe
{
private PipeStream pipeStream;
private byte[] _Buf = new byte[1024];
public bool RaiseEventsGui { get; set; } = true;
public ManagedPipeClient(string pipeName) : this(pipeName, ".")
{
}
public ManagedPipeClient(string pipeName, string serverName) : this(pipeName, serverName, -1)
{
}
public ManagedPipeClient(string pipeName, int connectionTimeout) : this(pipeName, ".", connectionTimeout)
{
}
public ManagedPipeClient(string pipeName, string serverName, int connectionTimeout)
{
var clnt = new NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
clnt.Connect(connectionTimeout);
if (!clnt.IsConnected)
{
throw new TimeoutException("Connection timeout!");
}
SetPipe(clnt);
}
public ManagedPipeClient(PipeStream pipe)
{
SetPipe(pipe);
}
private void SetPipe(PipeStream pipe)
{
pipeStream = pipe;
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
}
private void EndRead(IAsyncResult ar)
{
if (IsDisposed)
return;
int bytesCount = pipeStream.EndRead(ar);
if (bytesCount == 0) // leere Datenübermittlung signalisiert Verbindungsabbruch
{
if (RaiseEventsGui)
{
CrossThreadsInvokeing.RunGui(Dispose);
}
else
{
Dispose();
}
return;
}
var list = new List<byte>();
for (int i = 0, loopTo = bytesCount - 1; i <= loopTo; i++)
list.Add(_Buf[i]);
while (bytesCount == _Buf.Length)
{
bytesCount = pipeStream.Read(_Buf, 0, _Buf.Length);
for (int i = 0, loopTo1 = bytesCount - 1; i <= loopTo1; i++)
list.Add(_Buf[i]);
}
var deargs = new DataEventArgs(list.ToArray());
if (RaiseEventsGui)
{
CrossThreadsInvokeing.RunGui(OnRetriveData, deargs);
}
else
{
OnRetriveData(deargs);
}
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
}
public override Task SendAsnyc(byte[] bytes)
{
return Task.Run(() => Send(bytes));
}
public override void Send(byte[] data)
{
pipeStream.Write(data, 0, data.Length);
}
protected override void Dispose(bool disposing)
{
pipeStream.Dispose();
}
}
}

View File

@@ -1,91 +0,0 @@
Imports System.Net
Imports System.Text
Imports System.IO.Pipes
Imports Pilz.Threading
Public Class ManagedPipeClient : Inherits ManagedPipe
Private pipeStream As PipeStream
Private _Buf(&H400 - 1) As Byte
Public Property RaiseEventsGui As Boolean = True
Public Sub New(pipeName As String)
Me.New(pipeName, ".")
End Sub
Public Sub New(pipeName As String, serverName As String)
Me.New(pipeName, serverName, -1)
End Sub
Public Sub New(pipeName As String, connectionTimeout As Integer)
Me.New(pipeName, ".", connectionTimeout)
End Sub
Public Sub New(pipeName As String, serverName As String, connectionTimeout As Integer)
Dim clnt As New NamedPipeClientStream(serverName, pipeName, PipeDirection.InOut, PipeOptions.Asynchronous)
clnt.Connect(connectionTimeout)
If Not clnt.IsConnected Then
Throw New TimeoutException("Connection timeout!")
End If
SetPipe(clnt)
End Sub
Public Sub New(pipe As PipeStream)
SetPipe(pipe)
End Sub
Private Sub SetPipe(pipe As PipeStream)
pipeStream = pipe
pipeStream.BeginRead(_Buf, 0, _Buf.Length, AddressOf EndRead, Nothing)
End Sub
Private Sub EndRead(ar As IAsyncResult)
If IsDisposed Then Return
Dim bytesCount As Integer = pipeStream.EndRead(ar)
If bytesCount = 0 Then 'leere Datenübermittlung signalisiert Verbindungsabbruch
If RaiseEventsGui Then
CrossThreadsInvokeing.RunGui(AddressOf Dispose)
Else
Dispose()
End If
Return
End If
Dim list As New List(Of Byte)
For i As Integer = 0 To bytesCount - 1
list.Add(_Buf(i))
Next
Do While bytesCount = _Buf.Length
bytesCount = pipeStream.Read(_Buf, 0, _Buf.Length)
For i As Integer = 0 To bytesCount - 1
list.Add(_Buf(i))
Next
Loop
Dim deargs As New DataEventArgs(list.ToArray)
If RaiseEventsGui Then
CrossThreadsInvokeing.RunGui(AddressOf OnRetriveData, deargs)
Else
OnRetriveData(deargs)
End If
pipeStream.BeginRead(_Buf, 0, _Buf.Length, AddressOf EndRead, Nothing)
End Sub
Public Overrides Function SendAsnyc(bytes() As Byte) As Task
Return Task.Run(Sub() Send(bytes))
End Function
Public Overrides Sub Send(data As Byte())
pipeStream.Write(data, 0, data.Length)
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
pipeStream.Dispose()
End Sub
End Class

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using global::System.IO.Pipes;
using System.Threading.Tasks;
namespace Pilz.IO
{
public class ManagedPipeServer : ManagedPipe
{
// Pro Verbindung (Anfrage) wird ein Client-Objekt generiert, das den Datenaustausch dieser Verbindung abwickelt
public List<ManagedPipeClient> Clients { get; private set; } = new List<ManagedPipeClient>();
private readonly string pipeName = "";
private readonly int maxNumbersOfServerInstances;
private int numberOfStartedServerInstances = 0;
public ManagedPipeServer(string pipeName) : this(pipeName, 1)
{
}
public ManagedPipeServer(string pipeName, int maxNumbersOfServerInstances)
{
this.pipeName = pipeName;
this.maxNumbersOfServerInstances = maxNumbersOfServerInstances;
CreateWaitingStream();
}
private void CreateWaitingStream()
{
if (numberOfStartedServerInstances < maxNumbersOfServerInstances)
{
var strm = new NamedPipeServerStream(pipeName, PipeDirection.InOut, maxNumbersOfServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
numberOfStartedServerInstances += 1;
strm.BeginWaitForConnection(EndAccept, strm);
}
}
private void EndAccept(IAsyncResult ar)
{
NamedPipeServerStream strm = (NamedPipeServerStream)ar.AsyncState;
strm.EndWaitForConnection(ar);
if (IsDisposed)
{
strm.Dispose();
return;
}
{
var withBlock = new ManagedPipeClient(strm);
withBlock.RetriveData += Client_RetriveData;
withBlock.StatusMessage += Client_StatusMessage;
withBlock.Disposed += Client_Disposed;
withBlock.AddTo(Clients);
}
CreateWaitingStream();
}
/* TODO ERROR: Skipped RegionDirectiveTrivia */
private void Client_Disposed(ManagedPipe Sender)
{
// den Client für die beendete Verbindung entfernen
Sender.RemoveFrom(Clients);
numberOfStartedServerInstances -= 1;
CreateWaitingStream();
}
private void Client_RetriveData(object sender, DataEventArgs e)
{
// einkommende ChatMessages anzeigen, und an alle versenden
OnRetriveData(e);
}
private void Client_StatusMessage(object sender, DataEventArgs e)
{
// einkommende StatusMessages durchreichen (zur Anzeige)
OnStatusMessage(e);
}
/* TODO ERROR: Skipped EndRegionDirectiveTrivia */
public override Task SendAsnyc(byte[] bytes)
{
return Task.Run(() => Send(bytes));
}
public override void Send(byte[] data)
{
foreach (ManagedPipeClient client in Clients) // an alle versenden
client.Send(data);
}
protected override void Dispose(bool disposing)
{
if (numberOfStartedServerInstances < maxNumbersOfServerInstances)
{
using (var clnt = new NamedPipeClientStream(pipeName))
{
// Herstellen einer Dummi-Verbindung, damit der ServerStream aus dem Wartezustand herauskommt.
clnt.Connect();
}
}
for (int i = Clients.Count - 1; i >= 0; i -= 1)
Clients[i].Dispose();
}
}
}

View File

@@ -1,95 +0,0 @@
Imports System.Net
Imports System.IO.Pipes
Imports Pilz.Threading
Public Class ManagedPipeServer : Inherits ManagedPipe
'Pro Verbindung (Anfrage) wird ein Client-Objekt generiert, das den Datenaustausch dieser Verbindung abwickelt
Public ReadOnly Property Clients As New List(Of ManagedPipeClient)
Private ReadOnly pipeName As String = ""
Private ReadOnly maxNumbersOfServerInstances As Integer
Private numberOfStartedServerInstances As Integer = 0
Public Sub New(ByVal pipeName As String)
Me.New(pipeName, 1)
End Sub
Public Sub New(pipeName As String, maxNumbersOfServerInstances As Integer)
Me.pipeName = pipeName
Me.maxNumbersOfServerInstances = maxNumbersOfServerInstances
CreateWaitingStream()
End Sub
Private Sub CreateWaitingStream()
If numberOfStartedServerInstances < maxNumbersOfServerInstances Then
Dim strm = New NamedPipeServerStream(pipeName, PipeDirection.InOut, maxNumbersOfServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous)
numberOfStartedServerInstances += 1
strm.BeginWaitForConnection(AddressOf EndAccept, strm)
End If
End Sub
Private Sub EndAccept(ByVal ar As IAsyncResult)
Dim strm = DirectCast(ar.AsyncState, NamedPipeServerStream)
strm.EndWaitForConnection(ar)
If IsDisposed Then
strm.Dispose()
Return
End If
With New ManagedPipeClient(strm)
AddHandler .RetriveData, AddressOf Client_RetriveData
AddHandler .StatusMessage, AddressOf Client_StatusMessage
AddHandler .Disposed, AddressOf Client_Disposed
.AddTo(_Clients)
End With
CreateWaitingStream()
End Sub
#Region "_Clients-Ereignisverarbeitung"
Private Sub Client_Disposed(ByVal Sender As ManagedPipe)
'den Client für die beendete Verbindung entfernen
Sender.RemoveFrom(_Clients)
numberOfStartedServerInstances -= 1
CreateWaitingStream()
End Sub
Private Sub Client_RetriveData(ByVal sender As Object, ByVal e As DataEventArgs)
'einkommende ChatMessages anzeigen, und an alle versenden
OnRetriveData(e)
End Sub
Private Sub Client_StatusMessage(ByVal sender As Object, ByVal e As DataEventArgs)
'einkommende StatusMessages durchreichen (zur Anzeige)
OnStatusMessage(e)
End Sub
#End Region
Public Overrides Function SendAsnyc(bytes() As Byte) As Task
Return Task.Run(Sub() Send(bytes))
End Function
Public Overrides Sub Send(data As Byte())
For Each client As ManagedPipeClient In _Clients 'an alle versenden
client.Send(data)
Next
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If numberOfStartedServerInstances < maxNumbersOfServerInstances Then
Using clnt As New NamedPipeClientStream(pipeName)
'Herstellen einer Dummi-Verbindung, damit der ServerStream aus dem Wartezustand herauskommt.
clnt.Connect()
End Using
End If
For i As Integer = _Clients.Count - 1 To 0 Step -1
_Clients(i).Dispose()
Next
End Sub
End Class