166 lines
6.1 KiB
C#
166 lines
6.1 KiB
C#
/*
|
|
* 由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 { }
|
|
}
|
|
}
|
|
}
|