Skip to content

Commit 95ad66e

Browse files
Add daemon register/unregister behaviour, change console colours, add hostname property, add env variable to control daemon registration
1 parent b94a559 commit 95ad66e

File tree

9 files changed

+97
-60
lines changed

9 files changed

+97
-60
lines changed

src/microstack.Daemon.WindowsService/MicroStackListner.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ protected async override Task ExecuteAsync(CancellationToken stoppingToken)
3030
using (var pipe = new NamedPipeServerStream("microstack_pipe", PipeDirection.InOut, 5))
3131
{
3232
var managedThread = Thread.CurrentThread.ManagedThreadId;
33-
await pipe.WaitForConnectionAsync();
33+
await pipe.WaitForConnectionAsync(stoppingToken);
3434
Console.WriteLine("Connected");
3535
var processContract = Serializer.Deserialize<ProcessContract>(pipe);
3636
_processStateManager.AddProcess(processContract.ProcessId, processContract.MicroStackPID);
37+
Console.WriteLine($"Registered {processContract.ProcessId} with MicroStack PID {processContract.MicroStackPID}");
3738
pipe.Disconnect();
3839
}
3940
}

src/microstack.Daemon.WindowsService/Process/ProcessState.cs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,62 @@
11
using System;
22
using System.Diagnostics;
3+
using System.Management;
34
using System.Threading;
5+
// using Timer = System.Timers.Timer;
46

