C#反编译微软MSDN2003的帮助文档,并将反编译结果保存到一个SQLSERVER数据库中

using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms;

namespace MSDNOUT
{
	///
1<summary>
2    	/// 反编译微软MSDN2003文档并保存到数据库的程序主窗体
3    	/// </summary>

public class dlgMSDNOut : System.Windows.Forms.Form { /******************************************************************************************

		声明:本程序只是研究性的程序,没有损害微软对MSDN的版权的意图,并承认
		微软对 MSDN , Microsoft Help 2.0 SDK , HXS文件格式,MSDE 等版权所有权

		本程序能反编译微软MSDN2003的帮助文档,并将反编译结果保存到一个SQLSERVER数据库中
		
		本文件为一个独立的C#代码文件,不需要依赖任何其他文件,使用VS.NET建立一个
		C#的默认名称空间为MSDNOUT的Windows应用程序后将该文件内容覆盖掉系统自动生成
		的Form1.cs文件内容即可编译通过并执行,本程序在微软.NET框架1.1简体中文版的
		Windows2000Server环境下测试通过, MDAC版本2.7,数据库服务器为MSDE,版本8.00.760(SP3)
		
		本程序假定你将MSDN2003安装在 C:\Program Files\MSDN\2003FEB\2052
		还假定安装了 Microsoft Help 2.0 SDK , 并假定安装在目录
		"C:\Program Files\Microsoft Help 2.0 SDK" , 该SDK安装文件可在微软网站下载

		本程序长时间频繁的读写临时文件,因此可以使用一个虚拟硬盘工具在
		物理内存中虚拟一个磁盘,这样可以大大加快程序的运行速度
		可在 http://down1.tech.sina.com.cn/cgi-bin/download/download.cgi?s_id=3761#=1 
		下载一个虚拟硬盘工具
		
		程序使用的数据库为MSSQLSERVER,在此使用了MSDE,由于MSDE的单个数据库
		大小限制在2GB内,而MSDN文件总共超过了2GB,因此程序运行时还根据需要
		切换数据库,本程序使用的数据库文件保存在 f:\db 下面
		使用前请执行以下SQL语句来初始化数据库

		CREATE DATABASE MSDN1 ON (NAME = 'MSDN1', FILENAME = 'f:\db\MSDN1.mdf' )";

		CREATE TABLE [MSDNFileList] (
			[MFileID] [int] NOT NULL ,
			[MFileName] [varchar] (200) COLLATE Chinese_PRC_CI_AS NOT NULL ,
			[MDBName] [varchar] (10) COLLATE Chinese_PRC_CI_AS NULL ,
			[MFileLength] [int] NULL ,
			CONSTRAINT [PK_MSDNFileList] PRIMARY KEY  CLUSTERED 
			(
				[MFileName]
			)  ON [PRIMARY] 
		) ON [PRIMARY]
		GO

		CREATE TABLE [MSDNFile] (
			[MFileID] [int] NOT NULL ,
			[MFileContent] [image] NULL ,
			CONSTRAINT [PK_MSDNFile] PRIMARY KEY  CLUSTERED 
			(
				[MFileID]
			)  ON [PRIMARY] 
		) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

		 *****************************************************************************************/
		 
		///
1<summary>
2    		/// 取消操作标记
3    		/// </summary>

private bool bolCancel = false ; ///

1<summary>
2    		/// 暂停操作标记
3    		/// </summary>

private bool bolPause = false ; ///

1<summary>
2    		/// 主数据库连接字符串
3    		/// </summary>

private System.Data.SqlClient.SqlConnection MainConn = null; ///

1<summary>
2    		/// 文档数据库连接字符串
3    		/// </summary>

private System.Data.SqlClient.SqlConnection DataConn = null; ///

1<summary>
2    		/// 插入文档列表的命令对象
3    		/// </summary>

private System.Data.SqlClient.SqlCommand InsertNameCmd = null; ///

1<summary>
2    		/// 查询文档内容的命令对象
3    		/// </summary>

private System.Data.SqlClient.SqlCommand InsertCmd = null; ///

1<summary>
2    		/// 保存文档数据的数据库名称
3    		/// </summary>

private string CurrentDBName = "MSDN1" ; ///

1<summary>
2    		/// 进行数据处理的线程对象
3    		/// </summary>

private System.Threading.Thread myThread = null;

