Bigdra.Log

備忘録

Windowsの常駐アプリを作る

経緯

この記事でWindowsの常駐アプリが必要になったので、 作り方を調べてみます。

https://bigdra50.hatenablog.com/entry/2020/12/27/085509

本題

準備

WinFormアプリとして以下のような設定でプロジェクトを作成します。

タスクトレイに表示するアイコンが必要です。
icoファイルを用意し、 ソリュージョンエクスプローラーから用意したicoファイルを右クリック→プロパティ→Copy if newerとして、ビルド時に出力先のディレクトリへコピーされるようにしておきます。

常駐させる

NotifyIconクラスで通知領域へアイコンを作成します。

using System;
using System.Windows.Forms;

namespace WinFormsApp1
{
    static class Program
    {
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var taskTray = new TaskTray();
            Application.Run();
        }
    }
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WinFormsApp1
{
    public class TaskTray
    {
        private NotifyIcon _notifyIcon;

        public TaskTray()
        {
            Initialize();
        }

        private void Initialize()
        {
            _notifyIcon = new NotifyIcon {Icon = new Icon(@"./favicon.ico"), Visible = true, Text = "NotifyIcon"};

            var contextMenuStrip = new ContextMenuStrip();
            contextMenuStrip.Items.AddRange(new ToolStripItem[]
            {
                new ToolStripMenuItem("&Exit", null, (_, _) => Exit(), "Exit")
            });
            _notifyIcon.ContextMenuStrip = contextMenuStrip;
        }

        private void Exit()
        {
            var e = new CancelEventArgs();
            Application.Exit(e);
            if (e.Cancel)
            {
                Console.WriteLine("Application.Exit is canceled!");
            }
        }
    }
}

Windows起動時にアプリを自動で起動させる

「スタートアップ」フォルダの中にexeのショートカットを作成します。

private static void CreateShortcut()
{
    // Application.ExecutablePathがなぜかdotnet.exeのパスを返すから, 代わりにdllのパスを取得してexeに変更する
    var path = Assembly.GetEntryAssembly()?.Location;
    if (path == null) return;
    var exePath =
        Path.ChangeExtension(Path.Combine(Application.StartupPath, Path.GetFileName(path)), "exe");
    var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup),
        $"{Path.GetFileNameWithoutExtension(path)}.lnk");

    // WshShellを作成
    var type = Type.GetTypeFromCLSID(new Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8"));
    dynamic shell = Activator.CreateInstance(type);

    //WshShortcutを作成
    var shortcut = shell.CreateShortcut(shortcutPath);

    shortcut.TargetPath = exePath;
    shortcut.WorkingDirectory = Application.StartupPath;
    shortcut.Description = $"場所: {exePath}";
    shortcut.IconLocation = $@"{Application.StartupPath}/favicon.ico";
    shortcut.Save();

    //後始末
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shortcut);
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shell);
}

参考

C#のタスクトレイ常駐アプリの作り方のご紹介!
C# - Windows常駐アプリ(タスクトレイ) - Form表示なし
OS起動時にプログラムを自動的に実行する OS起動時に一回だけプログラムを自動的に実行する
C# ショートカットを作成する