2023年2月

在我的上一篇关于城市达人的接口编程中《
QQ城市达人接口编程及经验分享
》,介绍了关于如何获取QQ号码的接口使用,这个接口是绝大多数QQ号码采集软件使用的,
不过这个接口现在已经随着腾讯的屏蔽而失效
,于是,QQ号码采集软件倒下一大批,所有在华军或者网上能查到的QQ号码采集软件,统统不能采集到数据。

我的软件“QQ号码采集及邮件管理系统”,采集号码之前也是用了这个原理,所以有短时间也是采集不了数据,好在众多使用客户的一再反映,才知道不知何因,腾讯取消了该接口的支持。
因此,要实现号码的采集,只能另辟高招了,通过分析城市达人:"
http://city.qzone.qq.com/
" 的查询原理,很快找到了解决的方法,更新了获取数据的接口以及Jason数据对象,终于又可以实现数据的采集了,不过接口数据和之前的有一定的差异,但是总体上还是不错的。
下面截取一个软件的界面来看看先。


下面说说接口数据的问题,通过工具对HTTP访问的分析,腾讯的数据接口从原来的连接字符串:
变为了:

通过新的接口获取到的数据大概是这样子的:
searchProCb({
"
responseHeader
"
: {
"
status
"
:
"
0
"
,
"
QTime
"
:
"
21
"
},
"
response
"
: {
"
numFound
"
:
"
710
"
,
"
currentNum
"
:
"
10
"
,
"
results
"
:[
{

"
RQ
"
:
"
1240719692
"
,
"
MD
"
:
"
495094381
"
,
"
ID
"
:
""
,
"
XT
"
:
"
1000000
"
,
"
DT
"
:
"
1240719692
"
,
"
TI
"
:
"
阳光帅气
"
,
"
UR
"
:
"
http://city.qzone.qq.com/html/user/guest.htm#uin=495094381
"
,
"
QQ
"
:
"
495094381
"
,
"
TA
"
:
""
,
"
CL
"
:
""
,
"
GA
"
:
""
,
"
GB
"
:
"
0
"
,
"
GC
"
:
"
1002
"
,
"
GD
"
:
"
广东 韶关
"
,
"
GE
"
:
"
不限 不限
"
,
"
GF
"
:
"
1
"
,
"
GH
"
:
"
1983
"
,
"
GI
"
:
"
7
"
,
"
GJ
"
:
"
0
"
,
"
GK
"
:
"
0
"
,
"
GL
"
:
"
4
"
,
"
GM
"
:
"
173
"
,
"
GN
"
:
"
6
"
,
"
GO
"
:
"
3
"
,
"
GP
"
:
"
1
"
,
"
GQ
"
:
"
1
"
,
"
GR
"
:
"
1
"
,
"
GS
"
:
"
0
"
,
"
GT
"
:
"
1
"
,
"
GU
"
:
"
0
"
,
"
GV
"
:
"
音乐达人 101000 时尚达人 105000 旅游达人 106000 摄影达人 112000 舞蹈达人 116000
"
,
"
GW
"
:
"
0
"
,
"
GX
"
:
""
,
"
GY
"
:
"
0
"
,
"
GZ
"
:
"
0
"
,
"
HA
"
:
"
http://daren4.store.qq.com/city/7c8c3001014d7e2ecf5662efbf1a2302p/1/2
"
,
"
HB
"
:
"
http://daren1.store.qq.com/city/2931e30a6b4519ee62f5c4ab4bac94cbv/1/2
"
,
"
HC
"
:
"
440203
"
,
"
HD
"
:
"
0
"
,
"
HE
"
:
"
0
"
,
"
HF
"
:
""
,
"
EX
"
:
""
,
"
DX
"
:
"
0
"
,
"
TX
"
:
""
},

{

"
RQ
"
:
"
1189872826
"
,
"
MD
"
:
"
569867770
"
,
"
ID
"
:
""
,
"
XT
"
:
"
1000000
"
,
"
DT
"
:
"
1221702571
"
,
"
TI
"
:
"
当H5爱上N1
"
,
"
UR
"
:
"
http://city.qzone.qq.com/html/user/guest.htm#uin=569867770
"
,
"
QQ
"
:
"
569867770
"
,
"
TA
"
:
""
,
"
CL
"
:
""
,
"
GA
"
:
"
空间算唔算? QQ游戏
"
,
"
GB
"
:
"
19002200
"
,
"
GC
"
:
"
530
"
,
"
GD
"
:
"
广东 韶关
"
,
"
GE
"
:
"
广东 韶关
"
,
"
GF
"
:
"
1
"
,
"
GH
"
:
"
1984
"
,
"
GI
"
:
"
3
"
,
"
GJ
"
:
"
2
"
,
"
GK
"
:
"
42
"
,
"
GL
"
:
"
3
"
,
"
GM
"
:
"
173
"
,
"
GN
"
:
"
6
"
,
"
GO
"
:
"
3
"
,
"
GP
"
:
"
2
"
,
"
GQ
"
:
"
1
"
,
"
GR
"
:
"
1
"
,
"
GS
"
:
"
0
"
,
"
GT
"
:
"
1
"
,
"
GU
"
:
"
1
"
,
"
GV
"
:
"
汽车达人 104000 游戏达人 107000 体育达人 115000 动漫达人 118000 篮球达人 115001
"
,
"
GW
"
:
"
0
"
,
"
GX
"
:
"
127029|广东,韶关,浈江区,,金源网吧|163971|广东,韶关,武江区,,五月花网络休闲会所|127029|广东,韶关,浈江区,,金源网吧
"
,
"
GY
"
:
"
2
"
,
"
GZ
"
:
"
84
"
,
"
HA
"
:
"
http://daren2.store.qq.com/city/fd2c91ba6ad3e3762c8450dd933e5f46p/1/2
"
,
"
HB
"
:
"
http://daren3.store.qq.com/city/dcfbb28121e43bd0abfcc31945314d36v/1/2
"
,
"
HC
"
:
"
440203
"
,
"
HD
"
:
"
440203
"
,
"
HE
"
:
"
127029
"
,
"
HF
"
:
"
127029 163971 127029
"
,
"
EX
"
:
""
,
"
DX
"
:
"
0
"
,
"
TX
"
:
""
}],
"
CorrectPin
"
: [],
"
SimilarWords
"
: []}});

