Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine if .Net core console application is running in user interactive mode

Tags:

.net-core

Is it possible to determine if a .Net core console application is running in user interactive mode?

In previous versions of .Net it was possible to test Environment.UserInteractive to see if the user had access to the application. This doesn't seem to exist in .Net core.

like image 720
Remotec Avatar asked Jul 29 '17 19:07

Remotec


People also ask

What is user interactive mode?

Interactive mode allows you to rapidly analyze and visualize data using concise and efficient single-line commands. In interactive mode, commands typed at the IDL prompt are executed when the Enter key is pressed.

How do I run a .NET core console application from command prompt?

In . NET Core, it runs from the dll, so you have to just run the application by running the command prompt and using the command - dotnet run. Open your command prompt and go to that folder where your application persists.

How do I run a console application without showing the console?

If you created a Console app, when you launch your app by double-clicking it, the console is created and attached to your process before your code starts execution. There's no way to prevent the console window from showing up in that case.

What is environment UserInteractive in C#?

Gets a value indicating whether the current process is running in user interactive mode. public: static property bool UserInteractive { bool get(); }; C# Copy.


2 Answers

The problem that .NET Core faces more than classic .NET Framework is how "user interactive" is defined. Even on "classic" .NET, the Environment.UserInteractive feels hacky as it relies on a system API call to query user object flags and tests for a flag described as Window station has visible display surfaces. It is unclear what exactly this should semantically mean on a GUI-less windows nano server that you use to run commands from.

My suggestion is to determine the exact use case on what you want to test. You could for instance test if the attached input and output streams are redirected using Console.IsOutputRedirected and Console. IsInputRedirected. On non-windows systems, a call to isatty() could be made but that isn't currently available as .NET API (you'd have to write the PInvoke code). If you want to determine if you are running as a windows service, TopShelf checks if the process has been started by the service host. Another approach would be to add additional arguments for specific use cases - e.g. add and check for --noninteractive when you want to run a tool from a script.

like image 85
Martin Ullrich Avatar answered Sep 22 '22 17:09

Martin Ullrich


To complement Martin Ullrich's helpful answer:

If you're willing to define user-interactive as runs in a console/terminal window visible to the current user, you can use the following approach (C#), which should work on all supported platforms:

Note: Visible means visible in principle, i.e., can be made visible by the user if currently obscured or minimized.

using System;
using System.Runtime.InteropServices;

namespace net.same2u.pg
{
  static class Program
  {
    // P/Invoke declarations for Windows.
    [DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow();
    [DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr hWnd);

    // Indicates if the current process is running:
    //  * on Windows: in a console window visible to the user.
    //  * on Unix-like platform: in a terminal window, which is assumed to imply
    //    user-visibility (given that hidden processes don't need terminals).
    public static bool HaveVisibleConsole()
    {
      return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
                    IsWindowVisible(GetConsoleWindow())
                    :
                    Console.WindowHeight > 0;
    }

    static void Main(string[] args)
    {
      Console.WriteLine($"Running in visible console? {HaveVisibleConsole()}");
    }
  }
}

Note:

  • On Windows, all console-mode applications always run in a console window, whether that window is visible or not; the P/Invoke function declarations check if the console window (GetConsoleWindow()) - if any - associated with the current process is a visible window (IsWindowVisible(), on the current user's desktop).

  • On Unix-like platforms, non-GUI applications fundamentally don't need a terminal window to run, and launching such an application from a GUI app, for instance, does not involve a terminal. Therefore, the assumption is that if a terminal window is present at all, it implies that that window is visible; Console.WindowHeight only contains a positive value if a terminal window is present.

like image 29
mklement0 Avatar answered Sep 23 '22 17:09

mklement0