// Program.cs ------ 程序入口
// 目标框架:.NET Framework 4.8 / C# 5
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace MonitorGuard
{
internal static class Program
{
/// <summary>数据目录:优先 exe 所在目录,不可写则退回 %LOCALAPPDATA%\MonitorGuard。</summary>
public static string ResolveDataDir()
{
string exeDir = "";
try { exeDir = Path.GetDirectoryName(Application.ExecutablePath); }
catch { }
if (!string.IsNullOrEmpty(exeDir))
{
try
{
string probe = Path.Combine(exeDir, ".mg_write_test");
File.WriteAllText(probe, "ok");
File.Delete(probe);
return exeDir;
}
catch { }
}
string fallback = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), TrayContext.AppName);
try { Directory.CreateDirectory(fallback); }
catch { }
return fallback;
}
[STAThread]
private static void Main(string[] args)
{
// ---- 自检模式:扫描一次并输出报告,不驻留后台 ----
if (args.Length > 0)
{
string a = args[0].ToLowerInvariant();
if (a == "--scan" || a == "-scan" || a == "/scan")
{
RunOnceScan();
return;
}
}
// ---- 单实例 ----
bool createdNew = false;
Mutex mutex = null;
try
{
mutex = new Mutex(true, "MonitorGuard_SingleInstance_v1", out createdNew);
}
catch
{
createdNew = true;
}
if (!createdNew)
{
MessageBox.Show("MonitorGuard 已经在后台运行了。\n\n请在系统托盘(右下角通知区域)中找到盾牌图标。",
"MonitorGuard", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// ---- 全局异常兜底 ----
Application.ThreadException += delegate(object s, ThreadExceptionEventArgs e)
{
WriteCrashLog(e.Exception);
};
AppDomain.CurrentDomain.UnhandledException += delegate(object s, UnhandledExceptionEventArgs e)
{
WriteCrashLog(e.ExceptionObject as Exception);
};
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
bool openStatus = false;
if (args.Length > 0)
{
string opt = args[0].ToLowerInvariant();
if (opt == "--status" || opt == "-status" || opt == "/status") openStatus = true;
}
try
{
TrayContext ctx = new TrayContext();
if (openStatus) ctx.ShowStatusWindow();
Application.Run(ctx);
}
catch (Exception ex)
{
WriteCrashLog(ex);
MessageBox.Show("MonitorGuard 运行出错:\n" + ex.Message, "MonitorGuard",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (mutex != null)
{
try { mutex.ReleaseMutex(); }
catch { }
try { mutex.Dispose(); }
catch { }
}
}
}
/// <summary>执行一次扫描并把结果写到 scan-report.txt。</summary>
private static void RunOnceScan()
{
string dir = ResolveDataDir();
Logger log = new Logger(dir);
Config cfg = Config.Load(Path.Combine(dir, "config.ini"));
// 自检时不做基线跳过,直接看当前状态
ScanEngine engine = new ScanEngine(cfg, log);
ScanResult r = engine.Scan();
StringBuilder sb = new StringBuilder();
sb.AppendLine("MonitorGuard 一次性扫描报告");
sb.AppendLine("时间 : " + r.FinishedAt.ToString("yyyy-MM-dd HH:mm:ss"));
sb.AppendLine("耗时 : " + r.ElapsedMs + " ms");
sb.AppendLine("异常项 : " + r.Threats.Count);
sb.AppendLine(new string('-', 70));
if (r.Threats.Count == 0)
{
sb.AppendLine("未发现监控 / 截屏 / 录屏迹象。");
}
for (int i = 0; i < r.Threats.Count; i++)
{
Threat t = r.Threats[i];
sb.AppendLine("[" + t.LevelText + "][" + t.Category + "] " + t.Title);
sb.AppendLine(" 说明: " + t.Detail);
sb.AppendLine(" 来源: " + t.Source);
sb.AppendLine();
}
string reportPath = Path.Combine(dir, "scan-report.txt");
try
{
File.WriteAllText(reportPath, sb.ToString(), new UTF8Encoding(true));
}
catch { }
}
private static void WriteCrashLog(Exception ex)
{
if (ex == null) return;
try
{
string dir = ResolveDataDir();
string file = Path.Combine(dir, "crash.log");
File.AppendAllText(file,
"[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + ex.ToString()
+ Environment.NewLine + Environment.NewLine);
}
catch { }
}
}
}