diff --git a/插件库/Lskj.Main/Hosting/IExternalMainShell.cs b/插件库/Lskj.Main/Hosting/IExternalMainShell.cs
index 16864f7..6544f3a 100644
--- a/插件库/Lskj.Main/Hosting/IExternalMainShell.cs
+++ b/插件库/Lskj.Main/Hosting/IExternalMainShell.cs
@@ -16,6 +16,10 @@ namespace Lskj.Main.Hosting
void RequestRelogin();
+ void RequestLock();
+
+ void RequestSubscriptRefresh();
+
void RequestExit(string message);
}
}
diff --git a/插件库/Lskj.Main/Hosting/LegacyApplicationHost.cs b/插件库/Lskj.Main/Hosting/LegacyApplicationHost.cs
index b920ab1..4282b22 100644
--- a/插件库/Lskj.Main/Hosting/LegacyApplicationHost.cs
+++ b/插件库/Lskj.Main/Hosting/LegacyApplicationHost.cs
@@ -92,16 +92,58 @@ namespace Lskj.Main.Hosting
try
{
- Program.ShutdownMainProcess();
+ Manager.EndExternalSessionServices();
+ Manager.ExitSystem();
}
finally
{
- _mainProcessInitialized = false;
- _mainProcessShutdown = true;
- Manager.ExternalMainShell = null;
+ try
+ {
+ Program.ShutdownMainProcess();
+ }
+ finally
+ {
+ _mainProcessInitialized = false;
+ _mainProcessShutdown = true;
+ Manager.ExternalMainShell = null;
+ }
}
}
}
+
+ public static object CreateLoginRuntime()
+ {
+ return new LegacyLoginRuntime();
+ }
+
+ public static string PrepareAuthenticatedSession()
+ {
+ if (!ERPInfo.Instance.LoginResult)
+ return ResourceKeys.LoginFault;
+
+ DataTable enabled = MainImpl.EnableSubSystem();
+ ERPInfo.Instance.SubMenuCount = enabled == null
+ ? 0
+ : enabled.Rows.Count;
+ if (!Manager.TrySelectExternalMainShellSubSystem())
+ return ResourceKeys.SubSystemUnEnabled;
+
+ LegacyLoginRuntime.RefreshDelphiParameters();
+ Manager.BeginExternalSessionServices();
+ return string.Empty;
+ }
+
+ public static void CompleteAuthenticatedSession()
+ {
+ Manager.EndExternalSessionServices();
+ }
+
+ public static void ActivateSubSystem(string id, string caption)
+ {
+ ERPInfo.Instance.SubSysId = id ?? string.Empty;
+ ERPInfo.Instance.SubSysName = caption ?? string.Empty;
+ LegacyLoginRuntime.RefreshDelphiParameters();
+ }
}
///
@@ -111,6 +153,7 @@ namespace Lskj.Main.Hosting
public sealed partial class LegacyLoginRuntime
{
private DataTable _ledgerTable;
+ private bool _connectionInitialized;
public LegacyLoginRuntime()
{
@@ -175,11 +218,69 @@ namespace Lskj.Main.Hosting
public DataTable LoadLedgers()
{
+ EnsureInitialConnection();
_ledgerTable = MainImpl.GetLedgerList() ?? new DataTable("Ledgers");
SelectedLedgerName = ResolveSelectedLedgerName(_ledgerTable);
return _ledgerTable;
}
+ private void EnsureInitialConnection()
+ {
+ if (_connectionInitialized)
+ return;
+
+ if (string.Equals(
+ IniHelper.Read(SystemResourcesIniName, ConnectionModeKey),
+ "1",
+ StringComparison.Ordinal))
+ {
+ int port;
+ string host = IniHelper.Read(
+ SystemResourcesIniName,
+ DirectLastHostKey);
+ string name = IniHelper.Read(
+ SystemResourcesIniName,
+ DirectLastNameKey);
+ if (!int.TryParse(
+ IniHelper.Read(
+ SystemResourcesIniName,
+ DirectLastPortKey),
+ out port))
+ {
+ throw new InvalidOperationException(
+ "保存的直连端口无效,请重新设置连接。");
+ }
+
+ string error = ApplyDirectConnection(host, port, name);
+ if (!string.IsNullOrWhiteSpace(error))
+ throw new InvalidOperationException(error);
+ }
+ else
+ {
+ if (!DBConfig.Instance.CreateConnection(
+ DBConfig.Instance.Connection))
+ {
+ throw new InvalidOperationException(
+ ResourceKeys.UnConnectServer);
+ }
+ if (!string.Equals(
+ DBConfig.Instance.ServerType,
+ "达梦数据库",
+ StringComparison.Ordinal) &&
+ DelphiHelper.Delphi_Init(new StringBuilder(
+ DBConfig.Instance.GetDelphiConnection(
+ DBConfig.Instance.dephiConnection))) == 0)
+ {
+ throw new InvalidOperationException(
+ ResourceKeys.UnConnectServer + "[By Delphi]");
+ }
+ SystemInfo.RefreshSystemParam();
+ }
+
+ BaseResources.Localization(LocalizationType.CHS);
+ _connectionInitialized = true;
+ }
+
public DataTable LoadUsers()
{
DataTable users = SystemInfo.Instance.DisplayUserCode
@@ -220,6 +321,7 @@ namespace Lskj.Main.Hosting
string oldDataBook = DBConfig.Instance.DataBook;
string oldSelectedLedgerName = SelectedLedgerName;
string oldAccountBook = ERPInfo.Instance.AccountBook;
+ bool oldConnectionInitialized = _connectionInitialized;
try
{
DBConfig.Instance.ServerName = serverName;
@@ -238,10 +340,12 @@ namespace Lskj.Main.Hosting
}
SystemInfo.RefreshSystemParam();
+ BaseResources.Localization(LocalizationType.CHS);
DataTable users = LoadUsers();
SelectedLedgerName = dataBook;
ERPInfo.Instance.AccountBook = dataBook;
+ _connectionInitialized = true;
return users;
}
catch (Exception switchException)
@@ -251,6 +355,7 @@ namespace Lskj.Main.Hosting
DBConfig.Instance.DataBook = oldDataBook;
SelectedLedgerName = oldSelectedLedgerName;
ERPInfo.Instance.AccountBook = oldAccountBook;
+ _connectionInitialized = oldConnectionInitialized;
try
{
DBConfig.Instance.CreateConnection(DBConfig.Instance.Connection);
@@ -488,11 +593,11 @@ namespace Lskj.Main.Hosting
ERPInfo.Instance.LanguageName = "中文";
LanguageTranslation.GetLanguageComparisonTable();
- TrySetDelphiParameters();
+ RefreshDelphiParameters();
PubUtil.ClearFilesInDirectory(PubUtil.ImageDownloadPath);
}
- private static void TrySetDelphiParameters()
+ internal static void RefreshDelphiParameters()
{
try
{
diff --git a/插件库/Lskj.Main/Hosting/LegacyLoginRuntime.ConnectionSettings.cs b/插件库/Lskj.Main/Hosting/LegacyLoginRuntime.ConnectionSettings.cs
index 8856719..4acf479 100644
--- a/插件库/Lskj.Main/Hosting/LegacyLoginRuntime.ConnectionSettings.cs
+++ b/插件库/Lskj.Main/Hosting/LegacyLoginRuntime.ConnectionSettings.cs
@@ -9,6 +9,7 @@ using Lskj.Business;
using Lskj.Business.Impl;
using Lskj.Control.Model;
using Lskj.Core;
+using Lskj.Data;
using Lskj.Main.Model;
using Lskj.Model;
using Lskj.Util;
@@ -150,11 +151,13 @@ namespace Lskj.Main.Hosting
ValidateDatabase(candidate);
ValidateDelphi(candidate);
SystemInfo.RefreshSystemParam();
+ BaseResources.Localization(LocalizationType.CHS);
commit();
_ledgerTable = null;
SelectedLedgerName = candidate.AccountBookName;
ERPInfo.Instance.AccountBook = candidate.AccountBookName;
+ _connectionInitialized = true;
return string.Empty;
}
catch (Exception exception)
@@ -525,6 +528,7 @@ namespace Lskj.Main.Hosting
private string _delphiConnectionTemplate;
private string _selectedLedgerName;
private string _accountBook;
+ private bool _connectionInitialized;
public static LegacyConnectionStateSnapshot Capture(
LegacyLoginRuntime runtime)
@@ -540,7 +544,8 @@ namespace Lskj.Main.Hosting
_delphiConnectionTemplate =
DBConfig.Instance.dephiConnection,
_selectedLedgerName = runtime.SelectedLedgerName,
- _accountBook = ERPInfo.Instance.AccountBook
+ _accountBook = ERPInfo.Instance.AccountBook,
+ _connectionInitialized = runtime._connectionInitialized
};
}
@@ -556,6 +561,7 @@ namespace Lskj.Main.Hosting
_delphiConnectionTemplate;
runtime.SelectedLedgerName = _selectedLedgerName;
runtime._ledgerTable = null;
+ runtime._connectionInitialized = _connectionInitialized;
ERPInfo.Instance.AccountBook = _accountBook;
try
diff --git a/插件库/Lskj.Main/Model/Manager.cs b/插件库/Lskj.Main/Model/Manager.cs
index 99e2fd5..2a81be4 100644
--- a/插件库/Lskj.Main/Model/Manager.cs
+++ b/插件库/Lskj.Main/Model/Manager.cs
@@ -59,6 +59,10 @@ namespace Lskj.Main.Model
/// 由外部启动程序提供的可选主界面。默认为 null,旧 Ls_ERP.exe 仍打开 FrmMain。
///
public static IExternalMainShell ExternalMainShell { get; internal set; }
+ private static readonly object SessionMonitorSync = new object();
+ private static CancellationTokenSource _sessionMonitorCancellation;
+ private static readonly List SessionMonitorThreads =
+ new List();
///
/// 默认下载地址
///
@@ -182,9 +186,7 @@ namespace Lskj.Main.Model
/// 是否跳过子系统选择(适用于切换用户).
public static void ReStartMain(bool skipMenu = false)
{
- WhenConstraintLogin();
- LockApplication();
- if (SystemInfo.Instance.SubscriptRefreshTime > 0 && !SystemInfo.Instance.RefreshNotify) RefreshSubscript();
+ StartSessionMonitors();
if (_frmMain != null)
{
if (ERPInfo.Instance.WatermarkForm != null)
@@ -205,7 +207,7 @@ namespace Lskj.Main.Model
{
// WPF 主框架已经提供顶部子系统导航,不再打开旧 FrmSubSystem。
// 优先保留当前仍有权限的子系统,否则选择第一个可用子系统。
- isStart = SelectExternalMainShellSubSystem();
+ isStart = TrySelectExternalMainShellSubSystem();
}
else if (ERPInfo.Instance.SubMenuCount > 1 && !skipMenu)
{
@@ -634,8 +636,9 @@ namespace Lskj.Main.Model
}
return dllName;
}
- private static void ExitSystem()
+ internal static void ExitSystem()
{
+ StopSessionMonitors();
try
{
// 退出系统
@@ -720,7 +723,7 @@ namespace Lskj.Main.Model
/// 为外部 WPF 主框架选择登录后的初始子系统。
/// 旧 WinForms 入口仍由 FrmSubSystem 完成人工选择。
///
- private static bool SelectExternalMainShellSubSystem()
+ internal static bool TrySelectExternalMainShellSubSystem()
{
string where = string.IsNullOrEmpty(ERPInfo.Instance.SeriesId)
? string.Empty
@@ -951,192 +954,247 @@ namespace Lskj.Main.Model
return isSuccess;
}
#endregion
- ///
- /// 说明:强制登录下线
- /// 创建人:唐德馨
- /// 创建日期:2023-10-16
- /// 修改人:
- /// 修改日期:
- /// 修改备注:
- /// 版本:1.0
- ///
- private static void WhenConstraintLogin()
+ internal static void BeginExternalSessionServices()
{
- Thread thread = new Thread(() =>
+ StartSessionMonitors();
+ }
+
+ internal static void EndExternalSessionServices()
+ {
+ StopSessionMonitors();
+ }
+
+ private static void StartSessionMonitors()
+ {
+ StopSessionMonitors();
+
+ CancellationTokenSource cancellation =
+ new CancellationTokenSource();
+ var threads = new List();
+ if (SystemInfo.Instance.IsConstraintExit)
{
- bool isClose = false;
- while (SystemInfo.Instance.IsConstraintExit)
+ threads.Add(CreateSessionMonitor(
+ "ConstraintLoginMonitor",
+ delegate { MonitorConstraintLogin(cancellation.Token); }));
+ }
+ if (SystemInfo.Instance.AwaitTime > 10)
+ {
+ threads.Add(CreateSessionMonitor(
+ "ApplicationLockMonitor",
+ delegate { MonitorApplicationLock(cancellation.Token); }));
+ }
+ if (SystemInfo.Instance.SubscriptRefreshTime > 0 &&
+ !SystemInfo.Instance.RefreshNotify)
+ {
+ threads.Add(CreateSessionMonitor(
+ "SubscriptRefreshMonitor",
+ delegate { MonitorSubscriptRefresh(cancellation.Token); }));
+ }
+
+ lock (SessionMonitorSync)
+ {
+ _sessionMonitorCancellation = cancellation;
+ SessionMonitorThreads.AddRange(threads);
+ isAwaitTime = 10;
+ RefreshTime = 0;
+ }
+ foreach (Thread thread in threads)
+ thread.Start();
+ }
+
+ internal static void StopSessionMonitors()
+ {
+ CancellationTokenSource cancellation;
+ Thread[] threads;
+ lock (SessionMonitorSync)
+ {
+ cancellation = _sessionMonitorCancellation;
+ _sessionMonitorCancellation = null;
+ threads = SessionMonitorThreads.ToArray();
+ SessionMonitorThreads.Clear();
+ }
+
+ if (cancellation == null)
+ return;
+
+ cancellation.Cancel();
+ bool allStopped = true;
+ foreach (Thread thread in threads)
+ {
+ if (thread != null &&
+ thread != Thread.CurrentThread &&
+ thread.IsAlive)
{
- string hostName = "";
- string clientip = "";
- string loginMacAdress = "";
- DataTable loginTable = new DataTable();
+ if (!thread.Join(2000))
+ allStopped = false;
+ }
+ }
+ if (allStopped)
+ cancellation.Dispose();
+ }
+
+ private static Thread CreateSessionMonitor(
+ string name,
+ ThreadStart monitor)
+ {
+ return new Thread(monitor)
+ {
+ Name = name,
+ IsBackground = true
+ };
+ }
+
+ private static void MonitorConstraintLogin(CancellationToken token)
+ {
+ while (SystemInfo.Instance.IsConstraintExit &&
+ !token.IsCancellationRequested)
+ {
+ string clientip = string.Empty;
+ string loginMacAdress = string.Empty;
+ try
+ {
+ clientip = SqlHelper.ExecuteScalar(string.Format(
+ "select clientip from p_employeetab where employeeid = '{0}'",
+ ERPInfo.Instance.UserId)) + string.Empty;
+ loginMacAdress = SqlHelper.ExecuteScalar(string.Format(
+ "select macAdress from p_employeetab where employeeid = '{0}'",
+ ERPInfo.Instance.UserId)) + string.Empty;
+ }
+ catch (Exception)
+ {
+ }
+
+ if (!string.IsNullOrWhiteSpace(loginMacAdress) &&
+ !loginMacAdress.Equals(ERPInfo.Instance.MacAddress))
+ {
+ string message = string.Format(
+ "当前用户在另一电脑登录\r\nClientIp:{0}\r\nMacAdress:{1}\r\n当前系统即将关闭",
+ clientip,
+ loginMacAdress);
try
{
- loginTable = SqlHelper.ExecuteDataTable("select rtrim(ltrim(substring(hostname,1,100))) as hostname from master.dbo.sysprocesses where loginame = 'lserpAdmin' and (program_name = '' or program_name = '.Net SqlClient Data Provider')");
- hostName = SqlHelper.ExecuteScalar(string.Format("select hostname from p_LoginHostInfotab where OperatorId = '{0}' and Tagid = 1", ERPInfo.Instance.UserId)) + "";
- clientip = SqlHelper.ExecuteScalar(string.Format("select clientip from p_employeetab where employeeid = '{0}'", ERPInfo.Instance.UserId)) + "";
- loginMacAdress = SqlHelper.ExecuteScalar(string.Format("select macAdress from p_employeetab where employeeid = '{0}'", ERPInfo.Instance.UserId)) + "";
+ IExternalMainShell externalMainShell = ExternalMainShell;
+ if (externalMainShell != null &&
+ externalMainShell.IsOpen)
+ {
+ externalMainShell.RequestExit(message);
+ return;
+ }
+
+ bool isClose = false;
+ if (_frmSubSystem != null && _frmSubSystem.Visible)
+ {
+ _frmSubSystem.Invoke(new Action(delegate
+ {
+ _frmSubSystem.Opacity = 0;
+ MessageUtil.Show(message);
+ isClose = true;
+ }));
+ }
+ else if (_frmMain != null && _frmMain.Visible)
+ {
+ _frmMain.Invoke(new Action(delegate
+ {
+ _frmMain.Opacity = 0;
+ MessageUtil.Show(message);
+ isClose = true;
+ }));
+ }
+
+ if (isClose)
+ {
+ ExitSystem();
+ LogUtil.WriteDebug(
+ string.Empty,
+ "退出软件",
+ "软件退出",
+ "系统登录");
+ foreach (Process item in GetApplicationProcesses())
+ {
+ try
+ {
+ item.Kill();
+ }
+ catch (Exception)
+ {
+ }
+ }
+ Application.Exit();
+ return;
+ }
}
catch (Exception)
{
}
- //!string.IsNullOrEmpty(hostName) && loginTable.Select().Where(n => n["hostname"].Equals(hostName)).Count() > 0 && !loginMacAdress.Equals(ERPInfo.Instance.MacAddress)
- if (!loginMacAdress.Equals(ERPInfo.Instance.MacAddress))
- {
- try
- {
- if (_frmSubSystem != null && _frmSubSystem.Visible == true)
- {
- _frmSubSystem.Invoke(new Action(() =>
- {
- if (!isClose)
- {
- _frmSubSystem.Opacity = 0;
- MessageUtil.Show($"当前用户在另一电脑登录\r\nClientIp:{clientip}\r\nMacAdress:{loginMacAdress}\r\n当前系统即将关闭");
- isClose = true;
- }
- }));
- }
- else if (ExternalMainShell != null && ExternalMainShell.IsOpen)
- {
- ExternalMainShell.RequestExit($"当前用户在另一电脑登录\r\nClientIp:{clientip}\r\nMacAdress:{loginMacAdress}\r\n当前系统即将关闭");
- isClose = true;
- }
- else if (_frmMain != null && _frmMain.Visible == true)
- {
- _frmMain.Invoke(new Action(() =>
- {
- if (!isClose)
- {
- _frmMain.Opacity = 0;
- MessageUtil.Show($"当前用户在另一电脑登录\r\nClientIp:{clientip}\r\nMacAdress:{loginMacAdress}\r\n当前系统即将关闭");
- isClose = true;
- }
- }));
- }
- if (isClose)
- {
- if (DBConfig.Instance.NoticeExit)
- {
- Process[] p1 = Process.GetProcessesByName("Ls_Notice");
- foreach (Process item in p1)
- {
- try
- {
- item.Kill();
- }
- catch (Exception)
- {
- }
- }
- if (!string.IsNullOrWhiteSpace(SystemInfo.Instance.QuickMenuId))
- {
- Process[] p2 = Process.GetProcessesByName("Lskj.QuickModule");
- foreach (Process item in p2)
- {
- try
- {
- item.Kill();
- }
- catch (Exception)
- {
- }
- }
- }
- }
- //记录登出日志
- LogUtil.WriteDebug("", "退出软件", "软件退出", "系统登录");
- Process[] p = GetApplicationProcesses();
- foreach (Process item in p)
- {
- try
- {
- item.Kill();
- }
- catch (Exception)
- {
- }
- }
- //Environment.Exit(0);
- Application.Exit();
- break;
- }
- }
- catch (Exception)
- {
- }
- }
- Thread.Sleep(1000);
}
- });
- thread.Start();
- }
- ///
- /// 锁定程序
- ///
- private static void LockApplication()
- {
- Thread thread = new Thread(() =>
- {
- while (SystemInfo.Instance.AwaitTime > 10)
- {
- if (isAwaitTime == SystemInfo.Instance.AwaitTime)
- {
- isAwaitTime = 0;
- if (_frmMain != null && _frmMain.Visible == true)
- {
- _frmMain.Invoke(new Action(() =>
- {
- _frmMain.mainPanelControlEx.AwaitControl.BringToFront();
- _frmMain.mainPanelControlEx.AwaitControl.Visible = true;
- _frmMain.mainPanelControlEx.AwaitControl.OnFrmAwaitScreenLoad();
- }));
- }
- }
- isAwaitTime += 1;
- Thread.Sleep(1000);
- }
- });
- thread.Start();
+
+ if (token.WaitHandle.WaitOne(1000))
+ return;
+ }
}
-
-
-
-
-
- ///
- /// 刷新数量角标
- ///
- private static void RefreshSubscript()
+ private static void MonitorApplicationLock(CancellationToken token)
{
- Thread thread = new Thread(() =>
+ while (SystemInfo.Instance.AwaitTime > 10 &&
+ !token.IsCancellationRequested)
{
- while (SystemInfo.Instance.SubscriptRefreshTime > 0)
+ if (isAwaitTime >= SystemInfo.Instance.AwaitTime)
{
- if (RefreshTime >= SystemInfo.Instance.SubscriptRefreshTime)
+ isAwaitTime = 0;
+ IExternalMainShell externalMainShell = ExternalMainShell;
+ if (externalMainShell != null && externalMainShell.IsOpen)
{
- RefreshTime = 0;
- if (_frmMain != null && _frmMain.Visible == true)
+ externalMainShell.RequestLock();
+ return;
+ }
+ if (_frmMain != null && _frmMain.Visible)
+ {
+ _frmMain.Invoke(new Action(delegate
{
- XtraTabPage tabPage = _frmMain.mainPanelControlEx.tabMain.SelectedTabPage;
- if (tabPage.TabIndex == 0)
- {
- if (!SystemInfo.Instance.RefreshNotify)
- {
- Thread threadnew = new Thread(_frmMain.mainPanelControlEx.RefreshSubscript);
- threadnew.IsBackground = true;
- threadnew.Start();
- }
- }
+ _frmMain.mainPanelControlEx.AwaitControl.BringToFront();
+ _frmMain.mainPanelControlEx.AwaitControl.Visible = true;
+ _frmMain.mainPanelControlEx.AwaitControl.OnFrmAwaitScreenLoad();
+ }));
+ }
+ }
+ isAwaitTime += 1;
+ if (token.WaitHandle.WaitOne(1000))
+ return;
+ }
+ }
+
+ private static void MonitorSubscriptRefresh(CancellationToken token)
+ {
+ while (SystemInfo.Instance.SubscriptRefreshTime > 0 &&
+ !token.IsCancellationRequested)
+ {
+ if (RefreshTime >= SystemInfo.Instance.SubscriptRefreshTime)
+ {
+ RefreshTime = 0;
+ IExternalMainShell externalMainShell = ExternalMainShell;
+ if (externalMainShell != null && externalMainShell.IsOpen)
+ {
+ externalMainShell.RequestSubscriptRefresh();
+ }
+ else if (_frmMain != null && _frmMain.Visible)
+ {
+ XtraTabPage tabPage =
+ _frmMain.mainPanelControlEx.tabMain.SelectedTabPage;
+ if (tabPage != null &&
+ tabPage.TabIndex == 0 &&
+ !SystemInfo.Instance.RefreshNotify)
+ {
+ Thread refreshThread = new Thread(
+ _frmMain.mainPanelControlEx.RefreshSubscript);
+ refreshThread.IsBackground = true;
+ refreshThread.Start();
}
}
- RefreshTime += 1;
- Thread.Sleep(60000);
}
- });
- thread.Start();
+ RefreshTime += 1;
+ if (token.WaitHandle.WaitOne(60000))
+ return;
+ }
}