C# WPF 项目中无法使用Console输出时出现句柄无效的IO异常解决方法

来源:互联网 发布:方舟史上最强优化 编辑:程序博客网 时间:2024/05/19 23:01

如以下代码,重点看:ConsoleManager.Show()的位置注释即可;


using System;using System.Collections.Generic;using System.Windows;using System.IO;using System.Security;using System.Runtime.InteropServices;using System.Diagnostics;namespace GameLanguagePicker{    /// <summary>    /// 该类源于Stackoverflow 的一问题贴的回答:    /// 问题:No output to console from a WPF application?    /// 地址:http://stackoverflow.com/questions/160587/no-output-to-console-from-a-wpf-application/718505    /// </summary>    [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);        }    }    /// <summary>    /// @author Jave.Lin    /// @date 2014-1-9    /// </summary>    public class Programs    {        [STAThread]        public static void Main(string[] args)        {            try            {                var listArgs = new List<string>(args);                //listArgs.Add("-h");                listArgs.Add("-p");                listArgs.Add(@"E:\myWork");                if (listArgs.Count == 0 || !listArgs.Contains("-h")) // 可视化操作                {                    var win = new MainWindow();//你要启动的Window类;就是你继承自Window类的类,并加载了一些.xaml(不加也可以)的窗体类;                    Application app = new Application();//自己去new一个,或使用当前这个App也可以(它也是继承Application)                    app.MainWindow = win;                    //来种方式启动;                    //第一种:                    //wb.Show();                    //app.Run();//以MainWindow作为启动窗体                    //第二种                    var pIdx = listArgs.IndexOf("-p");                    if (pIdx != -1)                    {                        win.pathTextBox.Text = win.Picker.Path = listArgs[pIdx + 1];                        win.Start();                    }                    app.Run(win);//以指定的Window来启动                }                else // 控制台式操作                {                    // 如果这里不申请控制台,后台,所有用到:Console的API都会报:句柄无效的IO异常;                    // 可能是WPF 项目配置,还是其它的,在启动时,将Console指定了输出流吧;这个希望有知道的朋友可以告知一下                    ConsoleManager.Show();                    if (listArgs.Contains("-?") || (listArgs.Count > 1 && listArgs[0].ToLower() == "help") || !listArgs.Contains("-h") || !listArgs.Contains("-p"))                    {                        ShowUsage();                        Console.ReadLine();                    }                    else                    {                        var picker = new Picker();                        var left = Console.CursorLeft;                        var top = Console.CursorTop;                        var pIdx = listArgs.IndexOf("-p");                        picker.Path = listArgs[pIdx + 1];                        picker.Start((value, max) =>                         {                            // progress                            Console.SetCursorPosition(left, top);                            Console.WriteLine(string.Format("提取进度:{0} / {1}", value, max));                        }, () =>                         {                            // complete                            //Console.SetCursorPosition(left, top);                            Console.WriteLine(string.Format("提取完成:{0}, 耗时:{1}", picker.FileCount, picker.ElapsedTime));                            Console.ReadLine();                        }, (er) =>                         {                            // error                            throw er;                        });                    }                }                //Console.SetCursorPosition                Console.ReadLine();                //Console.ReadKey();            }            catch (Exception er)            {                Console.WriteLine("Exception!");                Console.WriteLine(er.ToString());            }        }        private static void ShowUsage()        {            Console.WriteLine("usage : GameLanguagePicker.exe [-options]");            Console.WriteLine("-options:");            Console.WriteLine("\t[-h]\t加-h说明:控制台方式操作,否则为:可视化窗口操作;不加则默认是:可视化窗口操作");            Console.WriteLine("\t[-p pathValue]\t指定要提取的路径,-p pathValue必须成对出现");            //Console.ReadLine();        }    }}


1 0