From 1bfa9c4b4bf805e019a23a1444502c2311753cc8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 10 Mar 2017 09:56:26 -0800 Subject: [PATCH] Make it possible to detect that a process is running inside dotnet-watch by setting 'DOTNET_WATCH=1' --- .../Internal/ProcessRunner.cs | 29 +++++++----- .../ProcessSpec.cs | 1 + src/Microsoft.DotNet.Watcher.Tools/Program.cs | 6 ++- .../DotNetWatcherTests.cs | 46 +++++++++++++++++++ .../Scenario/WatchableApp.cs | 2 +- .../KitchenSink/KitchenSink.csproj | 8 ++++ .../TestProjects/KitchenSink/Program.cs | 18 ++++++++ 7 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs create mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj create mode 100755 test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs diff --git a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs index f303e8fe53..592c657675 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Internal/ProcessRunner.cs @@ -63,20 +63,25 @@ namespace Microsoft.DotNet.Watcher.Internal private Process CreateProcess(ProcessSpec processSpec) { - var startInfo = new ProcessStartInfo - { - FileName = processSpec.Executable, - Arguments = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments), - UseShellExecute = false, - WorkingDirectory = processSpec.WorkingDirectory, - RedirectStandardOutput = processSpec.IsOutputCaptured, - RedirectStandardError = processSpec.IsOutputCaptured, - }; var process = new Process { - StartInfo = startInfo, - EnableRaisingEvents = true + EnableRaisingEvents = true, + StartInfo = + { + FileName = processSpec.Executable, + Arguments = ArgumentEscaper.EscapeAndConcatenate(processSpec.Arguments), + UseShellExecute = false, + WorkingDirectory = processSpec.WorkingDirectory, + RedirectStandardOutput = processSpec.IsOutputCaptured, + RedirectStandardError = processSpec.IsOutputCaptured, + } }; + + foreach (var env in processSpec.EnvironmentVariables) + { + process.StartInfo.Environment.Add(env.Key, env.Value); + } + return process; } @@ -131,4 +136,4 @@ namespace Microsoft.DotNet.Watcher.Internal } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs index 4b1508e5e2..ad5eb262b3 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/ProcessSpec.cs @@ -11,6 +11,7 @@ namespace Microsoft.DotNet.Watcher { public string Executable { get; set; } public string WorkingDirectory { get; set; } + public IDictionary EnvironmentVariables { get; } = new Dictionary(); public IEnumerable Arguments { get; set; } public OutputCapture OutputCapture { get; set; } diff --git a/src/Microsoft.DotNet.Watcher.Tools/Program.cs b/src/Microsoft.DotNet.Watcher.Tools/Program.cs index 261a92f31d..2f60889657 100644 --- a/src/Microsoft.DotNet.Watcher.Tools/Program.cs +++ b/src/Microsoft.DotNet.Watcher.Tools/Program.cs @@ -133,7 +133,11 @@ namespace Microsoft.DotNet.Watcher { Executable = DotNetMuxer.MuxerPathOrDefault(), WorkingDirectory = Path.GetDirectoryName(projectFile), - Arguments = args + Arguments = args, + EnvironmentVariables = + { + ["DOTNET_WATCH"] = "1" + }, }; await new DotNetWatcher(reporter) diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs new file mode 100644 index 0000000000..f9d16972ee --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/DotNetWatcherTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests +{ + public class DotNetWatcherTests : IDisposable + { + private readonly KitchenSinkApp _app; + + public DotNetWatcherTests(ITestOutputHelper logger) + { + _app = new KitchenSinkApp(logger); + _app.Prepare(); + } + + [Fact] + public async Task RunsWithDotnetWatchEnvVariable() + { + Assert.True(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_WATCH")), "DOTNET_WATCH cannot be set already when this test is running"); + + await _app.StartWatcherAsync().OrTimeout(); + const string messagePrefix = "DOTNET_WATCH = "; + var message = await _app.Process.GetOutputLineAsync(m => m.StartsWith(messagePrefix)); + var envValue = message.Substring(messagePrefix.Length); + Assert.Equal("1", envValue); + } + + public void Dispose() + { + _app.Dispose(); + } + + private class KitchenSinkApp : WatchableApp + { + public KitchenSinkApp(ITestOutputHelper logger) + : base("KitchenSink", logger) + { + } + } + } +} diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs index 6e4d6cc883..271a2832e4 100644 --- a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/Scenario/WatchableApp.cs @@ -93,7 +93,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests public virtual void Dispose() { - Process.Dispose(); + Process?.Dispose(); Scenario.Dispose(); } } diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj new file mode 100755 index 0000000000..abb9969a56 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/KitchenSink.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp1.1 + + + diff --git a/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs new file mode 100755 index 0000000000..5251cdc1e0 --- /dev/null +++ b/test/Microsoft.DotNet.Watcher.Tools.FunctionalTests/TestProjects/KitchenSink/Program.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; + +namespace KitchenSink +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Started"); + Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); + Console.WriteLine("DOTNET_WATCH = " + Environment.GetEnvironmentVariable("DOTNET_WATCH")); + } + } +}