Skip to content

Commit

Permalink
🐛 RunSingleInstancePipeServer
Browse files Browse the repository at this point in the history
  • Loading branch information
Aigio authored and Aigio committed Aug 31, 2023
1 parent ac91872 commit 44b4a3b
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ public static partial class Kernel32

const uint QueryLimitedInformation = 0x00001000;

public static string QueryFullProcessImageName(Process process)
public static string? QueryFullProcessImageName(Process process)
{
int capacity = 1024;
StringBuilder sb = new(capacity);
var handle = Kernel32_.OpenProcess(new(QueryLimitedInformation), false, process.Id);
Kernel32_.QueryFullProcessImageName(handle, 0, sb, ref capacity);
string fullPath = sb.ToString(0, capacity);
return fullPath;
try
{
int capacity = 1024;
StringBuilder sb = new(capacity);
var handle = Kernel32_.OpenProcess(new(QueryLimitedInformation), false, process.Id);
Kernel32_.QueryFullProcessImageName(handle, 0, sb, ref capacity);
string fullPath = sb.ToString(0, capacity);
return fullPath;
}
catch
{
return null;
}
}
}

Expand Down
63 changes: 55 additions & 8 deletions src/BD.WTTS.Client/Startup/Startup.SingleInstancePipeline.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#if WINDOWS
using System.Security.AccessControl;
#endif

// ReSharper disable once CheckNamespace
namespace BD.WTTS;

Expand Down Expand Up @@ -82,14 +86,31 @@ static IEnumerable<Process> GetCurrentAllProcess()
}
#endif
var currentMainModule = current.TryGetMainModule();
bool IsThisProgram(Process p, ProcessModule? pMainModule)
{
if (currentMainModule != null)
{
if (pMainModule != null)
{
return pMainModule.FileName == currentMainModule.FileName &&
pMainModule.ModuleName == currentMainModule.ModuleName;
}
else
{
#if WINDOWS
var path = Interop.Kernel32.QueryFullProcessImageName(p);
return path == currentMainModule.FileName;
#else
return false;
#endif
}
}
return true;
}
var query = from p in Process.GetProcessesByName(current.ProcessName)
let pMainModule = p.TryGetMainModule()
where p.Id != current.Id &&
p.ProcessName == current.ProcessName &&
(currentMainModule == null ||
(pMainModule != null &&
pMainModule.FileName == currentMainModule.FileName &&
pMainModule.ModuleName == currentMainModule.ModuleName))
p.ProcessName == current.ProcessName && IsThisProgram(p, pMainModule)
select p;
return query;
}
Expand Down Expand Up @@ -121,7 +142,7 @@ public static bool TryKillCurrentAllProcess()
static string GetPipeName()
{
var processPath = Environment.ProcessPath ?? string.Empty;
return AssemblyInfo.APPLICATION_ID + "_v3_" + Hashs.String.Crc32(processPath);
return AssemblyInfo.APPLICATION_ID + "_v" + AssemblyInfo.InformationalVersion + "_" + Hashs.String.Crc32(processPath);
}

CancellationTokenSource? cts;
Expand All @@ -131,9 +152,35 @@ void RunSingleInstancePipeServer()
{
cts = new CancellationTokenSource();
var name = GetPipeName();

NamedPipeServerStream GetNamedPipeServerStream()
{
const PipeDirection direction = PipeDirection.In;
const int maxNumberOfServerInstances = 5;
const PipeTransmissionMode transmissionMode = PipeTransmissionMode.Byte;
const PipeOptions options = PipeOptions.None;
const int inBufferSize = 0;
const int outBufferSize = 0;
#if WINDOWS
if (WindowsPlatformServiceImpl.IsPrivilegedProcess)
{
// https://github.com/dotnet-campus/dotnetCampus.Ipc/blob/2.0.0-alpha403/src/dotnetCampus.Ipc/Internals/IpcPipeServerMessageProvider.cs#L99
SecurityIdentifier securityIdentifier = new(WellKnownSidType.AuthenticatedUserSid, null);
PipeSecurity pipeSecurity = new();
pipeSecurity.AddAccessRule(new PipeAccessRule(securityIdentifier,
PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance,
AccessControlType.Allow));

var result = NamedPipeServerStreamAcl.Create(name, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity);
return result;
}
#endif
return new NamedPipeServerStream(name, direction, maxNumberOfServerInstances, transmissionMode, options);
}

while (true)
{
using var pipeServer = new NamedPipeServerStream(name, PipeDirection.In, 1);
using var pipeServer = GetNamedPipeServerStream();
try
{
pipeServer.WaitForConnection();
Expand Down Expand Up @@ -177,7 +224,7 @@ public static bool SendMessage(string value)
using var pipeClient = new NamedPipeClientStream(".", name,
PipeDirection.Out, PipeOptions.None,
TokenImpersonationLevel.Impersonation);
pipeClient.Connect(TimeSpan.FromSeconds(25));
pipeClient.Connect(TimeSpan.FromSeconds(7.7D));
using StreamWriter sw = new StreamWriter(pipeClient);
sw.WriteLine(value);
return true;
Expand Down

0 comments on commit 44b4a3b

Please sign in to comment.