public void TestDatabase() { DbConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder(); connectionStringBuilder.Add("server", hostName); connectionStringBuilder.Add("port", hostPort); connectionStringBuilder.Add("user", hostUser); connectionStringBuilder.Add("password", hostPassword); connectionStringBuilder.Add("database", hostDatabase); try { using (DbConnection connection = new MySqlConnection(connectionStringBuilder.ConnectionString)) { connection.Open(); } retryTestCount = 0; } catch (Exception ex) { Output.Error(ex.ToString()); if (retryTestCount++ > 5) { retryTestCount = 0; Output.Error("{0} is disable", ClassName); EnablePlugin(false); } } }
/// <summary> /// Insert soldiername and eaguid (Update soldiername if eaguid is exist). /// </summary> /// <param name="parameters"></param> private void InsertEAInfo(DbParameter[] parameters) { try { DbConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder(); connectionStringBuilder.Add("server", hostName); connectionStringBuilder.Add("port", hostPort); connectionStringBuilder.Add("user", hostUser); connectionStringBuilder.Add("password", hostPassword); connectionStringBuilder.Add("database", hostDatabase); using (DbConnection connection = new MySqlConnection(connectionStringBuilder.ConnectionString)) { connection.Open(); using (DbTransaction transaction = connection.BeginTransaction()) { using (DbCommand command = connection.CreateCommand()) { // select playerid by eaguid command.Transaction = transaction; command.Parameters.AddRange(parameters); command.CommandText = string.Format( "INSERT IGNORE INTO `{0}`.`{1}` (`serverid`,`gametype`,`soldiername`,`eaguid`,`firsttime`) VALUE (@serverid,@gametype,@soldiername,@eaguid,@firsttime);" + "UPDATE `{0}`.`{1}` SET `soldiername` = @soldiername, `lasttime` = @lasttime WHERE eaguid = @eaguid;", hostDatabase, ClassName); command.ExecuteNonQuery(); transaction.Commit(); } } } } catch (Exception ex) { Output.Error(ex.ToString()); } }
/// <summary> /// Restart remote PRoCon use powershell. /// <para>NOTE: MUST check the auto connection on remote PRoCon.</para> /// </summary> private void RestartPRoCon() { try { Output.Warning("Restart PRoCon {0}", DateTime.Now); string startProcessCmd = string.Empty; string processName = Process.GetCurrentProcess().ProcessName; string processFileName = Process.GetCurrentProcess().MainModule.FileName; // check for procon.service.exe if (processName.ToLower().Contains("service")) { // Reflection load missing dll string assemblyString = "System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; string typeName = "System.Management.ManagementObjectSearcher"; object searcher = Assembly.Load(assemblyString).CreateInstance(typeName); object query = searcher.GetType().GetProperty("Query").GetValue(searcher, null); query.GetType().GetProperty("QueryString").SetValue(query, "Select * from Win32_Service where ProcessId = " + Process.GetCurrentProcess().Id.ToString(), null); IEnumerable collection = searcher.GetType().GetMethod("Get", Type.EmptyTypes).Invoke(searcher, null) as IEnumerable; string serviceName = string.Empty; foreach (object item in collection) { serviceName = item.GetType().GetProperty("Item").GetValue(item, new object[] { "Name" }).ToString(); } if (string.IsNullOrEmpty(serviceName)) { Output.Error("Restart failed! Not found service"); return; } startProcessCmd = string.Format("start-service '{0}';", serviceName); } else { string commandLine = Environment.CommandLine; string argumentList = commandLine.Split(new string[] { "\"" + processFileName + "\"" }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault().Trim(); if (!string.IsNullOrEmpty(argumentList)) { argumentList = string.Format("-argumentlist '{0}'", argumentList); } startProcessCmd = string.Format("start-process '{0}' {1};", processFileName, argumentList); } int seconds = 10; string stopProcessCmd = string.Format("stop-process -id {0}", Process.GetCurrentProcess().Id); string startSleepCmd = string.Format("start-sleep -seconds {0}", seconds); string checkAndStartCmd = string.Format("if(!(get-process -name '{0}'|where path -eq '{1}')){{{2}}}", processName, processFileName, startProcessCmd); string cmd = string.Format("-windowstyle hidden -command \"{0};{1};{2}\"", stopProcessCmd, startSleepCmd, checkAndStartCmd); Output.Warning("Restart after {0} seconds", seconds); // use powershell can hidden powershell window Process.Start("powershell.exe", cmd); } catch (Exception ex) { Output.Error(ex.ToString()); } }
/// <summary> /// Create database by <see cref="hostDatabase"/> if not exist. /// </summary> private void InitDatabase() { DbConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder(); connectionStringBuilder.Add("server", hostName); connectionStringBuilder.Add("port", hostPort); connectionStringBuilder.Add("user", hostUser); connectionStringBuilder.Add("password", hostPassword); try { using (DbConnection connection = new MySqlConnection(connectionStringBuilder.ConnectionString)) { connection.Open(); using (DbTransaction transaction = connection.BeginTransaction()) { try { using (DbCommand command = connection.CreateCommand()) { command.Transaction = transaction; command.CommandText = string.Format("CREATE DATABASE if NOT EXISTS `{0}`", hostDatabase); command.ExecuteNonQuery(); command.CommandText = string.Format("USE `{0}`", hostDatabase); command.ExecuteNonQuery(); command.CommandText = string.Format("CREATE TABLE IF NOT EXISTS `{0}` (" + "`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT," + "`gameid` INT(10) UNSIGNED NOT NULL DEFAULT '0'," + "`ipaddress` VARCHAR(22) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "`clantag` VARCHAR(5) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "`soldiername` VARCHAR(20) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "`eaguid` VARCHAR(35) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "`pbguid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "`country` VARCHAR(30) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "`countrycode` VARCHAR(10) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci'," + "PRIMARY KEY(`id`), UNIQUE INDEX `Index 2` (`eaguid`), UNIQUE INDEX `Index 3` (`pbguid`)" + ") COLLATE = 'utf8mb4_general_ci'", ClassName); command.ExecuteNonQuery(); transaction.Commit(); } } catch { transaction.Rollback(); throw; } } } } catch (Exception ex) { Output.WriteLine("-------------------"); Output.Error(ex.ToString()); } }
/// <summary> /// Precompile code to check error. /// </summary> /// <param name="sourceCode">source code</param> /// <returns></returns> public bool CompilePlugin(string sourceCode) { CompilerParameters parameters = new CompilerParameters(); parameters.ReferencedAssemblies.Add("System.dll"); parameters.ReferencedAssemblies.Add("System.Core.dll"); parameters.ReferencedAssemblies.Add("System.Data.dll"); parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll"); parameters.ReferencedAssemblies.Add("System.Xml.dll"); parameters.ReferencedAssemblies.Add("MySql.Data.dll"); parameters.ReferencedAssemblies.Add("PRoCon.Core.dll"); parameters.GenerateInMemory = false; parameters.GenerateExecutable = false; #if DEBUG parameters.IncludeDebugInformation = true; #else parameters.IncludeDebugInformation = false; #endif using (CodeDomProvider codeDomProvider = new CSharpCodeProvider(new Dictionary <string, string>() { { "CompilerVersion", "v3.5" } })) { CompilerResults results = codeDomProvider.CompileAssemblyFromSource(parameters, sourceCode); // check for syntax and reference errors if (results.Errors.HasErrors == true && results.Errors[0].ErrorNumber != "CS0016") { Output.Error("Update file compilation error!"); foreach (CompilerError cError in results.Errors) { if (cError.ErrorNumber != "CS0016" && cError.IsWarning == false) { Output.Error("(Line: {0}, C: {1}) {2}: {3}", cError.Line, cError.Column, cError.ErrorNumber, cError.ErrorText); } } return(false); } // check for interface error Assembly assembly = results.CompiledAssembly; Type objType = assembly.GetTypes().FirstOrDefault(_ => _.GetInterfaces().Contains(typeof(IPRoConPluginInterface))); if (objType != null) { IPRoConPluginInterface obj = assembly.CreateInstance(objType.FullName) as IPRoConPluginInterface; Output.Information("Plugin:{0} {1}", obj.GetPluginName(), obj.GetPluginVersion()); return(true); } Output.Error("Not found implementation of {0}!", typeof(IPRoConPluginInterface).Name); return(false); } }
/// <summary> /// Create database by <see cref="hostDatabase"/> if not exist. /// </summary> private void InitDatabase() { DbConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder(); connectionStringBuilder.Add("server", hostName); connectionStringBuilder.Add("port", hostPort); connectionStringBuilder.Add("user", hostUser); connectionStringBuilder.Add("password", hostPassword); connectionStringBuilder.Add("database", hostDatabase); try { using (DbConnection connection = new MySqlConnection(connectionStringBuilder.ConnectionString)) { connection.Open(); using (DbTransaction transaction = connection.BeginTransaction()) { using (DbCommand command = connection.CreateCommand()) { command.Transaction = transaction; command.CommandText = string.Format("CREATE TABLE IF NOT EXISTS `{0}`.`{1}` (" + "`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT," + "`serverid` INT(10) DEFAULT NULL," + "`gametype` VARCHAR(10) NULL DEFAULT NULL," + "`ipaddress` VARCHAR(22) NULL DEFAULT NULL," + "`clantag` VARCHAR(5) NULL DEFAULT NULL," + "`soldiername` VARCHAR(20) NULL DEFAULT NULL," + "`eaguid` VARCHAR(35) NULL DEFAULT NULL ," + "`pbguid` VARCHAR(32) NULL DEFAULT NULL ," + "`country` VARCHAR(30) NULL DEFAULT NULL ," + "`countrycode` VARCHAR(10) NULL DEFAULT NULL ," + "`firsttime` datetime DEFAULT NULL," + "`lasttime` datetime DEFAULT NULL," + "PRIMARY KEY(`id`), " + "UNIQUE INDEX `Index 2` (`eaguid`), " + "UNIQUE INDEX `Index 3` (`pbguid`)" + ")", hostDatabase, ClassName); command.ExecuteNonQuery(); transaction.Commit(); } } } } catch (Exception ex) { Output.WriteLine("-------------------"); Output.Error(ex.ToString()); } }
public void OnPluginLoaded(string strHostName, string strPort, string strPRoConVersion) { Output.Listeners.Add(new TextWriterTraceListener(ClassName + "_" + strHostName + "_" + strPort + ".log") { TraceOutputOptions = TraceOptions.DateTime }); // output to debug file Output.Listeners.Add(new PRoConTraceListener(this)); // output to pluginconsole Output.AutoFlush = true; remoteCommand.OnError = _ => Output.Error(_); remoteCommand.OnOutput = _ => Output.Information(_); // Get common events in this class and PRoConPluginAPI BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; IEnumerable <string> baseMethods = typeof(PRoConPluginAPI).GetMethods().Where(_ => _.IsVirtual).Select(_ => _.Name); IEnumerable <string> commonMethods = GetType().GetMethods(bindingFlags).Where(_ => _.IsVirtual).Select(_ => _.Name).Intersect(baseMethods); RegisterEvents(ClassName, commonMethods.ToArray()); }
/// TODO #endregion #region Private Methods /// <summary> /// Update plugin file from <see cref="sourceFileUri"/> /// </summary> /// <param name="sourceFileUri"> /// source file uri,for example: /// <para>https://xxx/xx.cs</para> /// <para>file:///D:/xxx/xx.cs</para> /// </param> private void UpdatePlugin(string sourceFileUri) { try { // NOTE:DO NOT convert to string,it will lost UTF-8 BOM header download remote file WebClient webClient = new WebClient(); List <byte> srcDate = webClient.DownloadData(sourceFileUri).ToList(); webClient.Dispose(); // replace '\n' to '\r\n' byte CR = Convert.ToByte('\r'); byte LF = Convert.ToByte('\n'); for (int i = 0; i < srcDate.Count; i++) { if (srcDate[i] == LF && (i == 0 || srcDate[i - 1] != CR)) { srcDate.Insert(i++, CR); } } byte[] srcBuffer = srcDate.ToArray(); // load local file string currentPluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ClassName + ".cs"); byte[] dstBuffer = File.ReadAllBytes(currentPluginPath); // If the file MD5 is different, update. if (!Enumerable.SequenceEqual(MD5.Create().ComputeHash(srcBuffer), MD5.Create().ComputeHash(dstBuffer))) { string sourceString = Encoding.UTF8.GetString(srcBuffer); if (!string.IsNullOrEmpty(sourceString) && CompilePlugin(sourceString)) { File.WriteAllBytes(currentPluginPath, srcBuffer); Output.Information("Update succssful!"); return; } Output.Information("Update failed!"); return; } Output.Information("Already the latest version."); } catch (Exception ex) { Output.Error(ex.Message); } }
/// <summary> /// Insert all player info (if it's exist update by eaguid). /// </summary> /// <param name="parameters"></param> private void InsertPbInfo(DbParameter[] parameters) { DbConnectionStringBuilder connectionStringBuilder = new MySqlConnectionStringBuilder(); connectionStringBuilder.Add("server", hostName); connectionStringBuilder.Add("port", hostPort); connectionStringBuilder.Add("user", hostUser); connectionStringBuilder.Add("password", hostPassword); connectionStringBuilder.Add("database", hostDatabase); try { using (DbConnection connection = new MySqlConnection(connectionStringBuilder.ConnectionString)) { connection.Open(); using (DbTransaction transaction = connection.BeginTransaction()) { using (DbCommand command = connection.CreateCommand()) { // select playerid by eaguid command.Transaction = transaction; command.Parameters.AddRange(parameters); command.CommandText = string.Format("SELECT `id` from `{0}`.`{1}` WHERE `eaguid` = @eaguid", hostDatabase, ClassName); DbDataReader reader = command.ExecuteReader(); if (!reader.Read()) { // if not found playerid, insert player info to database. reader.Close(); command.CommandText = string.Format( "INSERT INTO `{0}`.`{1}` (" + "`ipaddress`," + "`clantag`," + "`soldiername`," + "`eaguid`," + "`pbguid`," + "`country`," + "`countrycode`" + ") VALUES (" + "@ipaddress," + "@clantag," + "@soldiername," + "@eaguid," + "@pbguid," + "@country," + "@countrycode" + ")", hostDatabase, ClassName); command.ExecuteNonQuery(); } else { // if found id by eaguid, update player info to database. var id = reader.GetInt64(0); reader.Close(); command.CommandText = string.Format( "UPDATE `{0}`.`{1}` SET " + "`ipaddress` = @ipaddress, " + "`clantag` = @clantag, " + "`soldiername` = @soldiername, " + "`pbguid` = @pbguid, " + "`country` = @country, " + "`countrycode` = @countrycode " + " WHERE `id` = @id", hostDatabase, ClassName); command.Parameters.Add(new MySqlParameter("@id", id)); command.ExecuteNonQuery(); } transaction.Commit(); } } } } catch (Exception ex) { Output.Error(ex.ToString()); } }
public List <CPluginVariable> GetDisplayPluginVariables() { // procon cmd if (!string.IsNullOrEmpty(rconCmd.Trim())) { var console = new PRoConTraceListener(this, 1); Output.Listeners.Add(console); Command(rconCmd.Split(' ')); var tmpList = rconCmdHistory.ToList(); tmpList.Add(rconCmd); rconCmdHistory = tmpList.ToArray(); rconCmd = string.Empty; Output.Listeners.Remove(console); } // remote shell if (remoteShellEnable) { if (!remoteCommand.IsRunning) { remoteCommand.Start(remoteShellName, _ => Output.Information(_), _ => Output.Error(_)); remoteShellPid = remoteCommand.Pid; } if (!string.IsNullOrEmpty(remoteCmd.Trim())) { remoteCommand.Executed(remoteCmd); var tmpList = remoteCmdHistory.ToList(); tmpList.Add(remoteCmd); remoteCmdHistory = tmpList.ToArray(); remoteCmd = string.Empty; } } else { remoteCommand.Close(); remoteShellPid = 0; } // restart if (restartProcon == enumBoolYesNo.Yes && confirmRestart == enumBoolYesNo.Yes) { confirmRestart = enumBoolYesNo.No; restartProcon = enumBoolYesNo.No; isRestart = 1; } else { // NOTE: MUST check autoconnection on remote PRoCon before restart. if (isRestart > 0) { isRestart = 0; RestartPRoCon(); } } return(GetVariables(true)); }