C# 通过程序逻辑添加控制台

C# 通过程序逻辑添加控制台,c#,service,C#,Service,我有一个windows服务。如果我从调试器启动它,我希望使用控制台输出运行它(因为您无法运行服务) 通常,Windows服务被设置为WindowApplication作为项目类型,并且没有“窗口”入口点。因此,它删除了好的旧控制台 如果需要控制台窗口,则需要将项目类型更改为ConsolePication。我希望在程序本身中执行此操作,而不是更改项目设置 有可能吗?您可以使用API 用于从进程中分离控制台: [DllImport("kernel32.dll")] static extern boo

我有一个windows服务。如果我从调试器启动它,我希望使用控制台输出运行它(因为您无法运行服务)

通常,Windows服务被设置为WindowApplication作为项目类型,并且没有“窗口”入口点。因此,它删除了好的旧控制台

如果需要控制台窗口,则需要将项目类型更改为ConsolePication。我希望在程序本身中执行此操作,而不是更改项目设置

有可能吗?

您可以使用API

用于从进程中分离控制台:

[DllImport("kernel32.dll")]
static extern bool FreeConsole();

一个好的做法是有两个程序(即,Visual Studio中生成可执行文件的两个项目,加上一个或多个用于共享应用程序逻辑的项目):

  • 一个用于软件的Windows服务变体
  • 另一个用于您的软件的控制台变体

  • 优点是您可以自由选择是将软件作为服务运行还是以控制台模式运行。例如,在控制台模式下运行时,使用Log4Net等框架,您可以将日志输出配置到控制台,这有助于诊断生产环境中的问题。

    我通常将任何程序开发为具有逻辑入口点的类库(或库集),然后添加launcher项目包装器:控制台应用程序,一个windows服务,一个网站

    如果在您的程序中有一个入口点(一个具有启动所有业务逻辑的方法的类),那么您可以将其构建为一个类库而不做任何更改,并向解决方案中添加一个控制台项目和一个windows服务项目,该项目在主类(例如program.cs)中实例化入口点并调用入口方法

    这种方法不会使用use方法侵入您的业务逻辑,并允许您在每次构建整个解决方案时构建每种使用模式。
    换句话说,它允许您分离关注点:程序和如何启动程序。

    是的,您可以通过多种方式来完成。我使用以下解决方案:

  • 创建控制台应用程序项目。把它命名为控制台、服务或其他东西

  • 转到服务类并创建以下代码:

    private static void Main()
    {            
        #if !DEBUG
        var servicesToRun = new [] { new DemoService() };
    
        Debug.WriteLine("Run service...");
        Run(servicesToRun);      
        #else
        DemoService service = new DemoService();
    
        service.OnStart(null);
    
        Console.WriteLine("Press ENTER to quit...");
        Console.ReadLine();
    
        service.OnStop();
    
        #endif
    }
    
  • 通过从服务项目链接到服务类,将现有项添加到Console应用程序项目。您可以通过单击“添加”按钮(添加为链接)旁边的箭头来执行此操作


  • 你完了。就像我说的,还有很多路要走。选择您最满意的一个。

    实际上,当程序开始运行时,您可以使用一个简单的检查来查看它是否作为服务运行,然后使用alloconsole命令启动控制台。下面是示例代码

    namespace TestService 
    {
       static class Program
       {
            [DllImport("kernel32.dll")]
            static extern bool AllocConsole();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static void Main()
            {
                if (!Environment.UserInteractive)                                
                {
                    ServiceBase[] ServicesToRun;
                    ServicesToRun = new ServiceBase[] 
                    { 
                        new Service1() 
                    };
                    ServiceBase.Run(ServicesToRun);
                }
                else 
                {
                    AllocConsole();
                    //Start Code that interfaces with console.
                }           
             }        
         }
     }
    
    命名空间测试服务
    {
    静态类程序
    {
    [DllImport(“kernel32.dll”)]
    静态外部布尔alloconsole();
    /// 
    ///应用程序的主要入口点。
    /// 
    静态void Main()
    {
    如果(!Environment.UserInteractive)
    {
    ServiceBase[]ServicesToRun;
    ServicesToRun=新的ServiceBase[]
    { 
    新服务1()
    };
    ServiceBase.Run(ServicesToRun);
    }
    其他的
    {
    allocsole();
    //启动与控制台接口的代码。
    }           
    }        
    }
    }
    
    您也可以尝试不使用
    GetStdHandle
    。属性告诉您应用程序是作为服务运行还是作为交互程序运行。出于不同的原因,我倾向于Debugger.IsAttached而不是Environment.UserInteractive,但解决方案很好。谢谢。和其他答案一样。将需要额外的测试,甚至需要不同的部署。所以这不是一个机会。
    namespace TestService 
    {
       static class Program
       {
            [DllImport("kernel32.dll")]
            static extern bool AllocConsole();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static void Main()
            {
                if (!Environment.UserInteractive)                                
                {
                    ServiceBase[] ServicesToRun;
                    ServicesToRun = new ServiceBase[] 
                    { 
                        new Service1() 
                    };
                    ServiceBase.Run(ServicesToRun);
                }
                else 
                {
                    AllocConsole();
                    //Start Code that interfaces with console.
                }           
             }        
         }
     }