| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789 | using System;using System.Collections.Generic;using System.Linq;using System.Security.Cryptography;using System.Text;using System.Text.RegularExpressions;using System.Web;using Core.Util.Common;namespace Core.Util.Extension{    public static class StringHelper    {        #region 正则表达式        private static readonly Regex WebUrlExpression = new Regex(            @"(http|https)://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.Singleline | RegexOptions.Compiled);        private static readonly Regex EmailExpression =            new Regex(@"^([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$",                RegexOptions.Singleline | RegexOptions.Compiled);        private static readonly Regex StripHtmlExpression = new Regex("<\\S[^><]*>",            RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.CultureInvariant |            RegexOptions.Compiled);        private static readonly char[] IllegalUrlCharacters =        {            ';', '/', '\\', '?', ':', '@', '&', '=', '+', '$', ',',            '<', '>', '#', '%', '.', '!', '*', '\'', '"', '(', ')', '[', ']', '{', '}', '|', '^', '`', '~', '–', '‘',            '’', '“', '”', '»', '«'        };        #endregion        #region 字符串判断        public static bool IsNullOrEmpty(this string target)        {            return target == null || target.Length <= 0 || string.IsNullOrEmpty(target);        }        /// <summary>是否空或者空白字符串</summary>        public static bool IsNullOrWhiteSpace(this string value)        {            return value == null || value.All(char.IsWhiteSpace);        }        /// <summary> 合法URL </summary>        public static bool IsWebUrl(this string target)        {            return !target.IsNullOrEmpty() && WebUrlExpression.IsMatch(target);        }        /// <summary> 合法邮箱地址 </summary>        public static bool IsEmail(this string target)        {            return !target.IsNullOrEmpty() && EmailExpression.IsMatch(target);        }        #endregion        #region 格式转换        /// <summary> 字符串转Hash </summary>        public static string Hash(this string target)        {            Argument.IsNotEmpty(target, "target");            using (var md5 = MD5.Create())            {                var data = Encoding.Unicode.GetBytes(target);                var hash = md5.ComputeHash(data);                return Convert.ToBase64String(hash);            }        }        /// <summary>字符串转数组 默认UTF8</summary>        public static byte[] GetBytes(this string target, Encoding encoding = null)        {            if (target == null) return null;            if (target == string.Empty) return new byte[0];            if (encoding == null) encoding = Encoding.UTF8;            return encoding.GetBytes(target);        }        /// <summary> 转脚本 </summary>        public static string StripHtml(this string target)        {            return StripHtmlExpression.Replace(target, string.Empty);        }        /// <summary> 转GUID </summary>        public static Guid ToGuid(this string target)        {            var result = Guid.Empty;            if (!string.IsNullOrEmpty(target) && (target.Trim().Length == 22))            {                var encoded = string.Concat(target.Trim().Replace("-", "+").Replace("_", "/"), "==");                try                {                    var base64 = Convert.FromBase64String(encoded);                    result = new Guid(base64);                }                catch (FormatException)                {                }            }            return result;        }        /// <summary> 字符串转枚举 </summary>        public static T ToEnum<T>(this string target, T defaultValue) where T : IComparable, IFormattable        {            var convertedValue = defaultValue;            if (!string.IsNullOrEmpty(target))            {                try                {                    convertedValue = (T) Enum.Parse(typeof (T), target.Trim(), true);                }                catch (ArgumentException)                {                }            }            return convertedValue;        }        /// <summary> 合法URL </summary>        public static string ToLegalUrl(this string target)        {            if (string.IsNullOrEmpty(target))            {                return target;            }            target = target.Trim();            if (target.IndexOfAny(IllegalUrlCharacters) > -1)            {                foreach (var character in IllegalUrlCharacters)                {                    target = target.Replace(character.ToString(Constants.CurrentCulture), string.Empty);                }            }            target = target.Replace(" ", "-");            while (target.Contains("--"))            {                target = target.Replace("--", "-");            }            return target;        }        /// <summary> 对URL字符串进行编码 </summary>        public static string UrlEncode(this string target)        {            return target;// HttpUtility.UrlEncode(target);        }        /// <summary> 对URL字符串进行解码 </summary>        public static string UrlDecode(this string target)        {            return target;// HttpUtility.UrlDecode(target);        }        /// <summary> 将字符串最小限度地转换为 HTML 编码的字符串。 </summary>        public static string AttributeEncode(this string target)        {            return target;// HttpUtility.HtmlAttributeEncode(target);        }        /// <summary> 将字符串转换为 HTML 编码的字符串。 </summary>        public static string HtmlEncode(this string target)        {            return target;// HttpUtility.HtmlEncode(target);        }        /// <summary> 将已经为 HTTP 传输进行过 HTML 编码的字符串转换为已解码的字符串。 </summary>        public static string HtmlDecode(this string target)        {            return target;// HttpUtility.HtmlDecode(target);        }        #endregion        #region 截取扩展        /// <summary>        ///     截断补.        /// </summary>        public static string WrapAt(this string target, int index)        {            const int dotCount = 3;            Argument.IsNotEmpty(target, "target");            Argument.IsNotNegativeOrZero(index, "index");            return target.Length <= index                ? target                : string.Concat(target.Substring(0, index - dotCount), new string('.', dotCount));        }        /// <summary>确保字符串以指定的另一字符串开始,不区分大小写</summary>        public static string EnsureStart(this string target, string start)        {            if (start.IsNullOrEmpty()) return target;            if (target.IsNullOrEmpty()) return start;            if (target.StartsWith(start, StringComparison.OrdinalIgnoreCase)) return target;            return start + target;        }        /// <summary>确保字符串以指定的另一字符串结束,不区分大小写</summary>        public static string EnsureEnd(this string target, string end)        {            if (end.IsNullOrEmpty()) return target;            if (target.IsNullOrEmpty()) return end;            if (target.EndsWith(end, StringComparison.OrdinalIgnoreCase)) return target;            return target + end;        }        /// <summary>从当前字符串开头移除另一字符串,不区分大小写,循环多次匹配前缀</summary>        public static string TrimStart(this string target, params string[] starts)        {            if (target.IsNullOrEmpty()) return target;            if (starts == null || starts.Length < 1 || string.IsNullOrEmpty(starts[0])) return target;            for (var i = 0; i < starts.Length; i++)            {                if (target.StartsWith(starts[i], StringComparison.OrdinalIgnoreCase))                {                    target = target.Substring(starts[i].Length);                    if (string.IsNullOrEmpty(target)) break;                    // 从头开始                    i = -1;                }            }            return target;        }        /// <summary>从当前字符串结尾移除另一字符串,不区分大小写,循环多次匹配后缀</summary>        public static string TrimEnd(this string target, params string[] ends)        {            if (target.IsNullOrEmpty()) return target;            if (ends == null || ends.Length < 1 || string.IsNullOrEmpty(ends[0])) return target;            for (var i = 0; i < ends.Length; i++)            {                if (target.EndsWith(ends[i], StringComparison.OrdinalIgnoreCase))                {                    target = target.Substring(0, target.Length - ends[i].Length);                    if (string.IsNullOrEmpty(target)) break;                    // 从头开始                    i = -1;                }            }            return target;        }        /// <summary>从字符串中检索子字符串,在指定头部字符串之后,指定尾部字符串之前</summary>        public static string Substring(this string target, string after, string before = null, int startIndex = 0,            int[] positions = null)        {            if (target.IsNullOrEmpty()) return target;            if (after.IsNullOrEmpty() && before.IsNullOrEmpty()) return target;            var p = -1;            if (!string.IsNullOrEmpty(after))            {                p = target.IndexOf(after, startIndex, StringComparison.Ordinal);                if (p < 0) return null;                p += after.Length;                // 记录位置                if (positions != null && positions.Length > 0) positions[0] = p;            }            if (string.IsNullOrEmpty(before)) return target.Substring(p);            var f = target.IndexOf(before, p >= 0 ? p : startIndex, StringComparison.Ordinal);            if (f < 0) return null;            // 记录位置            if (positions != null && positions.Length > 1) positions[1] = f;            if (p >= 0)                return target.Substring(p, f - p);            return target.Substring(0, f);        }        /// <summary>根据最大长度截取字符串,并允许以指定空白填充末尾</summary>        public static string Cut(this string str, int maxLength, string pad = null)        {            if (str.IsNullOrEmpty() || maxLength <= 0 || str.Length < maxLength) return str;            // 计算截取长度            var len = maxLength;            if (!pad.IsNullOrEmpty()) len -= pad.Length;            if (len <= 0) return pad;            return str.Substring(0, len) + pad;        }        /// <summary>根据最大长度截取字符串(二进制计算长度),并允许以指定空白填充末尾</summary>        /// <remarks>默认采用Default编码进行处理,其它编码请参考本函数代码另外实现</remarks>        /// <param name="str">字符串</param>        /// <param name="maxLength">截取后字符串的最大允许长度,包含后面填充</param>        /// <param name="pad">需要填充在后面的字符串,比如几个圆点</param>        /// <param name="strict">严格模式时,遇到截断位置位于一个字符中间时,忽略该字符,否则包括该字符。默认true</param>        /// <returns></returns>        public static string CutBinary(this string str, int maxLength, string pad = null, bool strict = true)        {            if (string.IsNullOrEmpty(str) || maxLength <= 0 || str.Length < maxLength) return str;            var encoding = Encoding.Default;            var buf = encoding.GetBytes(str);            if (buf.Length < maxLength) return str;            // 计算截取字节长度            var len = maxLength;            if (!string.IsNullOrEmpty(pad)) len -= encoding.GetByteCount(pad);            if (len <= 0) return pad;            // 计算截取字符长度。避免把一个字符劈开            int clen;            while (true)            {                try                {                    clen = encoding.GetCharCount(buf, 0, len);                    break;                }                catch (DecoderFallbackException)                {                    // 发生了回退,减少len再试                    len--;                }            }            // 可能过长,修正            if (strict) while (encoding.GetByteCount(str.ToCharArray(), 0, clen) > len) clen--;            return str.Substring(0, clen) + pad;        }        /// <summary>从当前字符串开头移除另一字符串以及之前的部分</summary>        /// <param name="str">当前字符串</param>        /// <param name="starts">另一字符串</param>        /// <returns></returns>        public static string CutStart(this string str, params string[] starts)        {            if (string.IsNullOrEmpty(str)) return str;            if (starts == null || starts.Length < 1 || string.IsNullOrEmpty(starts[0])) return str;            for (var i = 0; i < starts.Length; i++)            {                var p = str.IndexOf(starts[i], StringComparison.Ordinal);                if (p >= 0)                {                    str = str.Substring(p + starts[i].Length);                    if (string.IsNullOrEmpty(str)) break;                }            }            return str;        }        /// <summary>从当前字符串结尾移除另一字符串以及之后的部分</summary>        /// <param name="str">当前字符串</param>        /// <param name="ends">另一字符串</param>        /// <returns></returns>        public static string CutEnd(this string str, params string[] ends)        {            if (string.IsNullOrEmpty(str)) return str;            if (ends == null || ends.Length < 1 || string.IsNullOrEmpty(ends[0])) return str;            for (var i = 0; i < ends.Length; i++)            {                var p = str.LastIndexOf(ends[i], StringComparison.Ordinal);                if (p >= 0)                {                    str = str.Substring(0, p);                    if (string.IsNullOrEmpty(str)) break;                }            }            return str;        }        #endregion        #region 匹配查找        /// <summary>忽略大小写的字符串相等比较,判断是否以任意一个待比较字符串相等</summary>        public static bool EqualIgnoreCase(this string target, params string[] strs)        {            return !target.IsNullOrEmpty() &&                   strs.Any(item => string.Equals(target, item, StringComparison.OrdinalIgnoreCase));        }        /// <summary>忽略大小写的字符串开始比较,判断是否以任意一个待比较字符串开始</summary>        public static bool StartsWithIgnoreCase(this string target, params string[] strs)        {            return !target.IsNullOrEmpty() &&                   strs.Any(item => target.StartsWith(item, StringComparison.OrdinalIgnoreCase));        }        /// <summary>忽略大小写的字符串结束比较,判断是否以任意一个待比较字符串结束</summary>        public static bool EndsWithIgnoreCase(this string target, params string[] strs)        {            return !target.IsNullOrEmpty() &&                   strs.Any(item => target.EndsWith(item, StringComparison.OrdinalIgnoreCase));        }        public static int GetHashcode2(this string s)        {            if (string.IsNullOrEmpty(s)) return 0;            unchecked            {                int hash = 23;                foreach (char c in s)                {                    hash = (hash << 5) - hash + c;                }                if (hash < 0)                {                    hash = Math.Abs(hash);                }                return hash;            }        }        #endregion        #region 分隔        /// <summary>拆分字符串,过滤空格,无效时返回空数组</summary>        public static string[] Split(this string target, params string[] separators)        {            if (target.IsNullOrEmpty()) return new string[0];            if (separators == null || separators.Length < 1 || separators.Length == 1 && separators[0].IsNullOrEmpty())                separators = new[] {",", ";"};            return target.Split(separators, StringSplitOptions.RemoveEmptyEntries);        }        /// <summary>拆分字符串成为整型数组,默认逗号分号分隔,无效时返回空数组</summary>        public static int[] SplitAsInt(this string target, params string[] separators)        {            if (target.IsNullOrEmpty()) return new int[0];            if (separators == null || separators.Length < 1) separators = new[] {",", ";"};            var ss = target.Split(separators, StringSplitOptions.RemoveEmptyEntries);            var list = new List<int>();            foreach (var item in ss)            {                int id;                if (!int.TryParse(item.Trim(), out id)) continue;                list.Add(id);            }            return list.ToArray();        }        /// <summary>拆分字符串成为名值字典。逗号分号分组,等号分隔</summary>        public static IDictionary<string, string> SplitAsDictionary(this string target, string nameValueSeparator = "=",            params string[] separators)        {            var dic = new Dictionary<string, string>();            if (target.IsNullOrWhiteSpace()) return dic;            if (nameValueSeparator.IsNullOrEmpty()) nameValueSeparator = "=";            if (separators == null || separators.Length < 1) separators = new[] {",", ";"};            var ss = target.Split(separators, StringSplitOptions.RemoveEmptyEntries);            if (ss.Length < 1) return null;            foreach (var item in ss)            {                var p = item.IndexOf(nameValueSeparator, StringComparison.Ordinal);                // 在前后都不行                if (p <= 0 || p >= item.Length - 1) continue;                var key = item.Substring(0, p).Trim();                dic[key] = item.Substring(p + nameValueSeparator.Length).Trim();            }            return dic;        }        #endregion        #region 功能扩展        /// <summary> 安全字符串 </summary>        public static string NullSafe(this string target)        {            return (target ?? string.Empty).Trim();        }        /// <summary> 字符串格式化 </summary>        public static string FormatWith(this string target, params object[] args)        {            Argument.IsNotEmpty(target, "target");            for (var i = 0; i < args.Length; i++)            {                if (args[i] is DateTime)                {                    if (target.Contains("{" + i + "}")) args[i] = ((DateTime) args[i]).ToFullString();                }            }            return string.Format(target, args);        }        public static string Replace(this string target, ICollection<string> oldValues, string newValue)        {            oldValues.ForEach(oldValue => target = target.Replace(oldValue, newValue));            return target;        }        #endregion        #region 语音播放        /// <summary>调用语音引擎说出指定话</summary>        /// <param name="value"></param>        public static void Speak(this string value)        {            //Speecher.Speak(value);        }        /// <summary>调用语音引擎说出指定话</summary>        /// <param name="value"></param>        public static void SpeakAsync(this string value)        {            //Speecher.SpeakAsync(value);        }        #endregion        #region LD编辑距离算法        /// <summary>编辑距离搜索,从词组中找到最接近关键字的若干匹配项</summary>        /// <remarks>        ///     算法代码由@Aimeast 独立完成。http://www.cnblogs.com/Aimeast/archive/2011/09/05/2167844.html        /// </remarks>        /// <param name="key">关键字</param>        /// <param name="words">词组</param>        /// <returns></returns>        public static string[] LevenshteinSearch(string key, string[] words)        {            if (IsNullOrWhiteSpace(key)) return new string[0];            var keys = key.Split(new[] {' ', ' '}, StringSplitOptions.RemoveEmptyEntries);            foreach (var item in keys)            {                var maxDist = (item.Length - 1)/2;                var q = from str in words                    where item.Length <= str.Length                          && Enumerable.Range(0, maxDist + 1)                              .Any(dist =>                              {                                  return Enumerable.Range(0, Math.Max(str.Length - item.Length - dist + 1, 0))                                      .Any(                                          f =>                                          {                                              return LevenshteinDistance(item, str.Substring(f, item.Length + dist)) <=                                                     maxDist;                                          });                              })                    orderby str                    select str;                words = q.ToArray();            }            return words;        }        /// <summary>编辑距离</summary>        /// <remarks>        ///     又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。        ///     许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。        ///     算法代码由@Aimeast 独立完成。http://www.cnblogs.com/Aimeast/archive/2011/09/05/2167844.html        /// </remarks>        /// <param name="str1"></param>        /// <param name="str2"></param>        /// <returns></returns>        public static int LevenshteinDistance(string str1, string str2)        {            var n = str1.Length;            var m = str2.Length;            var C = new int[n + 1, m + 1];            int i, j, x, y, z;            for (i = 0; i <= n; i++)                C[i, 0] = i;            for (i = 1; i <= m; i++)                C[0, i] = i;            for (i = 0; i < n; i++)                for (j = 0; j < m; j++)                {                    x = C[i, j + 1] + 1;                    y = C[i + 1, j] + 1;                    if (str1[i] == str2[j])                        z = C[i, j];                    else                        z = C[i, j] + 1;                    C[i + 1, j + 1] = Math.Min(Math.Min(x, y), z);                }            return C[n, m];        }        #endregion        #region LCS算法        /// <summary>最长公共子序列搜索,从词组中找到最接近关键字的若干匹配项</summary>        /// <remarks>        ///     算法代码由@Aimeast 独立完成。http://www.cnblogs.com/Aimeast/archive/2011/09/05/2167844.html        /// </remarks>        /// <param name="key"></param>        /// <param name="words"></param>        /// <returns></returns>        public static string[] LCSSearch(string key, string[] words)        {            if (IsNullOrWhiteSpace(key) || words == null || words.Length == 0) return new string[0];            var keys = key                .Split(new[] {' ', '\u3000'}, StringSplitOptions.RemoveEmptyEntries)                .OrderBy(s => s.Length)                .ToArray();            //var q = from sentence in items.AsParallel()            var q = from word in words                let MLL = LCSDistance(word, keys)                where MLL >= 0                orderby (MLL + 0.5)/word.Length, word                select word;            return q.ToArray();        }        /// <summary>        ///     最长公共子序列问题是寻找两个或多个已知数列最长的子序列。        ///     一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。        ///     The longest common subsequence (LCS) problem is to find the longest subsequence common to all sequences in a set of        ///     sequences (often just two). Note that subsequence is different from a substring, see substring vs. subsequence. It        ///     is a classic computer science problem, the basis of diff (a file comparison program that outputs the differences        ///     between two files), and has applications in bioinformatics.        /// </summary>        /// <remarks>        ///     算法代码由@Aimeast 独立完成。http://www.cnblogs.com/Aimeast/archive/2011/09/05/2167844.html        /// </remarks>        /// <param name="word"></param>        /// <param name="keys">多个关键字。长度必须大于0,必须按照字符串长度升序排列。</param>        /// <returns></returns>        public static int LCSDistance(string word, string[] keys)        {            var sLength = word.Length;            var result = sLength;            var flags = new bool[sLength];            var C = new int[sLength + 1, keys[keys.Length - 1].Length + 1];            //int[,] C = new int[sLength + 1, words.Select(s => s.Length).Max() + 1];            foreach (var key in keys)            {                var wLength = key.Length;                int first = 0, last = 0;                int i = 0, j = 0, LCS_L;                //foreach 速度会有所提升,还可以加剪枝                for (i = 0; i < sLength; i++)                    for (j = 0; j < wLength; j++)                        if (word[i] == key[j])                        {                            C[i + 1, j + 1] = C[i, j] + 1;                            if (first < C[i, j])                            {                                last = i;                                first = C[i, j];                            }                        }                        else                            C[i + 1, j + 1] = Math.Max(C[i, j + 1], C[i + 1, j]);                LCS_L = C[i, j];                if (LCS_L <= wLength >> 1)                    return -1;                while (i > 0 && j > 0)                {                    if (C[i - 1, j - 1] + 1 == C[i, j])                    {                        i--;                        j--;                        if (!flags[i])                        {                            flags[i] = true;                            result--;                        }                        first = i;                    }                    else if (C[i - 1, j] == C[i, j])                        i--;                    else // if (C[i, j - 1] == C[i, j])                        j--;                }                if (LCS_L <= (last - first + 1) >> 1)                    return -1;            }            return result;        }        #endregion        #region 执行命令行        ///// <summary>以隐藏窗口执行命令行</summary>        ///// <param name="cmd">文件名</param>        ///// <param name="arguments">命令参数</param>        ///// <param name="msWait">等待毫秒数</param>        ///// <param name="output">进程输出内容。默认为空时输出到日志</param>        ///// <param name="onExit">进程退出时执行</param>        ///// <returns>进程退出代码</returns>        //public static int Run(this string cmd, string arguments = null, int msWait = 0, Action<string> output = null, Action<Process> onExit = null)        //{        //    if (XTrace.Debug) XTrace.WriteLine("Run {0} {1} {2}", cmd, arguments, msWait);        //    var p = new Process();        //    var si = p.StartInfo;        //    si.FileName = cmd;        //    si.Arguments = arguments;        //    si.WindowStyle = ProcessWindowStyle.Hidden;        //    // 对于控制台项目,这里需要捕获输出        //    if (msWait > 0)        //    {        //        si.RedirectStandardOutput = true;        //        si.RedirectStandardError = true;        //        si.UseShellExecute = false;        //        if (output != null)        //        {        //            p.OutputDataReceived += (s, e) => output(e.Data);        //            p.ErrorDataReceived += (s, e) => output(e.Data);        //        }        //        else if (HouDa.Runtime.IsConsole)        //        {        //            p.OutputDataReceived += (s, e) => XTrace.WriteLine(e.Data);        //            p.ErrorDataReceived += (s, e) => XTrace.Current.Error(e.Data);        //        }        //    }        //    if (onExit != null) p.Exited += (s, e) => onExit(s as Process);        //    p.Start();        //    if (msWait > 0 && (output != null || HouDa.Runtime.IsConsole))        //    {        //        p.BeginOutputReadLine();        //        p.BeginErrorReadLine();        //    }        //    if (msWait <= 0) return -1;        //    // 如果未退出,则不能拿到退出代码        //    if (!p.WaitForExit(msWait)) return -1;        //    return p.ExitCode;        //}        #endregion    }}
 |