using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace ryCommon
{
    /// <summary>
    /// 文件操作类
    /// </summary>
    public class RyFiles
    {
        #region 【内部类型定义】
        private struct SHFILEOPSTRUCT
        {
            public IntPtr hwnd;         //父窗口句柄 
            public WFunc wFunc;         //要执行的动作 
            public string pFrom;        //源文件路径，可以是多个文件，以结尾符号"\0"结束
            public string pTo;          //目标路径，可以是路径或文件名 
            public FILEOP_FLAGS fFlags;             //标志，附加选项 
            public bool fAnyOperationsAborted;      //是否可被中断 
            public IntPtr hNameMappings;            //文件映射名字，可在其它 Shell 函数中使用 
            public string lpszProgressTitle;        // 只在 FOF_SIMPLEPROGRESS 时，指定对话框的标题。
        }

        private enum WFunc
        {
            FO_MOVE = 0x0001,   //移动文件
            FO_COPY = 0x0002,   //复制文件
            FO_DELETE = 0x0003, //删除文件，只是用pFrom
            FO_RENAME = 0x0004  //文件重命名
        }

        private enum FILEOP_FLAGS
        {
            FOF_MULTIDESTFILES = 0x0001,    //pTo 指定了多个目标文件，而不是单个目录
            FOF_CONFIRMMOUSE = 0x0002,
            FOF_SILENT = 0x0044,            // 不显示一个进度对话框
            FOF_RENAMEONCOLLISION = 0x0008, // 碰到有抵触的名字时，自动分配前缀
            FOF_NOCONFIRMATION = 0x10,      // 不对用户显示提示
            FOF_WANTMAPPINGHANDLE = 0x0020, // 填充 hNameMappings 字段，必须使用 SHFreeNameMappings 释放
            FOF_ALLOWUNDO = 0x40,           // 允许撤销
            FOF_FILESONLY = 0x0080,         // 使用 *.* 时, 只对文件操作
            FOF_SIMPLEPROGRESS = 0x0100,    // 简单进度条，意味者不显示文件名。
            FOF_NOCONFIRMMKDIR = 0x0200,    // 建新目录时不需要用户确定
            FOF_NOERRORUI = 0x0400,         // 不显示出错用户界面
            FOF_NOCOPYSECURITYATTRIBS = 0x0800,     // 不复制 NT 文件的安全属性
            FOF_NORECURSION = 0x1000        // 不递归目录
        }
        #endregion 【内部类型定义】
        #region 【DllImport】

        [DllImport("shell32.dll")]
        private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);
        /// <summary>
        /// 
        /// </summary>
        public enum ShowCommands : int
        {
            /// <summary>
            /// 
            /// </summary>
            SW_HIDE = 0,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWNORMAL = 1,
            /// <summary>
            /// 
            /// </summary>
            SW_NORMAL = 1,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWMINIMIZED = 2,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWMAXIMIZED = 3,
            /// <summary>
            /// 
            /// </summary>
            SW_MAXIMIZE = 3,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWNOACTIVATE = 4,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOW = 5,
            /// <summary>
            /// 
            /// </summary>
            SW_MINIMIZE = 6,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWMINNOACTIVE = 7,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWNA = 8,
            /// <summary>
            /// 
            /// </summary>
            SW_RESTORE = 9,
            /// <summary>
            /// 
            /// </summary>
            SW_SHOWDEFAULT = 10,
            /// <summary>
            /// 
            /// </summary>
            SW_FORCEMINIMIZE = 11,
            /// <summary>
            /// 
            /// </summary>
            SW_MAX = 11
        }
        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        static extern int ShellExecute(
            IntPtr hwnd,
            string lpOperation,
            string lpFile,
            string lpParameters,
            string lpDirectory,
            ShowCommands nShowCmd);
        #endregion 【DllImport】
        #region 【删除文件操作】
        /// <summary>
        /// 删除单个文件。
        /// </summary>
        /// <param name="fileName">删除的文件名</param>
        /// <param name="toRecycle">指示是将文件放入回收站还是永久删除，true-放入回收站，false-永久删除</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认删除对话框，false-不显示确认删除对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框，true-显示，false-不显示。该参数当指定永久删除文件时有效</param>
        /// <param name="errorMsg">反馈错误消息的字符串</param>
        /// <returns>操作执行结果标识，删除文件成功返回0，否则，返回错误代码</returns>
        public static int DeleteFile(string fileName, bool toRecycle, bool showDialog, bool showProgress, ref string errorMsg)
        {
            try
            {
                string fName = fileName;
                if (fileName.IndexOf("*") < 0 && fileName.IndexOf("?") < 0)
                {
                    fName = GetFullName(fileName);
                }
                return ToDelete(fName, toRecycle, showDialog, showProgress, ref errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }
        /// <summary>
        /// 删除单个文件。
        /// </summary>
        /// <param name="fileName">删除的文件名</param>
        /// <param name="toRecycle">指示是将文件放入回收站还是永久删除，true-放入回收站，false-永久删除</param>
        /// <returns>操作执行结果标识，删除文件成功返回0，否则，返回错误代码</returns>
        public static int DeleteFile(string fileName, bool toRecycle)
        {
            string errorMsg = "";
            return DeleteFile(fileName,toRecycle,false,false,ref errorMsg);
        }
        /// <summary>
        /// 永久删除单个文件。
        /// </summary>
        /// <param name="fileName">永久删除的文件名</param>
        /// <returns>操作执行结果标识，删除文件成功返回0，否则，返回错误代码</returns>
        public static int DeleteFile(string fileName)
        {
            return DeleteFile(fileName, false);
        }
        /// <summary>
        /// 删除一组文件。
        /// </summary>
        /// <param name="fileNames">字符串数组，表示一组文件名</param>
        /// <param name="toRecycle">指示是将文件放入回收站还是永久删除，true-放入回收站，false-永久删除</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认删除对话框，false-不显示确认删除对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框，true-显示，false-不显示。该参数当指定永久删除文件时有效</param>
        /// <param name="errorMsg">反馈错误消息的字符串</param>
        /// <returns>操作执行结果标识，删除文件成功返回0，否则，返回错误代码</returns>
        public static int DeleteFiles(string[] fileNames, bool toRecycle, bool showDialog, bool showProgress, ref string errorMsg)
        {
            try
            {
                string fName = "";
                foreach (string str in fileNames)
                {
                    fName += GetFullName(str) + "\0";     //组件文件组字符串
                }

                return ToDelete(fName, toRecycle, showDialog, showProgress, ref errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }
        #endregion 【删除文件操作】

        #region 【移动文件操作】
        /// <summary>
        /// 移动文件到指定路径下
        /// </summary>
        /// <param name="sourceFileName">要移动的文件名</param>
        /// <param name="destinationPath">移动到的目的路径</param>
        /// <returns></returns>
        public static int MoveFile(string sourceFileName, string destinationPath)
        {
            string errorMsg = "";
            return MoveFile(sourceFileName, destinationPath,false,false,false,ref errorMsg);
        }
        /// <summary>
        /// 移动一个文件到指定路径下
        /// </summary>
        /// <param name="sourceFileName">要移动的文件名</param>
        /// <param name="destinationPath">移动到的目的路径</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认对话框，false-不显示确认对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框</param>
        /// <param name="autoRename">指示当文件名重复时，是否自动为新文件加上后缀名</param>
        /// <param name="errorMsg">反馈错误消息的字符串</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，失败返回错误代码</returns>
        public static int MoveFile(string sourceFileName, string destinationPath, bool showDialog, bool showProgress, bool autoRename, ref string errorMsg)
        {
            try
            {
                string sfName = GetFullName(sourceFileName);
                string dfName = GetFullName(destinationPath);

                return ToMoveOrCopy(WFunc.FO_MOVE, sfName, dfName, showDialog, showProgress, autoRename, ref errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }

        /// <summary>
        /// 移动一组文件到指定的路径下
        /// </summary>
        /// <param name="sourceFileNames">要移动的文件名数组</param>
        /// <param name="destinationPath">移动到的目的路径</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认对话框，false-不显示确认对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框</param>
        /// <param name="autoRename">指示当文件名重复时，是否自动为新文件加上后缀名</param>
        /// <param name="errorMsg">反馈错误消息的字符串</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，失败返回错误代码,-200:表示其他异常</returns>
        public static int MoveFiles(string[] sourceFileNames, string destinationPath, bool showDialog, bool showProgress, bool autoRename, ref string errorMsg)
        {
            try
            {
                string sfName = "";
                foreach (string str in sourceFileNames)
                {
                    sfName += GetFullName(str) + "\0";   //组件文件组字符串
                }
                string dfName = GetFullName(destinationPath);

                return ToMoveOrCopy(WFunc.FO_MOVE, sfName, dfName, showDialog, showProgress, autoRename, ref errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }
        #endregion 【移动文件操作】

        #region 【复制文件操作】
        /// <summary>
        /// 复制文件到指定的文件名或路径
        /// </summary>
        /// <param name="sourceFileName">要复制的文件名</param>
        /// <param name="destinationFileName">复制到的目的文件名或路径</param>
        /// <returns></returns>
        public static int CopyFile(string sourceFileName, string destinationFileName)
        {
            string errorMsg = "";
            return CopyFile(sourceFileName, destinationFileName,false,false,false,ref errorMsg);
        }
        /// <summary>
        /// 复制文件到指定的文件名或路径
        /// </summary>
        /// <param name="sourceFileName">要复制的文件名</param>
        /// <param name="destinationFileName">复制到的目的文件名或路径</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认对话框，false-不显示确认对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框</param>
        /// <param name="autoRename">指示当文件名重复时，是否自动为新文件加上后缀名</param>
        /// <param name="errorMsg">返回错误信息</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，失败返回错误代码,-200:表示其他异常</returns>
        public static int CopyFile(string sourceFileName, string destinationFileName, bool showDialog, bool showProgress, bool autoRename, ref string errorMsg)
        {
            try
            {
                string sfName = sourceFileName;
                string dfName = destinationFileName;

                return ToMoveOrCopy(WFunc.FO_COPY, sfName, dfName, showDialog, showProgress, autoRename, ref errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }

        /// <summary>
        /// 复制一组文件到指定的路径
        /// </summary>
        /// <param name="sourceFileNames">要复制的文件名数组</param>
        /// <param name="destinationPath">复制到的目的路径</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认对话框，false-不显示确认对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框</param>
        /// <param name="autoRename">指示当文件名重复时，是否自动为新文件加上后缀名</param>
        /// <param name="errorMsg">返回错误信息</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，失败返回错误代码,-200:表示其他异常</returns>
        public static int CopyFiles(string[] sourceFileNames, string destinationPath, bool showDialog, bool showProgress, bool autoRename, ref string errorMsg)
        {
            try
            {
                string sfName = "";
                foreach (string str in sourceFileNames)
                {
                    sfName += GetFullName(str) + "\0";     //组件文件组字符串
                }
                string dfName = GetFullName(destinationPath);

                return ToMoveOrCopy(WFunc.FO_COPY, sfName, dfName, showDialog, showProgress, autoRename, ref errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }
        /// <summary>
        /// 大文件多次复制文件  true：复制成功   false：复制失败
        /// </summary>
        /// <param name="soucrePath">原始文件路径</param>
        /// <param name="targetPath">复制目标文件路径</param>
        /// <returns></returns>
        public static bool CopyBigFile(string soucrePath, string targetPath)
        {
            try
            {
                //读取复制文件流
                using (FileStream fsRead = new FileStream(soucrePath, FileMode.Open, FileAccess.Read))
                {
                    //写入文件复制流
                    using (FileStream fsWrite = new FileStream(targetPath, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        byte[] buffer = new byte[1024 * 1024 * 2]; //每次读取2M
                        //可能文件比较大，要循环读取，每次读取2M
                        while (true)
                        {
                            //每次读取的数据    n：是每次读取到的实际数据大小
                            int n = fsRead.Read(buffer, 0, buffer.Count());
                            //如果n=0说明读取的数据为空，已经读取到最后了，跳出循环
                            if (n == 0)
                            {
                                break;
                            }
                            //写入每次读取的实际数据大小
                            fsWrite.Write(buffer, 0, n);
                        }
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 复制文件夹到目标文件夹
        /// </summary>
        /// <param name="fromDir">源文件夹</param>
        /// <param name="ToDir">目标文件夹</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，负数表示复制失败的文件数量。1表示源文件夹不存在</returns>
        public static int CopyFolder(string fromDir, string ToDir)
        {
            var _fromDir = fromDir.TrimEnd('\\');
            var _ToDir=ToDir.TrimEnd('\\');
            if (!Directory.Exists(_fromDir)) { return 1; }
            var files = Directory.GetFiles(fromDir);
            var error = 0;
            foreach (var file in files)
            {
                if (CopyFile(file, _ToDir + "\\" + Path.GetFileName(file)) != 0)
                {
                    error++;
                }
            }
            var dirs = Directory.GetDirectories(_fromDir);
            foreach (var dir in dirs)
            {
                if (CopyFolder(dir, _ToDir + "\\" + Path.GetFileName(dir)) > 0)
                {
                    error++;
                }
            }
            return -error;
        }
        #endregion 【复制文件操作】

        #region 【重命名文件】
        /// <summary>
        /// 重命名一个文件为新名称，建议您使用更方便的Microsoft.VisualBasic.FileSystem.ReName();替换该方法
        /// </summary>
        /// <param name="sourceFileName">要复制的文件名</param>
        /// <param name="destinationFileName">复制到的目的文件名或路径</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认对话框，false-不显示确认对话框</param>
        /// <param name="errorMsg">返回错误信息</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，失败返回错误代码,-200:表示其他异常</returns>
        [Obsolete("建议使用 Microsoft.VisualBasic.FileSystem.ReName()方法")]
        public static int ReNameFile(string sourceFileName, string destinationFileName, bool showDialog, ref string errorMsg)
        {

            try
            {
                SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT()
                {
                    wFunc = WFunc.FO_RENAME,
                    pFrom = GetFullName(sourceFileName) + "\0\0",         //将文件名以结尾字符"\0\0"结束
                    pTo = GetFullName(destinationFileName) + "\0\0",
                    fFlags = FILEOP_FLAGS.FOF_NOERRORUI
                };
                if (!showDialog)
                    lpFileOp.fFlags |= FILEOP_FLAGS.FOF_NOCONFIRMATION;     //设定不显示提示对话框


                lpFileOp.fAnyOperationsAborted = true;

                int n = SHFileOperation(ref lpFileOp);
                if (n == 0)
                    return 0;

                string tmp = GetErrorString(n);

                errorMsg = string.Format("{0}({1})", tmp, sourceFileName);

                return n;
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
                return -200;
            }
        }
        

        #endregion 【重命名文件】

        /// <summary>
        /// 删除单个或多个文件
        /// </summary>
        /// <param name="fileName">删除的文件名，如果是多个文件，文件名之间以字符串结尾符'\0'隔开</param>
        /// <param name="toRecycle">指示是将文件放入回收站还是永久删除，true-放入回收站，false-永久删除</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认删除对话框，false-不显示确认删除对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框，true-显示，false-不显示。该参数当指定永久删除文件时有效</param>
        /// <param name="errorMsg">反馈错误消息的字符串</param>
        /// <returns>操作执行结果标识，删除文件成功返回0，否则，返回错误代码</returns>
        private static int ToDelete(string fileName, bool toRecycle, bool showDialog, bool showProgress, ref string errorMsg)
        {
            SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT()
            {
                wFunc = WFunc.FO_DELETE,
                pFrom = fileName + "\0"       //将文件名以结尾字符"\0"结束
            };
            lpFileOp.fFlags = FILEOP_FLAGS.FOF_NOERRORUI;
            if (!showDialog)
                lpFileOp.fFlags |= FILEOP_FLAGS.FOF_NOCONFIRMATION;     //设定不显示提示对话框
            if (!showProgress)
                lpFileOp.fFlags |= FILEOP_FLAGS.FOF_SILENT;     //设定不显示进度对话框
            if (!toRecycle)
                lpFileOp.fFlags &= ~FILEOP_FLAGS.FOF_ALLOWUNDO;  //设定删除到回收站
            lpFileOp.fAnyOperationsAborted = true;

            int n = SHFileOperation(ref lpFileOp);
            if (n == 0)
                return 0;

            string tmp = GetErrorString(n);

            //.av 文件正常删除了但也提示 402 错误，不知道为什么。屏蔽之。
            if ((fileName.ToLower().EndsWith(".av") && n.ToString("X") == "402"))
                return 0;

            errorMsg = string.Format("{0}({1})", tmp, fileName);

            return n;
        }

        /// <summary>
        /// 移动或复制一个或多个文件到指定路径下
        /// </summary>
        /// <param name="flag">操作类型，是移动操作还是复制操作</param>
        /// <param name="sourceFileName">要移动或复制的文件名，如果是多个文件，文件名之间以字符串结尾符'\0'隔开</param>
        /// <param name="destinationFileName">移动到的目的位置</param>
        /// <param name="showDialog">指示是否显示确认对话框，true-显示确认对话框，false-不显示确认对话框</param>
        /// <param name="showProgress">指示是否显示进度对话框</param>
        /// <param name="autoRename">指示当文件名重复时，是否自动为新文件加上后缀名</param>
        /// <param name="errorMsg">反馈错误消息的字符串</param>
        /// <returns>返回移动操作是否成功的标识，成功返回0，失败返回错误代码</returns>
        private static int ToMoveOrCopy(WFunc flag, string sourceFileName, string destinationFileName, bool showDialog, bool showProgress, bool autoRename, ref string errorMsg)
        {
            SHFILEOPSTRUCT lpFileOp = new SHFILEOPSTRUCT()
            {
                wFunc = flag,
                pFrom = sourceFileName + "\0",         //将文件名以结尾字符"\0\0"结束
                pTo = destinationFileName + "\0\0"
            };
            lpFileOp.fFlags = FILEOP_FLAGS.FOF_NOERRORUI;
            lpFileOp.fFlags |= FILEOP_FLAGS.FOF_NOCONFIRMMKDIR; //指定在需要时可以直接创建路径
            if (!showDialog)
                lpFileOp.fFlags |= FILEOP_FLAGS.FOF_NOCONFIRMATION;     //设定不显示提示对话框
            if (!showProgress)
                lpFileOp.fFlags |= FILEOP_FLAGS.FOF_SILENT;     //设定不显示进度对话框
            if (autoRename)
                lpFileOp.fFlags |= FILEOP_FLAGS.FOF_RENAMEONCOLLISION;  //自动为重名文件添加名称后缀

            lpFileOp.fAnyOperationsAborted = true;

            int n = SHFileOperation(ref lpFileOp);
            if (n == 0)
                return 0;

            string tmp = GetErrorString(n);

            errorMsg = string.Format("{0}({1})", tmp, sourceFileName);

            return n;
        }
        /// <summary>
        /// 如果指定文件夹不存在，则创建文件夹
        /// </summary>
        /// <param name="path"></param>
       public static void CreateDirectory(string path)
        {
            if(!System.IO.Directory.Exists(path))
            {
                System.IO.Directory.CreateDirectory(path);
            }
        }
        /// <summary>
        /// 获取一个文件的全名
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns>返回生成文件的完整路径名</returns>
        private static string GetFullName(string fileName)
        {
            FileInfo fi = new FileInfo(fileName);
            return fi.FullName;
        }
        /// <summary>
        /// 获取一个文件的全名
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns>返回生成文件的完整路径名</returns>
        public static sType.FileTime GetFileDate(string fileName)
        {
            var result = new sType.FileTime();
            FileInfo fi = new FileInfo(fileName);
            result.AccessTime = fi.LastAccessTime;
            result.CreateTime = fi.CreationTime;
            result.LastWriteTime = fi.LastWriteTime;
            return result;
        }
        /// <summary>
        /// 解释错误代码
        /// </summary>
        /// <param name="n">代码号</param>
        /// <returns>返回关于错误代码的文字描述</returns>
        private static string GetErrorString(int n)
        {
            if (n == 0) return string.Empty;

            switch (n)
            {
                case 2:
                    return "系统找不到指定的文件。";
                case 7:
                    return "存储控制块被销毁。您是否选择的“取消”操作？";
                case 113:
                    return "文件已存在！";
                case 115:
                    return "重命名文件操作,原始文件和目标文件必须具有相同的路径名。不能使用相对路径。";
                case 117:
                    return "I/O控制错误";
                case 123:
                    return "指定了重复的文件名";
                case 116:
                    return "The source is a root directory, which cannot be moved or renamed.";
                case 118:
                    return "Security settings denied access to the source.";
                case 124:
                    return "The path in the source or destination or both was invalid.";
                case 65536:
                    return "An unspecified error occurred on the destination.";
                case 1026:
                    return "在试图移动或拷贝一个不存在的文件.";
                case 1223:
                    return "操作被取消！";
                default:
                    return "未识别的错误代码：" + n;
            }
        }    
    /// <summary>
    /// 运行文件
    /// </summary>
    /// <param name="FilePath"></param>
    /// <param name="PramCom"></param>
    /// <returns></returns>
        public static int RunFile(string FilePath, string PramCom)
        {
            return RunFile(FilePath, PramCom,"");
        }
        /// <summary>
        /// /运行文件
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="PramCom"></param>
        /// <param name="lpDirectory"></param>
        /// <returns></returns>
        public static int RunFile(string FilePath, string PramCom,string lpDirectory)
        {
            try
            {
                return ShellExecute(IntPtr.Zero, "open", FilePath, PramCom, lpDirectory, ShowCommands.SW_SHOWNORMAL);
                //System.Diagnostics.Process.Start(FilePath, PramCom);
                //return 1;
            }
            catch { return 0; }
        }
        /// <summary>
        /// 运行程序
        /// </summary>
        /// <param name="FilePath"></param>
        /// <returns></returns>
        public static int RunProc(string FilePath)
        {
            return RunFile(FilePath, "");
        }
        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="FilePath"></param>
        /// <returns></returns>
        public static int OpenFile(string FilePath)
        {
            return RunFile(FilePath, "");
        }
        [DllImport("Kernel32", CharSet = CharSet.Unicode)]
        private static extern Int32 GetShortPathName(String path, StringBuilder shortPath, Int32 shortPathLength);
        /// <summary>
        /// 打开文件夹并定位文件
        /// </summary>
        /// <param name="FilePath"></param>
        /// <returns></returns>
        public static int OpenFolderGotoFile(string FilePath)
        {
            StringBuilder shortpath = new StringBuilder(260);
            GetShortPathName(FilePath, shortpath, shortpath.Capacity);
            return RunFile("explorer.exe", "/select,\""+ shortpath.ToString()+ "\"");
        }
        /// <summary>
        /// 打开网址
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static int OpenUrl(string url)
        {
            return RunFile(url, "");
        }
        /// <summary>
        /// 判断文件名是否有效
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static bool IsValidFileName(string filename)
        {
            char[] no_validstr = @":\/|*?<>""".ToCharArray();
            for(int i=0;i<no_validstr.Length;i++)
            {
                if(filename.ToLower().IndexOf(no_validstr[i])>=0)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 转换到有效文件名
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static string ConvertToValidFileName(string filename)
        {
            char[] no_validstr = @":\/|*?<>""".ToCharArray();
            string _file = filename;
            for (int i = 0; i < no_validstr.Length; i++)
            {
                _file = _file.Replace(no_validstr[i].ToString(), "");
            }
            return _file;
        }
        /// <summary>
        /// 追加日志
        /// </summary>
        /// <param name="path"></param>
        /// <param name="content"></param>
        public void AppendLogs(string path, string content)
        {
            AppendAllText(path, DateTime.Now.ToString("yyyy-MM-dd HH：mm:ss") + "\t" + content);
        }
        /// <summary>
        /// 追加文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="content"></param>
        public void AppendAllText(string path, string content)
        {
            if (!System.IO.File.Exists(path))
            {
                RyFiles.WriteAllText(path, content, Encoding.UTF8);
            }
            else
            {
                System.IO.File.AppendAllText(path, "\r\n" +content, Encoding.UTF8);
            }
        }
        /// <summary>
        /// 读取文件内容,可以自动识别文件编码
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string ReadAllText(string path)
        {
            return ReadAllText(path, Encoding.Default);
        }
        /// <summary>
        /// 读取文件内容,可以自动识别文件编码
        /// </summary>
        /// <param name="path"></param>
        /// <param name="defaultEncoding"></param>
        /// <returns></returns>
        public static string ReadAllText(string path, Encoding defaultEncoding)
        {
            if (System.IO.File.Exists(path))
            {
                try
                {
                    return System.IO.File.ReadAllText(path, ryCommon.TxtFileEncoder.GetEncoding(path, defaultEncoding));
                }
                catch { return ""; }
            }
            return "";
        }
        /// <summary>
        /// 读取文件所有行,可以自动识别文件编码
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string[] ReadAllLines(string path)
        {
            return ReadAllLines(path, Encoding.Default);
        }
        /// <summary>
        /// 读取文件所有行,可以自动识别文件编码
        /// </summary>
        /// <param name="path"></param>
        /// <param name="defaultEncoding"></param>
        /// <returns></returns>
        public static string[] ReadAllLines(string path, Encoding defaultEncoding)
        {
            if (System.IO.File.Exists(path))
            {
                return System.IO.File.ReadAllLines(path, ryCommon.TxtFileEncoder.GetEncoding(path, defaultEncoding));
            }
            return null;
        }
        //static void ReadFile(string path,FileAccess fileAccess, FileShare fileShare)
        //{
        //    FileStream fs = new FileStream(path, FileMode.Open, fileAccess, fileShare);
        //    var buffer = new byte[fs.Length];
        //    fs.Position = 0;
        //    fs.Read(buffer, 0, buffer.Length);
        //    Console.WriteLine(Encoding.Default.GetString(buffer));
        //}
        /// <summary>
        /// 写入所有文本行到文件,如果文件夹不存在，会自动创建
        /// </summary>
        /// <param name="path"></param>
        /// <param name="content"></param>
        /// <param name="encoding"></param>
        public static void WriteAllLines(string path,string[] content,Encoding encoding)
        {
            if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(path)))
            {
                System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
            }
            System.IO.File.WriteAllLines(path, content, encoding);
        }
        /// <summary>
        /// 写入所有文本到文件,如果文件夹不存在，会自动创建
        /// </summary>
        /// <param name="path"></param>
        /// <param name="content"></param>
        /// <param name="encoding"></param>
        public static void WriteAllText(string path, string content, Encoding encoding)
        {
            if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(path)))
            {
                System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
            }
            System.IO.File.WriteAllText(path, content, encoding);
        }
        /// <summary>
        /// 从文件中加载图片,使用本方法，不会导致图片文件被占用。
        /// </summary>
        /// <param name="path"></param>
        public static Image LoadPicFromFile(string path)
        {
            if(!System.IO.File.Exists(path))
            { return null; }
            try
            {
                FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
                //把文件读取到字节数组 
                byte[] data = new byte[fs.Length];
                fs.Read(data, 0, data.Length);
                fs.Close();

                //实例化一个内存流--->把从文件流中读取的内容[字节数组]放到内存流中去 
                MemoryStream ms = new MemoryStream(data);
                //设置图片框 pictureBox1中的图片 
                return Image.FromStream(ms);
            }
            catch { return null; }
        }
        /// <summary>
        /// 获取文件大小
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static Int64 GetFileSize(string path)
        {
            try
            {
                FileInfo fileInfo = new FileInfo(path);
                return fileInfo.Length;
            }
            catch { return -1; }
        }
        /// <summary>
        /// 添加文件到指定文件夹,会进行自动重命名，并返回重命名后的文件名(含路径)
        /// </summary>
        /// <param name="filepath">要添加的文件路径</param>
        /// <param name="toFolder">要添加到的文件夹</param>
        /// <param name="RenameByTime">是否根据时间进行重命名</param>
        /// <param name="OK">返回是否成功执行</param>
        /// <returns>成功执行则返回路径，否则返回空</returns>
        public static string AddFileToFolder(string filepath,string toFolder,bool RenameByTime, out bool OK)
        {
            OK = false;
            var _toFolder = toFolder.TrimEnd('\\');
            CreateDirectory(_toFolder);
            if (!System.IO.Directory.Exists(_toFolder)) { return ""; }
            if (!System.IO.File.Exists(filepath) && !System.IO.Directory.Exists(filepath)) { return ""; }
            var filename = System.IO.Path.GetFileName(filepath);
            if (RenameByTime) { filename = DateTime.Now.ToString("yyyyMMddHHmmss") + System.IO.Path.GetExtension(filepath); }
            if(!System.IO.File.Exists(_toFolder+"\\"+ filename) && !System.IO.Directory.Exists(_toFolder + "\\" + filename)) {
                string errorMsg = "";
                if (ToMoveOrCopy(WFunc.FO_COPY, filepath, _toFolder + "\\" + filename, false, false, false, ref errorMsg) == 0)
                {
                    OK = true;
                    return _toFolder + "\\" + filename;
                }
                return "";//如果复制失败,则返回空路径
            }
            else //如果目标路径已经存在同名文件
            {
                int index = 0;
                string filename_noext;
                if (RenameByTime) { filename_noext = DateTime.Now.ToString("yyyyMMddHHmmss"); }
                else { filename_noext = System.IO.Path.GetFileNameWithoutExtension(filepath); }
                var ext= System.IO.Path.GetExtension(filepath);
                while (index<20) //最多重试20次
                {
                    Random rd = new Random(Guid.NewGuid().GetHashCode());
                    if (RenameByTime) { filename_noext = DateTime.Now.ToString("yyyyMMddHHmmss"); }
                    var to_path = _toFolder + "\\" + filename_noext+"_"+ rd.Next(1000, 9999)+ ext;    
                    if(!System.IO.File.Exists(to_path) && !System.IO.Directory.Exists(to_path))
                    {
                        string errorMsg = "";
                        if (ToMoveOrCopy(WFunc.FO_COPY, filepath, to_path, false, false, false, ref errorMsg) == 0)
                        {
                            OK = true;
                            return to_path;
                        }
                        return "";
                    }
                    index++;
                }
                return "";
            }
        }
        /// <summary>
        /// 获取文件大小字符串
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public static string GetFileSizeStr(long size)
        {
            if (size == -1) { return "未知"; }
            string s;
            string[] u = new string[] { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "NB", "DB" };
            double i = size;
            int n = 0;
            while (i > 1024)
            {
                i /= 1024.0;
                n++;
                if (n == 4) break;
            }
            s = i.ToString("F2") + u[n];
            return s;
        }
        /// <summary>
        /// 获取文件大小字符串
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static string GetFileSizeStr(string filepath)
        {
            return GetFileSizeStr(GetFileSize(filepath));
        }
        /// <summary>
        /// 复制内容到剪切板
        /// </summary>
        /// <param name="text"></param>
        public static void CopyToClip(string text)
        {
            try
            {
                Clipboard.Clear();
                Clipboard.SetText(text);
            }
            catch { }
        }
        private static ImageCodecInfo GetEncoderInfo(String mimeType)
        {
            int j;
            ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
            for (j = 0; j < encoders.Length; ++j)
            {
                if (encoders[j].MimeType == mimeType)
                    return encoders[j];
            }
            return null;
        }
        private static ImageCodecInfo GetEncoderInfo(ryCommon.sType.ImageType type)
        {
            #region 图片格式
            ImageCodecInfo myImageCodecInfo;
            string type_str = "image/jpeg";
            switch (type)
            {
                case sType.ImageType.Bmp:
                    type_str = "image/bmp";
                    break;
                case sType.ImageType.Jpeg:
                    type_str = "image/jpeg";
                    break;
                case sType.ImageType.Gif:
                    type_str = "image/gif";
                    break;
                case sType.ImageType.Tiff:
                    type_str = "image/tiff";
                    break;
                case sType.ImageType.Png:
                    type_str = "image/png";
                    break;
            }
            myImageCodecInfo = GetEncoderInfo(type_str);
            #endregion
            return myImageCodecInfo;
        }
        private static EncoderParameters GetEncoderParameters()
        {
            System.Drawing.Imaging.Encoder myEncoder;
            EncoderParameter myEncoderParameter;
            EncoderParameters myEncoderParameters;
            
            myEncoder = System.Drawing.Imaging.Encoder.Quality;
            myEncoderParameters = new EncoderParameters(1);
            // Save the bitmap as a JPEG file with quality level 100.
            myEncoderParameter = new EncoderParameter(myEncoder, 100L);
            myEncoderParameters.Param[0] = myEncoderParameter;
            return myEncoderParameters;
        }
        /// <summary>
        /// 添加某个控件为支持拖放属性
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        public static ElevatedDragDropManager AddDropDrag(IntPtr handle)
        {
            ElevatedDragDropManager.Instance.EnableDragDrop(handle);
            return ElevatedDragDropManager.Instance;
        }
        /// <summary>
        /// 使管理员方式运行时支持拖放
        /// </summary>
        /// <param name="handle"></param>
        /// <returns></returns>
        public static void AdminDragEnable(IntPtr handle)
        {
            ElevatedDragDropManager.AdminDragEnable(handle);
        }
        /// <summary>
        /// 保存高质量不失真照片
        /// </summary>
        /// <param name="m"></param>
        /// <param name="path"></param>
        /// <param name="type"></param>
        public static void SaveHighQualityImage(Bitmap m,string path,ryCommon.sType.ImageType type)
        {
            m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
        }
        /// <summary>
        /// 保存高质量不失真照片
        /// </summary>
        /// <param name="m"></param>
        /// <param name="ms"></param>
        /// <param name="type"></param>
        public static void SaveHighQualityImage(Bitmap m, MemoryStream ms, ryCommon.sType.ImageType type)
        {
            m.Save(ms, GetEncoderInfo(type), GetEncoderParameters());
        }
        /// <summary>
        /// 保存高质量不失真照片
        /// </summary>
        /// <param name="m"></param>
        /// <param name="path"></param>
        /// <param name="type"></param>
        public static void SaveHighQualityImage(Image m, string path, ryCommon.sType.ImageType type)
        {
            m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
        }
        /// <summary>
        /// 获取绝对路径
        /// </summary>
        /// <param name="_path"></param>
        /// <returns></returns>
        public static string GetRealPath(string _path)
        {
            string _tmp_path = _path.Replace("<app>", Application.StartupPath);
            _tmp_path = _tmp_path.Replace("<sys>", Environment.GetFolderPath(Environment.SpecialFolder.System));
            _tmp_path = _tmp_path.Replace("<sys_x86>", Environment.GetFolderPath(Environment.SpecialFolder.SystemX86));
            _tmp_path = _tmp_path.Replace("<prog>", Environment.GetEnvironmentVariable("ProgramW6432"));
            _tmp_path = _tmp_path.Replace("<prog_x86>", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86));
            _tmp_path = _tmp_path.Replace("<win>", Environment.GetFolderPath(Environment.SpecialFolder.Windows));
            _tmp_path = _tmp_path.Replace("<mydoc>", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
            _tmp_path = _tmp_path.Replace("<desktop>", Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
            _tmp_path = _tmp_path.Replace("<fonts>", Environment.GetFolderPath(Environment.SpecialFolder.Fonts));
            _tmp_path = Environment.ExpandEnvironmentVariables(_tmp_path);
            if(_tmp_path.IndexOf("%")>=0)
            {
                foreach (int i in Enum.GetValues(typeof(Environment.SpecialFolder)))
                {
                    string value = Environment.GetFolderPath((Environment.SpecialFolder)i);
                    string key= Enum.GetName(typeof(Environment.SpecialFolder), i);
                    if (_tmp_path.IndexOfEx(key) >= 0)
                    {
                        _tmp_path = _tmp_path.ReplaceEx("%"+key+"%", value);
                    }
                }
            }
            _tmp_path = _tmp_path.Replace("\\\\", "\\");
            return _tmp_path;
        }
        /// <summary>
        /// 获取相对路径
        /// </summary>
        /// <param name="_path"></param>
        /// <returns></returns>
        public static string GetRelativePath(string _path)
        {
            string _tmp_path = _path.Replace(Application.StartupPath, "<app>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.System), "<sys>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.SystemX86), "<sys_x86>");
            _tmp_path = _tmp_path.Replace(Environment.GetEnvironmentVariable("ProgramW6432"), "<prog>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "<prog_x86>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "<win>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "<mydoc>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "<desktop>");
            _tmp_path = _tmp_path.Replace(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "<fonts>");
            string wait_replace_value = "";
            string wait_replace_key = "";
            int max_length = 0;
            foreach (int i in Enum.GetValues(typeof(Environment.SpecialFolder)))
            {
                string value = Environment.GetFolderPath((Environment.SpecialFolder)i);
                if (value == "x86") { continue; }
                if (_tmp_path.IndexOfEx(value) >= 0)
                {
                    if (value.Length > max_length)
                    {
                        wait_replace_value = value;
                        wait_replace_key = Enum.GetName(typeof(Environment.SpecialFolder), i); ;
                        max_length = value.Length;
                    }
                }
            }
            if (max_length > 0)
            {
                _tmp_path = _tmp_path.ReplaceEx(wait_replace_value, "%" + wait_replace_key + "%");
            }
            max_length = 0;
            foreach (DictionaryEntry de in Environment.GetEnvironmentVariables())
            {
                string value = de.Value.ToString();
                if (value == "x86") { continue; }
                if (value.IndexOfEx(":")<0) { continue; }
                if (_tmp_path.IndexOfEx(value) >= 0 && !value.IsInt())
                {
                    if (value.Length > max_length)
                    {
                        wait_replace_value = value;
                        wait_replace_key = de.Key.ToString();
                        max_length = value.Length;
                    }
                }
            }
            if (max_length>0)
            {
                _tmp_path = _tmp_path.ReplaceEx(wait_replace_value, "%" + wait_replace_key + "%");
            }
            return _tmp_path;
        }
        /// <summary>
        /// 获取图标
        /// </summary>
        /// <param name="lpszFile"></param>
        /// <param name="nIconIndex"></param>
        /// <param name="cxIcon"></param>
        /// <param name="cyIcon"></param>
        /// <param name="phicon"></param>
        /// <param name="piconid"></param>
        /// <param name="nIcons"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        public static extern int PrivateExtractIcons(
            string lpszFile, //file name
            int nIconIndex,  //The zero-based index of the first icon to extract.
            int cxIcon,      //The horizontal icon size wanted.
            int cyIcon,      //The vertical icon size wanted.
            IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
            int[] piconid,   //(out) A pointer to a returned resource identifier.
            int nIcons,      //The number of icons to extract from the file. Only valid when *.exe and *.dll
            int flags        //Specifies flags that control this function.
        );
        /// <summary>
        /// 销毁图标
        /// </summary>
        /// <param name="hIcon"></param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        public static extern bool DestroyIcon(
            IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
        );
        /// <summary>
        /// 获取文件图标
        /// </summary>
        /// <param name="_path"></param>
        /// <param name="index"></param>
        /// <param name="count"></param>
        ///  <param name="size"></param>
        /// <returns></returns>
        public static Bitmap GetFileIcon(string _path,int index,out int count,int size)
        {
            var file = _path;
            //选中文件中的图标总数
            var iconTotalCount = PrivateExtractIcons(file, 0, 0, 0, null, null, 0, 0);
            //用于接收获取到的图标指针
            IntPtr[] hIcons = new IntPtr[iconTotalCount];
            //对应的图标id
            int[] ids = new int[iconTotalCount];
            //成功获取到的图标个数
            var successCount = PrivateExtractIcons(file, 0, size, size, hIcons, ids, iconTotalCount, 0);
            count = successCount;
            Bitmap bmp = null;
            if(index>=0 && index< successCount)
            {
                if (hIcons[index] == IntPtr.Zero) { bmp = null; }
                else
                {
                    bmp = Icon.FromHandle(hIcons[index]).ToBitmap();
                }
                //内存回收
                for (var i = 0; i < successCount; i++)
                {
                    //指针为空，跳过
                    if (hIcons[i] == IntPtr.Zero) continue;
                    //内存回收
                    DestroyIcon(hIcons[i]);
                }
            }
            return bmp;
        }
    }

}
