using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace RFIDServicePlate
{
public class MySQLInstallHelper
{
///
/// 数据库安装运行状态
///
public enum RunState
{
Error,
Running,
Finish,
Display,
NoDisplay
}
///
/// 数据库安装委托事件
///
/// 运行信息
/// 运行状态
public delegate void DataReceivedEvent(string resultString, RunState runState);
public event DataReceivedEvent DataReceivedEventClick;
public MySQLInstallHelper()
{
}
///
/// 安装MySQL数据库
///
///
/// 使用默认数据库服务名称:MySQL
/// 使用默认数据库服务端口:3306
///
public void StartMySQLInstall()
{
StartMySQLInstall("MySQL");
}
///
/// 安装MySQL数据库
///
/// 数据库服务名称
///
/// 使用默认数据库服务端口:3306
///
public void StartMySQLInstall(string serviceName)
{
StartMySQLInstall(serviceName, 3306);
}
///
/// 使用指定服务名称安装MySQL数据库
///
/// 数据库服务名称
/// 数据库服务端口
public void StartMySQLInstall(string serviceName, int servicePort)
{
if (string.IsNullOrWhiteSpace(serviceName))
{
DataReceivedEventClick?.Invoke("安装失败:数据库服务名称不能为空。", RunState.Error);
return;
}
string str_BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
//判断服务端口是否在有效范围
if (servicePort < 1 || servicePort > 65535)
{
//无效端口时,改为使用默认端口
servicePort = 3306;
}
//判断数据库服务是否已存在
//if (ESSupport.Lib.WindowsServiceHelper.IsServiceIsExisted(serviceName))
// {
//停止正在运行的服务
DataReceivedEventClick?.Invoke($"正在停止{serviceName}服务", RunState.Running);
Shell("net.exe", $"stop {serviceName}");
//移除已安装的MySQL服务
DataReceivedEventClick?.Invoke($"正在删除{serviceName}服务", RunState.Running);
ExecBatCommand(p =>
{
p($".\\bin\\mysqld remove {serviceName}");
p("exit 0");
}, str_BaseDirectory);
// }
//根据操作系统位数安装MySQL8.0运行所需的VC++2019运行库
DataReceivedEventClick?.Invoke("正在安装程序运行库...", RunState.Running);
if (Environment.Is64BitOperatingSystem)
{
Shell("VC2019_x64.exe", "/install /q /norestart");
}
else
{
Shell("VC2019_x86.exe", "/install /q /norestart");
}
if (!File.Exists(Path.Combine(str_BaseDirectory, "my.ini")))
{
//创建MySQL数据库配置文件
DataReceivedEventClick?.Invoke("正在创建数据库配置文件...", RunState.Running);
//MySQL数据库服务端口
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "port", servicePort.ToString());
//MySQL数据库安装目录
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "basedir", str_BaseDirectory);
//MySQL数据库文件目录
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "datadir", Path.Combine(str_BaseDirectory, "Data"));
//允许的最大连接数
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "max_connections", "200");
//MySQL服务端使用的默认字符集
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "character-set-server", "utf8mb4");
//创建新表时将使用的默认存储引擎
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "default-storage-engine", "INNODB");
//数据库用户密码默认的加密方式
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysqld", "default_authentication_plugin ", "mysql_native_password");
//MySQL客户端使用的默认字符集
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "mysql", "default-character-set ", "utf8mb4");
//客户端连接使用的默认端口
ESSupport.Lib.Win32API.INIWriteValue(Path.Combine(str_BaseDirectory, "my.ini"), "client", "port", servicePort.ToString());
}
DataReceivedEventClick?.Invoke("正在初始化数据库...", RunState.Running);
if (!Directory.Exists(Path.Combine(str_BaseDirectory, "Data")))
{
Directory.CreateDirectory(Path.Combine(str_BaseDirectory, "Data"));
}
ExecBatCommand(p =>
{
p(".\\bin\\mysqld --initialize-insecure --user=mysql");
p("exit 0");
}, str_BaseDirectory);
DataReceivedEventClick?.Invoke("正在安装数据库服务...", RunState.Running);
ExecBatCommand(p =>
{
p($".\\bin\\mysqld install {serviceName} --defaults-file=\"{Path.Combine(str_BaseDirectory, "my.ini")}\"");
p("exit 0");
}, str_BaseDirectory);
File.WriteAllLines(Path.Combine(str_BaseDirectory, "dba.sql"),
new string[]
{
"ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yskj2020';",
"FLUSH PRIVILEGES;"
});
DataReceivedEventClick?.Invoke("正在启动数据库服务...", RunState.Running);
Shell("net.exe", $"start {serviceName}");
DataReceivedEventClick?.Invoke("正在设置数据库密码...", RunState.Running);
ExecBatCommand(p =>
{
p(".\\bin\\mysqladmin -u root password \"yskj2020\"");
p($".\\bin\\mysql -u root -pyskj2020 <\"{Path.Combine(str_BaseDirectory, "dba.sql")}\"");
p($"%WINDIR%\\SYSTEM32\\setx MYSQL_HOME \"{str_BaseDirectory}\" /M");
p("exit 0");
}, str_BaseDirectory);
if (File.Exists(Path.Combine(str_BaseDirectory, "dba.sql")))
{
File.Delete(Path.Combine(str_BaseDirectory, "dba.sql"));
}
DataReceivedEventClick?.Invoke("运行结束", RunState.Finish);
}
///
/// 运行程序并输出执行结果
///
/// 需要运行的程序文件
/// 程序运行参数
private void Shell(string exeFile, string command)
{
Shell(exeFile, command, string.Empty);
}
///
/// 运行程序并输出执行结果
///
/// 需要运行的程序文件
/// 程序运行参数
/// 程序工作目录
private void Shell(string exeFile, string command, string workingDir)
{
Shell(exeFile, command, workingDir, 0);
}
///
/// 运行程序并输出执行结果
///
/// 需要运行的程序文件
/// 程序运行参数
/// 程序工作目录
/// 超时等待时间
private void Shell(string exeFile, string command, string workingDir, int timeout)
{
System.Diagnostics.Process process = null;
try
{
process = new System.Diagnostics.Process();
process.StartInfo.FileName = exeFile; //设置要启动的应用程序,如:fastboot
process.StartInfo.Arguments = command; // 设置应用程序参数,如: flash boot0 "A_Debug/boot0.img"
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.EnableRaisingEvents = true; // 获取或设置在进程终止时是否应激发 Exited 事件;不论是正常退出还是异常退出。
if (!string.IsNullOrWhiteSpace(workingDir))
{
process.StartInfo.WorkingDirectory = workingDir; // **重点**,工作目录,必须是 bat 批处理文件所在的目录
}
process.OutputDataReceived += (sender, e) => DataReceivedEventClick?.Invoke(e.Data, RunState.Running);
process.ErrorDataReceived += (sender, e) => DataReceivedEventClick?.Invoke(e.Data, RunState.Running);
process.Start();
process.BeginOutputReadLine(); // 开启异步读取输出操作
process.BeginErrorReadLine(); // 开启异步读取错误操作
if (timeout > 0)
{
process.WaitForExit(timeout);
}
else
{
process.WaitForExit();
}
}
finally
{
if (process != null && !process.HasExited)
{
process.Kill();
}
if (process != null)
{
process.Close();
}
}
}
///
/// 打开控制台执行拼接完成的批处理命令字符串
///
/// 需要执行的命令委托方法:每次调用 中的参数都会执行一次
private void ExecBatCommand(Action> inputAction, string workingDir)
{
System.Diagnostics.Process pro = null;
System.IO.StreamWriter sIn = null;
System.IO.StreamReader sOut = null;
try
{
pro = new System.Diagnostics.Process();
pro.StartInfo.FileName = "cmd.exe";
pro.StartInfo.UseShellExecute = false;
pro.StartInfo.CreateNoWindow = true;
pro.StartInfo.RedirectStandardInput = true;
pro.StartInfo.RedirectStandardOutput = true;
pro.StartInfo.RedirectStandardError = true;
if (!string.IsNullOrWhiteSpace(workingDir))
{
pro.StartInfo.WorkingDirectory = workingDir; // **重点**,工作目录,必须是 bat 批处理文件所在的目录
}
//pro.OutputDataReceived += (sender, e) => DataReceivedEventClick?.Invoke(e.Data, RunState.Running);
//pro.ErrorDataReceived += (sender, e) => DataReceivedEventClick?.Invoke(e.Data, RunState.Running);
pro.Start();
sIn = pro.StandardInput;
sIn.AutoFlush = true;
pro.BeginOutputReadLine();
inputAction(value => sIn.WriteLine(value));
pro.WaitForExit();
}
finally
{
if (pro != null && !pro.HasExited)
pro.Kill();
if (sIn != null)
sIn.Close();
if (sOut != null)
sOut.Close();
if (pro != null)
pro.Close();
}
}
}
}