2023年2月

本人做过多年的Visio二次开发,根据个人的经验总结及项目积累,写了一些小小的随笔文章(具体可参考《
伍华聪的Visio二次开发文章

》,上月有幸给深圳一个团队做了两天的Visio培训,当了一回客座老师,重新拉起Visio二次开发这面大旗,个人觉得这也是一次比较难忘的一次经历。

本次准备的培训,除了全面介绍Visio的相关知识和概念,还以实战开发的方式加深Visio二次开发的知识掌握,另外还通过试题来考核各个学生的掌握情况,本文主要是介绍我根据自己一直以来的Visio开发经验所得,准备的Visio二次开发试题,并提供相应的解答分析,希望大家批评指正,一起沟通交流。

虽然Visio已经在各行各业应用的很广,不过这两年来关注的博客文章,Visio二次开发方面的文章除了我零星写的一些,其他同行基本上没有文章涉及(可能是没有时间写这方面经验),虽然目前已经很少从项目上去升华、研究Visio二次开发方面的工作(除非又有一些特殊的项目合作需要)。因此,如果这方面我自己有一些新的心得或者资料,我是很乐意和大家一起分享。

一)判断题(每题5分,共20题,总分100分)

1)部署Visio二次开发的应用程序不需要安装Office Visio。
答案:错,开发、部署都需要。

2)Visio的“以开发人员模式运行”模式,能帮助我们查看更多、更细的Visio图元的信息。

答案: 对。

3)形状数据窗口显示的字段信息,是Visio图元内部固定的数据,不能通过代码进行更改。

答案:错,可以通过代码修改,增加、修改、删除均可。

4)通过宏录制功能,可以查看某个功能的具体实现代码,也能实现对图元(Shape对象)等对象属性的调试跟踪。

答案:对。

5)可以通过Visio来实现模具的绘制,修改,调整其内部相应的控制内容,但模具显示的图标不可修改。

答案:错,图标也一样可以修改。

6)Visio Drawing Control控件是一个COM控件,该控件除了提供界面显示Visio文档外,也提供了Visio二次开发中涉及到的Window、Document、Shape、Page、Selection等对象的事件处理。

答案:对。

7)Visio文档里面保存到Shape Data属性数据的时候,数值型、字符型的值保存均要再前后加双引号。

答案:错,数值型是不需要加双引号的。

8)Visio二次开发,可以通过代码实现形状数据窗口、模具文件窗口、扫视和缩放等窗口的可见性进行控制,但不能通过代码调用Visio控件里面的界面组件对象(如CommandBar等UI组件对象)。

答案:错,均可以。

9)Visio除了可以在Winform中通过控件实现对文档的编辑外,也可以通过安装Visio Viewer工具,实现Visio文档基于Web方式的修改编辑。

答案:错,Web方式只能查看,无法实现修改。

10) Visio Drawing Control控件,有一个重要的SRC属性是用来打开或者关闭当前文档,如果开始为该属性指定特定的文件路径后,再次设置SRC为空,那么控件显示的文档就会变为空白文档。

答案:错,SRC只是关闭对引用文件的操作,不会影响文档的显示,还是显示原来的文档。

11)模具文件属性的修改,必须先以读写方式打开模具文档,才能进行相关的操作。

答案:对。

12)Visio文档通过SRC打开指定文件后,如果要重新关联到不同的文件上去,需要通过Marshal.ReleaseComObject方法来释放已有的对象,如果是新建一个Visio文档,则不需要这样操作。
答案:错,均需要释放对象。

13)Visio开发的Winform程序,可以使用两种方式实现右键菜单:一种是通过捕捉Visio控件的MouseUpEvent事件,一种是通过RUNADDONWARGS函数来实现。两种方式效果一样,都带有Visio常用的复制、粘贴、格式、数据等基本的菜单项目。

答案:错,第一种没有其他菜单。

14)属性数据的下拉列表分为:固定列表、可变列表。两者区别前者不可以通过代码增加列表项目,后者可以增加;但两者都可以既从列表中选择数据,也可以输入新的内容。

答案:错误,他们都可以通过代码增加列表项目,只是后者可以选择已有的,也可以输入其他内容。

15)Visio文档提供打印当前页、当前视图、分页打印等操作,同时也支持打印选定区域。

答案:对。

16)如果修改了模具的Master对象的形状数据定义,如增加一个属性字段,那么图纸对应的Master和Shape也能自动实现更新。

答案:错,更新模具形状属性后,需要手动更新图纸的信息。

17)通过代码操作,除了可以修改Shape对象的值外,还可以实现Shape对象的文本内容、字体大小、线条粗细、显示颜色等属性的修改。
对。

18)Visio文档有且只有一个模具模板(Master对象),一个模具对象在文档中可有多个图元(Shape对象)。

答案:对。

19)一个形状文件包含一系列的模具组合,如开关模具组、跨越模具组。

答案:对。

20)Visio文档可以保存为XML格式文件,通过这个文件可以看到各种Visio对象之间的组织关系。

答案:对。

二)实战开发题(每题50分,共1
题,总分50分)

例子要求:

1、打开指定的Visio及模具文件,可以保存Visio文件,导出Visio为CAD。

2、选择打开不同的Visio文件,实现对象释放及重新加载。
3、模仿EnventSink.cs代码实现事件的侦听及处理操作。
4、为页面添加一个右键菜单【测试】,单击测试弹出对话框显示页面数量、当前页面名称、Shape数量。

5、可以打开、隐藏模具文件窗口。

答案:

打开相关的Visio文件,并在图纸上右键,显示右键菜单【测试】

响应菜单操作后,界面弹出对话框,提示相关的信息,如下图。

例子关键的代码如下所示:

private
void
btnOpen_Click(
object
sender, EventArgs e)
{
OpenFileDialog dlg =
new
OpenFileDialog();
dlg.Filter =
"
Visio文件(*.vsd)|*.vsd|所有文件(*.*)|*.*
"
;
dlg.FilterIndex =
1
;
if
(dlg.ShowDialog() == DialogResult.OK)
{
OpenVisio(dlg.FileName);
}
}

private
void
OpenVisio(
string
fileName)
{
VisioUtility.CloseAllStencileDocument(VisApplication);

Marshal.ReleaseComObject(VisApplication);
Marshal.ReleaseComObject(VisDocument.EventList);
Marshal.ReleaseComObject(VisDocument);
Marshal.ReleaseComObject(VisWindow);
GC.Collect();

Thread.Sleep(
100
);

this
.axDrawingControl1.Src = fileName;
this
.axDrawingControl1.Src =
""
;

InitEventSink(VisApplication, VisDocument);
this
.axDrawingControl1.Document.Saved =
true
;

List<
string
> filePaths = GetFilePaths(gStencileFileBasePath);
foreach
(
string
stencil
in
filePaths)
{
VisioUtility.OpenStencilRead(VisApplication.Documents, stencil);
}

AddContextMenu();
}

