blog文章太少了,继续帖代码凑数。这个程序基本上没什么看点,有兴趣就看吧,挑错和改进建议更是求之不得。。。
学校渣网络用的是联想天工的802.1x认证系统。由于常常掉线,给挂机下载工作造成了非常大的影响,所以我赶制了这个程序。。。
以下是代码:(诶?前言就这么点吗?)
首先是对用到的一些API函数的声明:
namespace Takamachi660.Common.Windows.API { public static class User32 { [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("user32.dll")] public static extern IntPtr SetActiveWindow(IntPtr hWnd); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); /// <summary> /// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter. /// </summary> [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll")] public static extern IntPtr GetTopWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); public enum GetWindow_Cmd : uint { GW_HWNDFIRST = 0, GW_HWNDLAST = 1, GW_HWNDNEXT = 2, GW_HWNDPREV = 3, GW_OWNER = 4, GW_CHILD = 5, GW_ENABLEDPOPUP = 6 } [DllImport("user32.dll")] public static extern IntPtr GetLastActivePopup(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool AnyPopup(); [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] public static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); } }
第一个类,用来对1xclient进行控制(其实就是start和kill进程)
using System; using System.Diagnostics; using System.Linq; namespace Takamachi660._1xHelper { /// <summary> /// 1xclient客户端程序控制类 /// </summary> public class C1xController : IDisposable { /// <summary> /// 1xclient客户端程序可执行文件名(不带".exe") /// </summary> protected string m_ExeFileName; /// <summary> /// 1xclient客户端程序所在的目录 /// </summary> protected string m_ExePath; /// <summary> /// 与1xclient客户端进程关联的Process对象 /// </summary> protected Process m_1xProcess; /// <summary> /// 获取一个值,该值指示1xclient的运行状态 /// </summary> public virtual bool Status { get { if (m_1xProcess == null) Reset1xProcess(); if (m_1xProcess == null) return false; else { return !m_1xProcess.HasExited; } } } /// <summary> /// 获取或设置等待1xclient.exe退出时间 /// </summary> public int WaitForExeExitTime { get; set; } /// <summary> /// 获取或设置轮询间隔时间 /// </summary> public int QueryInterval { get; set; } /// <summary> /// 获取或设置轮询重试次数 /// </summary> public Int16 QueryRetry { get; set; } /// <param name="ExePath">1xclient客户端程序所在的目录</param> /// <param name="ExeFileName">1xclient客户端程序可执行文件名(不带".exe")</param> public C1xController(string ExePath, string ExeFileName) { m_ExePath = ExePath; m_ExeFileName = ExeFileName; Reset1xProcess(); WaitForExeExitTime = 5000; QueryInterval = 300; QueryRetry = 30; } protected virtual void Reset1xProcess() { Process[] ps = Process.GetProcessesByName(m_ExeFileName + @".dll"); if (ps.Length > 0) m_1xProcess = ps.Single(); else m_1xProcess = null; } /// <summary> /// 启动ixclient /// </summary> public virtual void Start() { if (m_1xProcess != null && !m_1xProcess.HasExited) throw new InvalidOperationException("1xclient is already running!"); ProcessStartInfo startinfo = new ProcessStartInfo(); startinfo.FileName = m_ExePath + @"\" + m_ExeFileName + @".exe"; startinfo.CreateNoWindow = startinfo.UseShellExecute = startinfo.RedirectStandardInput = startinfo.RedirectStandardOutput = startinfo.RedirectStandardError = false; startinfo.WindowStyle = ProcessWindowStyle.Hidden; m_1xProcess = Process.Start(startinfo); if (!m_1xProcess.WaitForExit(WaitForExeExitTime)) throw new Exception("1xclient.exe didn't exit"); Int16 counter = 0; do { Reset1xProcess(); if (m_1xProcess != null) break; counter++; System.Threading.Thread.Sleep(QueryInterval); } while (counter < QueryRetry); if (counter >= QueryRetry) throw new Exception("1xclient.dll didn't start"); } /// <summary> /// 关闭1xclient /// </summary> public virtual void Stop() { do { m_1xProcess.Kill(); } while (!m_1xProcess.WaitForExit(WaitForExeExitTime)); m_1xProcess = null; } /// <summary> /// 重新启动1xclient /// </summary> public virtual void Restart() { Stop(); Start(); } /// <summary> /// 释放与此组件关联的资源 /// </summary> public virtual void Dispose() { if (m_1xProcess != null) m_1xProcess.Close(); } } }
第二个类,对第一个类的改进,增加了对1xclient窗口的控制以及错误信息的读取
using System; using System.Text; using Takamachi660.Common.Windows.API; namespace Takamachi660._1xHelper { /// <summary> /// 1xclient控制器异常 /// </summary> public class C1xControllerException : Exception { public C1xControllerException(string message) : base(message) { } public C1xControllerException(string message, Exception innerException) : base(message, innerException) { } } /// <summary> /// 1xclient客户端程序控制类改进版 /// </summary> public class C1xControllerEx : C1xController { /// <summary> /// 获取认证成功提示信息窗口的句柄 /// </summary> protected IntPtr HWND_Succeed { get { return Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "提示信息"); } } /// <summary> /// 获取认证失败提示信息窗口的句柄 /// </summary> //protected IntPtr HWND_Failed { get { return Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "1xClient"); } } protected IntPtr HWND_Failed { get { IntPtr[] hwnds = new IntPtr[2]; hwnds[0] = Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "1xClient"); hwnds[1] = Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "出错提示"); foreach (IntPtr hwnd in hwnds) { if (hwnd != IntPtr.Zero) return hwnd; } return IntPtr.Zero; } } /// <summary> /// 获取认证过程提示信息窗口的句柄 /// </summary> protected IntPtr HWND_Authentication { get { IntPtr[] hwnds = new IntPtr[4]; hwnds[0] = Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "寻找交换机......"); hwnds[1] = Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "正在连接......"); hwnds[2] = Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "认证成功!"); hwnds[3] = Takamachi660.Common.Windows.API.User32.FindWindowByCaption(IntPtr.Zero, "出错提示"); foreach (IntPtr hwnd in hwnds) { if (hwnd != IntPtr.Zero) return hwnd; } return IntPtr.Zero; } } public C1xControllerEx(string ExePath, string ExeFileName) : base(ExePath, ExeFileName) { } /// <summary> /// 启动ixclient /// </summary> public override void Start() { IntPtr ForeWindowHandle = User32.GetForegroundWindow(); try { base.Start(); int counter = 0; do { IntPtr hwnd_dlg = HWND_Authentication; if (hwnd_dlg == IntPtr.Zero) { counter++; } else { IntPtr hwnd_dlg2 = IntPtr.Zero; if ((hwnd_dlg2 = HWND_Succeed) != IntPtr.Zero) { ClickButton(hwnd_dlg2, "确定"); break; } else if ((hwnd_dlg2 = HWND_Failed) != IntPtr.Zero) { IntPtr hwnd_msg = User32.GetWindow(hwnd_dlg2, (uint)User32.GetWindow_Cmd.GW_CHILD); string Message = "Unknown error message"; do { if (User32.GetWindowTextLength(hwnd_msg) > 4) { StringBuilder sb = new StringBuilder(200); User32.GetWindowText(hwnd_msg, sb, 200); Message = sb.ToString(); } } while ((hwnd_msg = User32.GetWindow(hwnd_msg, (uint)User32.GetWindow_Cmd.GW_HWNDNEXT)) != IntPtr.Zero); this.Stop(); throw new C1xControllerException(Message); } else { StringBuilder sb = new StringBuilder(200); Takamachi660.Common.Windows.API.User32.GetWindowText(hwnd_dlg, sb, 200); if (sb.ToString() == "认证成功!") counter++; } } System.Threading.Thread.Sleep(QueryInterval); } while (counter < QueryRetry); if (counter >= QueryRetry) throw new Exception("Unknown error occurred!"); } catch (Exception e) { User32.SetForegroundWindow(ForeWindowHandle); throw new C1xControllerException("An exception occurred when starting 1xclient", e); } finally { User32.SetForegroundWindow(ForeWindowHandle); } } /// <summary> /// 关闭1xclient /// </summary> public override void Stop() { try { base.Stop(); } catch (Exception e) { throw new C1xControllerException("An exception occurred when stopping 1xclient", e); } } /// <summary> /// 重新启动1xclient /// </summary> public override void Restart() { try { base.Restart(); } catch (Exception e) { throw new C1xControllerException("An exception occurred when restarting 1xclient", e); } } protected virtual void ClickButton(IntPtr parentHandle, string buttonTitle) { const int BM_CLICK = 0x00F5; User32.SetForegroundWindow(parentHandle); if (string.IsNullOrEmpty(buttonTitle)) User32.PostMessage(User32.FindWindowEx(parentHandle, IntPtr.Zero, "Button", IntPtr.Zero), BM_CLICK, IntPtr.Zero, IntPtr.Zero); else User32.PostMessage(User32.FindWindowEx(parentHandle, IntPtr.Zero, "Button", buttonTitle), BM_CLICK, IntPtr.Zero, IntPtr.Zero); } } }
第三个类,很简单,ping网关以检测网络状态
(关于Ping造成的内存泄漏问题顺便再这里bs一下微软,到现在都没有修正)
using System.Net; using System.Net.NetworkInformation; namespace Takamachi660._1xHelper { /// <summary> /// 网络测试类 /// </summary> public class NetworkStatusTester { /// <summary> /// 获取或设置网关的IP地址 /// </summary> public IPAddress IpGateway { get; set; } /// <summary> /// 获取一个值,该值指示网络当前是否连通 /// </summary> public virtual bool IsConnected { get { using (Ping p = new Ping()) { bool IsSucceed = p.Send(IpGateway, 1000).Status == IPStatus.Success; return IsSucceed; } } } } }
第四个类,监视器,包含一个计时器和以上两个类的实例,作用是定期检查网络状态,发现断网即重连
using System; using System.Net; using System.Timers; using System.IO; namespace Takamachi660._1xHelper { /// <summary> /// 连接监视类 /// </summary> public class C1xWatcher { /// <summary> /// 1xclient控制器的弱引用对象 /// </summary> private WeakReference m_wref_1xController; /// <summary> /// 日志写入器的弱引用对象 /// </summary> private WeakReference m_wref_LogWriter; /// <summary> /// 网络状态测试器 /// </summary> protected NetworkStatusTester m_Tester; /// <summary> /// 计时器 /// </summary> protected Timer m_Tmr; /// <summary> /// 1xclient客户端程序可执行文件名(不带".exe") /// </summary> protected string m_1xExeFileName; /// <summary> /// 1xclient客户端程序所在的目录 /// </summary> protected string m_1xExePath; /// <summary> /// 最后发生的事件消息 /// </summary> protected string m_LastMessage; /// <summary> /// 连续失败次数 /// </summary> protected Int16 m_CounterFail; /// <summary> /// 本次运行过程中的掉线次数 /// </summary> protected Int16 m_CounterDisconnect; /// <summary> /// 获取1xclient控制器的强引用对象 /// </summary> protected C1xControllerEx m_1xController { get { if (!m_wref_1xController.IsAlive) m_wref_1xController.Target = new C1xControllerEx(m_1xExePath, m_1xExeFileName); return (C1xControllerEx)m_wref_1xController.Target; } } /// <summary> /// 获取日志写入器的强引用对象 /// </summary> protected StreamWriter m_LogWriter { get { if (!m_wref_LogWriter.IsAlive) m_wref_LogWriter.Target = new StreamWriter(new FileStream(Environment.CurrentDirectory + @"\" + LogFileName, FileMode.Append), System.Text.Encoding.UTF8); return (StreamWriter)m_wref_LogWriter.Target; } } /// <summary> /// 获取或设置测试网络状态的时间间隔,单位:毫秒 /// </summary> public double Interval { get { return m_Tmr.Interval; } set { m_Tmr.Interval = value; } } /// <summary> /// 获取或设置测试网络状态的重试次数 /// </summary> public Int16 PingRetry { get; set; } /// <summary> /// 检测到掉线后重新连接的延迟时间,单位:毫秒 /// </summary> public int DelayBeforeReconnect { get; set; } /// <summary> /// 重新连接后再次检测的延迟时间,单位:毫秒 /// </summary> public int DelayAfterReconnect { get; set; } /// <summary> /// 获取一个值,该值指示监视器是否工作中 /// </summary> public bool IsAlive { get { return m_Tmr.Enabled; } } /// <summary> /// 获取或设置网关的IP地址 /// </summary> public IPAddress IpGateway { get { return m_Tester.IpGateway; } set { m_Tester.IpGateway = value; } } /// <summary> /// 获取一个值,该值指示1xclient的运行状态 /// </summary> public bool ClientStatus { get { return m_1xController.Status; } } /// <summary> /// 获取一个值,该值指示网络当前是否连通 /// </summary> public bool ConnectionStatus { get { return m_Tester.IsConnected; } } /// <summary> /// 获取或设置日志文件名 /// </summary> public string LogFileName { get; set; } /// <summary> /// 获取最后发生的事件消息 /// </summary> public string LastMessage { get { return m_LastMessage; } } /// <summary> /// 获取连续失败次数 /// </summary> public Int16 CounterFail { get { return m_CounterFail; } } /// <summary> /// 获取本次运行过程中的掉线次数 /// </summary> public Int16 CounterDisconnect { get { return m_CounterDisconnect; } } /// <summary> /// 检测到掉线后发生 /// </summary> public event EventHandler Disconnected; /// <summary> /// 重新连接成功后发生 /// </summary> public event EventHandler Reconnected; /// <summary> /// 重新连接失败后发生 /// </summary> public event EventHandler ReconnectFailed; /// <param name="_1xExePath">1xclient客户端程序所在的目录</param> /// <param name="_1xExeFileName">1xclient客户端程序可执行文件名(不带".exe")</param> /// <param name="IpGateway">网关的IP地址</param> /// <param name="Interval">测试网络状态的时间间隔</param> public C1xWatcher(string _1xExePath, string _1xExeFileName, IPAddress IpGateway, double Interval) { m_1xExePath = _1xExePath; m_1xExeFileName = _1xExeFileName; m_wref_1xController = new WeakReference(null); m_wref_LogWriter = new WeakReference(null); m_Tester = new NetworkStatusTester(); m_Tester.IpGateway = IpGateway; m_Tmr = new Timer(Interval); m_Tmr.AutoReset = false; m_Tmr.Elapsed += new ElapsedEventHandler(m_Tmr_Elapsed); Disconnected += new EventHandler(C1xWatcher_Disconnected); PingRetry = 3; DelayBeforeReconnect = 0; DelayAfterReconnect = 5000; LogFileName = "Logs.txt"; } /// <summary> /// 立即检测网络状态 /// </summary> public virtual void CheckAtOnce() { lock (m_Tmr) { bool IsConnected = m_Tester.IsConnected; if (!IsConnected) { for (int count = 0; count < PingRetry; count++) { if (m_Tester.IsConnected) { IsConnected = true; break; } } if (!IsConnected) { try { OnDisconnected(); OnReconnected(); if (DelayAfterReconnect != 0) System.Threading.Thread.Sleep(DelayAfterReconnect); if (!m_Tester.IsConnected) OnReconnectFailed("警告:虽然1xclient显示连接成功,但网络依然没有接通!"); } catch (C1xControllerException ex) { Exception innerexception = ex; while (innerexception.InnerException != null) { innerexception = innerexception.InnerException; } OnReconnectFailed("重新连接失败!信息:" + innerexception.Message); } } } } } /// <summary> /// 立即检测网络状态并优先检测1xclient客户端的状态 /// </summary> public virtual void CheckAtOnceEx() { if (!m_1xController.Status) { try { m_1xController.Start(); } catch (C1xControllerException ex) { Exception innerexception = ex; while (innerexception.InnerException != null) { innerexception = innerexception.InnerException; } if (innerexception.Message == "请求的操作需要提升。") throw innerexception; } } else CheckAtOnce(); } /// <summary> /// 通过计时器定期检测网络状态 /// </summary> protected virtual void m_Tmr_Elapsed(object sender, ElapsedEventArgs e) { CheckAtOnce(); m_Tmr.Start(); } /// <summary> /// 检测到掉线后的处理方法 /// </summary> void C1xWatcher_Disconnected(object sender, EventArgs e) { if (DelayBeforeReconnect != 0) System.Threading.Thread.Sleep(DelayBeforeReconnect); WriteLog("开始重新连接!"); if (m_1xController.Status) m_1xController.Restart(); else m_1xController.Start(); } /// <summary> /// 启动监视器 /// </summary> public virtual void Start() { lock (m_Tmr) m_Tmr.Start(); } /// <summary> /// 停止监视器 /// </summary> public virtual void Stop() { lock (m_Tmr) m_Tmr.Stop(); } /// <summary> /// 触发Disconnected事件 /// </summary> protected virtual void OnDisconnected() { if (m_CounterFail == 0) m_CounterDisconnect++; WriteLog("检测到连接中断!"); m_LastMessage = FormatTimeSpan(DateTime.Now.TimeOfDay) + " 检测到连接中断!"; if (Disconnected != null) Disconnected(this, new EventArgs()); } /// <summary> /// 触发Reconnected事件 /// </summary> protected virtual void OnReconnected() { m_CounterFail = 0; WriteLog("重新连接成功!"); m_LastMessage = FormatTimeSpan(DateTime.Now.TimeOfDay) + " 重新连接成功!"; if (Reconnected != null) Reconnected(this, new EventArgs()); } /// <summary> /// 触发ReconnectFailed事件 /// </summary> protected virtual void OnReconnectFailed(string message) { m_CounterFail++; WriteLog(message); m_LastMessage = FormatTimeSpan(DateTime.Now.TimeOfDay) + " " + message; if (ReconnectFailed != null) ReconnectFailed(this, new EventArgs()); } protected virtual void WriteLog(string Msg) { StreamWriter sw = m_LogWriter; sw.WriteLine(DateTime.Now.ToString() + "\t" + Msg); sw.Flush(); } protected string FormatTimeSpan(TimeSpan t) { return t.Hours.ToString("00") + ":" + t.Minutes.ToString("00") + ":" + t.Seconds.ToString("00"); } } }
最后是几个配置类,对xml文档的读写进行封装,方便使用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using Microsoft.Win32; namespace Takamachi660._1xHelper { /// <summary> /// 配置信息读写类 /// </summary> public class Configurations { private const string ConfigFileName = "config.xml"; internal XmlDocument m_XmlDoc; private ConfigNode[] m_ConfigNodes; /// <summary> /// 获取1xClient配置节点 /// </summary> public Config_1xClient Config_1xClient { get { return (Config_1xClient)m_ConfigNodes[0]; } } /// <summary> /// 获取网络信息配置节点 /// </summary> public Config_Network Config_Network { get { return (Config_Network)m_ConfigNodes[1]; } } /// <summary> /// 获取监视器配置节点 /// </summary> public Config_1xWatcher Config_1xWatcher { get { return (Config_1xWatcher)m_ConfigNodes[2]; } } /// <summary> /// 获取杂项配置节点 /// </summary> public Config_Others Config_Others { get { return (Config_Others)m_ConfigNodes[3]; } } public Configurations() { m_XmlDoc = new XmlDocument(); m_ConfigNodes = new ConfigNode[4]; m_ConfigNodes[0] = new Config_1xClient(this); m_ConfigNodes[1] = new Config_Network(this); m_ConfigNodes[2] = new Config_1xWatcher(this); m_ConfigNodes[3] = new Config_Others(this); } /// <summary> /// 初始化配置 /// 若配置文件存在则读取 /// 不存在则以默认配置建立配置文件 /// </summary> public void Initialize() { string filepath = Environment.CurrentDirectory + @"\" + ConfigFileName; if (System.IO.File.Exists(filepath)) m_XmlDoc.Load(filepath); else CreateDefaultConfigFile(filepath); } /// <summary> /// 保存配置文件 /// </summary> public void SaveConfig() { m_XmlDoc.Save(Environment.CurrentDirectory + @"\" + ConfigFileName); } /// <summary> /// 以默认配置建立配置文件 /// </summary> /// <param name="filepath">文件名</param> private void CreateDefaultConfigFile(string filepath) { m_XmlDoc.AppendChild(m_XmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "")); m_XmlDoc.AppendChild(m_XmlDoc.CreateElement("Configurations")); m_XmlDoc.DocumentElement.AppendChild(m_XmlDoc.CreateElement("_1xClient")); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[0]).SetAttribute("Name", "1xClient"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[0]).SetAttribute("Path", Get1xClientPathFromReg()); m_XmlDoc.DocumentElement.AppendChild(m_XmlDoc.CreateElement("Network")); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[1]).SetAttribute("GatewayIp", GetDefaultGatewayIp()); m_XmlDoc.DocumentElement.AppendChild(m_XmlDoc.CreateElement("Watcher")); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[2]).SetAttribute("Interval", "10000.0"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[2]).SetAttribute("PingRetry", "2"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[2]).SetAttribute("DelayBeforeReconnect", "0"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[2]).SetAttribute("DelayAfterReconnect", "5000"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[2]).SetAttribute("LogFileName", "Logs.txt"); m_XmlDoc.DocumentElement.AppendChild(m_XmlDoc.CreateElement("Others")); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[3]).SetAttribute("ResponseTimeLimitMsg", "True"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[3]).SetAttribute("BalloonTipTimeout", "300"); ((XmlElement)m_XmlDoc.DocumentElement.ChildNodes[3]).SetAttribute("MaxRetry", "20"); m_XmlDoc.Save(filepath); } /// <summary> /// 从注册表读出1xClient的安装目录 /// </summary> private static string Get1xClientPathFromReg() { RegistryKey Key_SOFTWARE = Registry.LocalMachine.OpenSubKey("SOFTWARE"); RegistryKey Key_1xClient = null; string path = string.Empty; try { if (Key_SOFTWARE.OpenSubKey("Wow6432Node") != null) Key_1xClient = Key_SOFTWARE.OpenSubKey(@"Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\联想网络"); else Key_1xClient = Key_SOFTWARE.OpenSubKey(@"Microsoft\Windows\CurrentVersion\App Paths\联想网络"); if (Key_1xClient != null) path = ((string)Key_1xClient.GetValue("Path", string.Empty)).TrimEnd('\\'); } catch { } finally { Key_SOFTWARE.Close(); if (Key_1xClient != null) Key_1xClient.Close(); } return path; } /// <summary> /// 获取默认网关地址 /// </summary> private static string GetDefaultGatewayIp() { System.Net.NetworkInformation.NetworkInterface[] nets = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces(); foreach (System.Net.NetworkInformation.NetworkInterface net in nets) { if (net.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Ethernet) continue; RegistryKey Key_Net = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\" + net.Id + @"\Parameters\Tcpip"); if (Key_Net != null) { string gatewayip = ((string[])Key_Net.GetValue("DefaultGateway", string.Empty)).First(s => { System.Net.IPAddress ip; return System.Net.IPAddress.TryParse(s, out ip); }); Key_Net.Close(); if (!string.IsNullOrEmpty(gatewayip)) return gatewayip; } } return string.Empty; } } /// <summary> /// 配置节点基类 /// </summary> public abstract class ConfigNode { private Configurations m_ConfigSet; /// <summary> /// 节点名 /// </summary> private string m_NodeName; /// <summary> /// 读写该节点属性 /// </summary> /// <param name="AttributeName">属性名</param> /// <returns>属性值</returns> protected string this[string AttributeName] { get { return m_ConfigSet.m_XmlDoc.DocumentElement.GetElementsByTagName(m_NodeName)[0].Attributes[AttributeName].Value; } set { m_ConfigSet.m_XmlDoc.DocumentElement.GetElementsByTagName(m_NodeName)[0].Attributes[AttributeName].Value = value; } } public ConfigNode(Configurations ConfigSet, string NodeName) { m_ConfigSet = ConfigSet; m_NodeName = NodeName; } } /// <summary> /// 1xClient配置节点类 /// </summary> public sealed class Config_1xClient : ConfigNode { public Config_1xClient(Configurations ConfigSet) : base(ConfigSet, "_1xClient") { } /// <summary> /// 获取或设置文件名(不带".exe") /// </summary> public string Name { get { return base["Name"]; } set { base["Name"] = value; } } /// <summary> /// 获取或设置客户端安装目录 /// </summary> public string Path { get { return base["Path"]; } set { base["Path"] = value; } } } /// <summary> /// 网络信息配置节点类 /// </summary> public sealed class Config_Network : ConfigNode { public Config_Network(Configurations ConfigSet) : base(ConfigSet, "Network") { } /// <summary> /// 获取或设置网关IP地址 /// </summary> public System.Net.IPAddress IpGateway { get { return System.Net.IPAddress.Parse(base["GatewayIp"]); } set { base["GatewayIp"] = value.ToString(); } } } /// <summary> /// 监视器配置节点类 /// </summary> public sealed class Config_1xWatcher : ConfigNode { public Config_1xWatcher(Configurations ConfigSet) : base(ConfigSet, "Watcher") { } /// <summary> /// 获取或设置测试网络状态的时间间隔,单位:毫秒 /// </summary> public double Interval { get { return double.Parse(base["Interval"]); } set { base["Interval"] = value.ToString(); } } /// <summary> /// 获取或设置测试网络状态的重试次数 /// </summary> public Int16 PingRetry { get { return Int16.Parse(base["PingRetry"]); } set { base["PingRetry"] = value.ToString(); } } /// <summary> /// 获取或设置检测到掉线后重新连接的延迟时间,单位:毫秒 /// </summary> public int DelayBeforeReconnect { get { return int.Parse(base["DelayBeforeReconnect"]); } set { base["DelayBeforeReconnect"] = value.ToString(); } } /// <summary> /// 获取或设置重新连接后再次检测的延迟时间,单位:毫秒 /// </summary> public int DelayAfterReconnect { get { return int.Parse(base["DelayAfterReconnect"]); } set { base["DelayAfterReconnect"] = value.ToString(); } } /// <summary> /// 获取或设置日志文件名 /// </summary> public string LogFileName { get { return base["LogFileName"]; } set { base["LogFileName"] = value; } } } /// <summary> /// 杂项配置节点类 /// </summary> public sealed class Config_Others : ConfigNode { public Config_Others(Configurations ConfigSet) : base(ConfigSet, "Others") { } /// <summary> /// 获取或设置一个值,该值指示程序是否在收到“本时间段限制上网”消息时自动退出 /// </summary> public bool ResponseTimeLimitMsg { get { return bool.Parse(base["ResponseTimeLimitMsg"]); } set { base["ResponseTimeLimitMsg"] = value.ToString(); } } /// <summary> /// 获取或设置气球提示延迟时间 /// </summary> public int BalloonTipTimeout { get { return int.Parse(base["BalloonTipTimeout"]); } set { base["BalloonTipTimeout"] = value.ToString(); } } /// <summary> /// 获取或设置最大重试次数 /// </summary> public Int16 MaxRetry { get { return Int16.Parse(base["MaxRetry"]); } set { base["MaxRetry"] = value.ToString(); } } } }
至于主程序就不帖了,就是创建C1xWatcher类的实例进行监控,和提供参数设置的GUI界面。
/Files/takamachi660/1xHelper1.5_final_bin_src.rar