基线:全量源码首提(D1 版本控制落地,含第一轮优化 B1-B4/A1/A4/缩放修复)
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 由SharpDevelop创建。
|
||||
* 用户: 099978
|
||||
* 日期: 2026-08-25
|
||||
* 时间: 20:59
|
||||
*
|
||||
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace 成套报价软件
|
||||
{
|
||||
/// <summary>
|
||||
/// Class with program entry point.
|
||||
/// </summary>
|
||||
internal sealed class Program
|
||||
{
|
||||
/// <summary>主程序单实例互斥锁名。</summary>
|
||||
private const string SingleInstanceMutexName = "成套报价软件_SingleInstance";
|
||||
|
||||
/// <summary>二次实例向首实例转发导入命令的文件(覆盖式=只保留最新一条)。</summary>
|
||||
internal static string 导入命令文件路径
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(Path.GetTempPath(), "成套报价软件_导入命令.txt");
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); // 9=SW_RESTORE
|
||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern int ShellExecuteW(IntPtr hWnd, string verb, string file, string parameters, string directory, int showCmd);
|
||||
|
||||
/// <summary>
|
||||
/// Program entry point.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
// ★ 单实例:主程序窗口只允许一个(用户要求)
|
||||
bool createdNew;
|
||||
var mutex = new System.Threading.Mutex(true, SingleInstanceMutexName, out createdNew);
|
||||
if (!createdNew)
|
||||
{
|
||||
// 二次启动:转发导入命令(如果有)→激活已有窗口→退出,不新开窗口
|
||||
try
|
||||
{
|
||||
二次实例写日志("被判定为二次实例(锁已被占): args=" +
|
||||
(args != null && args.Length > 0 ? args[0] : "(无)"));
|
||||
if (args != null && args.Length > 0 && !string.IsNullOrWhiteSpace(args[0]))
|
||||
File.WriteAllText(导入命令文件路径, args[0], System.Text.Encoding.UTF8);
|
||||
激活已有主窗口();
|
||||
}
|
||||
catch { }
|
||||
return;
|
||||
}
|
||||
|
||||
// ★ 全局异常捕获(迁移自旧 主窗口.Main):只写日志不弹窗
|
||||
Application.ThreadException += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"logs\thread_exception.log"),
|
||||
"[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "] UI线程异常" +
|
||||
(e.Exception != null ? "\r\n" + e.Exception : "\r\n(无异常对象)") + "\r\n\r\n");
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"logs\thread_exception.log"),
|
||||
"[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "] 非UI线程异常" +
|
||||
(e.ExceptionObject != null ? "\r\n" + e.ExceptionObject : "\r\n(无异常对象)") + "\r\n\r\n");
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
try
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
// ★ 启动先登录(用户要求):登录成功才进主窗口;取消/关闭登录窗=退出程序。
|
||||
// 登录窗 Load 会自动回填"记住密码"的账号,勾着的用户点一下登录即可。
|
||||
var 登录窗 = new 登录();
|
||||
if (登录窗.ShowDialog() != System.Windows.Forms.DialogResult.OK)
|
||||
return;
|
||||
MainForm.当前登录手机号 = 登录窗.登录手机号;
|
||||
MainForm.当前会员类型 = 登录窗.登录会员类型;
|
||||
MainForm.当前有效期 = 登录窗.登录有效期;
|
||||
MainForm.当前登录密码 = 登录窗.登录密码; // 新版项目云协议需要(仅内存)
|
||||
|
||||
Application.Run(new MainForm(args.Length > 0 ? args[0] : null));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
File.WriteAllText(
|
||||
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "crash.log"),
|
||||
ex.ToString());
|
||||
MessageBox.Show("启动失败:\n\n" + ex, "成套报价软件",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { mutex.ReleaseMutex(); } catch { }
|
||||
mutex.Dispose();
|
||||
// ★改密重启(2026-09-26 用户要求:改密成功=关闭主窗口→弹登录窗):主窗体已关闭、
|
||||
// 单实例锁已释放,此刻启动新实例(新实例启动先弹登录窗,用新密码重新登录)。
|
||||
// 用 ShellExecuteW(与 OpenClawHost 同款 P/Invoke 通道)
|
||||
if (MainForm.改密重启)
|
||||
{
|
||||
try
|
||||
{
|
||||
int rc = ShellExecuteW(System.IntPtr.Zero, "open",
|
||||
System.Windows.Forms.Application.ExecutablePath, null, null, 1); // 1=SW_NORMAL
|
||||
if (rc <= 32)
|
||||
System.Windows.Forms.MessageBox.Show("密码已修改。请重新打开成套报价软件,用新密码登录。",
|
||||
"成套报价软件", System.Windows.Forms.MessageBoxButtons.OK,
|
||||
System.Windows.Forms.MessageBoxIcon.Information);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>找到已运行的主程序进程并把它带到前台(最小化时先还原)。</summary>
|
||||
private static void 激活已有主窗口()
|
||||
{
|
||||
try
|
||||
{
|
||||
int selfId = System.Diagnostics.Process.GetCurrentProcess().Id;
|
||||
foreach (var p in System.Diagnostics.Process.GetProcessesByName("成套报价软件"))
|
||||
{
|
||||
if (p.Id == selfId || p.MainWindowHandle == IntPtr.Zero) continue;
|
||||
ShowWindowAsync(p.MainWindowHandle, 9); // 还原(最小化时)
|
||||
SetForegroundWindow(p.MainWindowHandle); // 前台
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>二次实例诊断日志(与主日志同目录;排查"要双击两次才启动":首启慢时第二次双击会被单实例机制吞掉)。</summary>
|
||||
private static void 二次实例写日志(string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
|
||||
Directory.CreateDirectory(dir);
|
||||
File.AppendAllText(Path.Combine(dir, "diag_" + DateTime.Now.ToString("yyyy-MM-dd") + ".log"),
|
||||
DateTime.Now.ToString("HH:mm:ss.fff") + " [二次实例] " + msg + "\r\n");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user