private
void
AddContextMenu()
{
Visio.Page page = VisioUtility.GetPage(VisDocument,
"
馈线图
"
);
bool
isEnable =
true
;
if
(page !=
null
)
{
//
清除所有相关的菜单事件


page.PageSheet.DeleteSection((
short
)VisSectionIndices.visSectionAction);

//
加入新的菜单


VisioUtility.AddRightMouseAction(page.PageSheet,
"
\"测试\"
"
,
"
RUNADDONWARGS(\"QUEUEMARKEREVENT\", \"/Drawing=测试\")
"
,
isEnable,
true
,
false
,
false
,
true
,
true
);
}
}


下面提供本次例子的源码,希望对大家学习研究有所帮助:
Visio二次开发实战例子Demo(源码)

在网络化的环境中,特别是基于互联网发布的Winform程序,程序的自动更新功能是比较重要的操作,这样可以避免挨个给使用者打电话、发信息通知或者发送软件等,要求其对应用程序进行升级。实现程序的自动更新,在后期发布维护过程中,一个可以快速相应修正相关的Bug或者增加功能,二个可以避免给使用客户隔三差五的发送修改好的程序,省心省力。本文也是基于这个思想,在Winform开发框架中再引入一个自动升级更新的通用模块,这个自动升级的通用模块除了具备一般的功能外,可以通过配置程序标题、升级路径方式等方式,实现通用化的升级操作,其他需要升级的程序,拿过来就可以使用,经过项目的整合及优化,已经具备较好的应用前景了。

本通用自动更新模块具有下面几个特点:

1)程序标题可配置,更新路径可配置,适用于各种需要更新的项目整合。

2)支持文件复制或者对压缩包进行解压,适合更多琐碎程序集的整体升级。

3)支持文件更新后自动启动,或者带参数的启动方式。


下面是我的Winform开发框架中集成通用自动更新模块的截图,如下所示。

更新过程中会先关闭主程序,把更新的Zip文件下载后进行自动解压,然后启动主程序。


自动更新一般需要设置一些参数,如程序标题、更新地址路径、版本号等,本通用自动更新的XML文件如下所示。

自动更新虽然可以独立进行执行并更新,不过一般会在主程序中加入对自动更新的判断(毕竟使用客户大多数都是会运行主程序的),实现自动更新判断及执行,我们可以把其放到一个后台线程中执行判断,这样可以提供用户的体验,不会中断界面操作,我一般倾向于把自动更新放到登录界面的首页上,这样用户每次登录的时候,可选择性进行更新,登录后一般要进行业务操作,如果更新退出可能会导致客户的一些重要数据没有保存而丢失,这样影响不好。

///

<summary>


///
窗体加载实现的操作

///

</summary>


private
void
Logon_Load(
object
sender, EventArgs e)
{
.......................

#region
更新提示/判断是否自动更新
updateWorker =
new
BackgroundWorker();
updateWorker.DoWork +=
new
DoWorkEventHandler(updateWorker_DoWork);
updateWorker.RunWorkerCompleted +=
new
RunWorkerCompletedEventHandler(updateWorker_RunWorkerCompleted);

string
strUpdate = config.AppConfigGet(
"
AutoUpdate
"
);
if
(!
string
.IsNullOrEmpty(strUpdate))
{
bool
autoUpdate =
false
;
bool
.TryParse(strUpdate,
out
autoUpdate);
if
(autoUpdate)
{
updateWorker.RunWorkerAsync();
}
}
#endregion
}

#region
更新提示线程处理
private
void
updateWorker_RunWorkerCompleted(
object
sender, RunWorkerCompletedEventArgs e)
{
//
MessageUtil.ShowTips("版本更新完成");


}

private
void
updateWorker_DoWork(
object
sender, DoWorkEventArgs e)
{
try
{
UpdateClass update =
new
UpdateClass();
bool
newVersion = update.HasNewVersion;
if
(newVersion)
{
if
(MessageUtil.ShowYesNoAndTips(
"
有新的版本,是否需要更新
"
) == DialogResult.Yes)
{
Process.Start(Path.Combine(Application.StartupPath,
"
Updater.exe
"
),
"
121
"
);
Application.Exit();
}
}

}
catch
(Exception ex)
{
MessageUtil.ShowError(ex.Message);
}
}
#endregion


上面是介绍我Winform开发框架中应用的自动更新模块,当然经验丰富的你可能也有自己的更新模块,或者比这个更具有一些亮点的地方,这样的话非常开心大家一起交流研究。

本人多年来一直致力于开发一些共享软件,如送水管理系统、酒店管理系统、仓库管理系统、配电网络可视化管理系统、病人资料管理系统,以及一些小型的软件,如QQ搜通天、易博搜搜、赶集小神童、绿苗帮电脑监控系统等,以及在日常中,也是从事一些较为大型系统的开发工作。一直以来,有一个想法,就是尽可能利用好的、经过淬炼的技术,以及日常积累的经验所得,构建一个Winform开发框架的生态体系,目前这些体系基本上已经完整实现,并应用在实际项目和共享软件当中,并在实际中历练和升华。
这个体系包括有:
1)Database2Sharp代码生成工具,用来辅助生成复杂的架构基础代码,以及日常的一些琐碎反复的工作。
2)一个稳定成熟、反复应用过的Winform开发框架,集成应用程序必备的一些常用操作,新的业务系统只需要在其上面按既定的模式叠加业务操作即可,提供框架的可用性、稳定性以及完善性。
3)提供一个所有业务系统都很常见的权限管理系统以及一个也很常见的字典数据管理模块。这两个模块是组件化的模块,既相互独立,又可以和Winform框架进行集成,供业务系统重复调用。
4)一个集成多年经验积累、反复优化提炼的公用类库,类库封装日常开发所应用到的方方面面,如一把瑞士军刀,一个个奇兵,各有用处。
5)一系列界面控件的整合效果,提供各种报表生成的解决方案(普通二维报表、自定义模板报表、复杂报表等高级功能。
6)提供一个封装日常数据显示的分页控件,集成高性能的数据分页显示、数据打印、数据导出、常用数据操作等接口功能。
7)提供一个通用的程序自动更新模块,更快、更便捷实现程序的自动更新,避免挨个给使用者打电话、发信息通知或者发送软件等,要求其对应用程序进行升级。

8)基于上面第2点的Winform开发框架及整合所有通用模块,开发基于互联网软件发布模式的WCF开发框架,构建一个安全、高效、便捷、分布式的业务管理系统。

如果你对我的Winform开发框架有兴趣,还可以阅读下面几篇文章,如下:

Winform开发框架之字典数据管理

Winform开发框架之权限管理系统

Winform开发框架之终极应用

Winform开发框架之Office Ribbon界面

基于我的Winform开发框架扩展而成的WCF开发框架

早在《
Winform分页控件重大更新,并实现普通版、DotNetBar、DevExpress三大版本整合更新(附各种例子源码)
》随笔中,就集成了三种界面样式的分页控件(
普通版、基于DotNetBar样式和基于DevExpress样式三种)
,后来也就形成了我三种不同的Winform开发框架界面样式。

1)
基于传统经典模式的界面,采用了
OutLookBar
工具条以及鼎鼎有名的
Weifengluo
多文档布局控件,集成了分页控件、使用基于
Apose.Cell
控件的自定义报表等功能,能适应大多数业务系统的引用。框架数据编辑界面、普通查询窗体界面均采用窗体集成模式,简化开发代码,提高窗体开发效率以及统一界面的一致性。

