You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
8.1 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Common.HslAuthor.Framework;
using CompressorXN.Untils;
using CompressorXN_Common;
using CompressorXN_Communication.TuMos;
using CompressorXN_Log;
using CompressorXN_Service;
using Custom.Utils.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace CompressorXN
{
internal static class Program
{
#region 使用的Win32函数的声明
/// <summary>
/// 设置窗口的显示状态
/// </summary>
/// <param name="hWnd">窗口句柄</param>
/// <param name="cmdShow">指示窗口如何被显示</param>
/// <returns>如果窗体之前是可见,返回值为非零;如果窗体之前被隐藏,返回值为零</returns>
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
/// <summary>
/// 创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改变各种可视的记号。
/// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
/// </summary>
/// <param name="hWnd">将被激活并被调入前台的窗口句柄</param>
/// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零</returns>
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
// 指示窗口为普通显示
private const int WS_SHOWNORMAL = 1;
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
//设置应用程序处理异常方式ThreadException处理
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
//主线程异常捕获
Application.ThreadException += Application_ThreadException;
//子线程异常捕获
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#region 调用Win32 API,禁止程序重复运行并激活运行程序的窗口显示在最前端
/*
* 这种方式在VS调用的情况不成立的因为在VS中按F5运行的进程为OnlyInstanceRunning.vshost,从这个进程的命名就可以看出
该进程为OnlyInstanceRunning进程的宿主进程
而直接点OnlyInstanceRunning.exe运行的程序进程为OnlyInstanceRunning,
但是我们可以一些小的修改即currentProcess.ProcessName.Replace(".vshose","")此时无论如何都为 OnlyInstanceRunning
*/
//获得正在运行的程序,如果没有相同的程序,则运行该程序
Process process = RunningInstance();
if (process == null)
{
#region 授权
var communicationAuthor = HslAuthorize.HslCommunicationAuthor();
if (!communicationAuthor)
{
new FrmDialog("通讯授权失败!").ShowDialog();
}
var hslControlAuthor = HslAuthorize.HslControlsAuthor();
if (!hslControlAuthor)
{
new FrmDialog("控件授权失败!").ShowDialog();
}
#endregion
InitSystemConfigIni();//读取配置文件
//FrmLogin frmLogin = new FrmLogin();
//frmLogin.ShowDialog();
//if (frmLogin.DialogResult == DialogResult.OK)
//{
// Application.Run(new FrmMain());
//}
Application.Run(new FrmMain());
}
else
{
// 已经运行该程序,显示信息并使程序显示在前端
new FrmDialog("应用程序已经在运行中......").ShowDialog();
Thread.Sleep(1000);
Environment.Exit(Environment.ExitCode);
HandleRunningInstance(process);
}
#endregion
}
#region 异常捕获
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
LogHelper.Error(ex, "子线程异常捕获", string.Format("捕获到未处理异常:{0}\r\n异常信息{1}\r\n异常堆栈{2}\r\nCLR即将退出{3}", ex.GetType(), ex.Message, ex.StackTrace, e.IsTerminating));
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
Exception ex = e.Exception;
LogHelper.Error(ex, "主线程异常捕获", string.Format("捕获到未处理异常:{0}\r\n异常信息{1}\r\n异常堆栈{2}", ex.GetType(), ex.Message, ex.StackTrace));
}
#endregion
#region 禁止程序重复运行相关
/// <summary>
/// 获取正在运行的程序没有运行的程序则返回null
/// </summary>
/// <returns></returns>
private static Process RunningInstance()
{
// 获取当前活动的进程
Process currentProcess = Process.GetCurrentProcess();
// 根据当前进程的进程名获得进程集合
// 如果该程序运行进程的数量大于1
Process[] processcollection = Process.GetProcessesByName(currentProcess.ProcessName.Replace(".vshost", ""));
foreach (Process process in processcollection)
{
// 如果进程ID不等于当前运行进程的ID以及运行进程的文件路径等于当前进程的文件路径
// 则说明同一个该程序已经运行了,此时将返回已经运行的进程
if (process.Id != currentProcess.Id)
{
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == process.MainModule.FileName)
{
return process;
}
}
}
return null;
}
/// <summary>
/// 显示已运行的程序
/// </summary>
/// <param name="instance"></param>
private static void HandleRunningInstance(Process instance)
{
// 显示窗口
ShowWindow(instance.MainWindowHandle, WS_SHOWNORMAL);
// 把窗体放在前端
SetForegroundWindow(instance.MainWindowHandle);
}
#endregion
/// <summary>
/// 读取系统INI配置文件
/// </summary>
static void InitSystemConfigIni()
{
var iniFilePath = GlobalVar.IniFilePath;
GlobalVar.PlcIpAddress=IniHelper.Read("PlcConfig", "Ip", string.Empty,iniFilePath);
string strPlcPort = IniHelper.Read("PlcConfig", "port", string.Empty, iniFilePath);
int.TryParse(strPlcPort, out int plcPort);
GlobalVar.PlcPort = plcPort;
var dbServerIp = IniHelper.Read("DdataBaseConfig", "DbServerIp", "127.0.0.1", iniFilePath);
var port = IniHelper.Read("DdataBaseConfig", "Port", "5432", iniFilePath);
var database = IniHelper.Read("DdataBaseConfig", "Database", "", iniFilePath);
var userId = IniHelper.Read("DdataBaseConfig", "UserId", "postgres", iniFilePath);
var password = IniHelper.Read("DdataBaseConfig", "Password", "", iniFilePath);
var schema = IniHelper.Read("DdataBaseConfig", "Schema", "public", iniFilePath);
var strIsEncrypt = IniHelper.Read("DdataBaseConfig", "DbPwdIsEncrypt", "false", iniFilePath);
_ = bool.TryParse(strIsEncrypt, out bool isEncrypt);
//数据库连接
DbContext.GetConStr(dbServerIp, port, database, userId, password, isEncrypt, schema);
}
}
}