code optimization
This commit is contained in:
@@ -3,172 +3,169 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pilz.IO
|
||||
namespace Pilz.IO;
|
||||
|
||||
public class EmbeddedFilesContainer
|
||||
{
|
||||
public class EmbeddedFilesContainer
|
||||
[JsonProperty("CompressedFiles")]
|
||||
private readonly Dictionary<string, byte[]> compressedFiles = new Dictionary<string, byte[]>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the names of all embedded files.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public IEnumerable<string> AllFileNames
|
||||
{
|
||||
[JsonProperty("CompressedFiles")]
|
||||
private readonly Dictionary<string, byte[]> compressedFiles = new Dictionary<string, byte[]>();
|
||||
get => compressedFiles.Keys;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the names of all embedded files.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public IEnumerable<string> AllFileNames
|
||||
{
|
||||
get => compressedFiles.Keys;
|
||||
}
|
||||
/// <summary>
|
||||
/// Embeds a file to this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how it should be called in this container.</param>
|
||||
/// <param name="filePath">The file path to the file that should be embedded.</param>
|
||||
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
|
||||
public Task<bool> AddFileAsync(string fileName, string filePath)
|
||||
{
|
||||
return Task.Run(() => AddFile(fileName, filePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Embeds a file to this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how it should be called in this container.</param>
|
||||
/// <param name="filePath">The file path to the file that should be embedded.</param>
|
||||
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
|
||||
public Task<bool> AddFileAsync(string fileName, string filePath)
|
||||
{
|
||||
return Task.Run(() => AddFile(fileName, filePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Embeds a file to this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how it should be called in this container.</param>
|
||||
/// <param name="filePath">The file path to the file that should be embedded.</param>
|
||||
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
|
||||
public bool AddFile(string fileName, string filePath)
|
||||
{
|
||||
bool success;
|
||||
FileStream fs = null;
|
||||
MemoryStream compressed = null;
|
||||
/// <summary>
|
||||
/// Embeds a file to this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how it should be called in this container.</param>
|
||||
/// <param name="filePath">The file path to the file that should be embedded.</param>
|
||||
/// <returns>Returns a <see cref="bool"/> that defines if the file as been embedded successfully.</returns>
|
||||
public bool AddFile(string fileName, string filePath)
|
||||
{
|
||||
bool success;
|
||||
FileStream fs = null;
|
||||
MemoryStream compressed = null;
|
||||
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
#endif
|
||||
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||
compressed = new MemoryStream();
|
||||
using (var compressor = new DeflateStream(compressed, CompressionLevel.Optimal, true))
|
||||
fs.CopyTo(compressor);
|
||||
success = true;
|
||||
fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||
compressed = new MemoryStream();
|
||||
using (var compressor = new DeflateStream(compressed, CompressionLevel.Optimal, true))
|
||||
fs.CopyTo(compressor);
|
||||
success = true;
|
||||
#if !DEBUG
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (success)
|
||||
{
|
||||
var compressedBytes = compressed.ToArray();
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
compressedFiles[fileName] = compressedBytes;
|
||||
else
|
||||
compressedFiles.Add(fileName, compressedBytes);
|
||||
}
|
||||
|
||||
compressed?.Close();
|
||||
fs?.Close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a file from this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
public void RemoveFile(string fileName)
|
||||
if (success)
|
||||
{
|
||||
var compressedBytes = compressed.ToArray();
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
compressedFiles.Remove(fileName);
|
||||
compressedFiles[fileName] = compressedBytes;
|
||||
else
|
||||
compressedFiles.Add(fileName, compressedBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given file exists in this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns if the given file exists in this container.</returns>
|
||||
public bool HasFile(string fileName)
|
||||
compressed?.Close();
|
||||
fs?.Close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a file from this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
public void RemoveFile(string fileName)
|
||||
{
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
compressedFiles.Remove(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given file exists in this container.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns if the given file exists in this container.</returns>
|
||||
public bool HasFile(string fileName)
|
||||
{
|
||||
return compressedFiles.ContainsKey(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a file from this container as stream.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns a stream of the file with the given name.</returns>
|
||||
public Task<Stream> GetStreamAsync(string fileName)
|
||||
{
|
||||
return Task.Run(() => GetStream(fileName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a file from this container as stream.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns a stream of the file with the given name.</returns>
|
||||
public Stream GetStream(string fileName)
|
||||
{
|
||||
Stream decompressed = null;
|
||||
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
{
|
||||
return compressedFiles.ContainsKey(fileName);
|
||||
decompressed = new MemoryStream();
|
||||
DecompressToStream(decompressed, compressedFiles[fileName]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a file from this container as stream.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns a stream of the file with the given name.</returns>
|
||||
public Task<Stream> GetStreamAsync(string fileName)
|
||||
return decompressed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a given file to the users temp directory.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns the file path to the temp file.</returns>
|
||||
public Task<string> GetLocalFilePathAsync(string fileName)
|
||||
{
|
||||
return Task.Run(() => GetLocalFilePath(fileName));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves a given file to the users temp directory.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns the file path to the temp file.</returns>
|
||||
public string GetLocalFilePath(string fileName)
|
||||
{
|
||||
string filePath = string.Empty;
|
||||
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
{
|
||||
return Task.Run(() => GetStream(fileName));
|
||||
filePath = Path.GetTempFileName();
|
||||
|
||||
if (Path.HasExtension(fileName))
|
||||
filePath = Path.ChangeExtension(filePath, Path.GetExtension(fileName));
|
||||
|
||||
var decompressed = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
|
||||
DecompressToStream(decompressed, compressedFiles[fileName]);
|
||||
decompressed.Flush();
|
||||
decompressed.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a file from this container as stream.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns a stream of the file with the given name.</returns>
|
||||
public Stream GetStream(string fileName)
|
||||
{
|
||||
Stream decompressed = null;
|
||||
return filePath;
|
||||
}
|
||||
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
{
|
||||
decompressed = new MemoryStream();
|
||||
DecompressToStream(decompressed, compressedFiles[fileName]);
|
||||
}
|
||||
|
||||
return decompressed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a given file to the users temp directory.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns the file path to the temp file.</returns>
|
||||
public Task<string> GetLocalFilePathAsync(string fileName)
|
||||
{
|
||||
return Task.Run(() => GetLocalFilePath(fileName));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves a given file to the users temp directory.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name how the file is called.</param>
|
||||
/// <returns>Returns the file path to the temp file.</returns>
|
||||
public string GetLocalFilePath(string fileName)
|
||||
{
|
||||
string filePath = string.Empty;
|
||||
|
||||
if (compressedFiles.ContainsKey(fileName))
|
||||
{
|
||||
filePath = Path.GetTempFileName();
|
||||
|
||||
if (Path.HasExtension(fileName))
|
||||
filePath = Path.ChangeExtension(filePath, Path.GetExtension(fileName));
|
||||
|
||||
var decompressed = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
|
||||
DecompressToStream(decompressed, compressedFiles[fileName]);
|
||||
decompressed.Flush();
|
||||
decompressed.Close();
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private void DecompressToStream(Stream decompressed, byte[] compressedData)
|
||||
{
|
||||
var compressed = new MemoryStream(compressedData);
|
||||
var decompressor = new DeflateStream(compressed, CompressionMode.Decompress, true);
|
||||
decompressor.CopyTo(decompressed);
|
||||
decompressor.Close();
|
||||
compressed.Close();
|
||||
}
|
||||
private void DecompressToStream(Stream decompressed, byte[] compressedData)
|
||||
{
|
||||
var compressed = new MemoryStream(compressedData);
|
||||
var decompressor = new DeflateStream(compressed, CompressionMode.Decompress, true);
|
||||
decompressor.CopyTo(decompressed);
|
||||
decompressor.Close();
|
||||
compressed.Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace Pilz.IO
|
||||
{
|
||||
public class DataEventArgs : EventArgs
|
||||
{
|
||||
public readonly byte[] Data;
|
||||
namespace Pilz.IO;
|
||||
|
||||
public DataEventArgs(byte[] bytes) : base()
|
||||
{
|
||||
Data = bytes;
|
||||
}
|
||||
public class DataEventArgs : EventArgs
|
||||
{
|
||||
public readonly byte[] Data;
|
||||
|
||||
public DataEventArgs(byte[] bytes) : base()
|
||||
{
|
||||
Data = bytes;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,23 @@
|
||||
using Pilz.Runtime;
|
||||
using Pilz.Win32.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace Pilz.IO
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
static readonly int MAX_PATH = 255;
|
||||
namespace Pilz.IO;
|
||||
|
||||
public static string GetExecutablePath(bool checkRealOS = false)
|
||||
public static class Extensions
|
||||
{
|
||||
static readonly int MAX_PATH = 255;
|
||||
|
||||
public static string GetExecutablePath(bool checkRealOS = false)
|
||||
{
|
||||
if (RuntimeInformationsEx.IsOSPlatform(OSType.Windows, checkRealOS))
|
||||
{
|
||||
if (RuntimeInformationsEx.IsOSPlatform(OSType.Windows, checkRealOS))
|
||||
{
|
||||
var sb = new StringBuilder(MAX_PATH);
|
||||
Kernel32.GetModuleFileName(IntPtr.Zero, sb, MAX_PATH);
|
||||
return sb.ToString();
|
||||
}
|
||||
else
|
||||
return Process.GetCurrentProcess().MainModule.FileName;
|
||||
var sb = new StringBuilder(MAX_PATH);
|
||||
Kernel32.GetModuleFileName(IntPtr.Zero, sb, MAX_PATH);
|
||||
return sb.ToString();
|
||||
}
|
||||
else
|
||||
return Process.GetCurrentProcess().MainModule.FileName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,118 +1,117 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Pilz.IO
|
||||
namespace Pilz.IO;
|
||||
|
||||
public partial class FileLocker : IDisposable
|
||||
{
|
||||
public partial class FileLocker : IDisposable
|
||||
private FileStream fsLock = null;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the file path to the file that should be locked.
|
||||
/// </summary>
|
||||
public string FilePath { get; private set; }
|
||||
/// <summary>
|
||||
/// Defines the file path to the lock file that is used to identify the file lock.
|
||||
/// </summary>
|
||||
public string LockFile { get; private set; }
|
||||
/// <summary>
|
||||
/// Defines if the file is locked privatly by this instance.
|
||||
/// </summary>
|
||||
public bool LockedPrivate { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the file is locked by an other instance/program/user.
|
||||
/// </summary>
|
||||
public bool LockedExternal
|
||||
{
|
||||
private FileStream fsLock = null;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the file path to the file that should be locked.
|
||||
/// </summary>
|
||||
public string FilePath { get; private set; }
|
||||
/// <summary>
|
||||
/// Defines the file path to the lock file that is used to identify the file lock.
|
||||
/// </summary>
|
||||
public string LockFile { get; private set; }
|
||||
/// <summary>
|
||||
/// Defines if the file is locked privatly by this instance.
|
||||
/// </summary>
|
||||
public bool LockedPrivate { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the file is locked by an other instance/program/user.
|
||||
/// </summary>
|
||||
public bool LockedExternal
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LockedPrivate)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
string lockFile = FilePath + ".lock";
|
||||
bool isLocked = false;
|
||||
|
||||
if (File.Exists(lockFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fs = new FileStream(lockFile, FileMode.Open, FileAccess.Read);
|
||||
fs.Close();
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
isLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isLocked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new instance of <see cref="FileLocker"/> and locks the given file automatically.
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path to the file that should be locked.</param>
|
||||
public FileLocker(string filePath) : this(filePath, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new instance of <see cref="FileLocker"/>
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path to the file that should be locked.</param>
|
||||
/// <param name="autoLock">Defines if the file should be locked automatically right after creating this instance.</param>
|
||||
public FileLocker(string filePath, bool autoLock)
|
||||
{
|
||||
FilePath = filePath;
|
||||
LockFile = filePath + ".lock";
|
||||
if (autoLock) Lock();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks the file, if not already locked privatly.
|
||||
/// </summary>
|
||||
public void Lock()
|
||||
{
|
||||
if (!LockedPrivate)
|
||||
{
|
||||
fsLock = new FileStream(LockFile, FileMode.Create, FileAccess.ReadWrite);
|
||||
LockedPrivate = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks the file, if locked privatly.
|
||||
/// </summary>
|
||||
public void Unlock()
|
||||
get
|
||||
{
|
||||
if (LockedPrivate)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
fsLock.Close();
|
||||
fsLock.Dispose();
|
||||
fsLock = null;
|
||||
File.Delete(LockFile);
|
||||
LockedPrivate = false;
|
||||
string lockFile = FilePath + ".lock";
|
||||
bool isLocked = false;
|
||||
|
||||
if (File.Exists(lockFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fs = new FileStream(lockFile, FileMode.Open, FileAccess.Read);
|
||||
fs.Close();
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
isLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isLocked;
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
private bool disposedValue;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
Unlock();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
disposedValue = true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new instance of <see cref="FileLocker"/> and locks the given file automatically.
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path to the file that should be locked.</param>
|
||||
public FileLocker(string filePath) : this(filePath, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a new instance of <see cref="FileLocker"/>
|
||||
/// </summary>
|
||||
/// <param name="filePath">The file path to the file that should be locked.</param>
|
||||
/// <param name="autoLock">Defines if the file should be locked automatically right after creating this instance.</param>
|
||||
public FileLocker(string filePath, bool autoLock)
|
||||
{
|
||||
FilePath = filePath;
|
||||
LockFile = filePath + ".lock";
|
||||
if (autoLock) Lock();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks the file, if not already locked privatly.
|
||||
/// </summary>
|
||||
public void Lock()
|
||||
{
|
||||
if (!LockedPrivate)
|
||||
{
|
||||
fsLock = new FileStream(LockFile, FileMode.Create, FileAccess.ReadWrite);
|
||||
LockedPrivate = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks the file, if locked privatly.
|
||||
/// </summary>
|
||||
public void Unlock()
|
||||
{
|
||||
if (LockedPrivate)
|
||||
{
|
||||
fsLock.Close();
|
||||
fsLock.Dispose();
|
||||
fsLock = null;
|
||||
File.Delete(LockFile);
|
||||
LockedPrivate = false;
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
private bool disposedValue;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
Unlock();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
disposedValue = true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -2,66 +2,65 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pilz.IO
|
||||
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>
|
||||
/// stellt den Erben "Server" und "Client" 2 verschiedene
|
||||
/// Message-Events zur Verfügung, und ein Event-Raisendes Dispose
|
||||
/// Zur Ausgabe chat-verwaltungstechnischer Status-Informationen
|
||||
/// </summary>
|
||||
public abstract class ManagedPipe : IDisposable
|
||||
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)
|
||||
{
|
||||
public delegate void EventHandlerWithOneArgument<T0>(T0 Sender);
|
||||
StatusMessage?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <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;
|
||||
protected void OnRetriveData(DataEventArgs e)
|
||||
{
|
||||
RetriveData?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private bool _IsDisposed = false;
|
||||
public void RemoveFrom<T>(ICollection<T> Coll) where T : ManagedPipe
|
||||
{
|
||||
Coll.Remove((T)this);
|
||||
}
|
||||
|
||||
protected abstract void Dispose(bool disposing);
|
||||
public abstract void Send(byte[] bytes);
|
||||
public abstract Task SendAsnyc(byte[] bytes);
|
||||
|
||||
protected void OnStatusMessage(DataEventArgs e)
|
||||
public bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,90 +1,89 @@
|
||||
using System;
|
||||
using global::System.IO.Pipes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using global::System.IO.Pipes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pilz.IO
|
||||
namespace Pilz.IO;
|
||||
|
||||
public class ManagedPipeClient : ManagedPipe
|
||||
{
|
||||
public class ManagedPipeClient : ManagedPipe
|
||||
private PipeStream pipeStream;
|
||||
private byte[] _Buf = new byte[1024];
|
||||
|
||||
public ManagedPipeClient(string pipeName) : this(pipeName, ".")
|
||||
{
|
||||
private PipeStream pipeStream;
|
||||
private byte[] _Buf = new byte[1024];
|
||||
}
|
||||
|
||||
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!");
|
||||
}
|
||||
|
||||
public ManagedPipeClient(string pipeName, string serverName) : this(pipeName, serverName, -1)
|
||||
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
|
||||
{
|
||||
Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
public ManagedPipeClient(string pipeName, int connectionTimeout) : this(pipeName, ".", connectionTimeout)
|
||||
var list = new List<byte>();
|
||||
for (int i = 0, loopTo = bytesCount - 1; i <= loopTo; i++)
|
||||
list.Add(_Buf[i]);
|
||||
while (bytesCount == _Buf.Length)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
var list = new List<byte>();
|
||||
for (int i = 0, loopTo = bytesCount - 1; i <= loopTo; i++)
|
||||
bytesCount = pipeStream.Read(_Buf, 0, _Buf.Length);
|
||||
for (int i = 0, loopTo1 = bytesCount - 1; i <= loopTo1; 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());
|
||||
OnRetriveData(deargs);
|
||||
|
||||
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
|
||||
}
|
||||
|
||||
public override Task SendAsnyc(byte[] bytes)
|
||||
{
|
||||
return Task.Run(() => Send(bytes));
|
||||
}
|
||||
var deargs = new DataEventArgs(list.ToArray());
|
||||
OnRetriveData(deargs);
|
||||
|
||||
public override void Send(byte[] data)
|
||||
{
|
||||
pipeStream.Write(data, 0, data.Length);
|
||||
}
|
||||
pipeStream.BeginRead(_Buf, 0, _Buf.Length, EndRead, null);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
pipeStream.Dispose();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,108 +1,107 @@
|
||||
using System;
|
||||
using global::System.IO.Pipes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using global::System.IO.Pipes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pilz.IO
|
||||
namespace Pilz.IO;
|
||||
|
||||
public class ManagedPipeServer : ManagedPipe
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
// Pro Verbindung (Anfrage) wird ein Client-Objekt generiert, das den Datenaustausch dieser Verbindung abwickelt
|
||||
public List<ManagedPipeClient> Clients { get; private set; } = new List<ManagedPipeClient>();
|
||||
public ManagedPipeServer(string pipeName, int maxNumbersOfServerInstances)
|
||||
{
|
||||
this.pipeName = pipeName;
|
||||
this.maxNumbersOfServerInstances = maxNumbersOfServerInstances;
|
||||
CreateWaitingStream();
|
||||
}
|
||||
|
||||
private readonly string pipeName = "";
|
||||
private readonly int maxNumbersOfServerInstances;
|
||||
private int numberOfStartedServerInstances = 0;
|
||||
|
||||
public ManagedPipeServer(string pipeName) : this(pipeName, 1)
|
||||
private void CreateWaitingStream()
|
||||
{
|
||||
if (numberOfStartedServerInstances < maxNumbersOfServerInstances)
|
||||
{
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using global::System;
|
||||
using global::System.Reflection;
|
||||
using global::System.Runtime.InteropServices;
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user