2)
在基于传统经典模式的
Winform
框架基础上,引入
DotNetBar
优秀的界面组件,对界面的样式,布局均由很大程度的提升。工具栏统一集中放置在
Ribbon
工具条上,可以折叠分组等,另外也支持多文档的界面操作,非常方便和美观。

3)
基于
DevExpress
界面设计也在基于传统经典模式的
Winform
框架基础上,引入
DotNet
最为优秀的界面组件
DevExpress
,对界面布局、样式等模块提升到一个极高的高度,同时提供该样式的分页控件,使得整合更加完美。

介绍三种框架的布局及大致样式后,言归正传,介绍在Winform开发中,经常用到的对话框操作的封装,一般的对话框操作,包括有各种不同的方式,传统方式如下所示。

以上图片是Win7的效果,XP或者2000下基本上是灰头土脸的效果,如果但在不同的界面样式中,就不能一直用MessageBox.Show这个方法了,因为不同的界面样式提供了不同的对话框封装操作。下面分别介绍基于传统方式、基于DotNetBar界面控件方式、基于DevExpress界面样式方式,三种方式的对话框处理封装类。

1)、传统方式的对话框处理封装类代码如下

public
class
MessageUtil
{
///

<summary>


///
显示一般的提示信息

///

</summary>


///

<param name="message">
提示信息
</param>


public
static
DialogResult ShowTips(
string
message)
{
return
MessageBox.Show(message,
"
提示信息
"
,MessageBoxButtons.OK, MessageBoxIcon.Information);
}

///

<summary>


///
显示警告信息

///

</summary>


///

<param name="message">
警告信息
</param>


public
static
DialogResult ShowWarning(
string
message)
{
return
MessageBox.Show(message,
"
警告信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}

///

<summary>


///
显示错误信息

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowError(
string
message)
{
return
MessageBox.Show(message,
"
错误信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Error);
}

///

<summary>


///
显示询问用户信息,并显示错误标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoAndError(
string
message)
{
return
MessageBox.Show(message,
"
错误信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Error);
}

///

<summary>


///
显示询问用户信息,并显示提示标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoAndTips(
string
message)
{
return
MessageBox.Show(message,
"
提示信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Information);
}

///

<summary>


///
显示询问用户信息,并显示警告标志

///

</summary>


///

<param name="message">
警告信息
</param>


public
static
DialogResult ShowYesNoAndWarning(
string
message)
{
return
MessageBox.Show(message,
"
警告信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
}

///

<summary>


///
显示询问用户信息,并显示提示标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoCancelAndTips(
string
message)
{
return
MessageBox.Show(message,
"
提示信息
"
, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
}

///

<summary>


///
显示一个YesNo选择对话框

///

</summary>


///

<param name="prompt">
对话框的选择内容提示信息
</param>


///

<returns>
如果选择Yes则返回true,否则返回false
</returns>


public
static
bool
ConfirmYesNo(
string
prompt)
{
return
MessageBox.Show(prompt,
"
确认
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
}

///

<summary>


///
显示一个YesNoCancel选择对话框

///

</summary>


///

<param name="prompt">
对话框的选择内容提示信息
</param>


///

<returns>
返回选择结果的的DialogResult值
</returns>


public
static
DialogResult ConfirmYesNoCancel(
string
prompt)
{
return
MessageBox.Show(prompt,
"
确认
"
, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
}
}

2 )DotNetBar样式中对话框处理封装类如下所示

public
class
MessageExUtil
{
///

<summary>


///
显示一般的提示信息

///

</summary>


///

<param name="message">
提示信息
</param>


public
static
DialogResult ShowTips(
string
message)
{
return
MessageBoxEx.Show(message,
"
提示信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Information);
}

///

<summary>


///
显示警告信息

///

</summary>


///

<param name="message">
警告信息
</param>


public
static
DialogResult ShowWarning(
string
message)
{
return
MessageBoxEx.Show(message,
"
警告信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}

///

<summary>


///
显示错误信息

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowError(
string
message)
{
return
MessageBoxEx.Show(message,
"
错误信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Error);
}

///

<summary>


///
显示询问用户信息,并显示错误标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoAndError(
string
message)
{
return
MessageBoxEx.Show(message,
"
错误信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Error);
}

///

<summary>


///
显示询问用户信息,并显示提示标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoAndTips(
string
message)
{
return
MessageBoxEx.Show(message,
"
提示信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Information);
}

///

<summary>


///
显示询问用户信息,并显示警告标志

///

</summary>


///

<param name="message">
警告信息
</param>


public
static
DialogResult ShowYesNoAndWarning(
string
message)
{
return
MessageBoxEx.Show(message,
"
警告信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
}

///

<summary>


///
显示询问用户信息,并显示提示标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoCancelAndTips(
string
message)
{
return
MessageBoxEx.Show(message,
"
提示信息
"
, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
}
}

3)DevExpress样式中对话框处理封装类如下所示

public
class
MessageDxUtil
{
///

<summary>


///
显示一般的提示信息

///

</summary>


///

<param name="message">
提示信息
</param>


public
static
DialogResult ShowTips(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
提示信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Information);
}

///

<summary>


///
显示警告信息

///

</summary>


///

<param name="message">
警告信息
</param>


public
static
DialogResult ShowWarning(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
警告信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}

///

<summary>


///
显示错误信息

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowError(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
错误信息
"
, MessageBoxButtons.OK, MessageBoxIcon.Error);
}

///

<summary>


///
显示询问用户信息,并显示错误标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoAndError(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
错误信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Error);
}

///

<summary>


///
显示询问用户信息,并显示提示标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoAndTips(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
提示信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Information);
}

///

<summary>


///
显示询问用户信息,并显示警告标志

///

</summary>


///

<param name="message">
警告信息
</param>


public
static
DialogResult ShowYesNoAndWarning(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
警告信息
"
, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
}

///

<summary>


///
显示询问用户信息,并显示提示标志

///

</summary>


///

<param name="message">
错误信息
</param>


public
static
DialogResult ShowYesNoCancelAndTips(
string
message)
{
return
DevExpress.XtraEditors.XtraMessageBox.Show(message,
"
提示信息
"
, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
}
}


三个不同的对话框封装类,专门为不同的Winform界面样式服务,接口一样,返回的对话框结果一样,简化了对这些常用的操作封装的同时,也使得界面的整体性达到更一致,用户体验更好,否则在漂亮的DevExpress界面效果中,突然弹出一个灰头土脸的对话框提示信息,甚是大煞风景,给使用者不好的印象。

以上是我在我的三种界面样式的Winform开发框架中常用到的类,希望对大家有所帮助,并能在具体的项目中应用,有时间就推荐一下,在此感谢大家支持。

在Winform开发中,一直离不开分页处理,好的分页控件封装,能为开发节省很多时间和繁琐工作,对分页控件一直的改进和完善,也是我的兴趣之一。分页控件一直都有一些小的更新,不过基本上已能满足大多数的使用场景了。有一天,一个朋友告诉我:我们项目用的是Sqlite数据库做项目,这个分页控件能支持实现分页吗?由于分页控件虽然不直接访问数据,不过需要根据不同的数据库来构造不同的分页语句,因为之前听说过但没怎么研究过Sqlite数据库,当然也没有提供支持了。

既然朋友需要,那就得研究下,并提供相关的支持,经过一番小修改,即可完成内容的Sqlite分页支持了。在给出相关的分页实现例子之前,我们介绍一下,为什么项目使用Sqlite而不是使用Access数据库,他们之间有那些特点。

1、Access特点

我们做小项目的时候特别是小的MIS系统一般也都要用数据库来保存数据,大部分的小系统都是用Access数据库,Access使用上确实非常方便,也方便对数据进行管理维护等优点,复制过去即可使用。但其实Access数据库本身也存在很多的问题:性能不行;数据不安全,用户可以直接用Access打开数据库文件进行数据修改,即使加密后都可以直接破解;Access的数据量一大,文件本身的体积就异常庞大;Access数据库文件很容易损坏等。

2、 SQLite特点

SQLite是一个小型的C程序库,实现了独立的,可嵌入的,零配置的SQL数据库引擎,SQLite用的非常广泛,Web应用也都在用它,PHP5内置了SQLite的扩展,所以SQLite是桌面轻量级数据库的首选。
  • 事务操作是原子,一致,孤立,并且持久的(ACID),即使在系统崩溃和电源故障之后。

  • 零配置——不需要安装和管理。

  • 实现了绝大多数SQL92标准。

  • 整个数据库存储在一个单一的文件中。

  • 数据库文件可以在不同字节序的机器之间自由地共享。

  • 支持最大可达2T的数据库。 (241 字节)

  • 字符串和BLOB类型的大小最大可达 2G 字节(231字节)。

  • 小的代码: 完整配置的少于250KB,忽略一些可选特性的少于150KB。

  • 在大多数常见操作上比流行的客户/服务器数据库引擎更快。

  • 简单,易于使用的API。

  • 内建TCL绑定。 另外提供可用于许多其他语言的绑定。

  • 具有良好注释的源代码,95%经过测试。

  • 独立:没有外部依赖。

  • 源代码位于公共域。 可用于任何用途。

朋友介绍操作SQLite使用工具SQLiteSpy,实际上这个工具不支持数据库(如Access数据库)的导入,偶然发现还有SQLite Developer这样一个工具,管理上非常方便,操作图如下所示,使用发现功能比较丰富,支持对表字段定义的直接修改,编辑数据、Sql查询、创建、压缩、备份数据库等,对中文支持也不错。

言归正题,介绍完毕一些SQLite的使用后,继续介绍分页控件如何实现SQLite的分页处理吧。

普通版本的分页控件呈现效果如下所示。

DevExpress样式版本的分页控件效果如下所示(均支持SQLite分页)

基于SqlLite数据库的分页控件使用例子代码如下:

string
connectionString =
""
;

public
FrmCustomer()
{
InitializeComponent();

connectionString =
string
.Format(
@"
Data Source={0}\OrderWater.db;Version=3;
"
, Application.StartupPath);
}

private
void
FrmCustomer_Load(
object
sender, EventArgs e)
{
this
.winGridViewPager1.OnPageChanged +=
new
EventHandler(winGridViewPager1_OnPageChanged);
this
.winGridViewPager1.OnStartExport +=
new
EventHandler(winGridViewPager1_OnStartExport);
this
.winGridViewPager1.OnEditSelected +=
new
EventHandler(winGridViewPager1_OnEditSelected);
this
.winGridViewPager1.OnDeleteSelected +=
new
EventHandler(winGridViewPager1_OnDeleteSelected);
this
.winGridViewPager1.OnRefresh +=
new
EventHandler(winGridViewPager1_OnRefresh);
this
.winGridViewPager1.OnAddNew +=
new
EventHandler(winGridViewPager1_OnAddNew);
this
.winGridViewPager1.AppendedMenu =
this
.contextMenuStrip1;
this
.winGridViewPager1.ShowLineNumber =
true
;
//
显示行号


this
.winGridViewPager1.PagerInfo.PageSize =
20
;
//
页面大小


this
.winGridViewPager1.EventRowBackColor = Color.LightCyan;
//
间隔颜色


BindData();
}

private
void
winGridViewPager1_OnRefresh(
object
sender, EventArgs e)
{
BindData();
}

private
void
winGridViewPager1_OnDeleteSelected(
object
sender, EventArgs e)
{
if
(MessageUtil.ShowYesNoAndTips(
"
您确定删除选定的记录么?
"
) == DialogResult.No)
{
return
;
}

DataGridView grid =
this
.winGridViewPager1.dataGridView1;
if
(grid !=
null
)
{
foreach
(DataGridViewRow row
in
grid.SelectedRows)
{
//
BLLFactory<Customer>.Instance.Delete(row.Cells[0].Value.ToString());


}
BindData();
}
}

private
void
winGridViewPager1_OnEditSelected(
object
sender, EventArgs e)
{
DataGridView grid =
this
.winGridViewPager1.dataGridView1;
if
(grid !=
null
)
{
foreach
(DataGridViewRow row
in
grid.SelectedRows)
{
FrmEditCustomer dlg =
new
FrmEditCustomer();
dlg.ID = row.Cells[
0
].Value.ToString();
if
(DialogResult.OK == dlg.ShowDialog())
{
BindData();
}

break
;
}
}
}

private
void
winGridViewPager1_OnStartExport(
object
sender, EventArgs e)
{
string
where
= GetSearchSql();
PagerInfo info =
new
PagerInfo();
info.CurrenetPageIndex =
1
;
info.PageSize =
int
.MaxValue;
this
.winGridViewPager1.AllToExport = FindToDataTable(
where
, info);
}

private
void
winGridViewPager1_OnPageChanged(
object
sender, EventArgs e)
{
BindData();
}

#region
查询辅助函数

///

<summary>


///
执行SQL查询语句,返回查询结果的所有记录的第一个字段,用逗号分隔。

///

</summary>


///

<param name="sql">
SQL语句
</param>


///

<returns>


///
返回查询结果的所有记录的第一个字段,用逗号分隔。

///

</returns>



public
string
SqlValueList(
string
sql)
{
SQLiteConnection connection =
new
SQLiteConnection(connectionString);
SQLiteCommand cmd =
new
SQLiteCommand(sql, connection);

connection.Open();
StringBuilder result =
new
StringBuilder();
using
(SQLiteDataReader dr = cmd.ExecuteReader())
{
while
(dr.Read())
{
result.AppendFormat(
"
{0},
"
, dr[
0
].ToString());
}
}

string
strResult = result.ToString().Trim(
'
,
'
);
return
strResult;
}

///

<summary>


///
执行SQL查询语句,返回所有记录的DataTable集合。

///

</summary>


///

<param name="sql">
SQL查询语句
</param>


///

<returns></returns>



public
DataTable SqlTable(
string
sql)
{
DataSet ds =
new
DataSet();
SQLiteDataAdapter adpater =
new
SQLiteDataAdapter(sql, connectionString);
adpater.Fill(ds);

return
ds.Tables[
0
];
}

///

<summary>


///
标准的记录查询函数

///

</summary>


///

<param name="where"></param>


///

<param name="pagerInfo"></param>


///

<returns></returns>


private
DataTable FindToDataTable(
string
where
, PagerInfo pagerInfo)
{
WHC.Pager.WinControl.PagerHelper helper =
new
WHC.Pager.WinControl.PagerHelper(
"
All_Customer
"
,
"
*
"
,
"
LastUpdated
"
, pagerInfo.PageSize, pagerInfo.CurrenetPageIndex,
true
,
where
);
string
countSql = helper.GetPagingSql(WHC.Pager.WinControl.DatabaseType.SQLite,
true
);
string
dataSql = helper.GetPagingSql(WHC.Pager.WinControl.DatabaseType.SQLite,
false
);

string
value = SqlValueList(countSql);
pagerInfo.RecordCount = Convert.ToInt32(value);
//
为了显示具体的信息,需要设置总记录数


DataTable dt = SqlTable(dataSql);
return
dt;
}

///

<summary>


///
根据查询条件构造查询语句

///

</summary>


///

<returns></returns>


private
string
GetSearchSql()
{
SearchCondition condition =
new
SearchCondition();
condition.AddCondition(
"
Number
"
,
this
.txtNumber.Text, SqlOperator.Like)
.AddCondition(
"
Name
"
,
this
.txtName.Text, SqlOperator.Like)
.AddCondition(
"
Type
"
,
this
.cmbType.Text, SqlOperator.Like)
.AddCondition(
"
Area
"
,
this
.cmbArea.Text, SqlOperator.Like)
.AddCondition(
"
Address
"
,
this
.txtAddress.Text, SqlOperator.Like)
.AddCondition(
"
Company
"
,
this
.txtCompany.Text, SqlOperator.Like)
.AddCondition(
"
Note
"
,
this
.txtNote.Text, SqlOperator.Like)
.AddCondition(
"
Telephone1
"
,
this
.txtTelephone.Text, SqlOperator.Like,
true
,
"
Telephone
"
)
.AddCondition(
"
Telephone2
"
,
this
.txtTelephone.Text, SqlOperator.Like,
true
,
"
Telephone
"
)
.AddCondition(
"
Telephone3
"
,
this
.txtTelephone.Text, SqlOperator.Like,
true
,
"
Telephone
"
)
.AddCondition(
"
Telephone4
"
,
this
.txtTelephone.Text, SqlOperator.Like,
true
,
"
Telephone
"
)
.AddCondition(
"
Telephone5
"
,
this
.txtTelephone.Text, SqlOperator.Like,
true
,
"
Telephone
"
);

if
(chkUseDate.Checked)
{
condition.AddCondition(
"
CreateDate
"
, dateTimePicker1.Value.ToString(
"
yyyy-MM-dd
"
), SqlOperator.MoreThanOrEqual,
true
)
.AddCondition(
"
CreateDate
"
, dateTimePicker2.Value.AddDays(
1
).ToString(
"
yyyy-MM-dd
"
), SqlOperator.LessThanOrEqual,
true
);

}
string
where
= condition.BuildConditionSql().Replace(
"
Where
"
,
""
);
return
where
;
}
#endregion

private
void
BindData()
{
#region
添加别名解析
//
DisplayColumns与显示的字段名或者实体属性一致,大小写不敏感,顺序代表显示顺序,用逗号或者|分开


this
.winGridViewPager1.DisplayColumns =
"
Number,NAME,type,Area,Company,Address,Telephone1,Telephone2,Telephone3,Telephone4,Telephone5,CreateDate,Note,LastUpdated
"
;
this
.winGridViewPager1.AddColumnAlias(
"
ID
"
,
"
编号
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Number
"
,
"
客户编号
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Name
"
,
"
客户名称
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Type
"
,
"
客户类型
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Area
"
,
"
客户地区
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Company
"
,
"
客户单位
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Address
"
,
"
客户地址
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Telephone1
"
,
"
电话1
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Telephone2
"
,
"
电话2
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Telephone3
"
,
"
电话3
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Telephone4
"
,
"
电话4
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Telephone5
"
,
"
电话5
"
);
this
.winGridViewPager1.AddColumnAlias(
"
CreateDate
"
,
"
开户日期
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Shop_ID
"
,
"
分店ID
"
);
this
.winGridViewPager1.AddColumnAlias(
"
Note
"
,
"
备注
"
);
this
.winGridViewPager1.AddColumnAlias(
"
LastUpdated
"
,
"
更新日期
"
);

#endregion

string
where
= GetSearchSql();
this
.winGridViewPager1.DataSource = FindToDataTable(
where
,
this
.winGridViewPager1.PagerInfo);
}

private
void
btnSearch_Click(
object
sender, EventArgs e)
{
BindData();
}

以上例子关键的地方有3个

1、 数据库字符串

connectionString =
string
.Format(
@"
Data Source={0}\OrderWater.db;Version=3;
"
, Application.StartupPath);

2.、查询数据操作

数据查询通过调用 System.Data.SQLite.DLL 的程序集实现数据访问操作,如下所示。

public
DataTable SqlTable(
string
sql)
{
DataSet ds =
new
DataSet();
SQLiteDataAdapter adpater =
new
SQLiteDataAdapter(sql, connectionString);
adpater.Fill(ds);

return
ds.Tables[
0
];
}

3、 SQLite分页语句调用生成

调用内置的类实现分页语句的生成,代码如下所示。

WHC.Pager.WinControl.PagerHelper helper =
new
WHC.Pager.WinControl.PagerHelper(
"
All_Customer
"
,
"
*
"
,
"
LastUpdated
"
, pagerInfo.PageSize, pagerInfo.CurrenetPageIndex,
true
,
where
);
string
countSql = helper.GetPagingSql(WHC.Pager.WinControl.DatabaseType.SQLite,
true
);

string
dataSql = helper.GetPagingSql(WHC.Pager.WinControl.DatabaseType.SQLite,
false
);

完整可运行例子如下下载即可:

https://files.cnblogs.com/wuhuacong/TestPager_SqlLite.rar

俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。

本篇继续继续整理优化已有的共用类库,并继续发表随笔介绍公用类库的接口方法以及详细使用操作,力求给自己继续优化,积攒更丰富的公用类库资源,加深了解的同时,也给大家展现公用类库好的方面。

本篇的公用类库的介绍主题是加密解密的部分,加解密算法包括DES加解密、Base64加解密、

AES RijndaelManaged加解密、MD5加密、以及RSA非对称加密等操作
。如果你对前面的类库介绍文章有兴趣,可以参考下面的连接了解。

厚积薄发,丰富的公用类库积累,助你高效进行系统开发(7)



厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)


厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)






1、非对称加密、解密、验证辅助类 RSASecurityHelper

本人开发过很多共享软件,在共享软件注册方面积累了一些自己的经验,其中采用非对称加密方式实现注册码验证的操作,就是其中一个比较重要的步骤,由于其逻辑不可逆的特点,采用非对称加密方式,较一般的对称加密方式,能够隐藏授权的逻辑,因此具有更好的效果。 这个非对称的解密解密、验证操作,是我所有共享软件里面用到的授权操作,很早很多朋友就这个问题问过我很多次,现在奉献给大家注册码实现的思路及操作接口,希望大家能够在享受代码带来的便利外,也可以提高自己对知识产权的保护。

一般来说,非对称加密方式,结合代码混淆和强名称验证,是比较好的实现注册授权机制的功能。

实现效果
1)本辅助类主要是用来方便实现非对称加密、解密、验证等相关操作。
2)非对称加密有RSA、椭圆曲线等,最流行的是RSA。所谓的非对称,是因为它有两个密钥,一个称为公钥,一个称为私钥。公钥是可以对外发布的,而私钥是自己保存的。用公钥加密,必须用私钥解密,反之,用私钥加密必须用公钥解密。所以,我们可以在软件中保存公钥的内容,这个是可以公开的;私钥我们可以自己留着。别人拿不到私钥,根本计算不出注册码来。
3)使用辅助类RSASecurityHelper实现注册机制如下:
a. 注册码产生过程:
注册信息(包括用户名等信息)---> RSA私钥加密 ---> 注册码。
b. 软件验证注册码过程:
注册码 ---> RSA公钥验证 ---> 验证成功或失败。


