C# 程序通过匿名管道控制exe控制台程序 输入输出流重定向 WPF向控制台程序传递参数出现“句柄无效”问题

4 篇文章 0 订阅

在做WPF桌面端软件的时候需要调用别人的exe控制台程序,单独运行exe需要手动输入参数,并进行一些参数选择,要控制exe程序就需要用到匿名管道。
主要步骤:
1.启动控制台exe的Process对象
2.输入输出流重定向,获取exe的输入输出流,然后就可以进行输入了(相当于手动打开exe手动输入);
3.如果exe控制台程序需要接收某个按键消息,需要引用系统”user32.dll”调用系统API函数,获取exe窗口指针进行按键信息传递。

 [DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
        public static extern int PostMessage(IntPtr hWnd, int Msg, System.Windows.Forms.Keys wParam, int lParam);//传递按键消息
        private bool ConvertIMRFile(string imrPath, string outputPath)
        {
            if (!File.Exists(imrPath))
            {
                throw new Exception("File does not exist!");
            }
            if (runCount == 0)
            {
                ConsoleManager.Show(); // 分配控制台  这里主要是针对WPF程序,调用控制台程序需要进行控制台分配 
                handle = Process.GetCurrentProcess().MainWindowHandle;
                //ConsoleManager.ShowWindowAsync(handle, 0);
                runCount++;
            }
            long filesize = new FileInfo(imrPath).Length;
            int sec = (int)filesize / 500;
            ProcessStartInfo info = new ProcessStartInfo(systemPath + "Command/ReadWPG.exe");//控制台exe信息
            info.UseShellExecute = false;
            info.RedirectStandardInput = true;//输入流重定向为true
            info.WindowStyle = ProcessWindowStyle.Hidden;//隐藏窗口
            Process process = new Process();
            process.StartInfo = info;
            process.Start();

            StreamWriter writer = process.StandardInput;//获取输入流

            writer.WriteLine(imrPath);//输入字符串
            Thread.Sleep(1000);//连续输入尽量让线程停顿几秒,模拟人为输入间隔
            writer.WriteLine("*");
            PostMessage(handle, 256, System.Windows.Forms.Keys.S, 1);//输入按键消息S
            PostMessage(handle, 256, System.Windows.Forms.Keys.F, 1);
            writer.WriteLine(outputPath);
            Thread.Sleep(sec);

            PostMessage(handle, 256, System.Windows.Forms.Keys.Q, 1);
            Thread.Sleep(1000);
            writer.WriteLine("*");
            process.Kill();//程序终止
            process.Close();
            return true;
        }

WPF 程序调用exe控制台程序,执行过程中传递参数需要进行控制台管理,直接传递可能会出现“句柄无效” 的问题。

/// <summary>
    /// 控制台管理
    /// </summary>
    [SuppressUnmanagedCodeSecurity]
    public static class ConsoleManager
    {
        private const string Kernel32_DllName = "kernel32.dll";

        [DllImport(Kernel32_DllName)]
        private static extern bool AllocConsole();

        [DllImport(Kernel32_DllName)]
        public static extern bool FreeConsole();

        [DllImport(Kernel32_DllName)]
        private static extern IntPtr GetConsoleWindow();

        [DllImport(Kernel32_DllName)]
        private static extern int GetConsoleOutputCP();

        [DllImport("user32.dll")]
        public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        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);
        }
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值