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 [email protected]"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 < 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();
}//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 )
{
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
}