Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 950ea4d8a1 | |||
| 5e01995e17 | |||
| 6df28462be | |||
| 4d907cf1dd | |||
| 1fc67234ef | |||
| d96459d01b | |||
| f3994c6c6e | |||
| 4d3128bbfe | |||
| fa48419bd8 |
@@ -1,5 +1,6 @@
|
|||||||
using Lskj.Business;
|
using Lskj.Business;
|
||||||
using Lskj.Model;
|
using Lskj.Model;
|
||||||
|
using Lskj.Util;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -56,6 +57,19 @@ namespace Lskj.Control.BrowserSetting
|
|||||||
return contextMenuHandler;
|
return contextMenuHandler;
|
||||||
}
|
}
|
||||||
protected override bool OnProcessMessageReceived(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
|
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"))
|
if (message.Name.Equals("OpenModule"))
|
||||||
{
|
{
|
||||||
@@ -150,6 +164,46 @@ namespace Lskj.Control.BrowserSetting
|
|||||||
|
|
||||||
return base.OnProcessMessageReceived(browser, frame, sourceProcess, message);
|
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)
|
public void Created(CefBrowser cefBrowser)
|
||||||
{
|
{
|
||||||
if (OnCreated != null)
|
if (OnCreated != null)
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Lskj.Main.Hosting
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 旧启动流程与可选新主界面之间的中立扩展点。
|
||||||
|
/// 此接口只使用 .NET Framework 4.0/WinForms 基础类型,不引用 WPF 或 DevExpress 25.2。
|
||||||
|
/// </summary>
|
||||||
|
public interface IExternalMainShell
|
||||||
|
{
|
||||||
|
bool IsOpen { get; }
|
||||||
|
|
||||||
|
DialogResult ShowLoginDialog(object loginRuntime);
|
||||||
|
|
||||||
|
DialogResult ShowDialog();
|
||||||
|
|
||||||
|
void RequestRelogin();
|
||||||
|
|
||||||
|
void RequestLock();
|
||||||
|
|
||||||
|
void RequestSubscriptRefresh();
|
||||||
|
|
||||||
|
void RequestExit(string message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +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
|
||||||
|
{
|
||||||
|
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.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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -276,6 +276,9 @@
|
|||||||
<Compile Include="Model\BitMapHelper.cs" />
|
<Compile Include="Model\BitMapHelper.cs" />
|
||||||
<Compile Include="Model\Manager.cs" />
|
<Compile Include="Model\Manager.cs" />
|
||||||
<Compile Include="Model\winApi.cs" />
|
<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="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<EmbeddedResource Include="Control\AwaitScreenControl.resx">
|
<EmbeddedResource Include="Control\AwaitScreenControl.resx">
|
||||||
|
|||||||
+336
-173
@@ -15,6 +15,7 @@ using Lskj.Control;
|
|||||||
using Lskj.Control.Model;
|
using Lskj.Control.Model;
|
||||||
using Lskj.Core;
|
using Lskj.Core;
|
||||||
using Lskj.Data;
|
using Lskj.Data;
|
||||||
|
using Lskj.Main.Hosting;
|
||||||
using Lskj.Model;
|
using Lskj.Model;
|
||||||
using Lskj.Util;
|
using Lskj.Util;
|
||||||
using Lskj.Web.Core.Util;
|
using Lskj.Web.Core.Util;
|
||||||
@@ -55,6 +56,14 @@ namespace Lskj.Main.Model
|
|||||||
public static int isAwaitTime = 10;
|
public static int isAwaitTime = 10;
|
||||||
public static int RefreshTime = 0;
|
public static int RefreshTime = 0;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 由外部启动程序提供的可选主界面。默认为 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>
|
/// </summary>
|
||||||
private static string filePath = string.Empty;
|
private static string filePath = string.Empty;
|
||||||
@@ -82,8 +91,12 @@ namespace Lskj.Main.Model
|
|||||||
public static void StartForm()
|
public static void StartForm()
|
||||||
{
|
{
|
||||||
bool isStart = true;
|
bool isStart = true;
|
||||||
|
bool useLegacySplash = ExternalMainShell == null;
|
||||||
// 加载Splash动画界面
|
// 加载Splash动画界面
|
||||||
SplashForm.ShowForm();
|
if (useLegacySplash)
|
||||||
|
{
|
||||||
|
SplashForm.ShowForm();
|
||||||
|
}
|
||||||
//CheckLocalConfig();
|
//CheckLocalConfig();
|
||||||
// C#数据库连接检查
|
// C#数据库连接检查
|
||||||
bool isLocalConnect = false;
|
bool isLocalConnect = false;
|
||||||
@@ -103,7 +116,10 @@ namespace Lskj.Main.Model
|
|||||||
if (!DBConfig.Instance.CreateConnection(DBConfig.Instance.Connection))
|
if (!DBConfig.Instance.CreateConnection(DBConfig.Instance.Connection))
|
||||||
{
|
{
|
||||||
MessageUtil.Show(ResourceKeys.UnConnectServer);
|
MessageUtil.Show(ResourceKeys.UnConnectServer);
|
||||||
SplashForm.HideForm();
|
if (useLegacySplash)
|
||||||
|
{
|
||||||
|
SplashForm.HideForm();
|
||||||
|
}
|
||||||
DialogResult result = RunConfigForm();
|
DialogResult result = RunConfigForm();
|
||||||
isStart = result == DialogResult.OK;
|
isStart = result == DialogResult.OK;
|
||||||
}
|
}
|
||||||
@@ -115,7 +131,10 @@ namespace Lskj.Main.Model
|
|||||||
if (DelphiHelper.Delphi_Init(new StringBuilder(DBConfig.Instance.GetDelphiConnection(DBConfig.Instance.dephiConnection))) == 0)
|
if (DelphiHelper.Delphi_Init(new StringBuilder(DBConfig.Instance.GetDelphiConnection(DBConfig.Instance.dephiConnection))) == 0)
|
||||||
{
|
{
|
||||||
MessageUtil.Show(ResourceKeys.UnConnectServer + "[By Delphi]");
|
MessageUtil.Show(ResourceKeys.UnConnectServer + "[By Delphi]");
|
||||||
SplashForm.HideForm();
|
if (useLegacySplash)
|
||||||
|
{
|
||||||
|
SplashForm.HideForm();
|
||||||
|
}
|
||||||
RunConfigForm();
|
RunConfigForm();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -123,7 +142,10 @@ namespace Lskj.Main.Model
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
SplashForm.HideForm();
|
if (useLegacySplash)
|
||||||
|
{
|
||||||
|
SplashForm.HideForm();
|
||||||
|
}
|
||||||
// 汉化dev控件
|
// 汉化dev控件
|
||||||
BaseResources.Localization(LocalizationType.CHS);
|
BaseResources.Localization(LocalizationType.CHS);
|
||||||
// 启动登录页面
|
// 启动登录页面
|
||||||
@@ -145,7 +167,10 @@ namespace Lskj.Main.Model
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SplashForm.HideForm();
|
if (useLegacySplash)
|
||||||
|
{
|
||||||
|
SplashForm.HideForm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,9 +186,7 @@ namespace Lskj.Main.Model
|
|||||||
/// <param name="skipMenu">是否跳过子系统选择(适用于切换用户).</param>
|
/// <param name="skipMenu">是否跳过子系统选择(适用于切换用户).</param>
|
||||||
public static void ReStartMain(bool skipMenu = false)
|
public static void ReStartMain(bool skipMenu = false)
|
||||||
{
|
{
|
||||||
WhenConstraintLogin();
|
StartSessionMonitors();
|
||||||
LockApplication();
|
|
||||||
if (SystemInfo.Instance.SubscriptRefreshTime > 0 && !SystemInfo.Instance.RefreshNotify) RefreshSubscript();
|
|
||||||
if (_frmMain != null)
|
if (_frmMain != null)
|
||||||
{
|
{
|
||||||
if (ERPInfo.Instance.WatermarkForm != null)
|
if (ERPInfo.Instance.WatermarkForm != null)
|
||||||
@@ -180,7 +203,13 @@ namespace Lskj.Main.Model
|
|||||||
bool isOpenBs = false;
|
bool isOpenBs = false;
|
||||||
DialogResult result;
|
DialogResult result;
|
||||||
|
|
||||||
if (ERPInfo.Instance.SubMenuCount > 1 && !skipMenu)
|
if (ExternalMainShell != null)
|
||||||
|
{
|
||||||
|
// WPF 主框架已经提供顶部子系统导航,不再打开旧 FrmSubSystem。
|
||||||
|
// 优先保留当前仍有权限的子系统,否则选择第一个可用子系统。
|
||||||
|
isStart = TrySelectExternalMainShellSubSystem();
|
||||||
|
}
|
||||||
|
else if (ERPInfo.Instance.SubMenuCount > 1 && !skipMenu)
|
||||||
{
|
{
|
||||||
// 进入子系统界面
|
// 进入子系统界面
|
||||||
result = RunSubSystemForm();
|
result = RunSubSystemForm();
|
||||||
@@ -190,8 +219,19 @@ namespace Lskj.Main.Model
|
|||||||
if (isStart)
|
if (isStart)
|
||||||
{
|
{
|
||||||
// 直接进入主界面
|
// 直接进入主界面
|
||||||
RunMainForm();
|
result = RunMainForm();
|
||||||
if (ERPInfo.Instance.SubMenuCount > 1)
|
if (result == DialogResult.Retry)
|
||||||
|
{
|
||||||
|
StartForm();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ExternalMainShell != null)
|
||||||
|
{
|
||||||
|
// 外部主界面关闭即结束本次 WPF 入口,不返回旧子系统选择页。
|
||||||
|
ExitSystem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (ERPInfo.Instance.SubMenuCount > 1)
|
||||||
{
|
{
|
||||||
ReStartMain();
|
ReStartMain();
|
||||||
}
|
}
|
||||||
@@ -596,8 +636,9 @@ namespace Lskj.Main.Model
|
|||||||
}
|
}
|
||||||
return dllName;
|
return dllName;
|
||||||
}
|
}
|
||||||
private static void ExitSystem()
|
internal static void ExitSystem()
|
||||||
{
|
{
|
||||||
|
StopSessionMonitors();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 退出系统
|
// 退出系统
|
||||||
@@ -653,6 +694,9 @@ namespace Lskj.Main.Model
|
|||||||
/// <returns>DialogResult.</returns>
|
/// <returns>DialogResult.</returns>
|
||||||
private static DialogResult RunLoginForm()
|
private static DialogResult RunLoginForm()
|
||||||
{
|
{
|
||||||
|
if (ExternalMainShell != null)
|
||||||
|
return ExternalMainShell.ShowLoginDialog(new LegacyLoginRuntime());
|
||||||
|
|
||||||
FrmLogin frmLogin = new FrmLogin();
|
FrmLogin frmLogin = new FrmLogin();
|
||||||
return frmLogin.ShowDialog();
|
return frmLogin.ShowDialog();
|
||||||
}
|
}
|
||||||
@@ -674,6 +718,44 @@ namespace Lskj.Main.Model
|
|||||||
BsUrl = _frmSubSystem.BsUrl;
|
BsUrl = _frmSubSystem.BsUrl;
|
||||||
return dialogResult;
|
return dialogResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为外部 WPF 主框架选择登录后的初始子系统。
|
||||||
|
/// 旧 WinForms 入口仍由 FrmSubSystem 完成人工选择。
|
||||||
|
/// </summary>
|
||||||
|
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)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DataRow selectedRow = subSystems.AsEnumerable().FirstOrDefault(row =>
|
||||||
|
IsEnabledSubSystem(row) &&
|
||||||
|
string.Equals(
|
||||||
|
row["SubSysId"] + string.Empty,
|
||||||
|
ERPInfo.Instance.SubSysId,
|
||||||
|
StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (selectedRow == null)
|
||||||
|
selectedRow = subSystems.AsEnumerable().FirstOrDefault(IsEnabledSubSystem);
|
||||||
|
if (selectedRow == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ERPInfo.Instance.SubMenuCount = subSystems.AsEnumerable().Count(IsEnabledSubSystem);
|
||||||
|
ERPInfo.Instance.SubSysId = selectedRow["SubSysId"] + string.Empty;
|
||||||
|
ERPInfo.Instance.SubSysName = selectedRow["SubSysName"] + string.Empty;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsEnabledSubSystem(DataRow row)
|
||||||
|
{
|
||||||
|
return row != null &&
|
||||||
|
row.Table.Columns.Contains("UseEd") &&
|
||||||
|
row["UseEd"] != DBNull.Value &&
|
||||||
|
Convert.ToBoolean(row["UseEd"]);
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>说明:打开主程序</para>
|
/// <para>说明:打开主程序</para>
|
||||||
/// <para>创建人:龚宇超</para>
|
/// <para>创建人:龚宇超</para>
|
||||||
@@ -686,6 +768,10 @@ namespace Lskj.Main.Model
|
|||||||
/// <returns>DialogResult.</returns>
|
/// <returns>DialogResult.</returns>
|
||||||
private static DialogResult RunMainForm()
|
private static DialogResult RunMainForm()
|
||||||
{
|
{
|
||||||
|
IExternalMainShell externalMainShell = ExternalMainShell;
|
||||||
|
if (externalMainShell != null)
|
||||||
|
return externalMainShell.ShowDialog();
|
||||||
|
|
||||||
_frmMain = new FrmMain();
|
_frmMain = new FrmMain();
|
||||||
return _frmMain.ShowDialog();
|
return _frmMain.ShowDialog();
|
||||||
}
|
}
|
||||||
@@ -862,187 +948,247 @@ namespace Lskj.Main.Model
|
|||||||
return isSuccess;
|
return isSuccess;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
/// <summary>
|
internal static void BeginExternalSessionServices()
|
||||||
/// <para>说明:强制登录下线</para>
|
|
||||||
/// <para>创建人:唐德馨</para>
|
|
||||||
/// <para>创建日期:2023-10-16 </para>
|
|
||||||
/// <para>修改人:</para>
|
|
||||||
/// <para>修改日期:</para>
|
|
||||||
/// <para>修改备注:</para>
|
|
||||||
/// <para>版本:1.0</para>
|
|
||||||
/// </summary>
|
|
||||||
private static void WhenConstraintLogin()
|
|
||||||
{
|
{
|
||||||
Thread thread = new Thread(() =>
|
StartSessionMonitors();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void EndExternalSessionServices()
|
||||||
|
{
|
||||||
|
StopSessionMonitors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StartSessionMonitors()
|
||||||
|
{
|
||||||
|
StopSessionMonitors();
|
||||||
|
|
||||||
|
CancellationTokenSource cancellation =
|
||||||
|
new CancellationTokenSource();
|
||||||
|
var threads = new List<Thread>();
|
||||||
|
if (SystemInfo.Instance.IsConstraintExit)
|
||||||
{
|
{
|
||||||
bool isClose = false;
|
threads.Add(CreateSessionMonitor(
|
||||||
while (SystemInfo.Instance.IsConstraintExit)
|
"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 = "";
|
if (!thread.Join(2000))
|
||||||
string clientip = "";
|
allStopped = false;
|
||||||
string loginMacAdress = "";
|
}
|
||||||
DataTable loginTable = new DataTable();
|
}
|
||||||
|
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
|
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')");
|
IExternalMainShell externalMainShell = ExternalMainShell;
|
||||||
hostName = SqlHelper.ExecuteScalar(string.Format("select hostname from p_LoginHostInfotab where OperatorId = '{0}' and Tagid = 1", ERPInfo.Instance.UserId)) + "";
|
if (externalMainShell != null &&
|
||||||
clientip = SqlHelper.ExecuteScalar(string.Format("select clientip from p_employeetab where employeeid = '{0}'", ERPInfo.Instance.UserId)) + "";
|
externalMainShell.IsOpen)
|
||||||
loginMacAdress = SqlHelper.ExecuteScalar(string.Format("select macAdress from p_employeetab where employeeid = '{0}'", ERPInfo.Instance.UserId)) + "";
|
{
|
||||||
|
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)
|
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 (_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 = Process.GetProcessesByName("Ls_ERP");
|
|
||||||
foreach (Process item in p)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
item.Kill();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Environment.Exit(0);
|
|
||||||
Application.Exit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
thread.Start();
|
if (token.WaitHandle.WaitOne(1000))
|
||||||
}
|
return;
|
||||||
/// <summary>
|
}
|
||||||
/// 锁定程序
|
|
||||||
/// </summary>
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void MonitorApplicationLock(CancellationToken token)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 刷新数量角标
|
|
||||||
/// </summary>
|
|
||||||
private static void RefreshSubscript()
|
|
||||||
{
|
{
|
||||||
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;
|
externalMainShell.RequestLock();
|
||||||
if (_frmMain != null && _frmMain.Visible == true)
|
return;
|
||||||
|
}
|
||||||
|
if (_frmMain != null && _frmMain.Visible)
|
||||||
|
{
|
||||||
|
_frmMain.Invoke(new Action(delegate
|
||||||
{
|
{
|
||||||
XtraTabPage tabPage = _frmMain.mainPanelControlEx.tabMain.SelectedTabPage;
|
_frmMain.mainPanelControlEx.AwaitControl.BringToFront();
|
||||||
if (tabPage.TabIndex == 0)
|
_frmMain.mainPanelControlEx.AwaitControl.Visible = true;
|
||||||
{
|
_frmMain.mainPanelControlEx.AwaitControl.OnFrmAwaitScreenLoad();
|
||||||
if (!SystemInfo.Instance.RefreshNotify)
|
}));
|
||||||
{
|
}
|
||||||
Thread threadnew = new Thread(_frmMain.mainPanelControlEx.RefreshSubscript);
|
}
|
||||||
threadnew.IsBackground = true;
|
isAwaitTime += 1;
|
||||||
threadnew.Start();
|
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);
|
|
||||||
}
|
}
|
||||||
});
|
RefreshTime += 1;
|
||||||
thread.Start();
|
if (token.WaitHandle.WaitOne(60000))
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1107,6 +1253,12 @@ namespace Lskj.Main.Model
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static void ReLogin()
|
public static void ReLogin()
|
||||||
{
|
{
|
||||||
|
IExternalMainShell externalMainShell = ExternalMainShell;
|
||||||
|
if (externalMainShell != null && externalMainShell.IsOpen)
|
||||||
|
{
|
||||||
|
externalMainShell.RequestRelogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_frmMain != null)
|
if (_frmMain != null)
|
||||||
{
|
{
|
||||||
if (ERPInfo.Instance.WatermarkForm != null)
|
if (ERPInfo.Instance.WatermarkForm != null)
|
||||||
@@ -1121,5 +1273,16 @@ namespace Lskj.Main.Model
|
|||||||
StartForm();
|
StartForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回当前启动路线需要退出的主进程。
|
||||||
|
/// 旧入口保持原有 Ls_ERP 进程名语义,外部宿主只退出当前 WPF 进程。
|
||||||
|
/// </summary>
|
||||||
|
internal static Process[] GetApplicationProcesses()
|
||||||
|
{
|
||||||
|
return ExternalMainShell == null
|
||||||
|
? Process.GetProcessesByName("Ls_ERP")
|
||||||
|
: new[] { Process.GetCurrentProcess() };
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+158
-48
@@ -21,11 +21,22 @@ using System.Resources;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Resources;
|
using System.Resources;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Lskj.Main.Hosting;
|
||||||
|
|
||||||
namespace Lskj.Main
|
namespace Lskj.Main
|
||||||
{
|
{
|
||||||
static class Program
|
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")]
|
//[DllImport("user32.dll")]
|
||||||
//private static extern bool SetProcessDpiAwarenessContext(IntPtr dpiContext);
|
//private static extern bool SetProcessDpiAwarenessContext(IntPtr dpiContext);
|
||||||
|
|
||||||
@@ -36,61 +47,160 @@ namespace Lskj.Main
|
|||||||
/// 应用程序的主入口点。
|
/// 应用程序的主入口点。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main(string[] args)
|
static int Main(string[] args)
|
||||||
{
|
{
|
||||||
//SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
LegacyProcessStartResult processResult;
|
||||||
CefRuntime.Load();//cef浏览器模块设置加载
|
try
|
||||||
var mainArgs = new CefMainArgs(args);
|
{
|
||||||
var app = new DemoCefApp();
|
processResult = LegacyApplicationHost.PrepareProcess(args);
|
||||||
var settings = new CefSettings
|
}
|
||||||
|
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,
|
MultiThreadedMessageLoop = true,
|
||||||
LogSeverity = CefLogSeverity.Disable,
|
LogSeverity = CefLogSeverity.Disable,
|
||||||
LogFile = "CefGlue.log",
|
LogFile = "CefGlue.log",
|
||||||
Locale = "zh-CN"
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#region 浏览器处理类
|
#region 浏览器处理类
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user