		///
1<summary>
2    		/// 初始化数据库连接
3    		/// </summary>

private void InitDB() { if( MainConn != null) { MainConn.Dispose(); DataConn.Dispose(); InsertNameCmd.Dispose(); } // 打开数据库连接 MainConn = new System.Data.SqlClient.SqlConnection(); DataConn = new System.Data.SqlClient.SqlConnection(); MainConn.ConnectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=MSDN1;Data Source=(local)"; DataConn.ConnectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=" + CurrentDBName + ";Data Source=(local)"; MainConn.Open(); DataConn.Open();

			InsertNameCmd = MainConn.CreateCommand();
			InsertNameCmd.CommandText = "INSERT INTO MSDNFileList(MFileID, MFileName, MDBName, MFileLength) VALUES (@MFileID, @MFileName, @MDBName, @MFileLength) ";
			InsertNameCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MFileID", System.Data.SqlDbType.Int, 4, "MFileID"));
			InsertNameCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MFileName", System.Data.SqlDbType.VarChar, 200, "MFileName"));
			InsertNameCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MDBName", System.Data.SqlDbType.VarChar, 10, "MDBName"));
			InsertNameCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MFileLength", System.Data.SqlDbType.Int, 4, "MFileLength"));
			InitInsertCmd();
		}
		///
1<summary>
2    		/// 初始化插入数据内容的命令对象
3    		/// </summary>

private void InitInsertCmd() { if( InsertCmd != null) InsertCmd.Dispose(); InsertCmd = DataConn.CreateCommand(); InsertCmd.CommandText = "INSERT INTO MSDNFile(MFileID, MFileContent) VALUES (@MFileID, @MFileContent)"; InsertCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MFileID", System.Data.SqlDbType.Int, 4, "MFileID")); InsertCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@MFileContent", System.Data.SqlDbType.VarBinary, 2147483647, "MFileContent")); }

		///
1<summary>
2    		/// 反编译MSDN文档的主程序
3    		/// </summary>