实现代码
1)辅助类提供的方法接口如下所示:
///

<summary>


///
非对称加密生成的私钥和公钥

///

</summary>


///

<param name="privateKey">
私钥
</param>


///

<param name="publicKey">
公钥
</param>



public
static
void
GenerateRSAKey(
out
string
privateKey,
out
string
publicKey)

#region
非对称数据加密(公钥加密)

///

<summary>


///
非对称加密字符串数据,返回加密后的数据

///

</summary>


///

<param name="publicKey">
公钥
</param>


///

<param name="originalString">
待加密的字符串
</param>


///

<returns>
加密后的数据
</returns>



public
static
string
RSAEncrypt(
string
publicKey,
string
originalString)

///

<summary>


///
非对称加密字节数组,返回加密后的数据

///

</summary>


///

<param name="publicKey">
公钥
</param>


///

<param name="originalBytes">
待加密的字节数组
</param>


///

<returns>
返回加密后的数据
</returns>



public
static
string
RSAEncrypt(
string
publicKey,
byte
[] originalBytes)

#endregion

#region
非对称解密(私钥解密)

///

<summary>


///
非对称解密字符串,返回解密后的数据

///

</summary>


///

<param name="privateKey">
私钥
</param>


///

<param name="encryptedString">
待解密数据
</param>