57
namespace microstack.Daemon.WindowsService
68
{
79
public class ProcessState
810
{
911
private Timer _timer;
12+
private CancellationTokenSource _cts;
13+
private CancellationToken _cancellationToken;
14+
1015
public int MicroStackPID { get; set; }
1116
public int PID { get; set; }
1217
public ProcessMarkers ProcessMarker { get; set; }
1318
public int Ticks { get; private set; }
14-
15-
public ProcessState()
19+
private object _lock = new object();
20+
public ProcessState(int pid, int microStackPid, ProcessMarkers marker)
1621
{
22+
PID = pid;
23+
MicroStackPID = microStackPid;
24+
ProcessMarker = marker;
25+
1726
_timer = new Timer(CheckHealth, null, 0, 5);
27+
_cts = new CancellationTokenSource();
28+
_cancellationToken = _cts.Token;
29+
1830
Ticks = 0;
1931
}
2032

2133
private void CheckHealth(object state)
2234
{
2335
// Check if Microstack is alive
24-
var process = Process.GetProcessById(MicroStackPID);
25-
if (process == null)
36+
// Check WMI Database
37+
lock(_lock)
2638
{
27-
// Raise event to terminate associated PID
28-
ProcessMarker = ProcessMarkers.Black;
29-
OnProcessTerminationRequest(new ProcessEventArgs(){ PID = PID, ProcessMarker = ProcessMarker });
39+
if (!_cts.IsCancellationRequested)
40+
{
41+
var query = string.Format("SELECT * FROM Win32_Process WHERE ProcessId = {0}", MicroStackPID);
42+
var search = new ManagementObjectSearcher("root\\CIMV2", query);
43+
var results = search.Get().GetEnumerator();
44+
var next = results.MoveNext();
45+
// var queryObj = results.Current;
46+
// var pidInWmi = (uint)queryObj["ProcessId"];
47+
Ticks++;
48+
49+
if (!next)
50+
{
51+
// Raise event to terminate associated PID
52+
ProcessMarker = ProcessMarkers.Black;
53+
OnProcessTerminationRequest(new ProcessEventArgs(){ PID = PID, ProcessMarker = ProcessMarker });
54+
_cts.Cancel();
55+
_timer.Dispose();
56+
}
57+
}
3058
}
31-
Ticks++;
59+
3260
}
3361

3462
protected void OnProcessTerminationRequest(ProcessEventArgs args)

src/microstack.Daemon.WindowsService/ProcessStateManager.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.Linq;
5+
using System.Management;
46

57
namespace microstack.Daemon.WindowsService
68
{
@@ -17,19 +19,30 @@ public void TerminateProcess(object sender, ProcessEventArgs args)
1719
var processState = _states.FirstOrDefault(s => s.PID.Equals(args.PID));
1820
if (processState != null)
1921
{
20-
Process.GetProcessById(processState.PID)?.Kill(true);
22+
// Check WMI Database
23+
var query = string.Format("SELECT * FROM Win32_Process WHERE ProcessId = {0}", processState.PID);
24+
var search = new ManagementObjectSearcher("root\\CIMV2", query);
25+
var results = search.Get().GetEnumerator();
26+
var next = results.MoveNext();
27+
if (next)
28+
{
29+
var queryObj = results.Current;
30+
var pidInWmi = (uint)queryObj["ProcessId"];
31+
Console.WriteLine(pidInWmi);
32+
if (pidInWmi != 0)
33+
{
34+
var process = Process.GetProcessById(processState.PID);
35+
if (process != null)
36+
process.Kill(true);
37+
}
38+
}
2139
_states.Remove(processState);
2240
}
2341
}
2442

2543
public void AddProcess(int pid, int microStackPid)
2644
{
27-
var state = new ProcessState()
28-
{
29-
PID = pid,
30-
MicroStackPID = microStackPid,
31-
ProcessMarker = ProcessMarkers.Green,
32-
};
45+
var state = new ProcessState(pid, microStackPid, ProcessMarkers.Green);
3346
state.TerminateProcess += TerminateProcess;
3447
_states.Add(state);
3548
}

src/microstack.Daemon.WindowsService/Worker.cs

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/microstack.Daemon.WindowsService/microstack.Daemon.WindowsService.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<ItemGroup>
99
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.8" />
1010
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="3.1.8" />
11+
<PackageReference Include="Microsoft.Windows.Compatibility" Version="3.1.1" />
1112
<PackageReference Include="protobuf-net" Version="3.0.29" />
1213
</ItemGroup>
1314
</Project>

src/microstack.configuration/Models/Configuration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class Configuration
1414
public bool PullLatest { get; set; }
1515
public bool InMemoryGitFS { get; set; }
1616
public int Port { get; set; }
17+
public string HostName { get; set; }
1718
public bool Verbose { get; set; }
1819
public Dictionary<string, string> ConfigOverrides { get; set; }
1920

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace microstack.configuration.Models
2+
{
3+
public enum HealthChecks
4+
{
5+
Http
6+
}
7+
}

src/microstack/BackgroundTasks/ProcessQueueTask.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,28 @@ public void SpawnQueuedProcess(object state)
4646
{
4747
var process = Process.Start(processInfoObjectTuples.ProcessInfoObject);
4848
_processTuples.Add((processInfoObjectTuples.Name, process));
49-
using(var pipe = new NamedPipeClientStream(".", "microstack_pipe", PipeDirection.InOut, PipeOptions.None))
49+
50+
// Let users control registration if daemon fails
51+
bool.TryParse(Environment.GetEnvironmentVariable("DISABLE_MSTCK_PID_REG"), out var daemonRegistraction);
52+
53+
if (!daemonRegistraction)
5054
{
51-
try{
52-
pipe.Connect(5);
53-
ProtoBuf.Serializer.Serialize(pipe, new ProcessContract() {ProcessId = process.Id, MicroStackPID = Process.GetCurrentProcess().Id});
54-
}
55-
catch (TimeoutException ex)
56-
{
57-
_console.ForegroundColor = ConsoleColor.DarkRed;
58-
_console.Out.WriteLine($"Failed to register {processInfoObjectTuples.Name} with PID {process.Id} with Microstack Daemon, please ensure that Microstack Windows service is running by manually starting it or reinstalling Microstack");
59-
}
60-
finally
55+
using(var pipe = new NamedPipeClientStream(".", "microstack_pipe", PipeDirection.InOut, PipeOptions.None))
6156
{
62-
_console.Out.WriteLine($"Killing {processInfoObjectTuples.Name}");
63-
process.Kill(true);
64-
throw new Exception("Failed to connect to Microstack Daemon");
57+
try{
58+
pipe.Connect(5);
59+
_console.Out.WriteLine($"Registering {processInfoObjectTuples.Name} PID {process.Id} with Microstack Daemon");
60+
ProtoBuf.Serializer.Serialize(pipe, new ProcessContract() {ProcessId = process.Id, MicroStackPID = Process.GetCurrentProcess().Id});
61+
_console.ResetColor();
62+
}
63+
catch (TimeoutException ex)
64+
{
65+
_console.ForegroundColor = ConsoleColor.DarkRed;
66+
_console.Out.WriteLine($"Failed to register {processInfoObjectTuples.Name} with PID {process.Id} with Microstack Daemon, please ensure that Microstack Windows service is running by manually starting it or reinstalling Microstack");
67+
_console.Out.WriteLine($"Killing {processInfoObjectTuples.Name}");
68+
process.Kill(true);
69+
throw new Exception("Failed to connect to Microstack Daemon");
70+
}
6571
}
6672
}
6773
} catch(Exception ex)

src/microstack/Handlers/DotnetHandler.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,16 @@ public async override Task Handle(IList<Configuration> configurations, bool isVe
4040
for (var i = 0; i < _processInfoObjects.Count; i++)
4141
{
4242
_console.ForegroundColor = ConsoleColor.DarkYellow;
43-
_console.Out.WriteLine($"Starting {configurations[i].ProjectName} on https://localhost:{configurations[i].Port}");
43+
_console.Out.WriteLine($"Starting {configurations[i].ProjectName} on https://{configurations[i].HostName ?? "localhost"}:{configurations[i].Port}");
44+
45+
_console.ForegroundColor = ConsoleColor.DarkYellow;
46+
_console.Out.WriteLine("Configurations overridden");
47+
_console.ForegroundColor = ConsoleColor.Green;
48+
49+
foreach(var config in configurations[i].ConfigOverrides)
50+
{
51+
_console.Out.WriteLine($"\t {config.Key}: {config.Value}");
52+
}
4453
_console.ResetColor();
4554
}
4655

0 commit comments

Comments
 (0)