细细研究上面的字段,就可以发现里面的数据对应情况了,如QQ对应就是QQ号码(呵呵,废话),下面是我分析的一些说明,供参考,同时希望大家能够分析更多的字段信息出来:
TI:昵称
UR:详细介绍
QQ:号码
GD:想认识的人来自
GM:身高
GV:达人类型
HA:头像链接
HC:居住地
GH:出生年份
GF: 0女、1男
有了这些内容,我就基本上可以获取到一些有用的信息了。

通过修改截取数据的内容和实体类信息的构成,数据处理依然可以使用我原来的代码
List
<
QQData
>
entities
=

new
List
<
QQData
>
();


try

{
entities

=
(List
<
QQData
>
)JavaScriptConvert.DeserializeObject(json,
typeof
(List
<
QQData
>
));
}

catch
(Exception ex)
{
LogHelper.Error(ex);
}

希望大家能够多加讨论,获取更多有意义的数据和接口信息。

如果大家看过我的随笔文章《
查询控件、分页控件、页面展示控件,我的Web开发三大得力助手
》相信大家都对Web中的查询控件、页面展示控件有很多感触,现在我这两个发布两个Winform版本的相似控件:
Winfrom下的查询控件和内容展示控件。


首先我们回顾一下Web的查询控件和内容展示控件先。

WEB查询控件
1. 根据设定的字段属性在界面呈现相应的说明及控件
2. 支持下拉列表之间的联动,支持输入数据的验证操作。
3. 支持查询历史记录记忆功能
4. 支持日期控件的集成
5. 支持移动省公司界面样式集成


WEB页面展示控件

1. 支持查看、增加、编辑三种类型的页面展现
2. 根据设定的字段属性在界面呈现相应的说明及控件
3. 支持布局和样式修改
4. 支持日期控件的集成
5. 支持移动省公司界面样式集成

下面我来介绍下Winform下的两个控件。

Winfrom下的查询控件和内容展示控件和Web的属性和基本框架是一样的,都是根据字段信息,自动构筑UI,并提供对数据的验证,下拉列表联动等,以便减少界面代码和界面布局导致的工作量增加。

做这两个控件的主要目的是减少代码,并利于代码生成工具Database2Sharp自动生成UI内容(WEB和Winform界面),相当于把界面呈现的逻辑进行了封装。





虽然和Web界面的控件使用方法差不多,我们还是来展示下相关的代码把,这样有助于了解控件的使用方面。

查询控件窗体的部分代码:


private

