10 Commits

7 changed files with 1792 additions and 251 deletions
@@ -1,5 +1,6 @@
using Lskj.Business;
using Lskj.Model;
using Lskj.Util;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -56,6 +57,19 @@ namespace Lskj.Control.BrowserSetting
return contextMenuHandler;
}
protected override bool OnProcessMessageReceived(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
{
try
{
return OnProcessMessageReceivedCore(browser, frame, sourceProcess, message);
}
catch (Exception exception)
{
ReportProcessMessageFailure(exception);
return true;
}
}
private bool OnProcessMessageReceivedCore(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
{
if (message.Name.Equals("OpenModule"))
{
@@ -150,6 +164,46 @@ namespace Lskj.Control.BrowserSetting
return base.OnProcessMessageReceived(browser, frame, sourceProcess, message);
}
private static void ReportProcessMessageFailure(Exception exception)
{
try
{
LogHelper.Instance.WriteError(exception);
}
catch
{
// Logging must never rethrow across the native CEF callback.
}
Action showError = () =>
{
try
{
MessageUtil.Show(exception);
}
catch
{
// Error reporting must never terminate the browser callback.
}
};
try
{
System.Windows.Forms.Control mainControl = ERPInfo.Instance.MainControl;
if (mainControl == null || mainControl.IsDisposed || !mainControl.IsHandleCreated)
return;
if (mainControl.InvokeRequired)
mainControl.BeginInvoke(showError);
else
showError();
}
catch
{
// The main window may close while the CEF callback is reporting.
}
}
public void Created(CefBrowser cefBrowser)
{
if (OnCreated != null)
@@ -10,10 +10,16 @@ namespace Lskj.Main.Hosting
{
bool IsOpen { get; }
DialogResult ShowLoginDialog(object loginRuntime);
DialogResult ShowDialog();
void RequestRelogin();
void RequestLock();
void RequestSubscriptRefresh();
void RequestExit(string message);
}
}
@@ -1,29 +1,735 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using DevExpress.LookAndFeel;
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;
namespace Lskj.Main.Hosting
{
public sealed class LegacyProcessStartResult
{
internal LegacyProcessStartResult(
bool shouldRunApplication,
int exitCode)
{
ShouldRunApplication = shouldRunApplication;
ExitCode = exitCode;
}
public bool ShouldRunApplication { get; private set; }
public int ExitCode { get; private set; }
}
/// <summary>
/// 为独立的新启动程序公开原 Ls_ERP 初始化和登录流程。
/// </summary>
public static class LegacyApplicationHost
{
public static void Run(string[] args, IExternalMainShell externalMainShell)
{
if (externalMainShell == null)
throw new ArgumentNullException("externalMainShell");
if (Manager.ExternalMainShell != null)
throw new InvalidOperationException("旧程序已经由另一个外部主界面托管。");
private static readonly object ProcessSync = new object();
private static bool _mainProcessInitializationStarted;
private static bool _mainProcessInitialized;
private static bool _mainProcessShutdown;
public static LegacyProcessStartResult PrepareProcess(string[] args)
{
int code = Program.PrepareProcess(args ?? new string[0]);
return new LegacyProcessStartResult(code == -1, code);
}
public static void InitializeMainProcess(IExternalMainShell externalMainShell)
{
lock (ProcessSync)
{
if (_mainProcessInitialized)
throw new InvalidOperationException(
"旧主进程运行时已经初始化。");
if (_mainProcessShutdown)
throw new InvalidOperationException(
"旧主进程运行时已经关闭。");
_mainProcessInitializationStarted = true;
Manager.ExternalMainShell = externalMainShell;
try
{
Program.RunFromExternalHost(args);
Program.InitializeMainProcess();
_mainProcessInitialized = true;
}
catch
{
try
{
Program.ShutdownMainProcess();
}
finally
{
_mainProcessShutdown = true;
Manager.ExternalMainShell = null;
}
throw;
}
}
}
public static void ShutdownMainProcess()
{
lock (ProcessSync)
{
if (!_mainProcessInitializationStarted ||
_mainProcessShutdown)
{
return;
}
try
{
Manager.EndExternalSessionServices();
Manager.ExitSystem();
}
finally
{
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();
}
}
/// <summary>
/// 向外部 WPF 登录页提供旧账套、用户、认证和会话状态写入能力。
/// 该类型不创建 WinForms 控件,也不引用 WPF。
/// </summary>
public sealed partial class LegacyLoginRuntime
{
private DataTable _ledgerTable;
private bool _connectionInitialized;
public LegacyLoginRuntime()
{
ERPInfo.Instance.LoginResult = false;
}
public string SelectedLedgerName { get; private set; }
public string LoginName
{
get { return DBConfig.Instance.LoginName ?? string.Empty; }
}
public bool RememberPasswordEnabled
{
get { return !SystemInfo.Instance.DisableRememberPassword; }
}
public bool AutoUpdate
{
get
{
return SystemInfo.Instance.AutomaticUpdates ||
DBConfig.Instance.UpdateSet;
}
}
public bool AutoUpdateEnabled
{
get { return !SystemInfo.Instance.AutomaticUpdates; }
}
public bool SmartClient
{
get { return DBConfig.Instance.SmallClient; }
}
public bool SmartClientEnabled
{
get { return !SystemInfo.Instance.HiddenIntelligentClient; }
}
public bool SmartClientVisible
{
get { return !SystemInfo.Instance.HiddenIntelligentClient; }
}
public bool Notice
{
get
{
return SystemInfo.Instance.AutoCheckedNotice ||
SystemInfo.Instance.StartMessageBox ||
DBConfig.Instance.NoticeClient;
}
}
public bool NoticeEnabled
{
get { return !SystemInfo.Instance.StartMessageBox; }
}
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
? MainImpl.GetEmployeeListNew()
: MainImpl.GetEmployeeList();
return NormalizeUsersForLogin(
users ?? new DataTable("Users"),
SystemInfo.Instance.LoginUsername,
SystemInfo.Instance.DisplayUserCode);
}
public DataTable SelectLedger(string ledgerName)
{
if (string.IsNullOrWhiteSpace(ledgerName))
throw new InvalidOperationException("请选择账套。");
if (_ledgerTable == null)
LoadLedgers();
DataRow ledger = _ledgerTable.Rows.Cast<DataRow>().FirstOrDefault(
row => string.Equals(
Value(row, "ShowName"),
ledgerName,
StringComparison.OrdinalIgnoreCase));
if (ledger == null)
throw new InvalidOperationException("未找到所选账套,请重新选择。");
string serverName = Value(ledger, "IP");
string database = Value(ledger, "DBName");
string dataBook = Value(ledger, "ShowName");
if (string.IsNullOrWhiteSpace(serverName) ||
string.IsNullOrWhiteSpace(database))
{
throw new InvalidOperationException(ResourceKeys.UnSetServerAddress);
}
string oldServerName = DBConfig.Instance.ServerName;
string oldDatabase = DBConfig.Instance.DataBase;
string oldDataBook = DBConfig.Instance.DataBook;
string oldSelectedLedgerName = SelectedLedgerName;
string oldAccountBook = ERPInfo.Instance.AccountBook;
bool oldConnectionInitialized = _connectionInitialized;
try
{
DBConfig.Instance.ServerName = serverName;
DBConfig.Instance.DataBase = database;
DBConfig.Instance.DataBook = dataBook;
if (!DBConfig.Instance.CreateConnection(DBConfig.Instance.Connection))
throw new InvalidOperationException(ResourceKeys.ServerAddressFault);
if (!DBConfig.Instance.ServerType.Equals("达梦数据库") &&
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);
DataTable users = LoadUsers();
SelectedLedgerName = dataBook;
ERPInfo.Instance.AccountBook = dataBook;
_connectionInitialized = true;
return users;
}
catch (Exception switchException)
{
DBConfig.Instance.ServerName = oldServerName;
DBConfig.Instance.DataBase = oldDatabase;
DBConfig.Instance.DataBook = oldDataBook;
SelectedLedgerName = oldSelectedLedgerName;
ERPInfo.Instance.AccountBook = oldAccountBook;
_connectionInitialized = oldConnectionInitialized;
try
{
DBConfig.Instance.CreateConnection(DBConfig.Instance.Connection);
if (!DBConfig.Instance.ServerType.Equals("达梦数据库"))
{
DelphiHelper.Delphi_Init(new StringBuilder(
DBConfig.Instance.GetDelphiConnection(
DBConfig.Instance.dephiConnection)));
}
SystemInfo.RefreshSystemParam();
}
catch (Exception restoreException)
{
LogHelper.Instance.WriteError(restoreException);
}
LogHelper.Instance.WriteError(switchException);
throw;
}
}
public string LoadRememberedPassword(string loginName)
{
if (!RememberPasswordEnabled || string.IsNullOrWhiteSpace(loginName))
return null;
try
{
string encrypted = IniHelper.Read(
DBConfig.Instance.ServerName + loginName);
if (string.IsNullOrWhiteSpace(encrypted))
return null;
string[] parts = AESUtil.Decrypt(encrypted).Split('^');
bool remember;
if (parts.Length < 2 ||
!bool.TryParse(parts[0], out remember) ||
!remember)
{
return null;
}
return string.Join("^", parts.Skip(1).ToArray());
}
catch
{
return null;
}
}
public string Login(
string loginName,
string password,
bool rememberPassword,
bool forceLogin,
bool autoUpdate,
bool smartClient,
bool notice)
{
ERPInfo.Instance.LoginResult = false;
if (string.IsNullOrWhiteSpace(loginName))
return ResourceKeys.UserNameNotNull;
password = NormalizePassword(password);
try
{
DataTable users = MainImpl.GetEmployeeList();
string displayColumn = ResolveDisplayColumn(users);
List<DataRow> matches = users.Rows.Cast<DataRow>()
.Where(row =>
string.Equals(
Value(row, displayColumn),
loginName,
StringComparison.OrdinalIgnoreCase) ||
string.Equals(
Value(row, "UserCode"),
loginName,
StringComparison.OrdinalIgnoreCase))
.ToList();
if (matches.Count == 0)
return ResourceKeys.NameOrPasswordError;
if (matches.Count > 1)
return ResourceKeys.DuplicatedNameError;
DataRow user = matches[0];
string userId = Value(user, "UserId");
string userName = Value(user, "UserName");
string loginAccount = Value(user, "UserCode");
if (string.IsNullOrWhiteSpace(userId))
return ResourceKeys.UserNotFound;
ERPInfo.Instance.LoginResult = false;
if (SystemInfo.Instance.MacEnabled)
{
int macResult = MainImpl.CheckMacAddress(
ERPInfo.Instance.MacAddress,
userId);
MainImpl.LoginAfterRegister(
ERPInfo.Instance.MacAddress,
userId);
if (macResult == 0)
return ResourceKeys.LoginFault + ResourceKeys.UnKownMacAddress;
if (macResult == -1)
return ResourceKeys.LoginFault + ResourceKeys.UnKownMacAddressTable;
}
string keyError = VerifyEncryptionKey();
if (!string.IsNullOrEmpty(keyError))
return keyError;
if (!MainImpl.CheckingMacAddress(userId))
return ResourceKeys.MacAddressError +
",当前地址:" + ERPInfo.Instance.MacAddress;
int loginResult = MainImpl.Login(
userId,
password,
forceLogin);
if (loginResult != 0)
return LoginError(loginResult);
CompleteLogin(
userId,
userName,
loginAccount,
loginName,
password,
rememberPassword,
autoUpdate,
smartClient,
notice);
ERPInfo.Instance.LoginResult = true;
LogUtil.WriteDebug("", "登录软件", "进入操作", "系统登录");
return string.Empty;
}
catch (Exception exception)
{
ERPInfo.Instance.LoginResult = false;
LogUtil.WriteError(ResourceKeys.UserLogin, exception);
return ResourceKeys.LoginFault;
}
}
private static string VerifyEncryptionKey()
{
if (!SystemInfo.Instance.IsEncrypt)
return string.Empty;
int[] keyHandles = ERPInfo.Instance.keyHandles = new int[8];
int[] keyNumbers = ERPInfo.Instance.keyNumber = new int[8];
SmartX1Api.SmartX1Find(DBConfig.Instance.ServerName, keyHandles, keyNumbers);
int keyHandle = keyHandles[0];
int pin1 = Convert.ToInt32("0x987F6BCD", 16);
int pin2 = Convert.ToInt32("0xE193C5B2", 16);
int pin3 = Convert.ToInt32("0xD507CC28", 16);
int pin4 = Convert.ToInt32("0x4B125AF6", 16);
return SmartX1Api.SmartX1Open(keyHandle, pin1, pin2, pin3, pin4) == 0
? string.Empty
: "U盾数据获取失败,请重试或联系管理员";
}
private void CompleteLogin(
string userId,
string userName,
string loginAccount,
string enteredLoginName,
string password,
bool rememberPassword,
bool autoUpdate,
bool smartClient,
bool notice)
{
if (!MainImpl.HasExistsColumn("p_employeetab", "MacAdress"))
BaseImpl.ExecSqlValue("alter table p_employeetab add MacAdress varchar(100)");
BaseImpl.ExecSqlValue(string.Format(
"update p_employeetab set MacAdress = '{0}' where employeeid='{1}'",
(ERPInfo.Instance.MacAddress ?? string.Empty).Replace("'", "''"),
userId.Replace("'", "''")));
if (!MainImpl.HasExistsColumn("p_employeetab", "ClientIp"))
BaseImpl.ExecSqlValue("alter table p_employeetab add ClientIp varchar(100)");
BaseImpl.ExecSqlValue(string.Format(
"update p_employeetab set ClientIp = '{0}' where employeeid='{1}'",
(ERPInfo.Instance.LoginIPV4 ?? string.Empty).Replace("'", "''"),
userId.Replace("'", "''")));
if (SystemInfo.Instance.AutoSystemDataFormat)
{
FormatSystemDatetime formatter = new FormatSystemDatetime();
formatter.SetDateTimeFormat();
}
string skinName = MainImpl.GetUserSkin(userId);
skinName = string.IsNullOrEmpty(skinName)
? ERPInfo.Instance.SkinName
: skinName;
UserLookAndFeel.Default.SetSkinStyle(skinName);
IniHelper.Write(
DBConfig.Instance.ServerName + enteredLoginName,
AESUtil.Encrypt(rememberPassword + "^" + password));
ERPInfo.Instance.SeriesId = SystemInfo.Instance.seriesid;
ERPInfo.Instance.UserLinkPhone = MainImpl.GetUserPhone(userId);
ERPInfo.Instance.UserId = userId;
ERPInfo.Instance.UserName = userName;
ERPInfo.Instance.Password = SHAHelper.EncryptPassword(password);
ERPInfo.Instance.SkinName = skinName;
string accountBook = string.IsNullOrWhiteSpace(SelectedLedgerName)
? DBConfig.Instance.DataBook
: SelectedLedgerName;
ERPInfo.Instance.AccountBook = accountBook;
ERPInfo.Instance.LoginAccount = loginAccount;
ERPInfo.Instance.InPassWord = password;
ERPInfo.Instance.PrimitiveBrowser = SystemInfo.Instance.PrimitiveBrowser;
DBConfig.Instance.LoginName = enteredLoginName;
DBConfig.Instance.NoticeUserID = userId;
DBConfig.Instance.NoticeUserName = userName;
DBConfig.Instance.UpdateSet = autoUpdate;
DBConfig.Instance.SmallClient = smartClient;
DBConfig.Instance.NoticeClient = notice;
DBConfig.Instance.DataBook = accountBook;
DBConfig.Instance.WriteConfig();
if (userName.Equals("管理员") &&
!string.IsNullOrWhiteSpace(loginAccount))
{
ERPInfo.Instance.Password = SqlHelper.ExecuteString(
"Password",
"select Password from P_EmployeeTab where LoginAccount='" +
loginAccount.Replace("'", "''") + "'");
}
ERPInfo.Instance.LanguageName = "中文";
LanguageTranslation.GetLanguageComparisonTable();
RefreshDelphiParameters();
PubUtil.ClearFilesInDirectory(PubUtil.ImageDownloadPath);
}
internal static void RefreshDelphiParameters()
{
try
{
DelphiHelper.Delphi_SetParams(
Convert.ToInt32(ERPInfo.Instance.UserId),
string.IsNullOrWhiteSpace(ERPInfo.Instance.SubSysId)
? 0
: Convert.ToInt32(ERPInfo.Instance.SubSysId),
new StringBuilder(ERPInfo.Instance.UserName),
new StringBuilder(ERPInfo.Instance.WindowName),
new StringBuilder(ERPInfo.Instance.SkinName));
}
catch (Exception exception)
{
LogHelper.Instance.WriteError(exception);
}
}
private static string LoginError(int loginResult)
{
switch (loginResult)
{
case 1:
return ResourceKeys.NameOrPasswordError;
case 2:
return ResourceKeys.AlreadyLogin;
case -2:
return ResourceKeys.MultiFailedLogin;
default:
return ResourceKeys.LoginFault;
}
}
private static string ResolveSelectedLedgerName(DataTable ledgers)
{
DataRow selected = ledgers.Rows.Cast<DataRow>().FirstOrDefault(
row => string.Equals(
Value(row, "DBName"),
DBConfig.Instance.DataBase,
StringComparison.OrdinalIgnoreCase));
if (selected == null && !string.IsNullOrWhiteSpace(DBConfig.Instance.DataBook))
{
selected = ledgers.Rows.Cast<DataRow>().FirstOrDefault(
row => string.Equals(
Value(row, "ShowName"),
DBConfig.Instance.DataBook,
StringComparison.OrdinalIgnoreCase));
}
if (selected == null)
selected = ledgers.Rows.Cast<DataRow>().FirstOrDefault();
return selected == null ? string.Empty : Value(selected, "ShowName");
}
private static DataTable NormalizeUsersForLogin(
DataTable users,
string configuredLoginColumn,
bool displayUserCode)
{
DataTable normalized = new DataTable("Users");
normalized.Columns.Add("UserId", typeof(string));
normalized.Columns.Add("LoginName", typeof(string));
normalized.Columns.Add("DisplayName", typeof(string));
if (users == null)
return normalized;
string loginColumn = ResolveLoginColumn(
users,
configuredLoginColumn);
foreach (DataRow row in users.Rows)
{
string loginName = Value(row, loginColumn).Trim();
string userCode = Value(row, "UserCode").Trim();
if (string.IsNullOrWhiteSpace(loginName))
loginName = userCode;
if (string.IsNullOrWhiteSpace(loginName))
continue;
string displayName = loginName;
if (displayUserCode &&
!string.IsNullOrWhiteSpace(userCode) &&
!string.Equals(
loginName,
userCode,
StringComparison.OrdinalIgnoreCase))
{
displayName = loginName + "" + userCode + "";
}
normalized.Rows.Add(
Value(row, "UserId"),
loginName,
displayName);
}
return normalized;
}
private static string NormalizePassword(string password)
{
return (password ?? string.Empty).Trim();
}
private static string ResolveDisplayColumn(DataTable users)
{
return ResolveLoginColumn(
users,
SystemInfo.Instance.LoginUsername);
}
private static string ResolveLoginColumn(
DataTable users,
string configuredLoginColumn)
{
if (users != null &&
!string.IsNullOrWhiteSpace(configuredLoginColumn) &&
users.Columns.Contains(configuredLoginColumn))
{
return configuredLoginColumn;
}
return users != null && users.Columns.Contains("UserName")
? "UserName"
: "UserCode";
}
private static string Value(DataRow row, string columnName)
{
return row != null && row.Table.Columns.Contains(columnName)
? row[columnName] + string.Empty
: string.Empty;
}
}
}
@@ -0,0 +1,601 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Net;
using System.Text;
using Microsoft.Win32;
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;
namespace Lskj.Main.Hosting
{
public sealed partial class LegacyLoginRuntime
{
private const string RegistryFilePath = @"AA_LS_Erp V2.0\File";
private const string SystemResourcesIniName = "SystemResources.ini";
private const string SystemResourcesSection = "SystemResources";
private const string DirectHistoryPrefix = "DownloadAESStr_";
private const string DirectLastHostKey = "LocalLastIP";
private const string DirectLastPortKey = "LocalLastPort";
private const string DirectLastNameKey = "LocalLastPortName";
private const string ConnectionModeKey = "FrmConfigFlag";
private const int DirectRequestTimeoutMilliseconds = 5000;
public DataSet LoadConnectionSettings()
{
var result = new DataSet("LoginConnectionSettings");
DataTable settings = CreateSettingsTable();
DataTable savedConnections = CreateSavedConnectionsTable();
string directHost = IniHelper.Read(
SystemResourcesIniName,
DirectLastHostKey);
string directPort = IniHelper.Read(
SystemResourcesIniName,
DirectLastPortKey);
string directName = IniHelper.Read(
SystemResourcesIniName,
DirectLastNameKey);
bool directMode = string.Equals(
IniHelper.Read(SystemResourcesIniName, ConnectionModeKey),
"1",
StringComparison.Ordinal);
settings.Rows.Add(
directMode ? "Direct" : "Database",
ReadRegistryValue("ServerName"),
ReadRegistryValue("datastr"),
directHost,
directPort,
directName);
Dictionary<string, string> entries = IniHelper.GetSectionKeys(
SystemResourcesIniName,
SystemResourcesSection);
foreach (KeyValuePair<string, string> entry in entries)
{
if (!entry.Key.StartsWith(
DirectHistoryPrefix,
StringComparison.OrdinalIgnoreCase))
{
continue;
}
string endpoint = entry.Key.Substring(
DirectHistoryPrefix.Length);
string host;
int port;
if (!TrySplitEndpoint(endpoint, out host, out port))
continue;
string displayName = ReadHistoryDisplayName(entry.Value);
if (string.IsNullOrWhiteSpace(displayName))
continue;
savedConnections.Rows.Add(
entry.Key,
displayName,
host,
port);
}
result.Tables.Add(settings);
result.Tables.Add(savedConnections);
return result;
}
public string ApplyDatabaseConnection(
string serverName,
string databaseName)
{
try
{
ConnectionCandidate candidate = CreateDatabaseCandidate(
serverName,
databaseName);
return ApplyConnection(
candidate,
delegate { CommitDatabaseConnection(); });
}
catch (Exception exception)
{
LogSanitized(exception);
return ToSafeConnectionError(exception);
}
}
public string ApplyDirectConnection(
string host,
int port,
string accountBookName)
{
try
{
Uri resourceUri = BuildDirectResourceUri(host, port);
string encryptedPayload = DownloadDirectPayload(resourceUri);
string decryptedPayload = AESUtil.Decrypt(encryptedPayload);
string[] parts = ParseDirectPayload(decryptedPayload);
ConnectionCandidate candidate = CreateDirectCandidate(
parts,
host,
port,
accountBookName,
encryptedPayload);
return ApplyConnection(
candidate,
delegate { CommitDirectConnection(candidate); });
}
catch (Exception exception)
{
LogSanitized(exception);
return ToSafeConnectionError(exception);
}
}
private string ApplyConnection(
ConnectionCandidate candidate,
Action commit)
{
LegacyConnectionStateSnapshot snapshot =
LegacyConnectionStateSnapshot.Capture(this);
try
{
ApplyCandidate(candidate);
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)
{
snapshot.Restore(this);
LogSanitized(exception);
return ToSafeConnectionError(exception);
}
}
private static ConnectionCandidate CreateDatabaseCandidate(
string serverName,
string databaseName)
{
serverName = (serverName ?? string.Empty).Trim();
databaseName = (databaseName ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(serverName))
throw new ArgumentException("请输入数据库服务器地址。");
if (string.IsNullOrWhiteSpace(databaseName))
throw new ArgumentException("请输入数据库名称。");
return new ConnectionCandidate
{
ServerName = serverName,
DatabaseName = databaseName,
AccountBookName = DBConfig.Instance.DataBook ?? string.Empty,
ServerType = DBConfig.Instance.ServerType ?? "SqlServer",
ConnectionTemplate = string.Empty,
DelphiConnectionTemplate = string.Empty
};
}
private static ConnectionCandidate CreateDirectCandidate(
string[] parts,
string host,
int port,
string accountBookName,
string encryptedPayload)
{
accountBookName = (accountBookName ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(accountBookName))
throw new ArgumentException("请输入直连账套名称。");
string connectionTemplate =
"Server={0};Database={1};Persist Security Info=True;" +
"User ID=" + parts[2] + ";Password=" + parts[3] + ";" +
"Connection Timeout=5;MultipleActiveResultSets=true";
string delphiTemplate =
"Provider=SQLOLEDB.1;Server={0};Database={1};" +
"Persist Security Info=True;User ID=" + parts[2] +
";Password=" + parts[3] + ";Connection Timeout=5";
return new ConnectionCandidate
{
ServerName = parts[0],
DatabaseName = parts[1],
AccountBookName = accountBookName,
ServerType = DBConfig.Instance.ServerType ?? "SqlServer",
ConnectionTemplate = AESUtil.Encrypt(connectionTemplate),
DelphiConnectionTemplate = AESUtil.Encrypt(delphiTemplate),
DirectHost = (host ?? string.Empty).Trim().TrimEnd('/'),
DirectPort = port,
DirectEncryptedPayload = encryptedPayload
};
}
private static void ApplyCandidate(ConnectionCandidate candidate)
{
DBConfig.Instance.ServerName = candidate.ServerName;
DBConfig.Instance.DataBase = candidate.DatabaseName;
DBConfig.Instance.DataBook = candidate.AccountBookName;
DBConfig.Instance.ServerType = candidate.ServerType;
DBConfig.Instance.Connection = candidate.ConnectionTemplate;
DBConfig.Instance.dephiConnection =
candidate.DelphiConnectionTemplate;
}
private static void ValidateDatabase(ConnectionCandidate candidate)
{
if (!DBConfig.Instance.CreateConnection(
candidate.ConnectionTemplate))
{
throw new LegacyConnectionSettingsException(
"无法连接数据库,请检查服务器和数据库配置。");
}
}
private static void ValidateDelphi(ConnectionCandidate candidate)
{
if (string.Equals(
candidate.ServerType,
"达梦数据库",
StringComparison.Ordinal))
{
return;
}
string connection = DBConfig.Instance.GetDelphiConnection(
candidate.DelphiConnectionTemplate);
if (DelphiHelper.Delphi_Init(new StringBuilder(connection)) == 0)
{
throw new LegacyConnectionSettingsException(
"数据库已连接,但 Delphi 组件初始化失败。");
}
}
private static void CommitDatabaseConnection()
{
DBConfig.Instance.WriteConfig();
IniHelper.Write(
SystemResourcesIniName,
ConnectionModeKey,
"0");
}
private static void CommitDirectConnection(
ConnectionCandidate candidate)
{
string endpoint = candidate.DirectHost + ":" +
candidate.DirectPort;
string historyValue = candidate.AccountBookName + "^" +
candidate.DirectEncryptedPayload;
IniHelper.Write(
SystemResourcesIniName,
DirectHistoryPrefix + endpoint,
historyValue);
IniHelper.Write(
SystemResourcesIniName,
DirectLastHostKey,
candidate.DirectHost);
IniHelper.Write(
SystemResourcesIniName,
DirectLastPortKey,
candidate.DirectPort.ToString());
IniHelper.Write(
SystemResourcesIniName,
DirectLastNameKey,
candidate.AccountBookName);
IniHelper.Write(
SystemResourcesIniName,
ConnectionModeKey,
"1");
DBConfig.Instance.WriteConfig(
DirectLastHostKey,
candidate.DirectHost);
DBConfig.Instance.WriteConfig(
DirectLastPortKey,
candidate.DirectPort.ToString());
DBConfig.Instance.WriteConfig(
DirectLastNameKey,
candidate.AccountBookName);
}
private static Uri BuildDirectResourceUri(string host, int port)
{
host = (host ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(host))
throw new ArgumentException("请输入直连服务器地址。");
if (port < 1 || port > 65535)
throw new ArgumentOutOfRangeException(
"port",
"直连端口必须介于 1 和 65535 之间。");
if (!host.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
!host.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
host = "http://" + host;
}
Uri baseUri;
if (!Uri.TryCreate(host, UriKind.Absolute, out baseUri) ||
(baseUri.Scheme != Uri.UriSchemeHttp &&
baseUri.Scheme != Uri.UriSchemeHttps))
{
throw new ArgumentException("直连服务器地址格式无效。");
}
var builder = new UriBuilder(baseUri)
{
Port = port,
Path = "/SystemResources.txt",
Query = string.Empty,
Fragment = string.Empty
};
return builder.Uri;
}
private static string DownloadDirectPayload(Uri resourceUri)
{
var request = (HttpWebRequest)WebRequest.Create(resourceUri);
request.Method = "GET";
request.Timeout = DirectRequestTimeoutMilliseconds;
request.ReadWriteTimeout = DirectRequestTimeoutMilliseconds;
using (var response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
{
if (stream == null)
{
throw new InvalidDataException(
"直连服务器未返回连接配置。");
}
using (var reader = new StreamReader(
stream,
Encoding.UTF8,
true))
{
string payload = reader.ReadToEnd().Trim();
if (string.IsNullOrWhiteSpace(payload))
{
throw new InvalidDataException(
"直连服务器返回的连接配置为空。");
}
return payload;
}
}
}
private static string[] ParseDirectPayload(string decryptedPayload)
{
string[] parts = (decryptedPayload ?? string.Empty).Split('^');
if (parts.Length != 5)
{
throw new InvalidDataException(
"直连服务器返回的连接配置格式无效。");
}
for (int index = 0; index < parts.Length; index++)
{
parts[index] = (parts[index] ?? string.Empty).Trim();
if (string.IsNullOrWhiteSpace(parts[index]))
{
throw new InvalidDataException(
"直连服务器返回的连接配置不完整。");
}
}
return parts;
}
private static string ToSafeConnectionError(Exception exception)
{
if (exception is ArgumentException ||
exception is InvalidDataException ||
exception is LegacyConnectionSettingsException)
{
return exception.Message;
}
if (exception is WebException)
{
return "无法读取直连配置,请检查地址、端口和网络连接。";
}
return "连接设置失败,请检查配置和网络连接。";
}
private static void LogSanitized(Exception exception)
{
string exceptionType = exception == null
? "Unknown"
: exception.GetType().FullName;
LogHelper.Instance.WriteLog(
"WPF 登录连接设置失败。异常类型:" + exceptionType);
}
private static DataTable CreateSettingsTable()
{
var table = new DataTable("Settings");
table.Columns.Add("Mode", typeof(string));
table.Columns.Add("ServerName", typeof(string));
table.Columns.Add("DatabaseName", typeof(string));
table.Columns.Add("DirectHost", typeof(string));
table.Columns.Add("DirectPort", typeof(string));
table.Columns.Add("DirectAccountBookName", typeof(string));
return table;
}
private static DataTable CreateSavedConnectionsTable()
{
var table = new DataTable("SavedDirectConnections");
table.Columns.Add("Key", typeof(string));
table.Columns.Add("DisplayName", typeof(string));
table.Columns.Add("Host", typeof(string));
table.Columns.Add("Port", typeof(int));
return table;
}
private static string ReadRegistryValue(string valueName)
{
try
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(
RegistryFilePath,
false))
{
object value = key == null
? null
: key.GetValue(valueName, string.Empty);
return value == null ? string.Empty : value.ToString();
}
}
catch
{
return string.Empty;
}
}
private static bool TrySplitEndpoint(
string endpoint,
out string host,
out int port)
{
host = string.Empty;
port = 0;
if (string.IsNullOrWhiteSpace(endpoint))
return false;
int separatorIndex = endpoint.LastIndexOf(':');
if (separatorIndex <= 0 ||
separatorIndex >= endpoint.Length - 1)
{
return false;
}
host = endpoint.Substring(0, separatorIndex).Trim();
return !string.IsNullOrWhiteSpace(host) &&
int.TryParse(endpoint.Substring(separatorIndex + 1), out port) &&
port >= 1 &&
port <= 65535;
}
private static string ReadHistoryDisplayName(string value)
{
if (string.IsNullOrWhiteSpace(value))
return string.Empty;
int separatorIndex = value.IndexOf('^');
return separatorIndex < 0
? string.Empty
: value.Substring(0, separatorIndex).Trim();
}
private sealed class ConnectionCandidate
{
public string ServerName;
public string DatabaseName;
public string AccountBookName;
public string ServerType;
public string ConnectionTemplate;
public string DelphiConnectionTemplate;
public string DirectHost;
public int DirectPort;
public string DirectEncryptedPayload;
}
private sealed class LegacyConnectionStateSnapshot
{
private string _serverName;
private string _databaseName;
private string _dataBook;
private string _loginName;
private string _serverType;
private string _connectionTemplate;
private string _delphiConnectionTemplate;
private string _selectedLedgerName;
private string _accountBook;
private bool _connectionInitialized;
public static LegacyConnectionStateSnapshot Capture(
LegacyLoginRuntime runtime)
{
return new LegacyConnectionStateSnapshot
{
_serverName = DBConfig.Instance.ServerName,
_databaseName = DBConfig.Instance.DataBase,
_dataBook = DBConfig.Instance.DataBook,
_loginName = DBConfig.Instance.LoginName,
_serverType = DBConfig.Instance.ServerType,
_connectionTemplate = DBConfig.Instance.Connection,
_delphiConnectionTemplate =
DBConfig.Instance.dephiConnection,
_selectedLedgerName = runtime.SelectedLedgerName,
_accountBook = ERPInfo.Instance.AccountBook,
_connectionInitialized = runtime._connectionInitialized
};
}
public void Restore(LegacyLoginRuntime runtime)
{
DBConfig.Instance.ServerName = _serverName;
DBConfig.Instance.DataBase = _databaseName;
DBConfig.Instance.DataBook = _dataBook;
DBConfig.Instance.LoginName = _loginName;
DBConfig.Instance.ServerType = _serverType;
DBConfig.Instance.Connection = _connectionTemplate;
DBConfig.Instance.dephiConnection =
_delphiConnectionTemplate;
runtime.SelectedLedgerName = _selectedLedgerName;
runtime._ledgerTable = null;
runtime._connectionInitialized = _connectionInitialized;
ERPInfo.Instance.AccountBook = _accountBook;
try
{
if (!string.IsNullOrWhiteSpace(_serverName) &&
!string.IsNullOrWhiteSpace(_databaseName))
{
DBConfig.Instance.CreateConnection(
_connectionTemplate);
if (!string.Equals(
_serverType,
"达梦数据库",
StringComparison.Ordinal))
{
DelphiHelper.Delphi_Init(new StringBuilder(
DBConfig.Instance.GetDelphiConnection(
_delphiConnectionTemplate)));
}
SystemInfo.RefreshSystemParam();
}
}
catch (Exception restoreException)
{
LogSanitized(restoreException);
}
}
}
private sealed class LegacyConnectionSettingsException : Exception
{
public LegacyConnectionSettingsException(string message)
: base(message)
{
}
}
}
}
+1
View File
@@ -278,6 +278,7 @@
<Compile Include="Model\winApi.cs" />
<Compile Include="Hosting\IExternalMainShell.cs" />
<Compile Include="Hosting\LegacyApplicationHost.cs" />
<Compile Include="Hosting\LegacyLoginRuntime.ConnectionSettings.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Control\AwaitScreenControl.resx">
+226 -155
View File
@@ -59,6 +59,10 @@ namespace Lskj.Main.Model
/// 由外部启动程序提供的可选主界面。默认为 null,旧 Ls_ERP.exe 仍打开 FrmMain。
/// </summary>
public static IExternalMainShell ExternalMainShell { get; internal set; }
private static readonly object SessionMonitorSync = new object();
private static CancellationTokenSource _sessionMonitorCancellation;
private static readonly List<Thread> SessionMonitorThreads =
new List<Thread>();
/// <summary>
/// 默认下载地址
/// </summary>
@@ -87,8 +91,12 @@ namespace Lskj.Main.Model
public static void StartForm()
{
bool isStart = true;
bool useLegacySplash = ExternalMainShell == null;
// 加载Splash动画界面
if (useLegacySplash)
{
SplashForm.ShowForm();
}
//CheckLocalConfig();
// C#数据库连接检查
bool isLocalConnect = false;
@@ -108,7 +116,10 @@ namespace Lskj.Main.Model
if (!DBConfig.Instance.CreateConnection(DBConfig.Instance.Connection))
{
MessageUtil.Show(ResourceKeys.UnConnectServer);
if (useLegacySplash)
{
SplashForm.HideForm();
}
DialogResult result = RunConfigForm();
isStart = result == DialogResult.OK;
}
@@ -120,7 +131,10 @@ namespace Lskj.Main.Model
if (DelphiHelper.Delphi_Init(new StringBuilder(DBConfig.Instance.GetDelphiConnection(DBConfig.Instance.dephiConnection))) == 0)
{
MessageUtil.Show(ResourceKeys.UnConnectServer + "[By Delphi]");
if (useLegacySplash)
{
SplashForm.HideForm();
}
RunConfigForm();
return;
}
@@ -128,7 +142,10 @@ namespace Lskj.Main.Model
if (useLegacySplash)
{
SplashForm.HideForm();
}
// 汉化dev控件
BaseResources.Localization(LocalizationType.CHS);
// 启动登录页面
@@ -149,10 +166,13 @@ namespace Lskj.Main.Model
}
}
else
{
if (useLegacySplash)
{
SplashForm.HideForm();
}
}
}
/// <summary>
/// <para>说明:重新启动</para>
@@ -166,9 +186,7 @@ namespace Lskj.Main.Model
/// <param name="skipMenu">是否跳过子系统选择(适用于切换用户).</param>
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)
@@ -189,7 +207,7 @@ namespace Lskj.Main.Model
{
// WPF 主框架已经提供顶部子系统导航,不再打开旧 FrmSubSystem。
// 优先保留当前仍有权限的子系统,否则选择第一个可用子系统。
isStart = SelectExternalMainShellSubSystem();
isStart = TrySelectExternalMainShellSubSystem();
}
else if (ERPInfo.Instance.SubMenuCount > 1 && !skipMenu)
{
@@ -618,8 +636,9 @@ namespace Lskj.Main.Model
}
return dllName;
}
private static void ExitSystem()
internal static void ExitSystem()
{
StopSessionMonitors();
try
{
// 退出系统
@@ -675,6 +694,9 @@ namespace Lskj.Main.Model
/// <returns>DialogResult.</returns>
private static DialogResult RunLoginForm()
{
if (ExternalMainShell != null)
return ExternalMainShell.ShowLoginDialog(new LegacyLoginRuntime());
FrmLogin frmLogin = new FrmLogin();
return frmLogin.ShowDialog();
}
@@ -701,17 +723,14 @@ namespace Lskj.Main.Model
/// 为外部 WPF 主框架选择登录后的初始子系统。
/// 旧 WinForms 入口仍由 FrmSubSystem 完成人工选择。
/// </summary>
private static bool SelectExternalMainShellSubSystem()
internal static bool TrySelectExternalMainShellSubSystem()
{
string where = string.IsNullOrEmpty(ERPInfo.Instance.SeriesId)
? string.Empty
: string.Format("and SeriesId={0}", ERPInfo.Instance.SeriesId);
DataTable subSystems = MainImpl.GetSubSystems(where);
if (subSystems == null || subSystems.Rows.Count == 0)
{
MessageUtil.Show(ResourceKeys.SubSystemUnEnabled);
return false;
}
DataRow selectedRow = subSystems.AsEnumerable().FirstOrDefault(row =>
IsEnabledSubSystem(row) &&
@@ -722,10 +741,7 @@ namespace Lskj.Main.Model
if (selectedRow == null)
selectedRow = subSystems.AsEnumerable().FirstOrDefault(IsEnabledSubSystem);
if (selectedRow == null)
{
MessageUtil.Show(ResourceKeys.SubSystemUnEnabled);
return false;
}
ERPInfo.Instance.SubMenuCount = subSystems.AsEnumerable().Count(IsEnabledSubSystem);
ERPInfo.Instance.SubSysId = selectedRow["SubSysId"] + string.Empty;
@@ -932,142 +948,202 @@ namespace Lskj.Main.Model
return isSuccess;
}
#endregion
/// <summary>
/// <para>说明:强制登录下线</para>
/// <para>创建人:唐德馨</para>
/// <para>创建日期:2023-10-16 </para>
/// <para>修改人:</para>
/// <para>修改日期:</para>
/// <para>修改备注:</para>
/// <para>版本:1.0</para>
/// </summary>
private static void WhenConstraintLogin()
internal static void BeginExternalSessionServices()
{
Thread thread = new Thread(() =>
{
bool isClose = false;
while (SystemInfo.Instance.IsConstraintExit)
{
string hostName = "";
string clientip = "";
string loginMacAdress = "";
DataTable loginTable = new DataTable();
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)) + "";
StartSessionMonitors();
}
catch (Exception)
internal static void EndExternalSessionServices()
{
StopSessionMonitors();
}
//!string.IsNullOrEmpty(hostName) && loginTable.Select().Where(n => n["hostname"].Equals(hostName)).Count() > 0 && !loginMacAdress.Equals(ERPInfo.Instance.MacAddress)
if (!loginMacAdress.Equals(ERPInfo.Instance.MacAddress))
private static void StartSessionMonitors()
{
try
StopSessionMonitors();
CancellationTokenSource cancellation =
new CancellationTokenSource();
var threads = new List<Thread>();
if (SystemInfo.Instance.IsConstraintExit)
{
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;
threads.Add(CreateSessionMonitor(
"ConstraintLoginMonitor",
delegate { MonitorConstraintLogin(cancellation.Token); }));
}
}));
}
else if (ExternalMainShell != null && ExternalMainShell.IsOpen)
if (SystemInfo.Instance.AwaitTime > 10)
{
ExternalMainShell.RequestExit($"当前用户在另一电脑登录\r\nClientIp:{clientip}\r\nMacAdress:{loginMacAdress}\r\n当前系统即将关闭");
isClose = true;
threads.Add(CreateSessionMonitor(
"ApplicationLockMonitor",
delegate { MonitorApplicationLock(cancellation.Token); }));
}
else if (_frmMain != null && _frmMain.Visible == true)
if (SystemInfo.Instance.SubscriptRefreshTime > 0 &&
!SystemInfo.Instance.RefreshNotify)
{
_frmMain.Invoke(new Action(() =>
threads.Add(CreateSessionMonitor(
"SubscriptRefreshMonitor",
delegate { MonitorSubscriptRefresh(cancellation.Token); }));
}
lock (SessionMonitorSync)
{
if (!isClose)
{
_frmMain.Opacity = 0;
MessageUtil.Show($"当前用户在另一电脑登录\r\nClientIp:{clientip}\r\nMacAdress:{loginMacAdress}\r\n当前系统即将关闭");
isClose = true;
_sessionMonitorCancellation = cancellation;
SessionMonitorThreads.AddRange(threads);
isAwaitTime = 10;
RefreshTime = 0;
}
}));
}
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);
}
});
foreach (Thread thread in threads)
thread.Start();
}
/// <summary>
/// 锁定程序
/// </summary>
private static void LockApplication()
internal static void StopSessionMonitors()
{
Thread thread = new Thread(() =>
CancellationTokenSource cancellation;
Thread[] threads;
lock (SessionMonitorSync)
{
while (SystemInfo.Instance.AwaitTime > 10)
cancellation = _sessionMonitorCancellation;
_sessionMonitorCancellation = null;
threads = SessionMonitorThreads.ToArray();
SessionMonitorThreads.Clear();
}
if (cancellation == null)
return;
cancellation.Cancel();
bool allStopped = true;
foreach (Thread thread in threads)
{
if (isAwaitTime == SystemInfo.Instance.AwaitTime)
if (thread != null &&
thread != Thread.CurrentThread &&
thread.IsAlive)
{
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
{
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)
{
}
}
if (token.WaitHandle.WaitOne(1000))
return;
}
}
private static void MonitorApplicationLock(CancellationToken token)
{
while (SystemInfo.Instance.AwaitTime > 10 &&
!token.IsCancellationRequested)
{
if (isAwaitTime >= SystemInfo.Instance.AwaitTime)
{
isAwaitTime = 0;
if (_frmMain != null && _frmMain.Visible == true)
IExternalMainShell externalMainShell = ExternalMainShell;
if (externalMainShell != null && externalMainShell.IsOpen)
{
_frmMain.Invoke(new Action(() =>
externalMainShell.RequestLock();
return;
}
if (_frmMain != null && _frmMain.Visible)
{
_frmMain.Invoke(new Action(delegate
{
_frmMain.mainPanelControlEx.AwaitControl.BringToFront();
_frmMain.mainPanelControlEx.AwaitControl.Visible = true;
@@ -1076,48 +1152,43 @@ namespace Lskj.Main.Model
}
}
isAwaitTime += 1;
Thread.Sleep(1000);
if (token.WaitHandle.WaitOne(1000))
return;
}
});
thread.Start();
}
/// <summary>
/// 刷新数量角标
/// </summary>
private static void RefreshSubscript()
private static void MonitorSubscriptRefresh(CancellationToken token)
{
Thread thread = new Thread(() =>
{
while (SystemInfo.Instance.SubscriptRefreshTime > 0)
while (SystemInfo.Instance.SubscriptRefreshTime > 0 &&
!token.IsCancellationRequested)
{
if (RefreshTime >= SystemInfo.Instance.SubscriptRefreshTime)
{
RefreshTime = 0;
if (_frmMain != null && _frmMain.Visible == true)
IExternalMainShell externalMainShell = ExternalMainShell;
if (externalMainShell != null && externalMainShell.IsOpen)
{
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();
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);
if (token.WaitHandle.WaitOne(60000))
return;
}
});
thread.Start();
}
+158 -56
View File
@@ -21,11 +21,22 @@ using System.Resources;
using System.Runtime.InteropServices;
using System.Resources;
using System.Diagnostics;
using Lskj.Main.Hosting;
namespace Lskj.Main
{
static class Program
{
private static CefMainArgs _mainArgs;
private static DemoCefApp _cefApp;
private static CefSettings _cefSettings;
private static Messager _messageFilter;
private static EventHandler _cefIdleHandler;
private static AboutDevCompanion _devCompanion;
private static bool _cefInitialized;
private static bool _mainProcessInitialized;
private static bool _mainProcessShutdown;
//[DllImport("user32.dll")]
//private static extern bool SetProcessDpiAwarenessContext(IntPtr dpiContext);
@@ -36,69 +47,160 @@ namespace Lskj.Main
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
static int Main(string[] args)
{
//SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
CefRuntime.Load();//cef浏览器模块设置加载
var mainArgs = new CefMainArgs(args);
var app = new DemoCefApp();
var settings = new CefSettings
LegacyProcessStartResult processResult;
try
{
processResult = LegacyApplicationHost.PrepareProcess(args);
}
catch (Exception exception)
{
LogHelper.Instance.WriteError(exception);
return -1;
}
if (!processResult.ShouldRunApplication)
return processResult.ExitCode;
try
{
LegacyApplicationHost.InitializeMainProcess(null);
Manager.StartForm();
return 0;
}
catch (Exception exception)
{
MessageUtil.Show(exception);
LogHelper.Instance.WriteError(exception);
return -1;
}
finally
{
LegacyApplicationHost.ShutdownMainProcess();
}
}
internal static int PrepareProcess(string[] args)
{
if (_mainArgs != null)
throw new InvalidOperationException("CEF 进程分流已经执行。");
CefRuntime.Load();
_mainArgs = new CefMainArgs(args ?? new string[0]);
_cefApp = new DemoCefApp();
_cefSettings = CreateCefSettings();
int code = CefRuntime.ExecuteProcess(
_mainArgs,
_cefApp,
IntPtr.Zero);
Console.WriteLine(
"CefRuntime.ExecuteProcess() returns {0}",
code);
return code;
}
internal static void InitializeMainProcess()
{
if (_mainProcessInitialized)
throw new InvalidOperationException("旧主进程环境已经初始化。");
if (_mainProcessShutdown)
throw new InvalidOperationException("旧主进程环境已经关闭。");
if (_mainArgs == null || _cefApp == null || _cefSettings == null)
throw new InvalidOperationException("尚未执行 CEF 进程分流。");
try
{
CefRuntime.Initialize(
_mainArgs,
_cefSettings,
_cefApp,
IntPtr.Zero);
_cefInitialized = true;
Thread.CurrentThread.CurrentUICulture =
new CultureInfo("zh-CN");
BonusSkins.Register();
SkinManager.EnableFormSkins();
Application.SetUnhandledExceptionMode(
UnhandledExceptionMode.CatchException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_messageFilter = new Messager();
Application.AddMessageFilter(_messageFilter);
Application.ThreadException += Application_ThreadException;
AppDomain.CurrentDomain.UnhandledException +=
CurrentDomain_UnhandledException;
if (!_cefSettings.MultiThreadedMessageLoop)
{
_cefIdleHandler = delegate
{
CefRuntime.DoMessageLoopWork();
};
Application.Idle += _cefIdleHandler;
}
_devCompanion = new AboutDevCompanion(1, false);
_devCompanion.Run();
Register();
_mainProcessInitialized = true;
}
catch
{
ShutdownMainProcess();
throw;
}
}
internal static void ShutdownMainProcess()
{
if (_mainProcessShutdown)
return;
_mainProcessShutdown = true;
try
{
if (_cefIdleHandler != null)
{
Application.Idle -= _cefIdleHandler;
_cefIdleHandler = null;
}
Application.ThreadException -= Application_ThreadException;
AppDomain.CurrentDomain.UnhandledException -=
CurrentDomain_UnhandledException;
if (_messageFilter != null)
{
Application.RemoveMessageFilter(_messageFilter);
_messageFilter = null;
}
if (_devCompanion != null)
{
_devCompanion.Stop();
_devCompanion = null;
}
}
finally
{
if (_cefInitialized)
{
CefRuntime.Shutdown();
_cefInitialized = false;
}
_mainProcessInitialized = false;
}
}
private static CefSettings CreateCefSettings()
{
return new CefSettings
{
MultiThreadedMessageLoop = true,
LogSeverity = CefLogSeverity.Disable,
LogFile = "CefGlue.log",
Locale = "zh-CN"
};
try
{
var Code = CefRuntime.ExecuteProcess(mainArgs, app, IntPtr.Zero);
Console.WriteLine("CefRuntime.ExecuteProcess() returns {0}", Code);
}
catch (Exception ex)
{
}
CefRuntime.Initialize(mainArgs, settings, app, IntPtr.Zero);
try
{
// 汉化DevExpress界面
Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
// 设置皮肤
BonusSkins.Register();
SkinManager.EnableFormSkins();
//处理未捕获的异常
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.AddMessageFilter(new Messager());
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
if (!settings.MultiThreadedMessageLoop)//消息循环
{
Application.Idle += (sender, e) => { CefRuntime.DoMessageLoopWork(); };
}
AboutDevCompanion DC = new AboutDevCompanion(1, false);
DC.Run();
Register();
// 启动程序
Manager.StartForm();
CefRuntime.Shutdown();
DC.Stop();
}
catch (Exception ex)
{
MessageUtil.Show(ex);
LogHelper.Instance.WriteError(ex);
}
}
/// <summary>
/// 允许 .NET Framework 4.8 外部宿主复用原程序的 CEF、皮肤、异常、注册和登录初始化。
/// 正常启动 Ls_ERP.exe 仍由 Main 直接进入,不经过此方法。
/// </summary>
internal static void RunFromExternalHost(string[] args)
{
Main(args ?? new string[0]);
}
#region
/// <summary>