直播中
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace MSDNOUT
{
/// <summary>
/// 反編譯微軟MSDN2003文檔并保存到數(shù)據(jù)庫的程序主窗體
/// </summary>
public class dlgMSDNOut : System.Windows.Forms.Form
{
/******************************************************************************************
聲明:本程序只是研究性的程序,沒有損害微軟對MSDN的版權(quán)的意圖,并承認
微軟對 MSDN , Microsoft Help 2.0 SDK , HXS文件格式,MSDE 等版權(quán)所有權(quán)
本程序能反編譯微軟MSDN2003的幫助文檔,并將反編譯結(jié)果保存到一個SQLSERVER數(shù)據(jù)庫中
本文件為一個獨立的C#代碼文件,不需要依賴任何其他文件,使用VS.NET建立一個
C#的默認名稱空間為MSDNOUT的Windows應(yīng)用程序后將該文件內(nèi)容覆蓋掉系統(tǒng)自動生成
的Form1.cs文件內(nèi)容即可編譯通過并執(zhí)行,本程序在微軟.NET框架1.1簡體中文版的
Windows2000Server環(huán)境下測試通過, MDAC版本2.7,數(shù)據(jù)庫服務(wù)器為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安裝文件可在微軟網(wǎng)站下載
本程序長時間頻繁的讀寫臨時文件,因此可以使用一個虛擬硬盤工具在
物理內(nèi)存中虛擬一個磁盤,這樣可以大大加快程序的運行速度
可在 http://down1.tech.sina.com.cn/cgi-bin/download/download.cgi?s_id=3761&num=1
下載一個虛擬硬盤工具
程序使用的數(shù)據(jù)庫為MSSQLSERVER,在此使用了MSDE,由于MSDE的單個數(shù)據(jù)庫
大小限制在2GB內(nèi),而MSDN文件總共超過了2GB,因此程序運行時還根據(jù)需要
切換數(shù)據(jù)庫,本程序使用的數(shù)據(jù)庫文件保存在 f:\db 下面
使用前請執(zhí)行以下SQL語句來初始化數(shù)據(jù)庫
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>
/// 主數(shù)據(jù)庫連接字符串
/// </summary>
private System.Data.SqlClient.SqlConnection MainConn = null;
/// <summary>
/// 文檔數(shù)據(jù)庫連接字符串
/// </summary>
private System.Data.SqlClient.SqlConnection DataConn = null;
/// <summary>
/// 插入文檔列表的命令對象
/// </summary>
private System.Data.SqlClient.SqlCommand InsertNameCmd = null;
/// <summary>
/// 查詢文檔內(nèi)容的命令對象
/// </summary>
private System.Data.SqlClient.SqlCommand InsertCmd = null;
/// <summary>
/// 保存文檔數(shù)據(jù)的數(shù)據(jù)庫名稱
/// </summary>
private string CurrentDBName = "MSDN1" ;
/// <summary>
/// 進行數(shù)據(jù)處理的線程對象
/// </summary>
private System.Threading.Thread myThread = null;
/// <summary>
/// 初始化數(shù)據(jù)庫連接
/// </summary>
private void InitDB()
{
if( MainConn != null)
{
MainConn.Dispose();
DataConn.Dispose();
InsertNameCmd.Dispose();
}
// 打開數(shù)據(jù)庫連接
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>
/// 初始化插入數(shù)據(jù)內(nèi)容的命令對象
/// </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 , "當前數(shù)據(jù)庫:" + 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 ;
// 計算單個數(shù)據(jù)庫所能保存的數(shù)據(jù)大小,在此設(shè)置為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 + " 字節(jié) ..." );
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 ) ;
// 執(zhí)行命令行程序來反編譯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 , "正在導(dǎo)入到數(shù)據(jù)庫,共 " + 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;
// 讀取臨時文件數(shù)據(jù)
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 ++ ;
// 更換數(shù)據(jù)庫
if( FileSizeCount > DBMaxSize )
{
DBCount ++ ;
CurrentDBName = "MSDN" + DBCount.ToString();
InvokeSetLabelText( lblState , "更換數(shù)據(jù)庫為 " + 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 , "當前數(shù)據(jù)庫:" + 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 )
{
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 系統(tǒng)自動生成的代碼 ****************************************************************
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>
/// 必需的設(shè)計器變量。
/// </summary>
private System.ComponentModel.Container components = null;
public dlgMSDNOut()
{
//
// Windows 窗體設(shè)計器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 調(diào)用后添加任何構(gòu)造函數(shù)代碼
//
}
/// <summary>
/// 清理所有正在使用的資源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
/// <summary>
/// 應(yīng)用程序的主入口點。
/// </summary>
[STAThread]
static void Main(string[] args)
{
System.Windows.Forms.Application.Run( new dlgMSDNOut());
}//main
#endregion
#region Windows 窗體設(shè)計器生成的代碼 ******************************************************
/// <summary>
/// 設(shè)計器支持所需的方法 - 不要使用代碼編輯器修改
/// 此方法的內(nèi)容。
/// </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 = "結(jié)束";
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 = "當前數(shù)據(jù)庫";
//
// 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 = "狀態(tài)";
//
// 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 = "導(dǎo)出MSDN";
this.ResumeLayout(false);
}
#endregion
}//public class dlgMSDNOut
}