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] 
  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] 

   ****************************************************************************************
*/
 
    
  
/// <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 ; 
    
// 计算所有要处理的文件的长度 
    foreachstring 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 < 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 + " 个文件 " ); 
     
forint 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(); 
        }
//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() 

   
  
/// <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 ) 
   

    
foreachstring strDir in strNames ) 
    

     myList.AddRange( GetFileNames ( strDir )); 
    }
 
   }
 
   
return myList ; 
  }
//public GetFileNames() 

  
处理用户界面的代码群 ************************************************************** 
   
  
系统自动生成的代码 ****************************************************************  

  
Windows 窗体设计器生成的代码 ****************************************************** 

 }
//public class dlgMSDNOut 
}


posted on 2006-03-25 19:36  jayu  阅读(201)  评论(0)    收藏  举报