【问题标题】:How to find cmd.exe process id from which app is started?如何查找从哪个应用程序启动的 cmd.exe 进程 ID?
【发布时间】:2010-04-22 12:55:28
【问题描述】:

我有简单的 win 应用程序(使用 .net C# 编写),需要从 cmd.exe 启动,然后写入该控制台,但问题是我需要该 cmd.exe 进程的进程 ID。我可以得到所有正在运行的进程,

Process[] procList = Process.GetProcessesByName("cmd");

但是如何找到我的? :)

也许是读取输入,并检查里面是否写了“ApplicationName.exe”,或者获取当前处于活动状态的 cmd.exe 窗口?但是有什么功能呢?

【问题讨论】:

  • 为什么 Windows 应用程序需要写回某个控制台窗口?为什么不让 Windows 应用程序弹出一个非模态表单并将输出放在那里?你怎么能保证 Windows 应用程序甚至是从 cmd.exe 窗口启动的?
  • 阅读我的第二个答案。我的程序是命令行,但问题是使用“-off”参数我需要隐藏 cmd,然后应用程序在没有命令行窗口的情况下运行。但问题是当我使用 PInvoke ShowWindow 隐藏 cmd 时,窗口会闪烁,我讨厌这样:)。如果我将 cmd 编译为 Windows 应用程序,那么我可以在需要时分配新的 cmd。但问题是即使我从 cmd.exe 运行我的应用程序,它也会分配新的 cmd...
  • Tnx 你 RaphaelSP,我在这里找到了例子codeproject.com/KB/cs/ParentProcWindow.aspx

标签: c# process cmd


【解决方案1】:

即使你找到“你的”cmd,你打算怎么写进去?

有更好的方法来实现您所描述的。只需将您的项目编译为“控制台应用程序”,但无论如何都要让它创建一个 WinForms 窗口。是的,这是可能的,没有什么能阻止你。然后您就可以使用 System.Console 类写入控制台,无需任何魔法。

【讨论】:

    【解决方案2】:

    以下代码创建 WQL 事件查询来检测新进程,等待新进程启动,然后显示有关该进程的信息:

    WqlEventQuery query = new WqlEventQuery("__InstanceCreationEvent", new TimeSpan(0, 0, 1), "TargetInstance isa \"Win32_Process\"");
    ManagementEventWatcher watcher = new ManagementEventWatcher(query);
    ManagementBaseObject e = watcher.WaitForNextEvent();
    Console.WriteLine("Process {0} has been created, path is: {1}", 
    ((ManagementBaseObject)e["TargetInstance"])["Name"],
    ((ManagementBaseObject)e["TargetInstance"])["ExecutablePath"]);
    watcher.Stop();
    

    我认为您可以通过检查此 WMI 代码示例找到解决问题的方法。希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      将此函数添加到您的项目中的某个类中: (需要一个using System.Runtime.InteropServices; 在类的顶部)

          [DllImport("kernel32.dll")]
          private static extern bool AttachConsole(int dwProcessId);
          [DllImport("kernel32.dll")]
          private static extern bool FreeConsole();
      

      然后拨打AttachConsole(-1) 现在您可以像往常一样使用 System.Console 类来写入控制台并设置颜色等等。 如果您不再需要写入控制台,请调用FreeConsole() 将您的进程与其分离。

      请注意,这实际上并不会阻止控制台处理进一步的命令。用户仍然可以随时在控制台中输入任何内容。

      推荐方式如下:

      1. 创建控制台应用程序
      2. 想写什么就写什么。
      3. 如果您不再需要它,请致电FreeConsole()
      4. 使用Application.Run() 打开您的表单。不使用 application.Run 并且只显示表单不会创建正确的消息循环,并且可能会发生奇怪的事情。

      你可以切换3和4,但是一旦你调用Application.Run方法,代码将不会继续,直到窗体关闭。因此,要么在表单中写入控制台并从那里释放它,要么在单独的线程中生成表单(这会产生其他意想不到的副作用)

      您可以向 AttachConsole 函数提供任何进程 ID。 -1 默认为父进程,这很可能是您想要的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多