.netフォーム常駐アプリ(シャットダウンタイマー)


ソフトの説明

常駐アプリってどうやって作るのかなといろいろ調べておりましたら.net環境になりいろいろと代わってきましたので節電もかねてシャットダウンタイマーを作ってみました。 Windowsのサスペンドで不具合がでてしまう方などお使い頂ければさいわいです。動画サイトを見ながら寝てしまってもマウスのみを監視し一定時間動かなかったらシャットダウンします。


プログラムの説明やフレームワーク4.8から.netアプリに対応させた個所

1,常駐アプリですので最小化した状態で起動します。
2,起動時設定ファイルをなければ初期設定でxmlファイルをつくります。あればxmlファイルを読み込みます。※.netよりxml作成もずいぶん楽になりました。旧作成方法はコメントアウトしております。
3,参考にした常駐アプリがC#でしたので.netむけにTaskAwaitをつかい非同期メソッドにしてみました。
4,トラックバーを使ってみたのですが選択時,黒線が気になったので出ないようにしました。


シャットダウンタイマー

フォームではラベル7つとボタン1つタイトルを配置しました。

シャットダウンタイマー

program.cs

                using System;
                using System.Collections.Generic;
                using System.Linq;
                using System.Threading.Tasks;
                using System.Windows.Forms;

                namespace CloseWindows
                {
                static class Program
                {
                /// 
                    ///  The main entry point for the application.
                    ///
                
                [STAThread]
                static void Main()
                {
                Application.SetHighDpiMode(HighDpiMode.SystemAware);
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
                // Formを表示しないで実行
                new Form1();
                Application.Run();
                }
                }
                }
                

form.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;

namespace CloseWindows
{

    public partial class Form1 : Form
    {
        NotifyIcon notifyIcon;
        private TracBarTest tbt;
        //Settings appSettings = new Settings();

        bool isCancel;
        Task _task;
        int TBval;

        public Form1()
        {
            InitializeComponent();
            this.FormClosing += Form1_FormClosing;
            this.Resize += new System.EventHandler(this.Form1_ResizeEnd);
        }

        private void  Form1_Load(object sender, EventArgs e)
        {
            // タスクバーに表示しない
            this.MaximizeBox = false;
            this.Visible = false;
            this.ShowInTaskbar = false;

            //実行ファイルのフルパス
            String _location = System.Reflection.Assembly.GetEntryAssembly().Location;
            //実行ファイルディレクトリ
            String ExePath = Path.GetDirectoryName(_location);
            ExePath = ExePath + "\\setting.config";
            string fileName = @ExePath;

            //ファイルがあるかどうか あればxml読み込み数値を設定、なければXMLを作る。
            if (System.IO.File.Exists(ExePath))
            {
                //System.Xml.Linq.XDocument doc 
                //    = System.Xml.Linq.XDocument.Load(ExePath);
                //IEnumerable infos 
                //    = from item in doc.Elements("Settings")select item;
                //foreach (XElement info in infos)
                //{
                    //MessageBox.Show($"値:{info.Element("Number").Value}");
                //    TBval = int.Parse(info.Element("Number").Value);
                //}

                //1段しかないXMLは下記でデータ取得でもOK
                XDocument document = new XDocument();
                document.Declaration = new XDeclaration("1.0", "utf-8", "");
                document = XDocument.Load(fileName);
                XElement settings = document.Element("Settings");
                string Number = settings.Element("Number").Value;
                TBval = int.Parse(Number);


            }
            else
            {
                //<XMLファイルに書き込む>
                //XmlSerializerオブジェクトを作成
                //書き込むオブジェクトの型を指定する
                //System.Xml.Serialization.XmlSerializer serializer1 =
                //    new System.Xml.Serialization.XmlSerializer(typeof(Settings));
                //ファイルを開く(UTF-8 BOM無し)
                //System.IO.StreamWriter sw = new System.IO.StreamWriter(
                //    fileName, false, new System.Text.UTF8Encoding(false));
                //シリアル化し、XMLファイルに保存する
                //serializer1.Serialize(sw, appSettings);
                //閉じる
                //sw.Close();

                XDocument xdoc = new XDocument(new XElement("Settings"
                                                , new XElement("Text", "text")
                                                , new XElement("Number", "30")));

                // ファイルに保存する。
                xdoc.Save(@ExePath);

                TBval = 30;
            }

            this.setComponents(TBval);


            //trackbar border枠よけだがTrackBarをカスタマイズしたのでいらない
            //label1.Select();

            _task = Task.Run(async () =>
            {
            while (true) // キャンセルフラグが立ったら例外を投げる(例外投げるのはTaskのお約束
                {
                    SetText();
                    if (isCancel) throw new OperationCanceledException("canceled");
                    //Thread.Sleep(60000/*sec*/);
                    await Task.Delay(60000);
                }
            }); // 例外はハンドルしない
        }

