admin管理员组

文章数量:1306209

In .NET Framework 4.6.2, if I double-click an exe that's registered as a Windows service, I see this message:

Great! Prevents bad things from happening.

Now I'm on .NET 8 and I've written a Windows service that is a BackgroundTask with a Worker... how can I emulate this same behavior where someone tries to run it directly from the EXE? I want to prevent the thing from running unless it's a service. Can this be done?

In .NET Framework 4.6.2, if I double-click an exe that's registered as a Windows service, I see this message:

Great! Prevents bad things from happening.

Now I'm on .NET 8 and I've written a Windows service that is a BackgroundTask with a Worker... how can I emulate this same behavior where someone tries to run it directly from the EXE? I want to prevent the thing from running unless it's a service. Can this be done?

Share Improve this question asked Feb 3 at 13:25 FoxScullyFoxScully 635 bronze badges 6
  • 3 Perhaps check Environment.UserInteractive in your app's entry-point? (it should be false when running as a service) – Marc Gravell Commented Feb 3 at 13:35
  • @MarcGravell seems like a great solution for checking, thanks. But how can I also elegantly display a message? There's no System.Windows.Forms in this app... – FoxScully Commented Feb 3 at 13:54
  • @Marc Gravell — Exactly. Moreover, you can create an application working correctly as a normal application and as a service. And debug most of the code with ease. Please see my answer. – Sergey A Kryukov Commented Feb 3 at 13:56
  • @FoxScully — First, this is a very good, important question (upvoted). My answer already explained how you can show the message. But you won't need it. You can create an application correctly working in both ways. If you need clarifications on showing messages and UI in general, ask a question in a comment, and I'll answer. Let's say, you can use System.Window.Forms or WPF in your application. With WPF, you may need a special approach, without app.xaml, to start with Main, but this is pretty simple. I can explain it, too. – Sergey A Kryukov Commented Feb 3 at 14:05
  • I'll just do it like this: [DllImport( "User32.dll", CharSet = CharSet.Unicode )] public static extern int MessageBox( IntPtr h, string m, string c, int type ); static void Main() { if ( Environment.UserInteractive ) { MessageBox( (IntPtr)0, "Your Message", "My Message Box", 0 ); Environment.Exit( 1 ); return; } – FoxScully Commented Feb 3 at 14:07
 |  Show 1 more comment

1 Answer 1

Reset to default 4

This question is practically important.

This problem and related problems can be solved by using the property System.Environment.UserInteractive.

If the value of this property is true during runtime, the application was loaded and started as a normal application of any kind, for example, via the system Shell. Otherwise, it was started as a service, that is, loaded and started by the service controller.

In particular, you can do even better: you can create an application that can be started and work correctly in both ways. In the interactive mode, it can even execute some windowed UI. Also, if you share most of the code between interactive and service mode, you can debug this code the same way you do it for the normal (interactive application), which is a lot easier. For example, you can check the property in your Main and conditionally execute one of two branches:

class Program {

    // ...

    static void Main() {
        if (System.Environment.UserInteractive)
            StartUI();
        else
            StartService();
    } //Main

}

本文标签: