using System; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Reflection; using System.Resources; using System.Threading; using System.Net; using System.IO; using Ultron.Ngrok.Utils; using Ultron.Ngrok.Properties; namespace Ultron.Ngrok { public partial class FormMain : Form { public delegate void CmdInitAlready(); #region 属性 /// /// 命令行 /// public CmdUtils cmd { get; set; } /// /// 设置 /// public SettingForm setting { get; set; } /// /// 数据集名称 /// public string AssemblyProduct { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyProductAttribute)attributes[0]).Product; } } /// /// 数据集版本 /// public string AssemblyVersion { get { return Assembly.GetExecutingAssembly().GetName().Version.ToString(); } } #endregion #region 初始化 /// /// 构造 /// public FormMain() { //引用资源处理 AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; //初始化界面 InitializeComponent(); //初始化配置 InitSetting(); } /// /// 窗体Load /// /// /// private void FormMain_Load(object sender, EventArgs e) { //进程检测 CheckProcessAndKill(setting.ExeFile); CmdInitAlready callback = new CmdInitAlready(CmdCallBack); //初始化CMD Thread cmdThread = new Thread(InitCmd); cmdThread.IsBackground = true; cmdThread.Start(callback); //检查更新 Thread updateThread = new Thread(new ThreadStart(CheckUpdateAsync)); updateThread.IsBackground = true; updateThread.Start(); } public void CmdCallBack() { if(setting.ServerConfig.AutoStart) { startBtn_Click(null, null); } } #endregion #region 事件 private void startBtn_Click(object sender, EventArgs e) { //网络检测 NetworkUtils.CheckServeStatus(this); cmd.SendMsg(setting.ExecuteCommand,setting.ServerConfig.HideWindow); startBtn.Enabled = false; endBtn.Enabled = true; } private void endBtn_Click(object sender, EventArgs e) { CheckProcessAndKill(setting.ExeFile); cmd.CloseCmd(); startBtn.Enabled = true; endBtn.Enabled = false; } private void 设置ToolStripMenuItem_Click(object sender, EventArgs e) { setting.ReLoadConfig(); setting.ShowDialog(); } private void 帮助ToolStripMenuItem_Click(object sender, EventArgs e) { Process.Start("explorer.exe", "https://git.wixy.cn/wixy/Ultron.Ngrok/wiki/帮助"); } private void 关于ToolStripMenuItem_Click(object sender, EventArgs e) { AboutBox about = new AboutBox(); about.ShowDialog(); } private void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) { if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal; if (this.Visible == false) this.Show(); } private void FormMain_FormClosing(object sender, FormClosingEventArgs e) { if (setting.ServerConfig.UseNotifyMenu) { notifyIcon.Visible = true; this.Hide(); e.Cancel = true; } else { if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { // 关闭所有的线程 this.Dispose(); this.Close(); } else { e.Cancel = true; } } } private void 退出ToolStripMenuItem_Click(object sender, EventArgs e) { if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { this.Dispose(); this.Close(); } } private void 显示ToolStripMenuItem_Click(object sender, EventArgs e) { WindowState = FormWindowState.Normal; } #endregion #region 方法 Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", ""); dllName = dllName.Replace(".", "_"); if (dllName.EndsWith("_resources")) return null; ResourceManager rm = new ResourceManager(GetType().Namespace + ".Properties.Resources", Assembly.GetExecutingAssembly()); byte[] bytes = (byte[])rm.GetObject(dllName); return Assembly.Load(bytes); } public void CheckProcessAndKill(string processName) { Process[] proces = Process.GetProcessesByName(processName); foreach (var item in proces) { WriteLog("检测到进程:" + item.ProcessName + ",ID:" + item.Id + ""); item.Kill(); WriteLog("结束进程:" + item.Id + ""); } } public void CheckProcessAndKill(int id) { Process proces = Process.GetProcessById(id); if (proces != null) { WriteLog("检测到进程:" + proces.ProcessName + ",ID:" + proces.Id + ""); proces.Kill(); WriteLog("结束进程:" + proces.Id + ""); } } public void InitSetting() { setting = new SettingForm(); setting.WriteLogToForm += WriteLog; } public void InitCmd(object obj) { //创建CMD cmd = new CmdUtils(); cmd.ProcessMessageEvent += DealMessage; cmd.ProcessKilled += cmd_Exited; CmdInitAlready callback = obj as CmdInitAlready; callback(); } /// /// 检查更新 /// public void CheckUpdateAsync() { string checkUrl = "https://blog.wixy.cn/api/release/" + AssemblyProduct + "/" + AssemblyVersion; HttpGet(checkUrl); } public void DealMessage(int proId, string message) { if (message.StartsWith("Server failed to allocate tunnel")) { if (message.Contains("address already in use")) { string tcpErr = message.Substring(message.IndexOf("listen tcp")); WriteLog(tcpErr); int domainIndex = message.IndexOf("0.0.0.0:") + 8; int portIndex = message.IndexOf(": bind:"); string port = message.Substring(domainIndex, portIndex - domainIndex); MessageBox.Show("通道分配失败,端口:" + port + "已被使用!"); } else if (message.Contains("is already registered")) { string tcpErr = message.Substring(message.IndexOf("The tunnel ")); WriteLog(tcpErr); int domainIndex = message.IndexOf("http://"); int strIndex = message.IndexOf("is already"); string domain = message.Substring(domainIndex, strIndex - domainIndex); MessageBox.Show("通道分配失败,域名:" + domain + "已被使用!"); } CheckProcessAndKill(proId); startBtn.Enabled = true; endBtn.Enabled = false; } else { if (message.Contains("Microsoft Windows") || message.Contains("Microsoft Corporation") || message.Contains(".exe -config ngrok.cfg start")) return; WriteLog(message); } } public void WriteLog(string message) { StringBuilder sb = new StringBuilder(cmdLogTextArea.Text); cmdLogTextArea.Text = sb.AppendLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss ") + message).ToString(); cmdLogTextArea.SelectionStart = cmdLogTextArea.Text.Length; cmdLogTextArea.ScrollToCaret(); } public void cmd_Exited(object sender, EventArgs e) { WriteLog("结束运行!"); startBtn.Enabled = true; endBtn.Enabled = false; } public void HttpGet(string url) { string updateExe = Directory.GetCurrentDirectory() + @"\autoUpdate.exe"; if (File.Exists(updateExe)) { File.Delete(updateExe); } FileStream stream = new FileStream(updateExe, FileMode.OpenOrCreate); stream.Write(Resources.autoUpdate, 0, Resources.autoUpdate.Length); stream.Close(); WebClient wc = new WebClient(); Uri uri = new Uri(url, UriKind.RelativeOrAbsolute); wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted); wc.OpenReadAsync(uri); } public void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { try { StreamReader read = new StreamReader(e.Result); string str = read.ReadToEnd(); if (str.Contains("\"code\":1")) return; else { if (MessageBox.Show("检测到新版本,立即更新?", "版本更新", MessageBoxButtons.YesNo) == DialogResult.Yes) { int verStart = str.IndexOf("\"version\":\"") + 11; int verEnd = str.IndexOf("\",\"title\""); string version = str.Substring(verStart, verEnd - verStart); RunUpdateProgram(version); } } } catch(Exception ex) { string msg = ex.InnerException == null ? ex.Message : ex.InnerException.Message; MessageBox.Show($"无法检测更新:{msg}"); } } public void RunUpdateProgram(string verion) { ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "autoUpdate.exe"; startInfo.Arguments = "\"https://cloud-disk-1251608065.cos.ap-guangzhou.myqcloud.com/uNgrok_" + verion + ".exe" + " uNgrok.exe\""; startInfo.WindowStyle = ProcessWindowStyle.Normal; startInfo.UseShellExecute = false; Process.Start(startInfo); Environment.Exit(0); } #endregion } }