void
InitSearch()
{
SearchControl1.Dock

=
DockStyle.Fill;

//
SearchControl1.PanelBorderStyle = TableLayoutPanelCellBorderStyle.Single;



this
.groupBox1.Controls.Add(SearchControl1);


this
.SearchControl1.OutSQLValueChanged
+=

new
OutSQLChangedHandle(SearchControl1_OutSQLValueChanged);

this
.SearchControl1.OnAddNew
+=

new
AddNewHandler(SearchControl1_OnAddNew);

this
.SearchControl1.OnDelete
+=

new
DeleteHandler(SearchControl1_OnDelete);

Button appendButton

=
CreateButton(
"
btnAppended
"
,
"
其他
"
);

this
.SearchControl1.AppendedButtons
=

new
Button[] { appendButton };

FieldInfo nameInfo

=

new
FieldInfo(
"
Name
"
,
"
姓名
"
, FieldType.String);

FieldInfo cityInfo

=

new
FieldInfo(
"
City
"
,
"
城市
"
, FieldType.String);
cityInfo.Width

=

100
;
cityInfo.Items

=

new
CListItem[] {
new
CListItem(
"
北京市
"
,
"
北京
"
),
new
CListItem(
"
广州
"
),
new
CListItem(
"
成都
"
) };
cityInfo.TargetFieldName

=

"
Area
"
;
cityInfo.OnFillItem

+=

new
AddItemHandler(
this
.OnFillItem);

FieldInfo areaInfo

=

new
FieldInfo(
"
Area
"
,
"
地区
"
, FieldType.String);
areaInfo.Items

=

new
CListItem[
0
];

FieldInfo manInfo

=

new
FieldInfo(
"
Man
"
,
"
是否男性
"
, FieldType.Boolean);
FieldInfo birthInfo

=

new
FieldInfo(
"
Birthday
"
,
"
出生日期
"
, FieldType.DateTime);
FieldInfo ageInfo

=

new
FieldInfo(
"
Age
"
,
"
年龄
"
, FieldType.Numeric);


this
.SearchControl1.SearchFields
=

new
FieldInfo[] { nameInfo, cityInfo, areaInfo, manInfo, birthInfo, ageInfo };

this
.SearchControl1.RowControls
=

3
;

this
.SearchControl1.ShowAddNew
=

true
;

this
.SearchControl1.LabelHorizontalAlign
=
System.Windows.Forms.VisualStyles.HorizontalAlign.Right;

this
.SearchControl1.InSQL
=

"
Select * from Test
"
;

BindData();
}


private