private void MsdnOut() { try { // 检查MSDN安装目录 string strMSDNDir =@"C:\Program Files\MSDN\2003FEB\2052"; if( System.IO.Directory.Exists( strMSDNDir) == false) return ;

				// 检查反编译器程序
				string strExeFile = @"C:\Program Files\Microsoft Help 2.0 SDK\hxcomp.exe";
				if( System.IO.File.Exists( strExeFile ) == false)
					return ;

				// 准备临时文件目录
				string strOutDir = this.txtOutPath.Text ;
				if( strOutDir == null || strOutDir.Trim().Length == 0)
					return ;

				strOutDir = strOutDir.Trim();
				if( System.IO.Directory.Exists( strOutDir ) == false)
					System.IO.Directory.CreateDirectory( strOutDir );

				string strTempPath = System.IO.Path.Combine( strOutDir , "temp");
				if( System.IO.Directory.Exists( strTempPath ) == false)
					System.IO.Directory.CreateDirectory( strTempPath );

				bolCancel = false;
				bolPause = false;
				InitDB();
				using(System.Data.SqlClient.SqlCommand myCmd = MainConn.CreateCommand())
				{
					myCmd.CommandText = "Delete From MSDNFile";
					myCmd.ExecuteNonQuery();
					myCmd.CommandText = "Delete From MSDNFileList";
					myCmd.ExecuteNonQuery();
				}
				int DBCount = 1 ;
				long FileSizeCount = 0 ;
				long TotalFileSize = 0 ;
				int FileCount = 0 ;
				string[] strFileNames = System.IO.Directory.GetFiles( strMSDNDir , "*.hxs");
				this.InvokeSetLabelText( this.lblDB ,  "当前数据库:" + CurrentDBName );
				InvokeSetProgress( this.MainProgress , strFileNames.Length , 0 );
				long HXSFileSize = 0 ;
				// 计算所有要处理的文件的长度
				foreach( string strFileName in strFileNames)
				{
					System.IO.FileInfo myInfo = new System.IO.FileInfo( strFileName );
					HXSFileSize += myInfo.Length ;
				}
				long HXFileSizeCount = 0 ;
				// 计算单个数据库所能保存的数据大小,在此设置为1000MB
				int DBMaxSize = 1000 * 1024 * 1024 ;
				// 分别处理单个HXS文档
				for(int HXSFileCount = 0 ; HXSFileCount &lt; strFileNames.Length ; HXSFileCount ++ )
				{
					if( bolCancel ) break;
					string strFileName = ( string ) strFileNames[ HXSFileCount ];
					System.IO.FileInfo myInfo = new System.IO.FileInfo( strFileName );
					HXFileSizeCount += myInfo.Length ;
					InvokeSetProgress( this.MainProgress , (int)(HXSFileSize &gt;&gt; 5) ,  (int)( HXFileSizeCount &gt;&gt; 5 ) );
					string strModleName = System.IO.Path.GetFileNameWithoutExtension( strFileName ) + "\\" ;
					InvokeSetLabelText( lblFile , "正在处理第 " + HXSFileCount + " 个文件 " + System.IO.Path.GetFileName( strFileName )  + " " + myInfo.Length + " 字节  ..." );
					InvokeSetLabelText( lblState ,"正在反编译..." );
					string strOutSubDir = System.IO.Path.Combine( strOutDir ,"temp");
					if( System.IO.Directory.Exists( strOutSubDir) == false)
						System.IO.Directory.CreateDirectory( strOutSubDir );
					int BasePathLength = ( strOutSubDir.EndsWith("\\") ? strOutSubDir.Length : strOutSubDir.Length + 1 ) ;
					// 执行命令行程序来反编译HXS文档
					string strCmd =  " -d " + strOutSubDir + " -u \"" + strFileName + "\" -i -e -w -q";
					System.Diagnostics.ProcessStartInfo myPInfo = new System.Diagnostics.ProcessStartInfo( strExeFile , strCmd );
					myPInfo.CreateNoWindow = true;
					myPInfo.UseShellExecute = false;
					System.Diagnostics.Process myProcess = System.Diagnostics.Process.Start( myPInfo );
					myProcess.WaitForExit();
					if( bolCancel ) break;
					// 找到所有反编译所得的文件
					System.Collections.ArrayList myNames = GetFileNames( strOutSubDir );
					InvokeSetLabelText(lblState , "正在导入到数据库,共  " + myNames.Count + " 个文件 ..." );
					for( int iCount = 0 ; iCount &lt; myNames.Count ; iCount ++ )
					{
						try
						{
							if( bolPause ) myThread.Suspend();
							bolPause = false;
							InvokeSetProgress( this.myProgress , myNames.Count , iCount );
							if( bolCancel ) break;
							// 读取临时文件数据
							string strTempFileName = (string)myNames[iCount];
							System.IO.FileInfo myTempInfo = new System.IO.FileInfo( strTempFileName );
							byte[] bytData = new byte[ (int)myTempInfo.Length ];
							System.IO.FileStream myFile = new System.IO.FileStream( strTempFileName , System.IO.FileMode.Open );
							myFile.Read( bytData , 0 , bytData.Length );
							myFile.Close();
							InsertNameCmd.Parameters[0].Value = FileCount;
							InsertNameCmd.Parameters[1].Value = strModleName + strTempFileName.Substring( BasePathLength );
							InsertNameCmd.Parameters[2].Value = CurrentDBName ;
							InsertNameCmd.Parameters[3].Value = bytData.Length  ;

							InsertCmd.Parameters[0].Value = FileCount ;
							InsertCmd.Parameters[1].Value = bytData ;

							if( bolCancel ) break;

							InsertNameCmd.ExecuteNonQuery();
							InsertCmd.ExecuteNonQuery();

							FileSizeCount += bytData.Length ;
							TotalFileSize += bytData.Length ;
							FileCount ++ ;

							// 更换数据库
							if( FileSizeCount &gt;  DBMaxSize )
							{
								DBCount ++ ;
								CurrentDBName = "MSDN" + DBCount.ToString();
								InvokeSetLabelText( lblState , "更换数据库为 " + CurrentDBName );
								InsertCmd.Dispose();
								using( System.Data.SqlClient.SqlCommand myCmd = MainConn.CreateCommand())
								{
									myCmd.CommandText ="CREATE DATABASE " + CurrentDBName + " ON (NAME = '" + CurrentDBName + "', FILENAME = 'f:\\db\\" + CurrentDBName + ".mdf' )";
									myCmd.ExecuteNonQuery();
								}
								InsertCmd.Dispose();
								DataConn.ChangeDatabase( CurrentDBName );
								using( System.Data.SqlClient.SqlCommand myCmd = DataConn.CreateCommand())
								{
									myCmd.CommandText = @"
									CREATE TABLE [MSDNFile] (
										[MFileID] [int] NOT NULL ,
										[MFileContent] [image] NULL ,
										CONSTRAINT [PK_MSDNFile] PRIMARY KEY  CLUSTERED 
										(
											[MFileID]
										)  ON [PRIMARY] 
									) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
									";
									myCmd.ExecuteNonQuery();
								}//using
								InvokeSetLabelText(lblDB , "当前数据库:" + CurrentDBName );
								InitInsertCmd();
								FileSizeCount = 0 ;
							}//if
						}//try
						catch(Exception ext)
						{
							System.Windows.Forms.MessageBox.Show( ext.ToString());
							InitDB();
							FileCount ++ ;
						}
					}//for
					InvokeSetProgress( this.myProgress , myNames.Count , 0 );
					InvokeSetLabelText( lblState , "正在删除临时文件..." );
					System.IO.Directory.Delete( strOutSubDir , true );
					InvokeSetLabelText( lblState , "操作完毕");
				}//for
				string strDir2 = System.IO.Path.Combine( strOutDir ,"temp");
				if( System.IO.Directory.Exists( strDir2 ))
					System.IO.Directory.Delete( strDir2 , true );
				InsertNameCmd.Dispose();
				InsertCmd.Dispose();
				InvokeSetProgress( this.MainProgress ,1 , 0 );
			}//try
			catch(Exception ext)
			{
				System.Windows.Forms.MessageBox.Show( ext.ToString());
			}
			this.BeginInvoke( new System.EventHandler( this.EndProcess) , new object[]{null,null});
			MainConn.Close();
			MainConn.Dispose();
			DataConn.Close();
			DataConn.Dispose();
		}//public void MsdnOut()

		
		///