        private void setComponents(int xval)
        {
            this.Text = string.Format("{0}分マウスが動かなかったらシャットダウン", xval);
            label6.Text = string.Format("{0}", xval);

            //button1.Visible = false;
            button1.Enabled = false;

            //トラックバーフォーカス時に黒い枠線ができるので枠削除カスタマイズ
            tbt = new TracBarTest();
            this.tbt.Location = new System.Drawing.Point(150, 33);
            this.tbt.Maximum = 90;
            this.tbt.Minimum = 3;
            this.tbt.Name = "Tbt";
            this.tbt.Size = new System.Drawing.Size(240, 45);
            this.tbt.SmallChange = 5;
            this.tbt.TabIndex = 5;
            this.tbt.TickFrequency = 5;
            this.tbt.Value = xval;
            this.tbt.ValueChanged += new System.EventHandler(TrackBar1_ValueChanged);
            this.Controls.Add(tbt);

            notifyIcon = new NotifyIcon();
            notifyIcon.Icon = new Icon("wt.ico");
            notifyIcon.Visible = true;
            notifyIcon.Text = string.Format("{0} / {1}", SamePC, tbt.Value);

            ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
            ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
            toolStripMenuItem.Text = "&終了";
            toolStripMenuItem.Click += ToolStripMenuItem_Click;
            contextMenuStrip.Items.Add(toolStripMenuItem);
            notifyIcon.ContextMenuStrip = contextMenuStrip;

            // NotifyIconのクリックイベント
            notifyIcon.Click += NotifyIcon_Click;
        }

        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                //フォームを非表示にする
                this.Visible = false;
                this.WindowState = FormWindowState.Normal;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            isCancel = true;
            this.Visible = true;
            Application.ExitThread();
            notifyIcon.Dispose();
            Application.Exit();
        }

        private void ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            isCancel = true;
            Application.ExitThread();
            this.Visible = true;
            notifyIcon.Dispose();
            Application.Exit();
        }

        private void NotifyIcon_Click(object sender, EventArgs e)
        {
            // Formの表示/非表示を反転 Falseの時にNomalが効かないのでVisible後Normal
            this.Visible = !this.Visible;
            this.WindowState = FormWindowState.Normal;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process ShutDownProc
                = new System.Diagnostics.Process();

            ShutDownProc.StartInfo.FileName = "shutdown.exe";
            ShutDownProc.StartInfo.Arguments = "/a";
            ShutDownProc.Start();

            SamePC = 0;
            label5.Text = string.Format("{0}", SamePC);
            //button1.Visible = false;
            button1.Enabled = false;

        }


        public delegate void SetTextDelegate();
        int SamePC = 0;

        public void SetText()
        {
            if (InvokeRequired)
            {
                //別スレッドからUIを操作する。
                Invoke(new SetTextDelegate(SetText));
                return;
            }
            //this.Text = "x = " + Cursor.Position.X + " : y = " + Cursor.Position.Y;

            if (label2.Text == string.Format("{0}", Cursor.Position.X) && label3.Text == string.Format("{0}", Cursor.Position.Y))
            {
                SamePC++;
                label5.Text = string.Format("{0}", SamePC);
            }

            if (label2.Text != string.Format("{0}", Cursor.Position.X) && label3.Text != string.Format("{0}", Cursor.Position.Y))
            {
                SamePC = 0;
                label5.Text = string.Format("{0}", SamePC);
            }

            if (SamePC == TBval-2)
            {

                //button1.Visible = true;
                button1.Enabled = true;
                this.Visible = true;
                this.Activate();
                this.TopMost = true;
                this.WindowState = FormWindowState.Normal;


                System.Diagnostics.Process ShutDownProc = new System.Diagnostics.Process();
                ShutDownProc.StartInfo.FileName = "shutdown.exe";
                ShutDownProc.StartInfo.Arguments = "/s /t 120";
                ShutDownProc.Start();

            }


            //アプリ終了
            //if (SamePC == TBval - 1)
            //{
            //    isCancel = true;
            //    Application.ExitThread();
            //    this.Visible = true;
            //    notifyIcon.Dispose();
            //    Application.Exit();
            //}


            label2.Text = string.Format("{0}", Cursor.Position.X);
            label3.Text = string.Format("{0}", Cursor.Position.Y);
        }

        private void TrackBar1_ValueChanged(object sender, EventArgs e)
        {
            TBval = tbt.Value;
            this.TopMost = !this.TopMost;
            this.Text = string.Format("{0}分マウスが動かなかったらシャットダウン", TBval);
            label6.Text = string.Format("{0}", TBval);
            notifyIcon.Text = string.Format("{0} / {1}", SamePC, tbt.Value);

            //実行ファイルのフルパス
            String _location = System.Reflection.Assembly.GetEntryAssembly().Location;
            //実行ファイルディレクトリ
            String ExePath = Path.GetDirectoryName(_location);
            ExePath = ExePath + "\\setting.config";


            //xmlファイルを指定する
            XElement xml = XElement.Load(@ExePath);

            System.Xml.Linq.XDocument doc = System.Xml.Linq.XDocument.Load(ExePath);
            IEnumerable infos = from item in doc.Elements("Settings") select item;
            foreach (XElement info in infos)
            {
                info.Element("Number").Value = string.Format("{0}", TBval);
            }

            //変更を保存する
            doc.Save(@ExePath);
        }

        internal class TracBarTest : TrackBar
        {
            protected override void WndProc(ref Message m)
            {
                // フォーカスを定義します。
                const int WM_SETFOCUS = 0x0007;
                switch (m.Msg)
                {
                    case WM_SETFOCUS:
                        return;
                }
                base.WndProc(ref m);
            }
        }
        //public class Settings
        //{
        //    private string _text;
        //    private int _number;

        //    public string Text
        //    {
        //        get { return _text; }
        //        set { _text = value; }
        //    }
        //    public int Number
        //    {
        //        get { return _number; }
        //        set { _number = value; }
        //    }

        //    public Settings()
        //    {
        //        _text = "Text";
        //        _number = 30;
        //    }
        //}
    }
}

参考リンク Spcial thanks

.NET COLUM様
logo