void
BindData()
{

using
(SqlConnection conn
=

new
SqlConnection(CONNECTION_STRING))
{
conn.Open();


string
sql
=

this
.SearchControl1.OutSQL;
SqlCommand command

=

new
SqlCommand(sql, conn);

foreach
(
string
key
in

this
.SearchControl1.PagerParameters.Keys)
{
command.Parameters.Add(

new
SqlParameter(key,
this
.SearchControl1.PagerParameters[key]));
}

SqlDataAdapter adapter

=

new
SqlDataAdapter(command);
DataSet ds

=

new
DataSet();
adapter.Fill(ds,

"
test
"
);


this
.dataGridView1.DataSource
=
ds.Tables[
0
];
}


页面展示控件的窗体部分代码:


private

void
InitEditControl()
{
editControl.Dock

=
DockStyle.Fill;


//
editControl.ControlType = ControlType.Edit;

//
TestInfo info = new TestInfo();

//
info.Name = "wuhuacong";

//
editControl.EntityObject = info;



FieldInfo nameInfo

=

new
FieldInfo(
"
Name
"
,
"
姓名
"
, FieldType.String);
nameInfo.IsRequired

=

true
;
nameInfo.ToolTip

=

"
请输入用户名称
"
;
nameInfo.ColumnSpan

=

2
;
nameInfo.Width

=

400
;

//
nameInfo.MaxLength = 255;

//
nameInfo.TextColumns = 100;

//
nameInfo.TextRows = 2;

//
nameInfo.Enabled = false;


nameInfo.IsMultiLine
=

true
;

//
if (editControl.ControlType != ControlType.Add)

//
{

//
nameInfo.Enabled = false;
//
设置“名称”不可编辑

//
}



FieldInfo cityInfo

=

new
FieldInfo(
"
City
"
,
"
城市
"
, FieldType.String);
cityInfo.Items

=

new
CListItem[] {
new
CListItem(
"
北京市
"
,
"
北京
"
),
new
CListItem(
"
广州
"
),
new
CListItem(
"
成都
"
),
new
CListItem(
"
武汉
"
) };
cityInfo.TargetFieldName

=

"
Area
"
;
cityInfo.OnFillItem

=

new
AddItemHandler(
this
.AddItem);
cityInfo.ColumnSpan

=

2
;

FieldInfo areaInfo

=

new
FieldInfo(
"
Area
"
,
"
地区
"
, FieldType.String);
areaInfo.Items

=

new
CListItem[
0
];

FieldInfo manInfo

=

new
FieldInfo(
"
Man
"
,
"
是否男性
"
, FieldType.Boolean);
manInfo.Items

=

new
CListItem[] {
new
CListItem(
"
男性
"
,
"
True
"
),
new
CListItem(
"
女性
"
,
"
False
"
) };
manInfo.DefaultValue

=

"
False
"
;

FieldInfo birthInfo

=

new
FieldInfo(
"
Birthday
"
,
"
出生日期
"
, FieldType.DateTime);
birthInfo.IsRequired

=

true
;
birthInfo.DefaultValue

=

"
2009-1-1
"
;
birthInfo.CustomFormat

=

"
yyyy-MM-dd
"
;

FieldInfo ageInfo

=

new
FieldInfo(
"
Age
"
,
"
年龄
"
, FieldType.Numeric);

//
ageInfo.CustomFormat = "#.##";



FieldInfo favoriteInfo

=

new
FieldInfo(
"
Favorites
"
,
"
兴趣爱好
"
, FieldType.String);
favoriteInfo.Items

=

new
CListItem[] {
new
CListItem(
"
篮球
"
),
new
CListItem(
"
足球
"
),
new
CListItem(
"
网球
"
),

new
CListItem(
"
乒乓球
"
),
new
CListItem(
"
台球
"
,
"
t
"
),
new
CListItem(
"
羽毛球
"
,
"
y
"
) };
favoriteInfo.ItemsType

=
ListControlType.CheckBoxList;
favoriteInfo.ColumnSpan

=

2
;
favoriteInfo.Width

=

300
;

//
favoriteInfo.DefaultValue = "篮球,乒乓球,t,y";



editControl.EidtFields

=

new
FieldInfo[] { nameInfo, cityInfo, areaInfo, manInfo, birthInfo, ageInfo, favoriteInfo };
editControl.RowControls

=

2
;
//
默认一行放置2个控件组

//
editControl.ContentControlWidth = 200;
//
所有控件统一宽度


editControl.LabelHorizontalAlign
=
HorizontalAlign.Right;
//
标签文本对其方式


editControl.PanelBorderStyle
=
TableLayoutPanelCellBorderStyle.None;
//
表格样式



editControl.OnCancel

=

new
CancelHandler(
this
.OnCancel);
editControl.OnSaveData

=

new
SaveDataHandler(
this
.OnSaveData);

this
.groupBox1.Controls.Add(editControl);
}


private

void
Form1_Load(
object
sender, EventArgs e)
{
InitEditControl();
}


下面附上使用的例子,可以下载下来慢慢研究,其中Database.sql是测试例子的数据库脚本,允许例子前,请初始化数据库。

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

希望大家使用愉快,下一步我将集成UI的自动生成到Database2Sharp中,和Web一样,利用查询控件和分页控件、页面展示控件完成UI的生成。

用过C#内置的SMTP类的朋友大概知道,使用它发送邮件的时候,有时候总是出现莫名奇妙的错误,有时候可以发送成功,有时候说用户帐号验证失败,即使你设置了帐号验证信息,问题依旧,特别是在你使用QQ邮箱(好像163的用SMTP发送比较正常),基本上使用SMTP对象来发送邮件是不可能的事情,后来查询了一些资料,说QQ的协议好像是ESMTP协议了,也就是加强版的SMTP协议,不知道是不是,反正用QQ邮件的人比较多,发送的问题就比较突出了。

特别是我的软件“QQ号码采集及邮件发送系统”,之前一直使用SMTP类来处理邮件的发送,客户反映QQ邮件发送不成功的问题就特别突出,但是当时不知道如何处理这个问题,晚上找了很多资料,问题依旧,甚是头痛。先看看我这个邮件发送软件的界面先。

这个软件目前已经实现了ESMTP协议的批量发送功能了,测试发现163也支持ESMTP协议,估计大多数的SMTP提供商都是支持这个接口的了,因为对他们来说这个是更加安全、更少垃圾邮件的协议,好像有的像我们日常所说的“实名制”规则一样。
和SMTP类发送邮件不同,ESMTP是通过以流方式向服务器发送TCP/IP命令,进而获得交互响应的模式进行的,如要连接SMTP服务器,首先通过下面代码进行连接。

//
连接网络



try

{
tc

=

new
TcpClient(mailserver, mailserverport);
}

catch
(Exception e)
{
errmsg

=
e.ToString();

return

false
;
}

ns

=
tc.GetStream();


///

<summary>


///
接收SMTP服务器回应

///

</summary>



protected

string
RecvResponse()
{

int
StreamSize;

string
ReturnValue
=

"
false
"
;

byte
[] ReadBuffer
=

new

byte
[
4096
];


try

{
StreamSize

=
ns.Read(ReadBuffer,
0
, ReadBuffer.Length);
}

catch

{
errmsg

=

"
网络连接错误
"
;

return
ReturnValue;
}


if
(StreamSize
==

0
)
{

return
ReturnValue;
}

else

{
ReturnValue

=
Encoding.Default.GetString(ReadBuffer).Substring(
0
, StreamSize).Trim(); ;

//
logs+=ReturnValue;



return
ReturnValue;
}
}

一旦获得正常的响应后,就一步步向服务器发送请求命令或者数据来完成其他操作的。
发送命令的函数就是写入网络流的方式,通过下面的命令实现的

///

<summary>


///
发送SMTP命令

///

</summary>




protected

bool
SendCommand(
string
Command)
{

byte
[] WriteBuffer;

if
(Command
==

null

||
Command.Trim()
==

""
)
{

return

true
;
}

//
logs+=Command;


WriteBuffer
=
Encoding.Default.GetBytes(Command);

try

{
ns.Write(WriteBuffer,

0
, WriteBuffer.Length);
}

catch

{
errmsg

=

"
网络连接错误
"
;

return

false
;
}

return

true
;
}

ESMTP的特点就是需要验证用户,一旦验证用户通过后,用户就可以通过发送各类命令或者数据了,下面简单列出几个命令格式,其他的大家可以查询相关资料进行完成。

//
发件人信息


SendBufferstr
=

"
MAIL FROM:<
"

+
From
+

"
>
"

+
enter;

if
(
!
Dialog(SendBufferstr,
"
发件人地址错误,或不能为空
"
))

return

false
;


//
收件人列表


SendBuffer.Clear();

foreach
(String item
in
Recipient)
{
SendBuffer.Add(

"
RCPT TO:<
"

+
item
+

"
>
"

+
enter);
RecipientName

=
item;
//
这里其实只能支持一个收件人


}

if
(
!
Dialog(SendBuffer,
"
收件人地址有误
"
))

return

false
;

使用这个发送邮件,连最难对付的QQ邮箱也飞快的接收到了我的邮件了,不过大家不要滥发邮件,毕竟“实名制”的方式就是要对后果负责的。呵呵。

由于时间和研究方向的关系,虽然我的开发和工作,一直离不开我的代码生成工具,但是近来一直很少对Database2Sharp的功能进行更新了,最近发现我的一位同事在研究数据库文档的生成方面的内容,获得了很好的灵感,发现我的代码生成工具中数据库文档部分应该更新了,同时对整个数据库信息的模型做了一些完善,增加了视图字段信息的检索及显示,存储过程参数列表的获取,引入了Oracle数据库包信息的对象模型。这些内容都直接反映到数据库文档的生成中。
另外结合了上次博客中介绍到了《
发布一个实体类属性生成小工具,给开发加点料
》中提高的属性生成功能,集成到我的代码生成工具中。下面是我这次更新的一个日志:
增加实体类属性代码生成;增加自动生成数据库表文档(完善)、存储过程和视图文档的生成;增加Oracle的包信息展示;增加视图字段的展示;修正SqlServer和Oracle数据检索的错误问题;并修正一些界面的小问题。版本升级为6.0
Database2Sharp软件介绍及下载地址:
http://www.iqidi.com/Database2Sharp.htm
由于最近一直在Oracle平台上做开发,就发布一些Oracle相关的代码生成工具的截图吧,虽然SqlServer2005/SqlServer2000我也同时进行了测试的。

Oracle表信息界面如下所示:


Oracle视图信息界面(比原来的版本增加了视图字段的显示哦):


Oracle包的信息列表及展示(新增内容):


实体类属性生成功能界面:



数据库文档生成功能及生成的文档格式介绍



表数据的文档格式如下所示:


视图数据的文档格式如下所示:


存储过程的文档格式如下所示:


包数据的文档格式如下所示:


希望大家提出宝贵的意见。

在处理
Database2Sharp混淆的时候,经常会出现一些莫名奇妙的错误,而没有混淆的程序是正常的,开始基本上定位在反射方面的原因,因为反射经过混淆的程序集,可能会出现问题。

由于我是使用dotfuscator来进行混淆的,正常混淆很多没有使用反射操作的程序,一般都是没有问题的,因此偶尔出现问题的时候,就晚上找找看看有没有这方面的介绍文章。
看到一篇文章介绍了这方面的原因:
http://www.cnblogs.com/jeffreytan/archive/2004/11/11/62724.html
虽然是介绍了了
dotfuscator的原理知识,但是作者把由于dotfuscator导致应用反射操作出现的问题,阐述的还是比较清楚了,按照其操作,果然解决了原来在dotfuscator出现的问题。
Dotfuscator里面是可以设置将哪些符号改名的。默认情况下,它会将assembly里面的所有符号都改名,你可以在Dotfuscator的
"
Rename
"
选项卡处设定你所想要禁止Rename的符号,具体使用方法请参考Dotfuscator的帮助文档。
如果你使用默认设置Rename所有的符号,这会导致外面想要使用此assembly的代码出问题,可以证明如下:
我的工程里面有一个公有的方法

public

void
testmethod()
{
MessageBox.Show(

"
testmethod
"
);
}
将其生成的assembly使用Dotfuscator改变后。如果你使用以下Reflection代码调用原来assembly里面的testmethod方法,你将会成功,但是如果调用混淆后的assembly,你将会得到异常。

还有这段是说明如何解决问题的
在混淆前,你的Assembly将会执行成功。在混淆后(注意,使用默认设置,将public的方法也混淆掉),你点击Button1你将会得到运行时的UnhandledException,内部就是System.ArgumentNullException: Value cannot be
null
.
这个证明代码中的

"
reflectiontest.Form1
"

"
testmethod
"
并没有被混淆掉。

对于在VS.net IDE里面添加对这个Assembly的引用,它基本跟Reflection没有什么区别,只不过一个是在运行时动态绑定类型信息和调用,而另一个是在设计时就从Assembly里面调用提取了类型信息。Assembly的类型信息是存放在Metadata里面的,这两种方式都需要提取Metadata的信息,所以在IDE里面添加公有类名,命名空间名被混淆过的Assembly是会失败的,你可以将一个默认混淆过的Assembly添加到Toolbar中试试。但是,你可以控制Dotfuscator保留所有的公有符号不混淆,这样你的Assembly就可以正常添加,而不会出问题。具体,你可以这样保留不混淆Public符号:

在Rename选项卡里面点击

"
Add Type
"
,然后Name写上
"
*
"
,然后在右边的Spec列表框中选择
"
+Public
"

由于我使用了反射构建不同的数据库加载类,如SqlServer、Oracle、MySql的,因此要根据不同加载不同的程序集信息,但是很奇怪,SqlServer的类加载成功,可以列出数据库信息,而Oracle的类确加载不了,获取不到所需的信息。
如混淆,那么列出Oracle数据库的时候,是一片空白,跟踪代码,发现反射构建程序对象的时候有问题。


我的反射加载代码如下:

try

{
DatabaseSetting[] settings

=
DatabaseConfig.ReadSettings();

foreach
(DatabaseSetting db
in
settings)
{

if
(databaseType
==
db.DatabaseType)
{
objType

=
Assembly.Load(db.AssemblyName).CreateInstance(db.AssemblyType);
listDataInstance

=
objType
as
IListData;

if
(listDataInstance
!=

null
)
{
listDataInstance.ConnectString

=
db.ConnectString;
}

break
;
}
}
}

catch
(FileNotFoundException nfe)
{
log.Error(nfe);

throw
;
}

根据上面作者提到的操作,
在Rename选项卡里面点击
"
Add Type
"
,然后Name写上
"
*
"
,然后在右边的Spec列表框中选择
"
+Public
"
测试,果然OK,问题解决了,获取到的数据库信息如下所示。


希望对也使用Dotfuscator来混淆程序,碰到相同问题的朋友有帮助。