33,彻底关闭Excel进程
.NET中使用Excel属于使用非托管资源,使用完成后一般都要用GC回收资源,但是,调用GC的位置不正确,Excel进程可能无法彻底关闭,如下面的代码:
static void OpenExcelTest(int j) { //Application excel = null; excel = new Application(); excel.Visible = true; excel.Workbooks.Open("d:\\A1000.xla"); Workbook wb = excel.Application.Workbooks.Open("d:\\Book1.xlsx"); Worksheet sh = wb.Worksheets.Item["Sheet1"]; object[,] ssss = sh.Range[sh.Cells[1.1], sh.Cells[3, 1]].Value2; Console.WriteLine("opened excel no. {0}", j); Console.ReadLine(); try { //尝试程序关闭Excel进程 wb.Close(false); sh = null; wb = null; excel.Quit(); } catch (Exception ex) { Console.WriteLine("用户已经手工结束了Excel进程,内部错误消息:{0}",ex.Message ); } int generation = System.GC.GetGeneration(excel); //No.1 //System.Runtime.InteropServices.Marshal.ReleaseComObject(wb); //System.Runtime.InteropServices.Marshal.ReleaseComObject(sh); //System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); excel = null; //No.2 //GC.Collect(generation); Console.WriteLine("close excel no. {0}", j); Console.ReadLine(); }
在上面的代码中,如果取消 No.1,No.2位置处的注释,方法结束后,Excel进程是无法结束的,解决办法,只需要把
GC.Collect();
这行代码写到方法之外即可。
Application excel = null;
这个Excel应用程序对象定义在方法内或者外都是可以的,哪怕定义一个静态变量,结果都没有影响。
34,给ZIP文件添加文件头
将很多零散的文件打包成ZIP文件方便使用,但是ZIP文件使用相关的工具很容易解压,并且无法判断该文件是指定的文件。可以给ZIP文件增加文件头内容,在文件头里面写入要验证的标记。采用这种方式,加了标记的ZIP文件仍然可以被ZIP工具打开,从而制作只有自己能用的ZIP文件。
/// <summary> /// 创建文件包 /// </summary> /// <param name="userName">打包文件的用户名</param> /// <param name="savePath">保存的文件包路径</param> /// <param name="files">文件清单</param> /// <param name="businessID">业务ID</param> /// <param name="pkgVersion">文件包版本号</param> /// <returns>文件包全路径</returns> public string CreatePackage(string userName, string savePath, List<string> files, string businessID,string pkgVersion="00") { //DataPackages 存放导入导出项目文件包的目录,以此目录打包,最终压缩文件存放目录为用户指定路径下 //每次生成一个临时目录 string tempDir = DateTime.Now.ToString("yyyyMMddHHmmss"); string pkgDirRoot = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Packages"); string pkgDir = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Packages", businessID, tempDir); string pkgSaveFile = System.IO.Path.Combine(savePath, "SODPackage_"+ tempDir + ".pkg"); string pkgSaveFileTemp = System.IO.Path.Combine(savePath,"SODPackage_"+ tempDir + ".tmp"); try { if (!System.IO.Directory.Exists(pkgDir)) System.IO.Directory.CreateDirectory(pkgDir); StringBuilder sb = new StringBuilder(); //复制文件到压缩目录 foreach (string file in files) { int index = file.IndexOf(businessID); if (index > 0) { //假设给出的文件路径中都包含了业务ID string subStr = file.Substring(index + businessID.Length+1); string targetFile = System.IO.Path.Combine(pkgDir, subStr); string targetDir = System.IO.Path.GetDirectoryName(targetFile); if (!System.IO.Directory.Exists(targetDir)) System.IO.Directory.CreateDirectory(targetDir); System.IO.File.Copy(file, targetFile); sb.AppendLine(subStr); } } //写一个清单文件 string infoFile = System.IO.Path.Combine(pkgDir, "info.txt"); string infoText = string.Format("RemoteServer={0}\r\nUserName={1}\r\nProjectID={2}\r\nProjectName={3}\r\nData Version={4}\r\nPackage Dir={5}\r\nPackage Files List:\r\n{6}", remoteServer, userName, businessID,projectName, pkgVersion, pkgDir, sb.ToString()); System.IO.File.AppendAllText(infoFile, infoText); System.IO.Compression.ZipFile.CreateFromDirectory(pkgDir, pkgSaveFileTemp); //添加文件头,第一个整数字节,为文件头长度 using (var fs = System.IO.File.Create(pkgSaveFile)) { System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fs); string headStr = string.Format("XXXPackage&{0}&{1}&{2}", businessID, pkgVersion,userName); var headData = System.Text.Encoding.UTF8.GetBytes(headStr); bw.Write(headData.Length); bw.Write(headData); var fileData = System.IO.File.ReadAllBytes(pkgSaveFileTemp); bw.Write(fileData, 0, fileData.Length); bw.Close(); fs.Close(); } System.IO.File.Delete(pkgSaveFileTemp); return pkgSaveFile; } catch (Exception ex) { throw new Exception("打包项目文件失败:"+ex.Message, ex); } }