//==============================================================
//  版权所有：深圳杰文科技
//  文件名：ServerUpgrade.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者：
//  修改时间：
//  修改说明： 
//==============================================================

using System;
using System.IO;
using System.ServiceProcess;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;

namespace Framework.Upgrade
{
	internal class ServerUpgrade
	{
		/// <summary>
		/// args的参数：1.版本号；2：登录账号；3：登录密码；4：要启动的应用程序名。
		/// </summary>
		public static void Update(string[] args)
		{
			StopService(args[0]); //停止服务。
			KillProcess(args[0]); //某些时候，服务停止了，但进程还未关闭，因此再手动杀死进程。

			Thread.Sleep(1000); //为防止服务停止不及时导致占用了升级文件，因此暂停1秒再移动文件。
			Move();

			StartService(args[0]); //启动服务

			string processName = args[0];
			if (!processName.ToLower().EndsWith(".exe"))
			{
				processName = processName + ".exe";
			}

			processName = Path.Combine(Application.StartupPath, processName);
			Console.WriteLine("准备启动进程：" + processName);

			Process.Start(processName); //启动进程。
		}

		private static void Move()
		{
			string upgradePath = Application.StartupPath + "\\ServerUpgrade\\"; //升级文件的路径。

			DeleteFile(upgradePath); //删除目录和文件。

			MoveDir(upgradePath); //移动目录。
		}

		private static void DeleteFile(string upgradePath)
		{
			string fileName = upgradePath + "_upgrade_delete_.lst";
			if (!File.Exists(fileName))
			{
				return;
			}

			foreach (string file in File.ReadAllLines(fileName))
			{
				string path = Path.Combine(Application.StartupPath, file);
				try
				{
					Console.WriteLine("准备删除文件(夹) {0}", path);
					if (File.Exists(path)) //如果是文件，
					{
						File.Delete(path);
						Console.WriteLine("已删除文件 {0}", path);
					}
					else if (Directory.Exists(path)) //否则是文件夹。
					{
						Directory.Delete(path, true); //注意，不能删除中文名称的文件夹。
						Console.WriteLine("已删除文件夹 {0}", path);
					}
					else
					{
						Console.WriteLine("未发现文件(夹)，删除失败");
					}
				}
				catch (Exception ex)
				{
					Console.WriteLine();
					Console.WriteLine("文件(夹)删除失败 {0}", path);
					File.AppendAllText(Path.Combine(Application.StartupPath, "upgrade.log"), "\r\n" + ex.Message);
				}
			}

			File.Delete(fileName);
		}

		static void MoveDir(string rootDir)
		{
			//1.移动文件
			MoveDir(rootDir, rootDir);

			//2.移动子目录
			string[] directories = Directory.GetDirectories(rootDir);
			foreach (string subDir in directories)
			{
				MoveDir(rootDir, subDir);
			}
		}

		static void MoveDir(string rootDir, string dir)
		{
			if (!Directory.Exists(dir))
			{
				Console.WriteLine("目录{0}不存在", dir);
				return;
			}

			string[] files = Directory.GetFiles(dir);
			Console.WriteLine("准备移动{0}下的文件（共{1}个）", dir, files.Length);
			for (int i = 0; i < files.Length; i++)
			{
				string source = files[i];
				Console.WriteLine(Path.GetFileName(source));
				if (Path.GetFileName(source) == "Framework.Upgrade.exe")
				{
					Console.WriteLine("忽略 " + source);
					continue;
				}

				Console.WriteLine("准备移动 " + source);

				string dest = Path.Combine(Application.StartupPath, source.Replace(rootDir, ""));

				string destDir = Path.GetDirectoryName(dest);
				if (!Directory.Exists(destDir))
				{
					Console.WriteLine("创建目录 " + destDir);
					Directory.CreateDirectory(destDir);
				}

				File.SetAttributes(source, FileAttributes.Normal);
				if (File.Exists(dest))
				{
					Console.WriteLine("清除文件 " + dest);
					File.SetAttributes(dest, FileAttributes.Normal);

					try
					{
						File.Delete(dest);
					}
					catch (Exception ex)
					{
						File.AppendAllText(Path.Combine(Application.StartupPath, "upgrade.log"), "\r\n" + ex.Message);
					}
				}
				File.Move(source, dest);

				File.AppendAllText(Path.Combine(Application.StartupPath, "upgrade.log"), "\r\n" + "移动成功 " + dest);
			}
		}

		private static void KillProcess(string processName)
		{
			Process[] processes = Process.GetProcesses();
			foreach (Process p in processes)
			{
				if (p.ProcessName == processName)
				{
					p.Kill();
					Console.WriteLine("结束进程 " + p.ProcessName);
					File.AppendAllText(Path.Combine(Application.StartupPath, "upgrade.log"), "\r\n" + "结束进程 " + p.ProcessName);
					break;
				}
			}
		}

		private static void StopService(string serviceName)
		{
			foreach (ServiceController sc in ServiceController.GetServices())
			{
				if (sc.ServiceName == serviceName)
				{
					if (sc.CanStop)
					{
						sc.Stop();
						sc.Refresh();
						File.AppendAllText(Path.Combine(Application.StartupPath, "upgrade.log"), "\r\n" + "服务已停止");
						Console.WriteLine("服务已停止");
					}
					break;
				}
			}
		}

		private static void StartService(string serviceName)
		{
			foreach (ServiceController sc in ServiceController.GetServices())
			{
				if (sc.ServiceName == serviceName)
				{
					sc.Start();
					sc.Refresh();
					File.AppendAllText(Path.Combine(Application.StartupPath, "upgrade.log"), "\r\n" + "服务启动成功");
					break;
				}
			}
		}

	}
}
