none
想在wpf项目中方便地测试某些功能代码,在启动时,怎么以控制台的方式启动?也就是启动时调用控制台程序,开始时不启用窗体,启用某个类的Main方法。, RRS feed

  • 问题

  • 想在wpf项目中方便地测试程序,每次都得从主窗口进入到测试功能的地方进行测试,这很麻烦。还有测试从Nuget包中下载的某些组件中某些类的功能,若创建另一个控制台程序就得下载两次。

    在wpf项目中,在启动时,怎么以控制台的方式启动,也就是调用某个类的Main方法,不调用窗口程序?



    2017年5月10日 12:59

答案

  • Hi,

    请参考下面的代码,下面的类可以让你的WPF程序附加一个控制台.

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Security;
    
    [SuppressUnmanagedCodeSecurity]
    public static class ConsoleManager
    {
        private const string Kernel32_DllName = "kernel32.dll";
    
        [DllImport(Kernel32_DllName)]
        private static extern bool AllocConsole();
    
        [DllImport(Kernel32_DllName)]
        private static extern bool FreeConsole();
    
        [DllImport(Kernel32_DllName)]
        private static extern IntPtr GetConsoleWindow();
    
        [DllImport(Kernel32_DllName)]
        private static extern int GetConsoleOutputCP();
    
        public static bool HasConsole
        {
            get { return GetConsoleWindow() != IntPtr.Zero; }
        }
    
        /// <summary>
        /// Creates a new console instance if the process is not attached to a console already.
        /// </summary>
        public static void Show()
        {
            //#if DEBUG
            if (!HasConsole)
            {
                AllocConsole();
                InvalidateOutAndError();
            }
            //#endif
        }
    
        /// <summary>
        /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
        /// </summary>
        public static void Hide()
        {
            //#if DEBUG
            if (HasConsole)
            {
                SetOutAndErrorNull();
                FreeConsole();
            }
            //#endif
        }
    
        public static void Toggle()
        {
            if (HasConsole)
            {
                Hide();
            }
            else
            {
                Show();
            }
        }
    
        static void InvalidateOutAndError()
        {
            Type type = typeof(System.Console);
    
            System.Reflection.FieldInfo _out = type.GetField("_out",
                System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
    
            System.Reflection.FieldInfo _error = type.GetField("_error",
                System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
    
            System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
                System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
    
            Debug.Assert(_out != null);
            Debug.Assert(_error != null);
    
            Debug.Assert(_InitializeStdOutError != null);
    
            _out.SetValue(null, null);
            _error.SetValue(null, null);
    
            _InitializeStdOutError.Invoke(null, new object[] { true });
        }
    
        static void SetOutAndErrorNull()
        {
            Console.SetOut(TextWriter.Null);
            Console.SetError(TextWriter.Null);
        }
    }

    WPF默认的的程序启动入口是在APP类(继承于Application类)中, 通过StartupUri设置启动的窗体类。你可以在重写的OnStartup方法中调用 ConsoleManager.Show()方法来显示控制台。

       public partial class App : Application
        {
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
                {
                    ConsoleManager.Show();
                }
            }
        }

    你也可以自定义应用程序的启动类,在Main方法中调用ConsoleManager.Show()方法来显示控制台。

      public class StartUp
        {
            [STAThread]
            public static void Main(string[] args)
            {
                ConsoleManager.Show();
            }
        }

    注意:此时你需要在项目属性里修改程序的启动对象。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.




    2017年5月11日 2:06
    版主

全部回复

  • 修改Main启动方法

     public partial class App : Application

     {
            private static IKernel _kernel;

            protected override void OnStartup(StartupEventArgs e)
            {          
                base.OnStartup(e);
                base.ShutdownMode = ShutdownMode.OnMainWindowClose;
                //具体来说,就是在这里添加需要使用的方法
            }


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms


    2017年5月11日 0:43
  • Hi,

    请参考下面的代码,下面的类可以让你的WPF程序附加一个控制台.

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Security;
    
    [SuppressUnmanagedCodeSecurity]
    public static class ConsoleManager
    {
        private const string Kernel32_DllName = "kernel32.dll";
    
        [DllImport(Kernel32_DllName)]
        private static extern bool AllocConsole();
    
        [DllImport(Kernel32_DllName)]
        private static extern bool FreeConsole();
    
        [DllImport(Kernel32_DllName)]
        private static extern IntPtr GetConsoleWindow();
    
        [DllImport(Kernel32_DllName)]
        private static extern int GetConsoleOutputCP();
    
        public static bool HasConsole
        {
            get { return GetConsoleWindow() != IntPtr.Zero; }
        }
    
        /// <summary>
        /// Creates a new console instance if the process is not attached to a console already.
        /// </summary>
        public static void Show()
        {
            //#if DEBUG
            if (!HasConsole)
            {
                AllocConsole();
                InvalidateOutAndError();
            }
            //#endif
        }
    
        /// <summary>
        /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
        /// </summary>
        public static void Hide()
        {
            //#if DEBUG
            if (HasConsole)
            {
                SetOutAndErrorNull();
                FreeConsole();
            }
            //#endif
        }
    
        public static void Toggle()
        {
            if (HasConsole)
            {
                Hide();
            }
            else
            {
                Show();
            }
        }
    
        static void InvalidateOutAndError()
        {
            Type type = typeof(System.Console);
    
            System.Reflection.FieldInfo _out = type.GetField("_out",
                System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
    
            System.Reflection.FieldInfo _error = type.GetField("_error",
                System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
    
            System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
                System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
    
            Debug.Assert(_out != null);
            Debug.Assert(_error != null);
    
            Debug.Assert(_InitializeStdOutError != null);
    
            _out.SetValue(null, null);
            _error.SetValue(null, null);
    
            _InitializeStdOutError.Invoke(null, new object[] { true });
        }
    
        static void SetOutAndErrorNull()
        {
            Console.SetOut(TextWriter.Null);
            Console.SetError(TextWriter.Null);
        }
    }

    WPF默认的的程序启动入口是在APP类(继承于Application类)中, 通过StartupUri设置启动的窗体类。你可以在重写的OnStartup方法中调用 ConsoleManager.Show()方法来显示控制台。

       public partial class App : Application
        {
            protected override void OnStartup(StartupEventArgs e)
            {
                base.OnStartup(e);
                {
                    ConsoleManager.Show();
                }
            }
        }

    你也可以自定义应用程序的启动类,在Main方法中调用ConsoleManager.Show()方法来显示控制台。

      public class StartUp
        {
            [STAThread]
            public static void Main(string[] args)
            {
                ConsoleManager.Show();
            }
        }

    注意:此时你需要在项目属性里修改程序的启动对象。

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.




    2017年5月11日 2:06
    版主