|
|
using DevExpress.XtraEditors;
|
|
|
using HslCommunication.Profinet.Omron;
|
|
|
using MQTTnet.Client;
|
|
|
using SqlSugar;
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Configuration;
|
|
|
using System.Diagnostics;
|
|
|
using System.Reflection;
|
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Threading;
|
|
|
using System.Windows.Forms;
|
|
|
using ZJ_BYD.DB;
|
|
|
using ZJ_BYD.Model;
|
|
|
using ZJ_BYD.Untils;
|
|
|
using ZJ_BYD.ViewModel;
|
|
|
|
|
|
namespace ZJ_BYD
|
|
|
{
|
|
|
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()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
//设置应用程序处理异常方式:ThreadException处理
|
|
|
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
|
|
//主线程异常捕获
|
|
|
Application.ThreadException += Application_ThreadException;
|
|
|
//子线程异常捕获
|
|
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
|
|
|
|
|
Application.EnableVisualStyles();
|
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
|
|
|
WindowsFormsSettings.UseAdvancedTextEdit = DevExpress.Utils.DefaultBoolean.True;//添加这一行MemoEdit设置字体颜色的事件才会触发
|
|
|
|
|
|
LogHelper.SetConfig();
|
|
|
DBHelper.GetConnStr();
|
|
|
|
|
|
//控件激活
|
|
|
var controlAuthor = HslControls.Authorization.SetAuthorizationCode("75a6294c-7cda-451d-a8b3-d8e54b5debf1");
|
|
|
if (!controlAuthor)
|
|
|
{
|
|
|
LogHelper.WriteLog("控件授权到期");
|
|
|
}
|
|
|
|
|
|
//注册
|
|
|
var communicationAuthor = HslCommunication.Authorization.SetAuthorizationCode("f562cc4c-4772-4b32-bdcd-f3e122c534e3");
|
|
|
if (!communicationAuthor)
|
|
|
{
|
|
|
LogHelper.WriteLog("通讯授权到期");
|
|
|
XtraMessageBox.Show("通讯授权到期");
|
|
|
}
|
|
|
|
|
|
LoadAppConfig();
|
|
|
|
|
|
GetCurrentConfig();
|
|
|
|
|
|
#region 加载当前工控机的有效工位
|
|
|
stationInfos = MskCodeHelper.QueryUsingMaChineTypeVM().OrderBy(a => a.SortIndex).ToList();
|
|
|
Program.PointKeyValues = PlcPointHelper.QueryActivePlcPoints().Where(m => m.IsActive)
|
|
|
.Where(m => m.IpcId == Program.CurrentIpcId)
|
|
|
.Select(m => new PointKeyValue
|
|
|
{
|
|
|
StationCode = m.StationCode,
|
|
|
Key = m.PointCode,
|
|
|
FieldCode = m.ResultField,
|
|
|
KeyDesc = m.PointName,
|
|
|
Address = m.PointStartAddress,
|
|
|
Length = m.PointLength,
|
|
|
DataType = m.PointDataType,
|
|
|
IsShowMain = m.IsShowMain,
|
|
|
IsSub = m.IsSub,
|
|
|
IsTestItem = m.IsTestItem,
|
|
|
IsResponseData = m.IsResponseData,
|
|
|
IsSaveDb = m.IsSaveDb,
|
|
|
SortIndex = m.SortIndex
|
|
|
}).ToList();
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
t_MaskCodes = MskCodeHelper.QueryMskCodes().ToList();
|
|
|
|
|
|
#region 获取连接PLC对象
|
|
|
var connectPLC = new ConnectPLC();
|
|
|
Program.omronCipNet = connectPLC.GetOmronCipNet();
|
|
|
#endregion
|
|
|
|
|
|
#region 定时任务
|
|
|
_ = QuartzHelper.Start();
|
|
|
#endregion
|
|
|
|
|
|
#region 调用Win32 API,禁止程序重复运行并激活运行程序的窗口显示在最前端
|
|
|
/*
|
|
|
* 这种方式在VS调用的情况不成立的,因为在VS中按F5运行的进程为OnlyInstanceRunning.vshost,从这个进程的命名就可以看出
|
|
|
该进程为OnlyInstanceRunning进程的宿主进程
|
|
|
而直接点OnlyInstanceRunning.exe运行的程序进程为OnlyInstanceRunning,
|
|
|
但是我们可以一些小的修改,即currentProcess.ProcessName.Replace(".vshose","")此时无论如何都为 OnlyInstanceRunning
|
|
|
*/
|
|
|
|
|
|
//获得正在运行的程序,如果没有相同的程序,则运行该程序
|
|
|
Process process = RunningInstance();
|
|
|
if (process == null)
|
|
|
{
|
|
|
Application.EnableVisualStyles();
|
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
Application.Run(new StartForm());
|
|
|
Application.Run(new LoginFrom());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 已经运行该程序,显示信息并使程序显示在前端
|
|
|
MessageBox.Show("应用程序已经在运行中......");
|
|
|
Thread.Sleep(1000);
|
|
|
Environment.Exit(1);
|
|
|
HandleRunningInstance(process);
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
MessageBox.Show(ex.ToString());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
|
|
{
|
|
|
Exception ex = e.ExceptionObject as Exception;
|
|
|
LogHelper.WriteErrorLog(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.WriteErrorLog(string.Format("捕获到未处理异常:{0}\r\n异常信息:{1}\r\n异常堆栈:{2}", ex.GetType(), ex.Message, ex.StackTrace));
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取基础配置信息
|
|
|
/// </summary>
|
|
|
static void GetCurrentConfig()
|
|
|
{
|
|
|
var configInfo = CurrentConfigHelper.QueryCurrentConfigs()
|
|
|
.Where(m => m.IpcId == Program.CurrentIpcId && m.LineCode == Program.CurrentLineCode)
|
|
|
.First();
|
|
|
if (configInfo != null)
|
|
|
{
|
|
|
Program.LineName = configInfo.LineName;
|
|
|
Program.MesIpAddress = configInfo.MesIp;
|
|
|
Program.MesPort = configInfo.MesPort;
|
|
|
Program.PlcIpAddress = configInfo.PlcIp;
|
|
|
Program.PlcPort = string.IsNullOrWhiteSpace(configInfo.PlcPort) ? 44818 : int.Parse(configInfo.PlcPort);
|
|
|
Program.MenuPwd = configInfo.MenuPwd;
|
|
|
Program.HightPwd = configInfo.HightPwd;
|
|
|
Program.areacode = configInfo.AreaCode;
|
|
|
Program.deptcode = configInfo.DeptCode;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <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);
|
|
|
}
|
|
|
|
|
|
#region 全局变量
|
|
|
|
|
|
/// <summary>
|
|
|
/// 数据库类型
|
|
|
/// </summary>
|
|
|
//public static DbType CurrentDbType = DbType.MySql;
|
|
|
public static DbType CurrentDbType = DbType.PostgreSQL;
|
|
|
|
|
|
public static IMqttClient mqttClient; //MQTT客户端实例
|
|
|
|
|
|
/// <summary>
|
|
|
/// 地域代码
|
|
|
/// </summary>
|
|
|
public static string areacode { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 工厂代码
|
|
|
/// </summary>
|
|
|
public static string deptcode { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 读取PLC的频率
|
|
|
/// </summary>
|
|
|
public static int readplcrate = 1000;
|
|
|
|
|
|
/// <summary>
|
|
|
/// PLC通讯状态
|
|
|
/// </summary>
|
|
|
public static string communicationstatus { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 当前工控机标识
|
|
|
/// </summary>
|
|
|
public static string CurrentIpcId { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 当前产线编码
|
|
|
/// </summary>
|
|
|
public static string CurrentLineCode { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 激活中的工位编码
|
|
|
/// </summary>
|
|
|
public static string ActiveStatinCode { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// PLC连接对象
|
|
|
/// </summary>
|
|
|
public static OmronCipNet omronCipNet = null;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 测试文件名称
|
|
|
/// </summary>
|
|
|
public static string testfilename { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 程序版本
|
|
|
/// </summary>
|
|
|
public static string programversion { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// PLC IP地址
|
|
|
/// </summary>
|
|
|
public static string PlcIpAddress { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// PLC端口
|
|
|
/// </summary>
|
|
|
public static int PlcPort = 44818;
|
|
|
|
|
|
/// <summary>
|
|
|
/// MES IP地址
|
|
|
/// </summary>
|
|
|
public static string MesIpAddress { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// MES端口
|
|
|
/// </summary>
|
|
|
public static string MesPort { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 菜单权限口令
|
|
|
/// </summary>
|
|
|
public static string MenuPwd { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 最高权限口令
|
|
|
/// </summary>
|
|
|
public static string HightPwd { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 系统模式
|
|
|
/// 0:离线
|
|
|
/// 1:在线
|
|
|
/// </summary>
|
|
|
public static bool SysMode { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 产线名称
|
|
|
/// </summary>
|
|
|
public static string LineName { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 软件版本号校验长度
|
|
|
/// </summary>
|
|
|
public static int SoftVersionLen = 17;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 标签码
|
|
|
/// </summary>
|
|
|
public static string PrintBarCode { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 标签码的流水号
|
|
|
/// </summary>
|
|
|
public static string SerialNum { get; set; }
|
|
|
|
|
|
public static List<StationInfo> stationInfos { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 掩码表集合
|
|
|
/// </summary>
|
|
|
public static List<T_MaskCode> t_MaskCodes { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 存储各工位读取PLC的返回值
|
|
|
/// </summary>
|
|
|
public static List<PointKeyValue> PointKeyValues { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// mes请求超时时间
|
|
|
/// </summary>
|
|
|
public static int MesPostTimeout { get; set; } = 15000;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 机型
|
|
|
/// </summary>
|
|
|
public static string MachineType { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 转子充磁工位编号
|
|
|
/// </summary>
|
|
|
public static string ZZCC_ST { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 转子工序
|
|
|
/// </summary>
|
|
|
public static string ZZCC_Procedure { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 是否查询动静盘支线
|
|
|
/// </summary>
|
|
|
public static bool SearchDongJingPanBranch = true;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 动静盘站号
|
|
|
/// </summary>
|
|
|
public static string DongJingPanST { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 静盘工序
|
|
|
/// </summary>
|
|
|
public static string JingPanProcedure { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 静盘参数
|
|
|
/// </summary>
|
|
|
public static string JingPan_Param { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 静盘线
|
|
|
/// </summary>
|
|
|
public static string[] JingPanLines { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 动盘工序
|
|
|
/// </summary>
|
|
|
public static string DongPanProcedure { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 动盘线
|
|
|
/// </summary>
|
|
|
public static string[] DongPanLines { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 动盘参数
|
|
|
/// </summary>
|
|
|
public static string DongPan_Param { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 动静盘差值
|
|
|
/// </summary>
|
|
|
public static List<float> DongJingDvalue { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 补油(B90)
|
|
|
/// </summary>
|
|
|
public static string YZCS_ST { get; set; }
|
|
|
|
|
|
#region 存数据库时使用
|
|
|
public static Type type = null;
|
|
|
|
|
|
public static PropertyInfo[] properties = null;
|
|
|
#endregion
|
|
|
|
|
|
#region 人脸识别系统
|
|
|
/// <summary>
|
|
|
/// 是否启用人脸识别系统
|
|
|
/// </summary>
|
|
|
public static bool IsUseFace = false;
|
|
|
|
|
|
public static string DeviceIp { get; set; }
|
|
|
|
|
|
public static string DeviceUserName { get; set; }
|
|
|
|
|
|
public static string DevicePwd { get; set; }
|
|
|
|
|
|
public static ushort DevicePort = 8000;
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 加载App.config配置文件
|
|
|
/// </summary>
|
|
|
static void LoadAppConfig()
|
|
|
{
|
|
|
CurrentIpcId = ConfigurationManager.AppSettings["ipccode"];
|
|
|
CurrentLineCode = ConfigurationManager.AppSettings["lincode"];
|
|
|
testfilename = ConfigurationManager.AppSettings["testfilename"];
|
|
|
programversion = ConfigurationManager.AppSettings["programversion"];
|
|
|
int.TryParse(ConfigurationManager.AppSettings["readplcrate"], out readplcrate);
|
|
|
MesPostTimeout = int.Parse(ConfigurationManager.AppSettings["MesPostTimeout"]);
|
|
|
ZZCC_ST = ConfigurationManager.AppSettings["ZZCC_ST"];
|
|
|
ZZCC_Procedure = ConfigurationManager.AppSettings["ZZCC_Procedure"];
|
|
|
DongJingPanST = ConfigurationManager.AppSettings["DongJingPanST"];
|
|
|
JingPanProcedure = ConfigurationManager.AppSettings["JingPanProcedure"];
|
|
|
JingPanLines = ConfigurationManager.AppSettings["JingPanLines"]?.Split(',');
|
|
|
JingPan_Param = ConfigurationManager.AppSettings["JingPan_Param"];
|
|
|
DongPanProcedure = ConfigurationManager.AppSettings["DongPanProcedure"];
|
|
|
DongPanLines = ConfigurationManager.AppSettings["DongPanLines"]?.Split(',');
|
|
|
DongPan_Param = ConfigurationManager.AppSettings["DongPan_Param"];
|
|
|
DongJingDvalue = new List<float>();
|
|
|
var strDongJing = ConfigurationManager.AppSettings["DongJingDvalue"];
|
|
|
if (!string.IsNullOrWhiteSpace(strDongJing))
|
|
|
{
|
|
|
string[] dvalue = strDongJing.Split('-');
|
|
|
if (dvalue.Length > 0)
|
|
|
{
|
|
|
foreach (string s in dvalue)
|
|
|
{
|
|
|
DongJingDvalue.Add(float.Parse(s));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
YZCS_ST = ConfigurationManager.AppSettings["YZCS_ST"];
|
|
|
|
|
|
var strSearchDongJingPanBranch = ConfigurationManager.AppSettings["SearchDongJingPanBranch"];
|
|
|
bool.TryParse(strSearchDongJingPanBranch, out SearchDongJingPanBranch);
|
|
|
|
|
|
#region 人脸识别系统
|
|
|
DeviceIp = ConfigurationManager.AppSettings["DeviceIp"];
|
|
|
DeviceUserName = ConfigurationManager.AppSettings["DeviceUserName"];
|
|
|
DevicePwd = ConfigurationManager.AppSettings["DevicePwd"];
|
|
|
var strDevicePort = ConfigurationManager.AppSettings["DevicePort"];
|
|
|
ushort.TryParse(strDevicePort, out DevicePort);
|
|
|
var strIsUseFace = ConfigurationManager.AppSettings["IsUseFace"];
|
|
|
bool.TryParse(strIsUseFace, out IsUseFace);
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|