///

<returns>
返回解密后的数据
</returns>



public
static
string
RSADecrypt(
string
privateKey,
string
encryptedString)

///

<summary>


///
非对称解密字节数组,返回解密后的数据

///

</summary>


///

<param name="privateKey">
私钥
</param>


///

<param name="encryptedBytes">
待解密数据
</param>


///

<returns></returns>



public
static
string
RSADecrypt(
string
privateKey,
byte
[] encryptedBytes)

#endregion

#region
非对称加密签名、验证

///

<summary>


///
使用非对称加密签名数据

///

</summary>


///

<param name="privateKey">
私钥
</param>


///

<param name="originalString">
待加密的字符串
</param>


///

<returns>
加密后的数据
</returns>



public
static
string
RSAEncrypSignature(
string
privateKey,
string
originalString)

///

<summary>


///
对私钥加密签名的字符串,使用公钥对其进行验证

///

</summary>


///

<param name="originalString">
未加密的文本,如机器码
</param>


///

<param name="encrytedString">
加密后的文本,如注册序列号
</param>


///

<returns>
如果验证成功返回True,否则为False
</returns>



public
static
bool
Validate(
string
originalString,
string
encrytedString)

///

<summary>


///
对私钥加密的字符串,使用公钥对其进行验证

///

</summary>