1<summary>
2    		/// 获得指定目录及下层目录下所有的文件的绝对路径文件名
3    		/// </summary>

///

1<param name="strRootDir"/>

根目录 ///

1<returns>保存文件名的列表对象</returns>

public System.Collections.ArrayList GetFileNames( string strRootDir) { System.Collections.ArrayList myList = new System.Collections.ArrayList(); string[] strNames = System.IO.Directory.GetFiles( strRootDir , "."); if( strNames != null && strNames.Length > 0 ) { myList.AddRange( strNames ); } strNames = System.IO.Directory.GetDirectories( strRootDir , "."); if( strNames != null && strNames.Length > 0 ) { foreach( string strDir in strNames ) { myList.AddRange( GetFileNames ( strDir )); } } return myList ; }//public GetFileNames()

		#region 处理用户界面的代码群 **************************************************************
		public delegate void SetLabelTextHandler( System.Windows.Forms.Label lbl , string Text );
		public delegate void SetProgressBarHandler( System.Windows.Forms.ProgressBar pb , int vMaxValue ,  int vValue);

		private void InvokeSetProgress( System.Windows.Forms.ProgressBar pb , int vMaxValue ,  int vValue)
		{
			this.Invoke( new SetProgressBarHandler( this.SetProgressBar ) , new object[]{ pb , vMaxValue , vValue });
		}
		private void InvokeSetLabelText( System.Windows.Forms.Label lbl , string Text )
		{
			this.Invoke( new SetLabelTextHandler( this.SetLabelText ) , new object[]{ lbl , Text });
		}
		private void SetLabelText( System.Windows.Forms.Label lbl , string Text )
		{
			lbl.Text = Text ;
			lbl.Refresh();
		}
		private void SetProgressBar ( System.Windows.Forms.ProgressBar pb , int vMaxValue ,  int vValue)
		{
			if( pb.Maximum != vMaxValue )
				pb.Maximum = vMaxValue ;
			if( vValue &gt;= 0 &amp;&amp; vValue &lt;= vMaxValue )
				pb.Value = vValue ;
		}
		private void EndProcess( object sender , System.EventArgs e )
		{
			txtOutPath.Enabled	= true;
			cmdStart.Enabled	= true;
			cmdStop.Enabled		= false;
			cmdPose.Enabled		= false;
		}
		private void cmdStart_Click(object sender, System.EventArgs e)
		{
			cmdStart.Enabled	= false;
			txtOutPath.Enabled	= false;
			cmdStop.Enabled		= true;
			cmdPose.Enabled		= true;
			System.Threading.ThreadStart st = new System.Threading.ThreadStart( this.MsdnOut );
			myThread = new System.Threading.Thread(st);
			myThread.Start();
		}

		private void cmdStop_Click(object sender, System.EventArgs e)
		{
			bolCancel = true;
		}

		private void cmdPose_Click(object sender, System.EventArgs e)
		{
			bolPause = true;
			System.Windows.Forms.MessageBox.Show("正在暂停");
			bolPause = false;
			myThread.Resume();
		}
		#endregion
		
		#region 系统自动生成的代码 ****************************************************************
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.TextBox txtOutPath;
		private System.Windows.Forms.Label lblFile;
		private System.Windows.Forms.Button cmdStart;
		private System.Windows.Forms.Button cmdStop;
		private System.Windows.Forms.Label lblDB;
		private System.Windows.Forms.Label lblState;
		private System.Windows.Forms.ProgressBar myProgress;
		private System.Windows.Forms.ProgressBar MainProgress;
		private System.Windows.Forms.Button cmdPose;
		///
