【问题标题】:How to pass arguments to a console application if it is already running?如果控制台应用程序已经在运行,如何将参数传递给它?
【发布时间】:2010-07-15 15:47:52
【问题描述】:

我在 Windows Mobile 中使用控制台应用程序来处理传入消息拦截。在同一个控制台应用程序中,我接受基于参数的参数(字符串 args[]),注册消息拦截器。

InterceptorType 是一个枚举

static void Main(string[] args)
        {                 

            if (args[0] == "Location")
            {               

                addInterception(InterceptorType.Location, args[1],args[2]);
            } 

        }


private static void addInterception(InterceptorType type, string Location, string Number )
    {

        if (type == InterceptorType.Location)
        {

           using (MessageInterceptor interceptor = new MessageInterceptor(InterceptionAction.NotifyAndDelete, false))
           {

               interceptor.MessageCondition = new MessageCondition(MessageProperty.Sender, MessagePropertyComparisonType.Contains, Number, false);

               string myAppPath = Assembly.GetExecutingAssembly().GetName().CodeBase;

               interceptor.EnableApplicationLauncher("Location", myAppPath);

               interceptor.MessageReceived += new MessageInterceptorEventHandler(interceptor_MessageReceived);


           }


        }


    }


static void interceptor_MessageReceived(object sender, MessageInterceptorEventArgs e)
    {

        //Do something



    }

我将此作为控制台应用程序,因为我希望它继续在后台运行并拦截传入的消息。

这是第一次正常工作。但问题是我必须不断调用addInterception方法来添加后续的拦截规则。这使得控制台应用程序在我每次添加规则时一次又一次地启动。如何让它只运行一次并添加更多消息拦截器规则?

【问题讨论】:

    标签: c# windows-mobile message interceptor single-instance


    【解决方案1】:

    由于您已经有了调用命令提示符一次的方法,因此可以通过一些简单的循环来更新您的逻辑,以便您可以传递 N 个命令。

    编辑:我写了一个完全可编译的例子来告诉你我在说什么。请注意如何在不重新启动的情况下多次调用子进程。这不仅仅是一个传递参数的简单命令行启动,因为这个想法会导致 X 进程,这正是你不想要的。

    父进程:(带有 System.Diagnostics.Process 的那个)

    /// <summary>
        /// This is the calling application.  The one where u currently have System.Diagnostics.Process
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                System.Diagnostics.Process p = new Process();
                p.StartInfo.CreateNoWindow = false;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.FileName = @"C:\AppfolderThing\ConsoleApplication1.exe";
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.RedirectStandardInput = true;
                p.StartInfo.RedirectStandardOutput = true;
    
    
                p.Start();            
                p.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e)
                {
                    Console.WriteLine("Output received from application: {0}", e.Data);
                };
                p.ErrorDataReceived += delegate(object sender, DataReceivedEventArgs e)
                {
                    Console.WriteLine("Output received from application: {0}", e.Data);
                };
                p.BeginErrorReadLine();
                p.BeginOutputReadLine();
                StreamWriter inputStream = p.StandardInput;
                inputStream.WriteLine(1);
                inputStream.WriteLine(2);
                inputStream.WriteLine(-1);//tell it to exit
                p.WaitForExit();
            }
    
        }
    

    子进程:

        using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication3
    {
        enum InterceptorType
        {
            foo,
            bar,
            zee,
            brah
        } 
        /// <summary>
        /// This is the child process called by System.Diagnostics.Process
        /// </summary>
        class Program
        {
            public static void Main()
            {
                while (true)
                {
                    int command = int.Parse(Console.ReadLine());
                    if (command == -1)
                        Environment.Exit(0);
                    else
                        addInterception((InterceptorType)command, "some location", "0");
                }
            }
            private static void addInterception(InterceptorType type, string Location, string Number)
            {
                switch (type)
                {
                    case InterceptorType.foo: Console.WriteLine("bind foo"); break;
                    case InterceptorType.bar: Console.WriteLine("bind bar"); break;
                    default: Console.WriteLine("default bind zee"); break;
                }
    
            }
    
    
            static void interceptor_MessageReceived(object sender, EventArgs e)
            {
                //Do something  
            }  
        }
    }
    

    请注意,codeplex 有一个 managed service library

    【讨论】:

    • 请您解释一下 while(true) 循环中发生了什么。这不是无限循环吗?
    • 循环一直运行,直到您将退出代码传递给它。您可以突破并陷入其他逻辑。鉴于我不知道您的应用程序所做的一切,这只是对可能发生的事情的演示;另请注意服务库。您也可以查看异步线程,具体取决于您的要求。只要确保主线程在你想要的时候不会失败并死掉。
    • 这如何防止他遇到的多进程问题?
    • “既然你已经有了一个方法来调用命令提示符一次”
    • 我正在使用 System.Diagnostics.Process.Start() 方法来启动应用程序。
    【解决方案2】:

    编辑

    似乎人们误解了你的问题(或者我是),所以这里澄清一下我是如何看待这个问题的。

    您有一个接受命令行参数的控制台应用程序。这些参数用于某些事情(实际上无关紧要的事情)。您希望能够在应用已经运行后通过使用新的命令行参数调用应用来添加参数。

    发生的情况是,当您在第一次之后的任何时间调用应用程序时,会启动一个新的进程实例,而不是将命令行参数传递给现有的、已经运行的应用程序。

    结束编辑

    解决方案相当简单,需要两部分。

    1. 你需要一个命名互斥体。无论出于何种(糟糕的)原因,CF 都不会公开带有名称的互斥锁版本,因此您必须 P/Invoke CreateMutex 或使用已经拥有它的库(如 SDF)。您的应用程序需要在启动时创建互斥锁并检查它是否已经存在。如果不是,您是第一个运行的实例并正常运行。如果互斥体存在,您需要将命令行参数传递给已经通过P2P queue 运行的那个,然后直接退出。

    2. 检查互斥体后,第一个实例会生成一个工作线程。该线程在 P2P 队列上侦听消息。当他们进来时,你处理他们。

    【讨论】:

    • 是的。你猜对了。我实际上想调用addInterception 函数来注册另一个消息拦截器事件,而无需启动控制台应用程序的另一个实例。
    • 编辑错误:他只需要重新使用流程实例并覆盖流,而不是每次都创建一个新流程。将此与某种循环逻辑和 wala 结合起来,不再需要多进程来挂钩新事件。
    猜你喜欢
    • 2015-02-12
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 2011-09-03
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 2011-05-31
    相关资源
    最近更新 更多