///

<param name="originalString">
未加密的文本,如机器码
</param>


///

<param name="encrytedString">
加密后的文本,如注册序列号
</param>


///

<param name="publicKey">
非对称加密的公钥
</param>


///

<returns>
如果验证成功返回True,否则为False
</returns>



public
static
bool
Validate(
string
originalString,
string
encrytedString,
string
publicKey)

#endregion

2) 辅助类RSASecurityHelper的使用例子代码如下所示
//
生成加解密私钥、公钥


string
publicKey =
""
;
string
privateKey =
""
;
RSASecurityHelper.GenerateRSAKey(
out
privateKey,
out
publicKey);

string
originalString =
"
testdata
"
;
string
encryptedString = RSASecurityHelper.RSAEncrypt(publicKey, originalString);
string
originalString2 = RSASecurityHelper.RSADecrypt(privateKey, encryptedString);
if
(originalString == originalString2)
{
MessageUtil.ShowTips(
"
解密完全正确
"
);
}
else
{
MessageUtil.ShowWarning(
"
解密失败
"
);
}

string
regcode = RSASecurityHelper.RSAEncrypSignature(privateKey, originalString);
bool
validated = RSASecurityHelper.Validate(originalString, regcode, publicKey);

MessageUtil.ShowTips( validated ?
"
验证成功
"
:
"
验证失败
"
);


3)实际项目使用的注册验证代码如下所示。

///

<summary>


///
每次程序运行时候,检查用户是否注册

///

</summary>


///

<returns>
如果用户已经注册, 那么返回True, 否则为False
</returns>



public
bool
CheckRegister()
{
//
先获取用户的注册码进行比较


string
serialNumber =
string
.Empty;
//
注册码


RegistryKey reg = Registry.CurrentUser.OpenSubKey(UIConstants.SoftwareRegistryKey,
true
);
if
(
null
!= reg)
{
serialNumber = (
string
)reg.GetValue(
"
SerialNumber
"
);
Portal.gc.bRegisted = Portal.gc.Register(serialNumber);
}

return
Portal.gc.bRegisted;
}

///

<summary>


///
调用非对称加密方式对序列号进行验证

///

</summary>


///

<param name="serialNumber">
正确的序列号
</param>


///

<returns>
如果成功返回True,否则为False
</returns>



public
bool
Register(String serialNumber)
{
string
hardNumber = HardwareInfoHelper.GetCPUId();
return
RSASecurityHelper.Validate(hardNumber, serialNumber);
}

public
string
GetHardNumber()
{
return
HardwareInfoHelper.GetCPUId();

}

2、
DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作辅助类 EncodeHelper

实现效果
1)本辅助类主要是用来方便实现DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作。
2)本辅助类实现多种加解密处理,可以实现字符串、文件、文件流等加密处理。该加密辅助类汇集各种加密处理逻辑,是一个非常常用、方便应对各种加密处理的辅助类。
实现代码
1)辅助类提供的方法接口如下所示:
///

<summary>


///
使用默认加密

///

</summary>


///

<param name="strText"></param>


///

<returns></returns>



public
static
string
DesEncrypt(
string
strText)

///

<summary>


///
使用默认解密

///

</summary>


///

<param name="strText">
解密字符串
</param>


///

<returns></returns>



public
static
string
DesDecrypt(
string
strText)

///

<summary>


///
加密字符串,注意strEncrKey的长度为8位

///

</summary>


///

<param name="strText">
待加密字符串
</param>


///

<param name="strEncrKey">
加密键
</param>


///

<returns></returns>



public
static
string
DesEncrypt(
string
strText,
string
strEncrKey)

///

<summary>


///
解密字符串,注意strEncrKey的长度为8位

///

</summary>


///

<param name="strText">
待解密的字符串
</param>


///

<param name="sDecrKey">
解密键
</param>


