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);
            }
        }       
创建文件包

相关文章: