|
|
using System;
|
|
|
using System.Collections.Concurrent;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.IO;
|
|
|
using System.IO.Ports;
|
|
|
using System.Linq;
|
|
|
using System.Reflection;
|
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Windows.Forms;
|
|
|
using POSV.Entity;
|
|
|
using POSV.HttpApi;
|
|
|
using POSV.ShoppingCart;
|
|
|
using POSV.Utils;
|
|
|
using System.Data.SQLite;
|
|
|
using POSV.Cef.Client.ClientComm;
|
|
|
using POS.Language.Language;
|
|
|
using POSV.OtherWaiMai;
|
|
|
using POSV.QiMai;
|
|
|
using POSV.Common.Util;
|
|
|
using NLog.RestTarget;
|
|
|
using POSV.Common.Wlan;
|
|
|
using System.Net.NetworkInformation;
|
|
|
using POSV.Payment.Abmcs;
|
|
|
using System.Security.Cryptography;
|
|
|
using POSV.Dianping;
|
|
|
using POSV.Card;
|
|
|
|
|
|
namespace POSV
|
|
|
{
|
|
|
static class Program
|
|
|
{
|
|
|
private const int SW_HIDE = 0;
|
|
|
private const int SW_NORMAL = 1;
|
|
|
private const int SW_MAXIMIZE = 3;
|
|
|
private const int SW_SHOWNOACTIVATE = 4;
|
|
|
private const int SW_SHOW = 5;
|
|
|
private const int SW_MINIMIZE = 6;
|
|
|
private const int SW_RESTORE = 9;
|
|
|
private const int SW_SHOWDEFAULT = 10;
|
|
|
private static ExceptionForm exception = null;
|
|
|
|
|
|
/// 该函数设置由不同线程产生的窗口的显示状态
|
|
|
/// </summary>
|
|
|
/// <param name="hWnd">窗口句柄</param>
|
|
|
/// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分</param>
|
|
|
/// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零</returns>
|
|
|
[DllImport("User32.dll")]
|
|
|
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
|
|
|
/// <summary>
|
|
|
/// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。
|
|
|
/// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
|
|
|
/// </summary>
|
|
|
/// <param name="hWnd">将被激活并被调入前台的窗口句柄</param>
|
|
|
/// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零</returns>
|
|
|
[DllImport("User32.dll")]
|
|
|
private static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
|
|
|
|
public static Mutex AppMutex;
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 应用程序的主入口点。
|
|
|
/// </summary>
|
|
|
[STAThread]
|
|
|
static void Main()
|
|
|
{
|
|
|
//全局异常捕捉
|
|
|
Application.ThreadException += ApplicationThreadException; //UI线程异常
|
|
|
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
|
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; //多线程异常
|
|
|
|
|
|
//NetworkInterface[] allInterfaces = NetworkInterface.GetAllNetworkInterfaces();
|
|
|
//NetworkInterface firstInterface = allInterfaces[0];
|
|
|
|
|
|
//foreach (var i in allInterfaces)
|
|
|
//{
|
|
|
// bool interfaceSupportsIPv6 = InterfaceHasIpv6Enabled(i);
|
|
|
//}
|
|
|
|
|
|
bool createdNew = true;
|
|
|
AppMutex = new System.Threading.Mutex(true, Application.ProductName, out createdNew);
|
|
|
|
|
|
if (createdNew)
|
|
|
{
|
|
|
|
|
|
Application.EnableVisualStyles();
|
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
|
|
|
SplashScreen.ShowSplashScreen();
|
|
|
|
|
|
//初始化NLog
|
|
|
NLogUtils.InitLogger();
|
|
|
SplashScreen.SetStatus("加载运行日志...");
|
|
|
|
|
|
|
|
|
Global.Instance.Restart = false;
|
|
|
|
|
|
AutoUpdateNew();
|
|
|
|
|
|
var _type = Global.Instance.GlobalConfigStringValue(ConfigConstant.LAYOUT_LANGUAGETYPE, "中文");
|
|
|
|
|
|
LangProxy.SetLangTypeVal(_type);
|
|
|
|
|
|
//检测是否WiFi网路连接
|
|
|
Global.Instance.IsWiFi = WiFiApi.Connected();
|
|
|
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("检测本机网络连接..."));
|
|
|
var openApiTask = Task.Factory.StartNew<bool>(() => { return HttpClientUtils.IsAvailable(); });
|
|
|
Task.WaitAll(openApiTask);
|
|
|
|
|
|
//网络可用:a)网卡工作;b)可以联网;c)开放平台正常
|
|
|
bool isConnected = openApiTask.Result;
|
|
|
|
|
|
//网络连接压入全局参数
|
|
|
Global.Instance.Online = isConnected;
|
|
|
|
|
|
SplashScreen.SetStatus(string.Format(LangProxy.ToLang("本机网络连接{0}..."), isConnected ? LangProxy.ToLang("正常") : LangProxy.ToLang("不正常")));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("检测服务中心连接..."));
|
|
|
try
|
|
|
{
|
|
|
Global.Instance.MessageCenterOnline = MessageCenterUtils.Instance.IsAvailable();
|
|
|
}
|
|
|
catch { }
|
|
|
|
|
|
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("设备自检中..."));
|
|
|
var finger = DeviceUtils.Instance;
|
|
|
|
|
|
bool isGo = true;
|
|
|
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("检测数据库版本..."));
|
|
|
|
|
|
bool isException = AutoUpdateDatabase();
|
|
|
|
|
|
if (isException)
|
|
|
{
|
|
|
isGo = false;
|
|
|
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("数据更新失败,即将退出..."));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("数据更新成功..."));
|
|
|
}
|
|
|
|
|
|
if (isGo)
|
|
|
{
|
|
|
SplashScreen.SetStatus(LangProxy.ToLang("启动定时任务..."));
|
|
|
|
|
|
JobUtils.Startup();
|
|
|
|
|
|
|
|
|
SplashScreen.CloseForm();
|
|
|
|
|
|
//初始化来电猫全局参数,应用关闭后主动关闭端口
|
|
|
Global.Instance.Cats = new List<SerialPort>();
|
|
|
|
|
|
//登陆窗口,并最大化
|
|
|
FastLoginForm loginForm = new FastLoginForm();
|
|
|
ShowWindowAsync(loginForm.Handle, SW_MAXIMIZE);//显示
|
|
|
SetForegroundWindow(loginForm.Handle);//当到最前端
|
|
|
|
|
|
if (DialogResult.OK == loginForm.ShowDialog())
|
|
|
{
|
|
|
//zhangy 2020-03-05 Add 登陆成功后,更新数据库默认参数
|
|
|
//AutoUpdateParamVersion();
|
|
|
|
|
|
//联机状态
|
|
|
if (Global.Instance.Online)
|
|
|
{
|
|
|
var download = new FastDownloading();
|
|
|
if (DialogResult.OK == download.ShowDialog())
|
|
|
{
|
|
|
var wsse = WSSE.Instance;
|
|
|
|
|
|
StartTheme();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
var wsse = WSSE.Instance;
|
|
|
|
|
|
StartTheme();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//关闭来电猫端口
|
|
|
Global.Instance.Cats.ForEach(x =>
|
|
|
{
|
|
|
if (x != null && x.IsOpen)
|
|
|
{
|
|
|
x.Close();
|
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("关闭来电参数<{0},{1}>", x.PortName, x.BaudRate);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
//关闭云端推送连接
|
|
|
Proxy.Mqtt.MqttClientUtils.Instance.Stop();
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("关闭云端推送连接");
|
|
|
|
|
|
//关闭消息中心连接
|
|
|
MqttUtils.Instance.Stop();
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("关闭消息中心连接");
|
|
|
|
|
|
//关闭计划任务
|
|
|
JobUtils.Stop();
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("关闭计划任务");
|
|
|
|
|
|
if (Global.Instance.Restart)
|
|
|
{
|
|
|
AppMutex.ReleaseMutex();
|
|
|
AppMutex.Dispose();
|
|
|
AppMutex = null;
|
|
|
|
|
|
Application.Exit();
|
|
|
System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
|
|
System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
|
|
|
currentProcess.Kill();
|
|
|
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
|
|
|
currentProcess.Kill();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
Thread.Sleep(3000);
|
|
|
|
|
|
SplashScreen.CloseForm();
|
|
|
Application.ExitThread();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
Process instance = Instance();
|
|
|
ShowWindowAsync(instance.MainWindowHandle, SW_MAXIMIZE);//显示
|
|
|
SetForegroundWindow(instance.MainWindowHandle);//当到最前端
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 启动对应主题布局界面
|
|
|
/// </summary>
|
|
|
private static void StartTheme()
|
|
|
{
|
|
|
Global.Instance.ReloadConfig();
|
|
|
try
|
|
|
{
|
|
|
//版本选择
|
|
|
ThemeEnum enableTheme = ThemeEnum.快餐;
|
|
|
var layoutTheme = Global.Instance.GlobalConfigStringValue(ConfigConstant.LAYOUT_THEME, ThemeEnum.快餐.ToString());
|
|
|
Enum.TryParse<ThemeEnum>(layoutTheme, out enableTheme);
|
|
|
|
|
|
switch (enableTheme)
|
|
|
{
|
|
|
case ThemeEnum.茶饮:
|
|
|
{
|
|
|
Application.Run(new TeaTemplate());
|
|
|
}
|
|
|
break;
|
|
|
case ThemeEnum.新食堂:
|
|
|
{
|
|
|
DownloadCefDependentFile DownloadCef = new DownloadCefDependentFile();
|
|
|
if (!DownloadCef.Needtodownload())
|
|
|
{
|
|
|
DownloadCef.ShowDialog();
|
|
|
|
|
|
if (!DownloadCef.IsAccomplish)
|
|
|
{
|
|
|
//zhangy 2020-03-01 Add 新食堂版本依赖CEF环境,如果环境异常,重置到快餐模式,以便于下次正常启动
|
|
|
using (var db = Global.Instance.OpenDataBase)
|
|
|
{
|
|
|
var config = db.Single<Config>(" where [group] = @0 and keys = @1", ConfigConstant.LAYOUT_GROUP, ConfigConstant.LAYOUT_THEME);
|
|
|
if (config != null)
|
|
|
{
|
|
|
config.Values = ThemeEnum.快餐.ToString();
|
|
|
using (var trans = db.GetTransaction())
|
|
|
{
|
|
|
db.Save(config);
|
|
|
trans.Complete();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
MessageBox.Show("运行环境出现问题,已经恢复到快餐模式,请与管理员联系!");
|
|
|
|
|
|
Application.ExitThread();
|
|
|
}
|
|
|
}
|
|
|
Application.Run(new POSV.Cef.FastTemplate.FastTemplate());
|
|
|
|
|
|
}
|
|
|
break;
|
|
|
case ThemeEnum.食堂:
|
|
|
{
|
|
|
Application.Run(new FastTemplate());//zhangy 2020-002-18 Add 已经在参数配置中屏蔽
|
|
|
}
|
|
|
break;
|
|
|
case ThemeEnum.称重:
|
|
|
{
|
|
|
Application.Run(new WeightTemplate());
|
|
|
}
|
|
|
break;
|
|
|
case ThemeEnum.快餐:
|
|
|
default:
|
|
|
{
|
|
|
Application.Run(new DefaultTemplate());
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
if (exception == null || exception.IsDisposed)
|
|
|
{
|
|
|
exception = new ExceptionForm();
|
|
|
}
|
|
|
exception.SetMessage = ex.Message;
|
|
|
exception.SetErrorMessage = ex.StackTrace;
|
|
|
exception.ShowDialog();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 只运行一个实例
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private static Process Instance()
|
|
|
{
|
|
|
Process current = Process.GetCurrentProcess();
|
|
|
Process[] processes = Process.GetProcessesByName(current.ProcessName);
|
|
|
|
|
|
foreach (Process process in processes)
|
|
|
{
|
|
|
//如果实例已经存在则忽略当前进程
|
|
|
if (process.Id != current.Id)
|
|
|
{
|
|
|
//保证要打开的进程同已经存在的进程来自同一文件路径
|
|
|
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
|
|
|
{
|
|
|
//返回已经存在的进程
|
|
|
return process;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 主程序更新 AutoUpdater.exe
|
|
|
/// </summary>
|
|
|
static void AutoUpdateNew()
|
|
|
{
|
|
|
string auto_update = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"AutoUpdater.exe");
|
|
|
string auto_update_new = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constant.AUTO_UPDATER_NEW);
|
|
|
string auto_update_backup = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\backup\AutoUpdater.exe");
|
|
|
if (File.Exists(auto_update_new))
|
|
|
{
|
|
|
if (File.Exists(auto_update))
|
|
|
{
|
|
|
if (File.Exists(auto_update_backup))
|
|
|
{
|
|
|
File.Delete(auto_update_backup);
|
|
|
}
|
|
|
File.Move(auto_update, auto_update_backup);
|
|
|
}
|
|
|
|
|
|
FileInfo fi = new FileInfo(auto_update_new);
|
|
|
fi.MoveTo(auto_update);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//static void AutoUpdateParamVersion()
|
|
|
//{
|
|
|
|
|
|
// try
|
|
|
// {
|
|
|
// ApplicationVersion entity = null;
|
|
|
|
|
|
// //判断数据库中记录的版本
|
|
|
// using (var db = Global.Instance.OpenDataBase)
|
|
|
// {
|
|
|
// entity = db.Query<ApplicationVersion>().OrderByDescending(x => x.ModifyDate).FirstOrDefault();
|
|
|
// }
|
|
|
|
|
|
// if(entity != null)
|
|
|
// {
|
|
|
// //数据库版本大于参数版本
|
|
|
// if (string.Compare(entity.DbVersion,entity.ParamVersion) > 0)
|
|
|
// {
|
|
|
// var _name = string.Format("data.db_{0}.txt", entity.DbVersion);
|
|
|
|
|
|
// //获得正在运行类所在的名称空间
|
|
|
// Type type = MethodBase.GetCurrentMethod().DeclaringType;
|
|
|
// string _namespace = type.Namespace;
|
|
|
// //获得当前运行的Assembly
|
|
|
// Assembly _assembly = Assembly.GetExecutingAssembly();
|
|
|
// //根据名称空间和文件名生成资源名称
|
|
|
// string resourceName = _namespace + "." + _name;
|
|
|
|
|
|
// var list = new ConcurrentQueue<string>();
|
|
|
|
|
|
// using (var stream = _assembly.GetManifestResourceStream(resourceName))
|
|
|
// {
|
|
|
// if (stream != null)
|
|
|
// {
|
|
|
// NLog.LogManager.GetCurrentClassLogger().Info("默认参数更新<{0}>", _name);
|
|
|
|
|
|
// string json = string.Empty;
|
|
|
// using (StreamReader reader = new StreamReader(stream))
|
|
|
// {
|
|
|
// json = reader.ReadToEnd();
|
|
|
// }
|
|
|
|
|
|
// if (!string.IsNullOrEmpty(json))
|
|
|
// {
|
|
|
// var migrate = DynamicJson.Parse(json);
|
|
|
// if (migrate != null)
|
|
|
// {
|
|
|
// //处理租户更新,影响具体租户全部门店
|
|
|
// if (migrate.IsDefined("tenant") && Global.Instance.Authc != null)
|
|
|
// {
|
|
|
// var tenant = migrate["tenant"];
|
|
|
// //zhangy 2020-03-05 JSON解析有问题,不能以数字开头
|
|
|
// var tenantNo = "tenant_" + Global.Instance.Authc.TenantId;
|
|
|
// if (tenant.IsDefined(tenantNo))
|
|
|
// {
|
|
|
// var arrayJson = tenant[tenantNo];
|
|
|
// foreach (var item in arrayJson)
|
|
|
// {
|
|
|
// list.Enqueue(item);
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// //处理租户门店更新,影响具体租户具体门店
|
|
|
// if (migrate.IsDefined("store") && Global.Instance.Authc != null)
|
|
|
// {
|
|
|
// var storeNo = "store" + Global.Instance.Authc.TenantId + "_" + Global.Instance.Authc.StoreNo;
|
|
|
|
|
|
// var tenant = migrate["store"];
|
|
|
// if (tenant.IsDefined(storeNo))
|
|
|
// {
|
|
|
// var arrayJson = tenant[storeNo];
|
|
|
// foreach (var item in arrayJson)
|
|
|
// {
|
|
|
// list.Enqueue(item);
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// if(list.Count > 0)
|
|
|
// {
|
|
|
// SqliteUtils.ExecuteTransaction(list);
|
|
|
// //刷新参数
|
|
|
// Global.Instance.ReloadConfig();
|
|
|
|
|
|
// NLog.LogManager.GetCurrentClassLogger().Info("门店默认参数更新成功");
|
|
|
// }
|
|
|
|
|
|
// entity.ParamVersion = entity.DbVersion;
|
|
|
|
|
|
// using (var db = Global.Instance.OpenDataBase)
|
|
|
// {
|
|
|
// using (var trans = db.GetTransaction())
|
|
|
// {
|
|
|
// db.Save(entity);
|
|
|
// trans.Complete();
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
// }
|
|
|
// else
|
|
|
// {
|
|
|
// NLog.LogManager.GetCurrentClassLogger().Info("门店默认参数更新失败:原因:<pos_version>表没有数据");
|
|
|
// }
|
|
|
// }
|
|
|
// catch (Exception ex)
|
|
|
// {
|
|
|
// NLog.LogManager.GetCurrentClassLogger().Error(ex, "数据库升级异常");
|
|
|
// }
|
|
|
//}
|
|
|
|
|
|
|
|
|
static bool AutoUpdateDatabase()
|
|
|
{
|
|
|
bool isException = false;
|
|
|
|
|
|
//当前程序嵌入的数据库版本
|
|
|
int _version = 1;
|
|
|
//数据库的版本
|
|
|
int _dbVersion = 1;
|
|
|
|
|
|
ApplicationVersion entity = null;
|
|
|
try
|
|
|
{
|
|
|
var _array = Application.ProductVersion.Split('.');
|
|
|
int major = 0;
|
|
|
int.TryParse(_array[0], out major);
|
|
|
int minor = 0;
|
|
|
int.TryParse(_array[1], out minor);
|
|
|
int build = 2;
|
|
|
int.TryParse(_array[2], out build);
|
|
|
|
|
|
//当前程序嵌入的数据库版本
|
|
|
_version = major * 100 + minor * 10 + build;
|
|
|
|
|
|
//应用的版本
|
|
|
var _appVersion = Application.ProductVersion;
|
|
|
|
|
|
//判断数据库中记录的版本
|
|
|
using (var db = Global.Instance.OpenDataBase)
|
|
|
{
|
|
|
entity = db.Query<ApplicationVersion>().OrderByDescending(x => x.ModifyDate).FirstOrDefault();
|
|
|
}
|
|
|
|
|
|
if (entity == null)
|
|
|
{
|
|
|
entity = new ApplicationVersion();
|
|
|
entity.Id = IdWorkerUtils.Instance.NextId();
|
|
|
|
|
|
entity.AppVersion = _appVersion;
|
|
|
entity.DbVersion = _dbVersion.ToString();
|
|
|
}
|
|
|
|
|
|
|
|
|
int.TryParse(entity.DbVersion, out _dbVersion);
|
|
|
|
|
|
//升级前备份数据文件
|
|
|
string sourceFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\posv2.s3db");
|
|
|
|
|
|
string destFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format(@"data\backup\posv2.s3db", ""));
|
|
|
|
|
|
//数据库需要升级
|
|
|
if (_version > _dbVersion)
|
|
|
{
|
|
|
SplashScreen.SetStatus(string.Format("备份历史数据<{0}>...", _dbVersion));
|
|
|
System.IO.File.Copy(sourceFileName, destFileName, true);
|
|
|
|
|
|
for (int i = _dbVersion + 1; i <= _version; i++)
|
|
|
{
|
|
|
var _name = string.Format("data.db_{0}.txt", i);
|
|
|
|
|
|
//获得正在运行类所在的名称空间
|
|
|
Type type = MethodBase.GetCurrentMethod().DeclaringType;
|
|
|
string _namespace = type.Namespace;
|
|
|
//获得当前运行的Assembly
|
|
|
Assembly _assembly = Assembly.GetExecutingAssembly();
|
|
|
//根据名称空间和文件名生成资源名称
|
|
|
string resourceName = _namespace + "." + _name;
|
|
|
|
|
|
Tuple<bool, ConcurrentQueue<string>> migrate = null;
|
|
|
|
|
|
using (Stream stream = _assembly.GetManifestResourceStream(resourceName))
|
|
|
{
|
|
|
if (stream == null)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("发布数据库更新<{0}>", _name);
|
|
|
|
|
|
string json = string.Empty;
|
|
|
using (StreamReader reader = new StreamReader(stream))
|
|
|
{
|
|
|
json = reader.ReadToEnd();
|
|
|
}
|
|
|
|
|
|
if (!string.IsNullOrEmpty(json))
|
|
|
{
|
|
|
migrate = ParseDbMigrate(json);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (migrate != null && migrate.Item1)
|
|
|
{
|
|
|
var sqls = migrate.Item2;
|
|
|
|
|
|
SplashScreen.SetStatus(string.Format("更新数据,请稍候..."));
|
|
|
|
|
|
foreach (var sql in migrate.Item2)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
SqliteUtils.Execute(sql);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
if (ex.Message.Contains("duplicate column name"))
|
|
|
{
|
|
|
NLog.LogManager.GetCurrentClassLogger().Error(ex, "列名升级失败,已存在:"+ sql);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
NLog.LogManager.GetCurrentClassLogger().Error(ex, "数据库升级异常");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
isException = true;
|
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Error(ex, "数据库升级异常");
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
if (!isException)
|
|
|
{
|
|
|
entity.AppVersion = Application.ProductVersion;
|
|
|
entity.DbVersion = _version.ToString();
|
|
|
|
|
|
using (var db = Global.Instance.OpenDataBase)
|
|
|
{
|
|
|
using (var trans = db.GetTransaction())
|
|
|
{
|
|
|
db.Save(entity);
|
|
|
trans.Complete();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//刷新Http请求的AppKey,避免调用错误
|
|
|
OpenApiUtils.Instance.Refresh();
|
|
|
}
|
|
|
|
|
|
return isException;
|
|
|
}
|
|
|
|
|
|
static Tuple<bool, ConcurrentQueue<string>> ParseDbMigrate(string json)
|
|
|
{
|
|
|
|
|
|
Tuple<bool, ConcurrentQueue<string>> result = null;
|
|
|
try
|
|
|
{
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("解析数据库更新脚本......");
|
|
|
|
|
|
var list = new ConcurrentQueue<string>();
|
|
|
|
|
|
var migrate = DynamicJson.Parse(json);
|
|
|
if (migrate != null)
|
|
|
{
|
|
|
//处理全局更新,影响全部客户
|
|
|
if (migrate.IsDefined("global"))
|
|
|
{
|
|
|
var global = migrate["global"];
|
|
|
if (global.IsDefined("all"))
|
|
|
{
|
|
|
var arrayJson = global["all"];
|
|
|
foreach (var item in arrayJson)
|
|
|
{
|
|
|
list.Enqueue(item);
|
|
|
}
|
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Info("处理数据库全局更新......");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
////处理租户更新,影响具体租户全部门店
|
|
|
//if (migrate.IsDefined("tenant") && Global.Instance.Authc != null)
|
|
|
//{
|
|
|
// var tenant = migrate["tenant"];
|
|
|
|
|
|
// var tenantNo = Global.Instance.Authc.TenantId;
|
|
|
// if (tenant.IsDefined(tenantNo))
|
|
|
// {
|
|
|
// var arrayJson = tenant[tenantNo];
|
|
|
// foreach (var item in arrayJson)
|
|
|
// {
|
|
|
// list.Enqueue(item);
|
|
|
// }
|
|
|
|
|
|
// NLog.LogManager.GetCurrentClassLogger().Info("处理数据库租户更新,受影响的记录:<{0}>", arrayJson != null ? arrayJson.Length : 0);
|
|
|
// }
|
|
|
//}
|
|
|
|
|
|
////处理租户门店更新,影响具体租户具体门店
|
|
|
//if (migrate.IsDefined("store") && Global.Instance.Authc != null)
|
|
|
//{
|
|
|
// var storeNo = Global.Instance.Authc.TenantId+"_"+ Global.Instance.Authc.StoreNo;
|
|
|
|
|
|
// var tenant = migrate["store"];
|
|
|
// if (tenant.IsDefined(storeNo))
|
|
|
// {
|
|
|
// var arrayJson = tenant[storeNo];
|
|
|
// foreach (var item in arrayJson)
|
|
|
// {
|
|
|
// list.Enqueue(item);
|
|
|
// }
|
|
|
|
|
|
// NLog.LogManager.GetCurrentClassLogger().Info("处理数据库租户更新,受影响的记录:<{0}>", arrayJson != null ? arrayJson.Length : 0);
|
|
|
// }
|
|
|
//}
|
|
|
}
|
|
|
|
|
|
result = new Tuple<bool, ConcurrentQueue<string>>(true, list);
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
NLog.LogManager.GetCurrentClassLogger().Error(ex, "数据库升级文件格式错误");
|
|
|
|
|
|
result = new Tuple<bool, ConcurrentQueue<string>>(false, null);
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 修改数据库密码
|
|
|
/// </summary>
|
|
|
public static void ChangePwd(string pwd)
|
|
|
{
|
|
|
SQLiteConnectionStringBuilder builder = new SQLiteConnectionStringBuilder();
|
|
|
builder.DataSource = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\posv2.s3db");
|
|
|
builder.Password = "passwd";
|
|
|
builder.Version = 3;
|
|
|
builder.CacheSize = 10000;
|
|
|
builder.DefaultTimeout = 5000;
|
|
|
builder.PageSize = 4096;
|
|
|
builder.FailIfMissing = true;
|
|
|
builder.Pooling = true;
|
|
|
builder.DefaultIsolationLevel = System.Data.IsolationLevel.ReadCommitted;
|
|
|
builder.SyncMode = SynchronizationModes.Off;
|
|
|
builder.JournalMode = SQLiteJournalModeEnum.Truncate;
|
|
|
builder.UseUTF16Encoding = false;
|
|
|
|
|
|
using (SQLiteConnection connection = new SQLiteConnection(builder.ToString()))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
connection.Open();
|
|
|
connection.ChangePassword(pwd);
|
|
|
}
|
|
|
catch (SQLiteException ex)
|
|
|
{
|
|
|
throw new Exception(ex.Message);
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
connection.Close();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//UI线程异常
|
|
|
static void ApplicationThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
|
|
|
{
|
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Error(e.Exception, "ApplicationThreadException");
|
|
|
|
|
|
Global.Instance.BugReport(e.Exception);
|
|
|
|
|
|
}
|
|
|
|
|
|
//多线程异常
|
|
|
static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
|
|
{
|
|
|
|
|
|
NLog.LogManager.GetCurrentClassLogger().Error(e.ExceptionObject as Exception, "ApplicationThreadException");
|
|
|
|
|
|
Global.Instance.BugReport(e.ExceptionObject as Exception);
|
|
|
}
|
|
|
|
|
|
public static bool InterfaceHasIpv6Enabled(NetworkInterface @interface)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
var properties = @interface.GetIPProperties().GetIPv6Properties();
|
|
|
return properties.Index > -999;
|
|
|
}
|
|
|
catch (NetworkInformationException)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
throw ex;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|