///

<returns>
解密后的字符串
</returns>



public
static
string
DesDecrypt(
string
strText,
string
sDecrKey)

///

<summary>


///
加密数据文件,注意strEncrKey的长度为8位

///

</summary>


///

<param name="m_InFilePath">
待加密的文件路径
</param>


///

<param name="m_OutFilePath">
输出文件路径
</param>


///

<param name="strEncrKey">
加密键
</param>



public
static
void
DesEncrypt(
string
m_InFilePath,
string
m_OutFilePath,
string
strEncrKey)

///

<summary>


///
解密数据文件,注意strEncrKey的长度为8位

///

</summary>


///

<param name="m_InFilePath">
待解密的文件路径
</param>


///

<param name="m_OutFilePath">
输出路径
</param>


///

<param name="sDecrKey">
解密键
</param>



public
static
void
DesDecrypt(
string
m_InFilePath,
string
m_OutFilePath,
string
sDecrKey)

#endregion

#region
对称加密算法AES RijndaelManaged加密解密

///

<summary>


///
对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法)

///

</summary>


///

<param name="encryptString">
待加密字符串
</param>


///

<returns>
加密结果字符串
</returns>



public
static
string
AES_Encrypt(
string
encryptString)

///

<summary>


///
对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法)

///

</summary>


///

<param name="encryptString">
待加密字符串
</param>


///

<param name="encryptKey">
加密密钥,须半角字符
</param>


///

<returns>
加密结果字符串
</returns>



public
static
string
AES_Encrypt(
string
encryptString,
string
encryptKey)

///

<summary>


///
对称加密算法AES RijndaelManaged解密字符串

///

</summary>


///

<param name="decryptString">
待解密的字符串
</param>


///

<returns>
解密成功返回解密后的字符串,失败返源串
</returns>



public
static
string
AES_Decrypt(
string
decryptString)

///

<summary>


///
对称加密算法AES RijndaelManaged解密字符串

///

</summary>


///

<param name="decryptString">
待解密的字符串
</param>


///

<param name="decryptKey">
解密密钥,和加密密钥相同
</param>


///

<returns>
解密成功返回解密后的字符串,失败返回空
</returns>



public
static
string
AES_Decrypt(
string
decryptString,
string
decryptKey)


///

<summary>


///
加密文件流

///

</summary>


///

<param name="fs">
文件流
</param>


///

<returns></returns>



public
static
CryptoStream AES_EncryptStrream(FileStream fs,
string
decryptKey)

///

<summary>


///
解密文件流

///

</summary>


///

<param name="fs">
文件流
</param>


///

<returns></returns>



public
static
CryptoStream AES_DecryptStream(FileStream fs,
string
decryptKey)

///

<summary>


///
对指定文件加密

///

</summary>


///

<param name="InputFile">
输入文件
</param>


///

<param name="OutputFile">
输出文件
</param>


///

<returns></returns>



public
static
bool
AES_EncryptFile(
string
InputFile,
string
OutputFile)

///

<summary>


///
对指定的文件解压缩

///

</summary>


///

<param name="InputFile">
输入文件
</param>


///

<param name="OutputFile">
输出文件
</param>


///

<returns></returns>



public
static
bool
AES_DecryptFile(
string
InputFile,
string
OutputFile)

#endregion

#region
Base64加密解密
///

<summary>


///
Base64是一種使用64基的位置計數法。它使用2的最大次方來代表僅可列印的ASCII 字元。

///
這使它可用來作為電子郵件的傳輸編碼。在Base64中的變數使用字元A-Z、a-z和0-9 ,

///
這樣共有62個字元,用來作為開始的64個數字,最後兩個用來作為數字的符號在不同的

///
系統中而不同。

///
Base64加密

///

</summary>


///

<param name="str">
Base64方式加密字符串
</param>


///

<returns></returns>



public
static
string
Base64Encrypt(
string
str)

///

<summary>


///
Base64解密字符串

///

</summary>


///

<param name="str">
待解密的字符串
</param>


///

<returns></returns>



public
static
string
Base64Decrypt(
string
str)

#endregion

#region
MD5加密

///

<summary>


///
使用MD5加密字符串

///

</summary>


///

<param name="strText">
待加密的字符串
</param>


///

<returns>
MD5加密后的字符串
</returns>



public
static
string
MD5Encrypt(
string
strText)

///

<summary>


///
使用MD5加密的Hash表

///

</summary>


///

<param name="input">
待加密字符串
</param>


///

<returns></returns>



public
static
string
MD5EncryptHash(String input)

///

<summary>


///
使用Md5加密为16进制字符串

///

</summary>


///

<param name="input">
待加密字符串
</param>


///

<returns></returns>



public
static
string
MD5EncryptHashHex(String input)

///

<summary>


///
MD5 三次加密算法.计算过程: (QQ使用)

///
1. 验证码转为大写

///
2. 将密码使用这个方法进行三次加密后,与验证码进行叠加

///
3. 然后将叠加后的内容再次MD5一下,得到最终验证码的值

///

</summary>


///

<param name="s"></param>


///

<returns></returns>



public
static
string
EncyptMD5_3_16(
string
s)

#endregion

///

<summary>


///
SHA256函数

///

</summary>


///

<param name="str">
原始字符串
</param>


///

<returns>
SHA256结果(返回长度为44字节的字符串)
</returns>



public
static
string
SHA256(
string
str)

///

<summary>


///
加密字符串(使用MD5+Base64混合加密)

///

</summary>


///

<param name="input">
待加密的字符串
</param>


///

<returns></returns>



public
static
string
EncryptString(
string
input)

///

<summary>


///
解密加过密的字符串(使用MD5+Base64混合加密)

///

</summary>


///

<param name="input">
待解密的字符串
</param>


///

<param name="throwException">
解密失败是否抛异常
</param>


///

<returns></returns>



public
static
string
DecryptString(
string
input,
bool
throwException)

2) 辅助类EncodeHelper的使用例子代码如下所示
///

<summary>


///
对字符串加密

///

</summary>


///

<returns></returns>



private
string
EncodePassword(
string
passwordText)
{
return
EncodeHelper.MD5Encrypt(passwordText);

}

