首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在调用AttachConsole(-1)之后使用Console.ReadKey()会挂起ReadKey()上的应用程序

在调用AttachConsole(-1)之后使用Console.ReadKey()会挂起ReadKey()上的应用程序
EN

Stack Overflow用户
提问于 2016-07-11 21:48:27
回答 1查看 376关注 0票数 0

目前,我正在尽我最大的努力拥有一个可以通过命令提示符或windows窗体应用程序使用的应用程序。此应用程序也将用作服务。由于显而易见的原因(比如重写代码和跟踪两个应用程序的更改),我只想创建一个应用程序。

目前我正在使用以下方法来实现这一点(我已经包含了我所有的调试代码,以防任何人有任何具体的建议)……

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyApplicationSpace
{
    static class Program
    {
        #region Private class APIs
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool AttachConsole(int pid);

        [DllImport("kernel32")]
        private static extern bool AllocConsole();

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool FreeConsole();
        #endregion

        #region Constructor
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main(string[] args)
        {
            if (args.Contains("-service"))
            {
                ServiceBase[] servicesToRun;
                servicesToRun = new ServiceBase[]
                {
                new MyServiceClass()
                };

                if (Environment.UserInteractive)
                {
                    if (!AttachConsole(-1)) AllocConsole();

                    RunInteractive(servicesToRun);

                    FreeConsole();
                    SendKeys.SendWait("{ENTER}");
                }
                else
                    ServiceBase.Run(servicesToRun);
            }
            else
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
        #endregion

        #region Private class functions
        private static void RunInteractive(ServiceBase[] servicesToRun)
        {
            Console.WriteLine("Services running in interactive mode.");
            Console.WriteLine();

            MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (ServiceBase service in servicesToRun)
            {
                Console.Write("Starting {0}...", service.ServiceName);
                onStartMethod.Invoke(service, new object[] { new string[] { } });
                Console.Write("Started");
            }

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Press any key to stop the services and end the process...");
            Console.WriteLine("BEFORE ReadKey");

            File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "error.log", "BEFORE ReadKey");
            try
            {
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "error.log", ex.Message);
            }
            File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "error.log", "AFTER ReadKey");

            Console.WriteLine("AFTER ReadKey");
            Console.WriteLine();

            Console.WriteLine("Continuing...");

            MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
            Console.WriteLine("onStopMethod is null = " + (onStopMethod == null));

            Console.WriteLine("Foreach service in service to run count:" + servicesToRun.Count());
            foreach (ServiceBase service in servicesToRun)
            {
                Console.Write("Stopping {0}...", service.ServiceName);
                onStopMethod.Invoke(service, null);
                Console.WriteLine("Stopped");
            }

            Console.WriteLine("All services stopped.");
            // Keep the console alive for a second to allow the user to see the message.
            Thread.Sleep(1000);
        }
        #endregion
    }
}

当我尝试调用Console.ReadKey()时出现问题。程序似乎在某种程度上挂起或退出。例如,当我从命令提示符运行它时,它会按预期运行,然后显示"Press any key to stop the services and end the process...“以及“在ReadKey之前”。然后,一旦我点击[ENTER],控制台就会返回到默认的命令提示符。然而,由于某些原因,应用程序仍然在任务管理器中显示为正在运行。它看起来好像挂了起来。

如果我将应用程序类型更改为console application,一切都会正常工作,而且看起来很棒。但我需要将其构建为windows application。我认为问题在于使用AttachConsole(-1)与将其构建为控制台应用程序是不同的。

EN

回答 1

Stack Overflow用户

发布于 2016-07-12 01:38:21

这归功于汉斯。我不确定他为什么删除了他的答案,但我希望他不会这样做。

基本上,命令过程和我的应用程序正在争夺命令窗口(他说得比我优雅得多)。

他建议我可以做两件事中的一件。

  1. 创建一个独立于我的应用程序"my app name.com"的小应用程序"my app name.exe",并让它自己创建一个新的命令窗口来启动服务。
  2. 使用my start命令来运行应用程序,而不是尝试正常运行它。

我选择使用阶梯方法。使用wait开关,它会强制命令处理器等待,直到应用程序完成,直到它再次尝试抓取按键。在运行start时,请注意第三个参数。它是"",它是在/wait参数之后传递一个空参数的两个双引号。这是必要的,以便在运行应用程序后传递参数。

在此之前

C:\“我的应用程序name.exe”-service

之后

C:\start /wait "my app name.exe“-service

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38308641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档