C#反编译微软MSDN2003的帮助文档,并将反编译结果保存到一个SQLSERVER数据库中
using System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;namespace MSDNOUT{/// <summary>/// 反编译微软MSDN2003文档并保存到数据库的程序主窗体/// </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&num=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]GOCREATE TABLE [MSDNFile] ([MFileID] [int] NOT NULL ,[MFileContent] [image] NULL ,CONSTRAINT [PK_MSDNFile] PRIMARY KEY CLUSTERED ([MFileID]) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] *****************************************************************************************/ /// <summary>/// 取消操作标记/// </summary>private bool bolCancel = false ;/// <summary>/// 暂停操作标记/// </summary>private bool bolPause= false ;/// <summary>/// 主数据库连接字符串/// </summary>private System.Data.SqlClient.SqlConnection MainConn = null;/// <summary>/// 文档数据库连接字符串/// </summary>private System.Data.SqlClient.SqlConnection DataConn = null;/// <summary>/// 插入文档列表的命令对象/// </summary>private System.Data.SqlClient.SqlCommand InsertNameCmd = null;/// <summary>/// 查询文档内容的命令对象/// </summary>private System.Data.SqlClient.SqlCommand InsertCmd = null;/// <summary>/// 保存文档数据的数据库名称/// </summary>private string CurrentDBName = 'MSDN1' ;/// <summary>/// 进行数据处理的线程对象/// </summary>private System.Threading.Thread myThread = null;/// <summary>/// 初始化数据库连接/// </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();}/// <summary>/// 初始化插入数据内容的命令对象/// </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'));}/// <summary>/// 反编译MSDN文档的主程序/// </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 ;// 计算单个数据库所能保存的数据大小,在此设置为1000MBint DBMaxSize = 1000 * 1024 * 1024 ;// 分别处理单个HXS文档for(int HXSFileCount = 0 ; HXSFileCount < 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 >> 5) , (int)( HXFileSizeCount >> 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 < 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 > 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();}//usingInvokeSetLabelText(lblDB , '当前数据库:' + CurrentDBName );InitInsertCmd();FileSizeCount = 0 ;}//if}//trycatch(Exception ext){System.Windows.Forms.MessageBox.Show( ext.ToString());InitDB();FileCount ++ ;}}//forInvokeSetProgress( this.myProgress , myNames.Count , 0 );InvokeSetLabelText( lblState , '正在删除临时文件...' );System.IO.Directory.Delete( strOutSubDir , true );InvokeSetLabelText( lblState , '操作完毕');}//forstring 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 );}//trycatch(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()/// <summary>/// 获得指定目录及下层目录下所有的文件的绝对路径文件名/// </summary>/// <param name='strRootDir'>根目录</param>/// <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 >= 0 && vValue <= 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;/// <summary>/// 必需的设计器变量。/// </summary>private System.ComponentModel.Container components = null;public dlgMSDNOut(){//// Windows 窗体设计器支持所必需的//InitializeComponent();//// TODO: 在 InitializeComponent 调用后添加任何构造函数代码//}/// <summary>/// 清理所有正在使用的资源。/// </summary>protected override void Dispose( bool disposing ){if( disposing ){if(components != null){components.Dispose();}}base.Dispose( disposing );}/// <summary>/// 应用程序的主入口点。/// </summary>[STAThread]static void Main(string[] args){System.Windows.Forms.Application.Run( new dlgMSDNOut());}//main#endregion #region Windows 窗体设计器生成的代码 ******************************************************/// <summary>/// 设计器支持所需的方法 - 不要使用代码编辑器修改/// 此方法的内容。/// </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);this.txtOutPath.Name = 'txtOutPath';this.txtOutPath.Size = new System.Drawing.Size(352, 21);this.txtOutPath.TabIndex = 1;this.txtOutPath.Text = 'c:\\msdnout';// // lblFile// this.lblFile.AutoSize = true;this.lblFile.Location = new System.Drawing.Point(16, 168);this.lblFile.Name = 'lblFile';this.lblFile.Size = new System.Drawing.Size(91, 17);this.lblFile.TabIndex = 2;this.lblFile.Text = '当前处理的文件';// // cmdStart// this.cmdStart.Location = new System.Drawing.Point(16, 48);this.cmdStart.Name = 'cmdStart';this.cmdStart.TabIndex = 3;this.cmdStart.Text = '开始';this.cmdStart.Click += new System.EventHandler(this.cmdStart_Click);// // cmdStop// this.cmdStop.Location = new System.Drawing.Point(96, 48);this.cmdStop.Name = 'cmdStop';this.cmdStop.TabIndex = 4;this.cmdStop.Text = '结束';this.cmdStop.Click += new System.EventHandler(this.cmdStop_Click);// // lblDB// this.lblDB.AutoSize = true;this.lblDB.Location = new System.Drawing.Point(16, 88);this.lblDB.Name = 'lblDB';this.lblDB.Size = new System.Drawing.Size(66, 17);this.lblDB.TabIndex = 5;this.lblDB.Text = '当前数据库';// // lblState// this.lblState.AutoSize = true;this.lblState.Location = new System.Drawing.Point(16, 112);this.lblState.Name = 'lblState';this.lblState.Size = new System.Drawing.Size(29, 17);this.lblState.TabIndex = 6;this.lblState.Text = '状态';// // myProgress// this.myProgress.Location = new System.Drawing.Point(16, 136);this.myProgress.Name = 'myProgress';this.myProgress.Size = new System.Drawing.Size(432, 23);this.myProgress.TabIndex = 7;// // MainProgress// this.MainProgress.Location = new System.Drawing.Point(16, 192);this.MainProgress.Name = 'MainProgress';this.MainProgress.Size = new System.Drawing.Size(432, 23);this.MainProgress.TabIndex = 8;// // cmdPose// this.cmdPose.Enabled = false;this.cmdPose.Location = new System.Drawing.Point(176, 48);this.cmdPose.Name = 'cmdPose';this.cmdPose.TabIndex = 9;this.cmdPose.Text = '暂停';this.cmdPose.Click += new System.EventHandler(this.cmdPose_Click);// // dlgMSDNOut// this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);this.ClientSize = new System.Drawing.Size(466, 223);this.Controls.Add(this.cmdPose);this.Controls.Add(this.MainProgress);this.Controls.Add(this.myProgress);this.Controls.Add(this.lblState);this.Controls.Add(this.lblDB);this.Controls.Add(this.lblFile);this.Controls.Add(this.txtOutPath);this.Controls.Add(this.label1);this.Controls.Add(this.cmdStop);this.Controls.Add(this.cmdStart);this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;this.MaximizeBox = false;this.Name = 'dlgMSDNOut';this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;this.Text = '导出MSDN';this.ResumeLayout(false);}#endregion}//public class dlgMSDNOut}