private
void
btnEncrypt_Click(
object
sender, EventArgs e)
{
string
original =
"
测试加密字符串
"
;
Console.WriteLine(
"
original:
"
+ original);

string
encrypt = EncodeHelper.SHA256(original);
Console.WriteLine(
"
EncodeHelper.SHA256
"
+ encrypt);

//
DES加解密


encrypt = EncodeHelper.DesEncrypt(original);
Console.WriteLine(
"
EncodeHelper.DesEncrypt:
"
+ encrypt);

string
decrypt = EncodeHelper.DesDecrypt(encrypt);
Console.WriteLine(
"
EncodeHelper.DesDecrypt:
"
+ decrypt);

//
MD5加密


encrypt = EncodeHelper.MD5Encrypt(original);
Console.WriteLine(
"
EncodeHelper.MD5Encrypt:
"
+ encrypt);
encrypt = EncodeHelper.MD5EncryptHash(original);
Console.WriteLine(
"
EncodeHelper.MD5EncryptHash:
"
+ encrypt);
encrypt = EncodeHelper.MD5EncryptHashHex(original);
Console.WriteLine(
"
EncodeHelper.MD5EncryptHashHex
"
+ encrypt);
encrypt = EncodeHelper.EncyptMD5_3_16(original);
Console.WriteLine(
"
EncodeHelper.EncyptMD5_3_16:
"
+ encrypt);

//
Base64加解密


encrypt = EncodeHelper.Base64Encrypt(original);
Console.WriteLine(
"
EncodeHelper.Base64Encrypt
"
+ encrypt);
decrypt = EncodeHelper.Base64Encrypt(encrypt);
Console.WriteLine(
"
EncodeHelper.Base64Encrypt
"
+ decrypt);

encrypt = EncodeHelper.AES_Encrypt(original);
Console.WriteLine(
"
EncodeHelper.AES_Encrypt
"
+ encrypt);
decrypt = EncodeHelper.AES_Decrypt(encrypt);

Console.WriteLine(
"
EncodeHelper.AES_Decrypt
"
+ decrypt);

3、 MD5各种长度加密字符、验证MD5等操作辅助类 MD5Util

实现效果
1)本辅助类主要是用来方便实现MD5各种长度加密字符、验证MD5等操作。
2)MD5即Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致。是计算机广泛使用的散列算法之一(又译摘要算法、哈希算法)。
3)MD5已经广泛使用在为文件传输提供一定的可靠性方面。例如,服务器预先提供一个MD5校验和,用户下载完文件以后,用MD5算法计算下载文件的MD5校验和,然后通过检查这两个校验和是否一致,就能判断下载的文件是否出错
实现代码
1)辅助类提供的方法接口如下所示:
///

<summary>


///
获得32位的MD5加密

///

</summary>



public
static
string
GetMD5_32(
string
input)

///

<summary>


///
获得16位的MD5加密

///

</summary>



public
static
string
GetMD5_16(
string
input)

///

<summary>


///
获得8位的MD5加密

///

</summary>



public
static
string
GetMD5_8(
string
input)

///

<summary>


///
获得4位的MD5加密

///

</summary>



public
static
string
GetMD5_4(
string
input)

///

<summary>


///
添加MD5的前缀,便于检查有无篡改

///

</summary>



public
static
string
AddMD5Profix(
string
input)

///

<summary>


///
移除MD5的前缀

///

</summary>



public
static
string
RemoveMD5Profix(
string
input)

///

<summary>


///
验证MD5前缀处理的字符串有无被篡改

///

</summary>



public
static
bool
ValidateValue(
string
input)

#region
MD5签名验证

///

<summary>


///
对给定文件路径的文件加上标签

///

</summary>


///

<param name="path">
要加密的文件的路径
</param>


///

<returns>
标签的值
</returns>



public
static
bool
AddMD5(
string
path)

///

<summary>


///
对给定路径的文件进行验证,如果一致返回True,否则返回False

///

</summary>


///

<param name="path"></param>


///

<returns>
是否加了标签或是否标签值与内容值一致
</returns>

public
static
bool
CheckMD5(
string
path)

2) 辅助类

MD5Util
的使用例子代码如下所示

//
为文件增加MD5编码标签,然后验证是否被修改


string
file =
@"
c:\test.xls
"
;
bool
flag2 = MD5Util.AddMD5(file);
Console.WriteLine(flag2);

//
对给定路径的文件进行验证,如果一致返回True,否则返回False


bool
flag3 = MD5Util.CheckMD5(file);

Console.WriteLine(flag3);

4、基于Base64的加密编码辅助类 Base64Util
实现效果
1)本辅助类主要是用来方便实现基于Base64的加密编码。
2)Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。Base64编码一般在电子邮件中可以查看到,打开一封Email,查看其原始信息(您可以通过收取、导出该邮件用文本编辑器查看)。加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。
3)采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
实现代码
1)辅助类提供的方法接口如下所示:
///

<summary>


///
使用默认的密码表加密字符串

///

</summary>


///

<param name="input">
待加密字符串
</param>


///

<returns></returns>



public
static
string
Encrypt(
string
input)

///

<summary>


///
使用默认的密码表解密字符串

///

</summary>


///

<param name="input">
待解密字符串
</param>


///

<returns></returns>



public
static
string
Decrypt(
string
input)

///

<summary>


///
获取具有标准的Base64密码表的加密类

///

</summary>


///

<returns></returns>

public
static
Base64Util GetStandardBase64()

2) 辅助类Base64Util的使用例子代码如下所示
private
void
btnBase64_Click(
object
sender, EventArgs e)
{
string
original =
"
这是一个测试的Base64加密字符串
"
;
string
encrypt = Base64Util.Encrypt(original);
Console.WriteLine(encrypt);
//
输出内容:6L*Z5pi_5LiA5Liq5rWL6K*V55qEQmFzZTY05Yqg5b*G5b2X56ym5Liy


string
decrypt = Base64Util.Decrypt(encrypt);
Debug.Assert(original == decrypt);
//
验证相等

}


5、QQ密码加密操作辅助类 QQEncryptUtil
实现效果
1)本辅助类主要是用来方便实现QQ密码加密操作。
2)在QQ的很多模拟网页采集数据,需要输入用户账号、密码,其中密码是需要进行加密操作的,一般使用js脚本实现,这里把它转化为C#的代码操作,其实也就是把密码和验证码通过3次MD5加密实现的。
实现代码
1)辅助类提供的方法接口如下所示:
///

<summary>


///
QQ根据密码及验证码对数据进行加密

///

</summary>


///

<param name="password">
原始密码
</param>


///

<param name="verifyCode">
验证码
</param>


///

<returns></returns>
public
static
string
EncodePasswordWithVerifyCode(
string
password,
string
verifyCode)
2) 辅助类QQEncryptUtil的使用例子代码如下所示
private
bool
CheckLogin()
{
HttpHelper httpHelper =
new
HttpHelper();
string
refUrl =
"
http://ui.ptlogin2.qq.com/cgi-bin/login?appid=3000801&s_url=http%3A%2F%2Fqun.qq.com%2Fgod%2Fsucc.htm&f_url=loginerroralert&lang=2052&bgcolor=ffffff&style=1&low_login=1&link_target=blank&target=self&hide_title_bar=1&dummy=1
"
;

string
verifyCode =
this
.txtVerify.Text;
string
postData =
string
.Format(
"
u={0}&p={1}&verifycode={2}&aid=3000801&u1=http%3A%2F%2Fqun.qq.com%2Fgod%2Fsucc.htm&h=1&ptredirect=0&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert
"
,
this
.txtUsername.Text, QQEncryptUtil.EncodePasswordWithVerifyCode(
this
.txtPassword.Text, verifyCode), verifyCode);

string
result = httpHelper.GetHtml(
"
http://ptlogin2.qq.com/login?
"
+ postData, Portal.gc.cookieQun, refUrl);
string
errorTxt = result;
bool
isLogin = result.Contains(
"
登录成功!
"
);
return
isLogin;

}


CHM帮助文档持续更新中,统一下载地址是:
http://www.iqidi.com/download/commonshelp.rar

最新公用类库DLL+XML注释文件下载地址是:
https://files.cnblogs.com/wuhuacong/WHC.OrderWater.Commons.rar