1<summary>
2    		/// 必需的设计器变量。
3    		/// </summary>

private System.ComponentModel.Container components = null;

		public dlgMSDNOut()
		{
			//
			// Windows 窗体设计器支持所必需的
			//
			InitializeComponent();

			//
			// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
			//
		}

		///
1<summary>
2    		/// 清理所有正在使用的资源。
3    		/// </summary>

protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); }

		///
1<summary>
2    		/// 应用程序的主入口点。
3    		/// </summary>

[STAThread] static void Main(string[] args) { System.Windows.Forms.Application.Run( new dlgMSDNOut()); }//main

		#endregion 

		#region Windows 窗体设计器生成的代码 ******************************************************
		///
1<summary>
2    		/// 设计器支持所需的方法 - 不要使用代码编辑器修改
3    		/// 此方法的内容。
4    		/// </summary>

private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.txtOutPath = new System.Windows.Forms.TextBox(); this.lblFile = new System.Windows.Forms.Label(); this.cmdStart = new System.Windows.Forms.Button(); this.cmdStop = new System.Windows.Forms.Button(); this.lblDB = new System.Windows.Forms.Label(); this.lblState = new System.Windows.Forms.Label(); this.myProgress = new System.Windows.Forms.ProgressBar(); this.MainProgress = new System.Windows.Forms.ProgressBar(); this.cmdPose = new System.Windows.Forms.Button(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(16, 16); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(72, 17); this.label1.TabIndex = 0; this.label1.Text = "临时文件夹:"; // // txtOutPath // this.txtOutPath.Location = new System.Drawing.Point(96, 16

Published At
Categories with Web编程
Tagged with
comments powered by Disqus