【问题标题】:Starting a Windows application in the background在后台启动 Windows 应用程序
【发布时间】:2011-10-24 06:35:48
【问题描述】:

我有一个使用 winforms 用 C# 编写的 Windows 应用程序。我想确保每当有人使用 process.start 从任何其他应用程序启动它时,UI 都不会显示,并且应用程序应该静默启动。

我无法控制其他应用程序,因此无法使用:

var p = new Process();
p.StartInfo = new ProcessStartInfo(); 
p.StartInfo.UseShellExecute = true; 
p.StartInfo.WorkingDirectory = ConfigurationManager.AppSettings["exeFolder"].ToString(); p.StartInfo.WindowStyle = ProcessWindowStyle.Normal; 
p.StartInfo.FileName = ConfigurationManager.AppSettings["exeName"].ToString(); 
p.Start();

【问题讨论】:

  • Windows 服务很有用

标签: .net c# winforms


【解决方案1】:

感谢您的回复。很抱歉没有早点提供我的解决方案。我已经解决了这个问题,并将解决方案记录在案以供其他人将来使用。

您可以找到解决方案here

如何 · 创建一个新的windows项目并删除默认窗体(Form1)。 · 在 Program.cs 中创建一个新类并从 Form 继承它。 · 请参考下面的代码。 · 现在更改 Main 方法。在 Application.Run 中,将启动对象从 Form1 更改为 ApplicationStartUp。

using System;
using System.Drawing;
using System.Windows.Forms;
using BackgroundApp.Properties;

namespace BackgroundApp
{
    static class Program
    {
        /// <summary>


   /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new ApplicationStartUp());
    }
}

public class ApplicationStartUp : Form
{
    private NotifyIcon trayIcon;
    private ContextMenu trayMenu;

    private void InitializeComponent()
    {
        trayMenu = new ContextMenu();
        trayMenu.MenuItems.Add("Exit", OnExit);
        trayIcon = new NotifyIcon();
        trayIcon.Text = Resources.TrayIcon;
        trayIcon.Icon = new                            Icon(global::BackgroundApp.Properties.Resources.IntegratedServer, 40, 40);
        trayIcon.ContextMenu = trayMenu;
        trayIcon.Visible = true;
    }

    //Ctor
    public ApplicationStartUp()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        Visible = false;
        ShowInTaskbar = false;
        base.OnLoad(e);
    }

    private void OnExit(object sender, EventArgs e)
    {
        // Release the icon resource.
        trayIcon.Dispose();
        Application.Exit();
    }

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            // Release the icon resource.
            trayIcon.Dispose();
        }
        base.Dispose(isDisposing);
    }
}

【讨论】:

    【解决方案2】:

    大多数时候,当一个应用程序从另一个应用程序启动时,它是在没有参数的情况下启动的。

    因此,您可以让您的应用程序检查起始参数。如果没有参数,则在隐藏窗口的情况下启动它。如果有参数,请在窗口可见的情况下启动应用程序。

    您必须将 Program.cs 文件中的 main 方法修改为如下所示:

    using System.Diagnostics;
    
    static class Program
    {
        // get the current process
        var thisProc = Process.GetCurrentProcess();
        // file name of this process
        var procFileName = new System.IO.FileInfo(thisProc.MainModule.FileName).Name;
    
        // look for all with the same file name as this one.
        foreach (var proc in Process.GetProcessesByName(
                             procFileName.Substring(0, procFileName.LastIndexOf('.'))))
        {
            // if there is another process with the same file name and a different id
            // it means there is a previous instance of the application running
            if (proc.MainModule.FileName == thisProc.MainModule.FileName &&
                proc.Id != thisProc.Id)
            {
                MessageBox.Show("An instance of this application is already running.");
                return; // stop running this instance
            }
        }
    
        static internal bool useGui;
    
        /// <summary>The main entry point for the application.</summary>
        [STAThread]
        static void Main(string[] args)
        {
            useGui = (from arg in args where arg.ToLower() == "/gui").Any();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    

    然后在Form1.Show 的事件处理程序中通过读取useGui 变量的值来使表单可见或不可见。

    private void Form1_Show(object sender, EventArgs e)
    {
        this.Visible = Program.useGui;
    }
    

     

    编辑

    Form.Load 事件中设置表单的Visible 属性不会隐藏它。您应该像更新后的代码一样在Form.Shown 事件处理程序中设置它。

    如果您打算为应用程序提供此功能,您应该考虑以下几点。

    1. “正常”启动应用程序会导致它闪烁并被隐藏。这可能会使用户在不知情的情况下多次启动应用程序。因此建议检查程序的副本是否已经在 Program.Main 方法中运行。
    2. 应用程序在运行时将被隐藏。因此,如果您在它完成所有操作后没有输入代码来关闭它,用户将不得不终止该进程才能终止它。

     

    编辑 2
    更新了 class Program 的代码并修复了问题 #1。

    【讨论】:

      【解决方案3】:

      您的应用程序是否必须有一个 GUI?

      如果没有,您可以在没有人的情况下重新编写它。如果您随后需要配置 GUI,您可以编写第二个应用程序连接到第一个应用程序来配置它。

      【讨论】:

      • 实际上我无法创建 Windows 服务,我需要我的应用程序继续运行,这就是我选择 gui 应用程序的原因。我还需要这个应用程序能够通过消息框和气球显示消息,因此我正在创建 winform 应用程序。
      【解决方案4】:

      您可以为您的应用程序添加参数。启动你的应用程序的另一个应用程序可以传入一个参数,例如/noui。或者您可以默认为无 gui 并使用诸如 /ui 之类的参数以 gui 开头。由于您无法控制调用应用程序,因此您可能会选择第二种选择。

      【讨论】:

      • 我很好,没有默认的 ui 并且始终如此。但是我应该如何在 c# 中实现这一点。
      • 我根本不会启动主 UI 表单。而是使用其他一些包含您的主要行为的控制类,并在您的主要表单中使用相同的类。所以你在你的static void Main() 中分支:if (useGui) { ... show main form... } else { new ControllingClass().Run(); }
      【解决方案5】:

      所以,如果您没有 UI,那么无论如何您都已经完成了一些处理,并且当发生适当的事件时,启动部分 UI(您说的是消息框)。

      我的建议是从 program.cs 的Main() 触发一个线程 - 并在该线程中进行处理。稍后,当您需要显示某些内容时,您将使用 MessageBox.Show 这样简单的代码来显示它 - 因为您的新线程将有自己的消息循环。

      不要尝试在主窗体中设置visible=false,因为有时会出现闪烁。

      【讨论】:

        猜你喜欢
        • 2018-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-30
        • 1970-01-01
        • 1970-01-01
        • 2023-04-08
        相关资源
        最近更新 更多