关于a标签的onclick与href的执行顺序

作者:freethy 发布于:2016-5-13 10:00 Friday

  • onclick的事件被先执行,其次是href中定义的(页面跳转或者javascript)
  • 同时存在两个定义的时候(onclick与href都定义了),如果想阻止href的动作,在onclick必须加上return false;
  • 在href中定义的函数如果有返回值的话,当前页面的内容将被返回值代替

评论(0) 引用(0) 浏览(1338)

【P2P网络】BitTorrent的DHT协议(译自官方版本)

作者:freethy 发布于:2016-3-1 16:22 Tuesday

译者前序

DHT协议早在2005年就已经成为了官方BitTorrent协议的一部份,但是我竟然一直没有找到国内的官方翻译稿,所以将其进行翻译,若文中错误,欢迎各位指正。

其次,若想彻底理解DHT协议的原理,建议各位阅读Kademlia协议,在本博客中,有其翻译稿,参见DHT协议基础12.

本文英文版官方地址:http://www.bittorrent.org/beps/bep_0005.html


DHT协议

BitTorrent使用一种叫做分布式哈希表(distributedsloppy hashtable)的技术,来实现在无trackertorrent文件中peer的联系信息存储。这个时候,每个peer都是一个tracker。这个协议是基于Kademila协议的,并且在UDP协议基础上实现。

请注意本文档所使用的术语以免引起混淆。peer”是一个实现了BT协议,且正在监听TCP端口的client/servernode”是实现了DHT协议的,且正在监听UDP端口的client/serverDHTnodes组成并保存peer的位置信息。BitTorrent客户端也包括DHTnode,这个DHTnode主要是用来联系DHT中的其他nodes,以得peer的位置信息,从而通过BitTorrent协议下载。

概述

每一个node都有一个全局的唯一标识nodeID”NodeIDS的产生是随机的,且使用与BitTorrentinfohashes相同的160-bit空间。distancemetric”用来比较2nodeIDs或者nodeIDinfohash的接近程度。Nodes必须维护一个路由表,其中保存了一部分其他nodes的联系信息。越接近自身节点时,路由表的信息会更加详细。nodes保存了很多接近自己的节点,但是离自己很远的节点的联系信息确知道得很少。

Kademlia中,distancemetric”采用XOR异或计算,并转换为一个无符号整数。distance(A,B)= |A xor B| ,并且距离越小表示2个节点越接近。

当一个node想得到某个torrent文件的peers,它首先使用distancemetric来比较torrent文件的info_hash和路由表中节点的nodeID。接下来向路由表中nodeIDinfo_hash最接近的那些节点发送请求,得到当前正在下载这个torrent文件数据的peers的联系信息。如果被请求的节点知道这个torrent文件的peers,那么peer的联系信息将包含在回复中。否则,被请求的节点必须返回他的路由表中更接近info_hash得那些节点。原始的请求node不断向新获得的那些node中,更接近目标info_hash的那些node发送请求,直到不能获得更近的nodes。当查找结束时,client将自己的信息作为一个peer插入到在刚才请求中给出回复的那些节点中,nodeidinfo_hash最接近的哪个节点上,这样,哪个节点又多保存了一个peer信息。

在请求peers的时候,对方给我们的回复必须还包含一个不透明的令牌,我们称他为token”。这样当我们宣布我们正在下载某个torrent,想让对方保存我们的信息时,我们必须使用对方向我们发送的最近的一个token。这样当我们宣布我们在下载一个torrent时,被请求的node检查这个tokenIP是否与之前他们向我们回复的一样。这样是为了防止恶意的攻击。由于token仅仅由请求的节点返回,所以我们不规定他的具体实现。但是token必须有一个可接受的时间范围,超过这个时间,token将失效。在BitTorrent的实现中,token是在IP地址后面连接一个secret(可以视为一个随机数),这个secret每五分钟改变一次,其中token在十分钟以内是可接受的。

路由表

每一个node维护一个路由表保存已知的好节点。这些路由表中的nodes被作为DHT请求的起始节点。路由表中的nodes是在不断的向其他node请求过程中,对方节点回复的。

并不是我们在请求过程中收到得节点都是平等的,有的node是好的,而有的node是死掉的。很多使用DHT协议的nodes都可以发送请求并接收回复,但是不能主动回复其他节点的请求(我认为这是由于防火墙或者NAT的原因)。对每一个node的路由表,只包含好的nodes是很重要的。好的node是指在过去的15分钟以内,曾经对我们的某一个请求给出过回复的节点;或者曾经对我们的请求给出过一个回复(不用在15分钟以内),并且在过去的15分钟给我们发送过请求。上述两种情况都可将node视为好的node。在15分钟之后,对方没有上述2种情况发生,这个node将变为可疑的。当nodes不能给我们的一系列请求给出回复时,这个节点将变为坏的。相比未知状态的nodes,我们将给好的节点更高的优先权。

路由表覆盖从02160完整的nodeID空间。路由表又被划分为buckets(),每一个bucket包含一个子部分的nodeID空间。一个空的路由表只有一个bucket,它的ID范围从min=0max=2160。当一个nodeIDN”node插入到表中时,它将被放到ID范围在min<= N <maxbucket中。一个空的路由表只有一个bucket所以所有的node都将被放到这个bucket中。每一个bucket最多只能保存Knodes,当前K=8。当一个bucket放满了好的nodes之后,将不再允许新的节点加入,除非我们自身的nodeID在这个bucket的范围内。在这样的情况下,这个bucket将被分裂为2个新的buckets,每一个新桶的范围都是原来旧桶的一半。原来旧桶中的nodes将被重新分配到这两个新的buckets中。如果是一个只有一个bucket的新表,这个包含整个范围的bucket将总被分裂为2个新的buckets,第一个的覆盖范围从0..2159,第二个的范围从2159..2160

bucket装满了好的nodes,那么新的node将被丢弃。一旦bucket中的某一个node变为了坏的node,那么我们就用新的node来替换这个坏的node。如果bucket中有在15分钟内都没有活跃过的节点,我们将这样的节点视为可疑的节点,这时我们向最久没有联系的节点发送ping。如果被pinged的节点给出了回复,那么我们向下一个可疑的节点发送ping,不断这样循环下去,直到有某一个node没有给出ping的回复,或者当前bucket中的所有nodes都是好的(也就是所有nodes都不是可疑nodes,他们在过去15分钟内都有活动)。如果bucket中的某个node没有对我们的ping给出回复,我们最好再试一次(再发送一次ping,因为这个node也许仍然是活跃的,但由于网络拥塞,所以发生了丢包现象,注意DHT的包都是UDP),而不是立即丢弃这个node或者直接用新node来替代它。这样,我们得路由表将充满稳定的长时间在线的nodes

每一个bucket都应该维持一个lastchange”字段来表明bucket中的nodes有多新鲜。当一个bucket中的nodeping并给出了回复,或者一个node被加入到了bucket,或者一个node被一个新的node所替代,bucketlastchanged”字段都应当被更新。如果一个bucketlastchange”在过去的15分钟内都没有变化,那么我们将更新它。这个更新bucket操作是这样完成的:从这个bucket所覆盖的范围中随机选择一个ID,并对这个ID执行find_nodes查找操作。常常收到请求的nodes通常不需要常常更新自己的buckets,反之,不常常收到请求的nodes常常需要周期性的执行更新所有buckets的操作,这样才能保证当我们用到DHT的时候,里面有足够多的好的nodes

在第一个node插入路由表并开始服务后,这个node应该试着查找离自身更近的node,这个查找工作是通过不断的发布find_node消息给越来越近的nodes来完成的,当不能找到更近的节点时,这个扩散工作就结束了。路由表应当被启动工作和客户端软件保存(也就是启动的时候从客户端中读取路由表信息,结束的时候客户端软件记录到文件中)。

BitTorret协议扩展

BitTorrent协议已经被扩展为可以在通过tracker得到的peer之间互相交换nodeUDP端口号(也就是告诉对方我们的DHT服务端口号),在这样的方式下,客户端可以通过下载普通的种子文件来自动扩展DHT路由表。新安装的客户端第一次试着下载一个无tracker的种子时,它的路由表中将没有任何nodes,这是它需要在torrent文件中找到联系信息。

peers如果支持DHT协议就将BitTorrent协议握手消息的保留位的第八字节的最后一位置为1。这时如果peer收到一个handshake表明对方支持DHT协议,就应该发送PORT消息。它由字节0x09开始,payload的长度是2个字节,包含了这个peerDHT服务使用的网络字节序的UDP端口号。当peer收到这样的消息是应当向对方的IP和消息中指定的端口号的node发送ping。如果收到了ping的回复,那么应当使用上述的方法将新node的联系信息加入到路由表中。

Torrent文件扩展

一个无trackertorrent文件字典不包含announce关键字,而使用一个nodes关键字来替代。这个关键字对应的内容应该设置为torrent创建者的路由表中K个最接近的nodes。可供选择的,这个关键字也可以设置为一个已知的可用节点,比如这个torrent文件的创建者。请不要自动加入router.bittorrent.comtorrent文件中或者自动加入这个node到客户端路由表中。

nodes= [["<host>", <port>], ["<host>",<port>], ...]

nodes= [["127.0.0.1", 6881], ["your.router.node",4804]]

KRPC协议

KRPC协议是由B编码组成的一个简单的RPC结构,他使用UDP报文发送。一个独立的请求包被发出去然后一个独立的包被回复。这个协议没有重发。它包含3种消息:请求,回复和错误。对DHT协议而言,这里有4种请求:pingfind_node,get_peers,announce_peer

一个KRPC消息由一个独立的字典组成,其中有2个关键字是所有的消息都包含的,其余的附加关键字取决于消息类型。每一个消息都包含t关键字,它是一个代表了transactionID的字符串类型。transactionID由请求node产生,并且回复中要包含回显该字段,所以回复可能对应一个节点的多个请求。transactionID应当被编码为一个短的二进制字符串,比如2个字节,这样就可以对应2^16个请求。另一个每个KRPC消息都包含的关键字是y,它由一个字节组成,表明这个消息的类型。y对应的值有三种情况:q表示请求,r表示回复,e表示错误。

联系信息编码

Peers的联系信息被编码为6字节的字符串。又被称为"CompactIP-address/port info",其中前4个字节是网络字节序的IP地址,后2个字节是网络字节序的端口。

Nodes的联系信息被编码为26字节的字符串。又被称为"Compactnode info",其中前20字节是网络字节序的nodeID,后面6个字节是peers"CompactIP-address/port info"

请求

请求,对应于KPRC消息字典中的y”关键字的值是q”,它包含2个附加的关键字q”a”。关键字q”是一个字符串类型,包含了请求的方法名字。关键字a”一个字典类型包含了请求所附加的参数。

回复

回复,对应于KPRC消息字典中的y”关键字的值是r”,包含了一个附加的关键字r。关键字r”是一个字典类型,包含了返回的值。发送回复消息是在正确解析了请求消息的基础上完成的。

错误

错误,对应于KPRC消息字典中的y关键字的值是e”,包含一个附加的关键字e。关键字e”是一个列表类型。第一个元素是一个数字类型,表明了错误码。第二个元素是一个字符串类型,表明了错误信息。当一个请求不能解析或出错时,错误包将被发送。下表描述了可能出现的错误码:

错误码

错误描述

201

一般错误

202

服务错误

203

协议错误,比如不规范的包,无效的参数,或者错误的token

204

未知方法

错误包例子:

一般错误={"t":"aa", "y":"e", "e":[201,"A Generic Error Ocurred"]}

B编码=d1:eli201e23:AGenericErrorOcurrede1:t2:aa1:y1:ee

DHT请求

所有的请求都包含一个关键字id,它包含了请求节点的nodeID。所有的回复也包含关键字id,它包含了回复节点的nodeID

ping

最基础的请求就是ping。这时KPRC协议中的q”=“ping”Ping请求包含一个参数id,它是一个20字节的字符串包含了发送者网络字节序的nodeID。对应的ping回复也包含一个参数id,包含了回复者的nodeID

参数: {"id"&nbsp;: "<querying nodes id>"}

回复:{"id"&nbsp;: "<queried nodes id>"}

报文包例子

ping请求={"t":"aa", "y":"q","q":"ping", "a":{"id":"abcdefghij0123456789"}}

B编码=d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe

回复={"t":"aa", "y":"r", "r":{"id":"mnopqrstuvwxyz123456"}}

B编码=d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

find_node

Findnode被用来查找给定IDnode的联系信息。这时KPRC协议中的q=“find_node”find_node请求包含2个参数,第一个参数是id,包含了请求nodenodeID。第二个参数是target,包含了请求者正在查找的nodenodeID。当一个node接收到了find_node的请求,他应该给出对应的回复,回复中包含2个关键字idnodesnodes是一个字符串类型,包含了被请求节点的路由表中最接近目标nodeK(8)个最接近的nodes的联系信息。

参数: {"id"&nbsp;: "<querying nodes id>","target"&nbsp;: "<id of target node>"}

回复:{"id"&nbsp;: "<queried nodes id>","nodes"&nbsp;: "<compact node info>"}

报文包例子

find_node请求={"t":"aa", "y":"q","q":"find_node", "a":{"id":"abcdefghij0123456789","target":"mnopqrstuvwxyz123456"}}

B编码=d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe

回复={"t":"aa", "y":"r", "r":{"id":"0123456789abcdefghij", "nodes":"def456..."}}

B编码=d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re

get_peers

Getpeerstorrent文件的info_hash有关。这时KPRC协议中的q”=”get_peers”get_peers请求包含2个参数。第一个参数是id,包含了请求nodenodeID。第二个参数是info_hash,它代表torrent文件的infohash。如果被请求的节点有对应info_hashpeers,他将返回一个关键字values,这是一个列表类型的字符串。每一个字符串包含了"CompactIP-address/portinfo"格式的peers信息。如果被请求的节点没有这个infohashpeers,那么他将返回关键字nodes,这个关键字包含了被请求节点的路由表中离info_hash最近的Knodes,使用"Compactnodeinfo"格式回复。在这两种情况下,关键字token都将被返回。token关键字在今后的annouce_peer请求中必须要携带。Token是一个短的二进制字符串。

参数: {"id"&nbsp;: "<querying nodes id>","info_hash"&nbsp;: "<20-byte infohash of targettorrent>"}

回复:{"id"&nbsp;: "<queried nodes id>","token"&nbsp;:"<opaque write token>","values"&nbsp;: ["<peer 1 info string>","<peer 2 info string>"]}

or:{"id"&nbsp;: "<queried nodes id>","token"&nbsp;:"<opaque write token>","nodes"&nbsp;: "<compact node info>"}

报文包例子

get_peers请求={"t":"aa", "y":"q","q":"get_peers", "a":{"id":"abcdefghij0123456789","info_hash":"mnopqrstuvwxyz123456"}}

B编码=d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe

回复peers ={"t":"aa", "y":"r", "r":{"id":"abcdefghij0123456789", "token":"aoeusnth","values": ["axje.u", "idhtnm"]}}

B编码=d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re

回复最接近的nodes= {"t":"aa", "y":"r", "r":{"id":"abcdefghij0123456789", "token":"aoeusnth","nodes": "def456..."}}

B编码=d1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re

announce_peer

这个请求用来表明发出announce_peer请求的node,正在某个端口下载torrent文件。announce_peer包含4个参数。第一个参数是id,包含了请求nodenodeID;第二个参数是info_hash,包含了torrent文件的infohash;第三个参数是port包含了整型的端口号,表明peer在哪个端口下载;第四个参数数是token,这是在之前的get_peers请求中收到的回复中包含的。收到announce_peer请求的node必须检查这个token与之前我们回复给这个节点get_peerstoken是否相同。如果相同,那么被请求的节点将记录发送announce_peer节点的IP和请求中包含的port端口号在peer联系信息中对应的infohash下。

参数: {"id": "<querying nodes id>", "info_hash" :"<20-byte infohash of target torrent>", "port": <port number>, "token" : "<opaque token>"}

回复: {"id": "<queried nodes id>"}

报文包例子

announce_peers请求={"t":"aa", "y":"q","q":"announce_peer", "a":{"id":"abcdefghij0123456789","info_hash":"mnopqrstuvwxyz123456", "port":6881, "token": "aoeusnth"}}

B编码=d1:ad2:id20:abcdefghij01234567899:info_hash20:<br />

mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe

回复={"t":"aa", "y":"r", "r":{"id":"mnopqrstuvwxyz123456"}}

B编码=d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

译者注:

在实践观察中发现两种新的消息

1.vote:表示客户端发送速度过快,希望可以减慢

2.v:表示客户端的版本号


--------------------------------------------------------------------------------------------------------

原文链接:http://blog.csdn.net/xxxxxx91116/article/details/7970815

评论(0) 引用(0) 浏览(1185)

SQL Server 根据表名获取表的所有列及属性

作者:freethy 发布于:2015-12-26 11:13 Saturday

实例一:             

select a.name columnname,c.name as typename,case when a.is_nullable =then 'Not Nullelse 'Nullend as nullable,a.*
from sys.columns a , sys.objects b, sys.types c 
where a.object_id= b.object_id and b.name='表名and a.system_type_id=c.system_type_id order by a.column_id

实例二:

select
     c.name as [字段名],t.name as [字段类型]
     ,convert(bit,c.IsNullable)  as [可否为空]
     ,convert(bit,case when exists(select 1 from sysobjects where xtype='PK' and parent_obj=c.id and name in (
         select name from sysindexes where indid in(
             select indid from sysindexkeys where id = c.id and colid=c.colid))) then 1 else 0 end
                 as [是否主键]
     ,convert(bit,COLUMNPROPERTY(c.id,c.name,'IsIdentity')) as [自动增长]
     ,c.Length as [占用字节] 
     ,COLUMNPROPERTY(c.id,c.name,'PRECISION'as [长度]
     ,isnull(COLUMNPROPERTY(c.id,c.name,'Scale'),0as [小数位数]
     ,ISNULL(CM.text,''as [默认值]
     ,isnull(ETP.value,''AS [字段描述]
     --,ROW_NUMBER() OVER (ORDER BY C.name) AS [Row]
from syscolumns c
inner join systypes t on c.xusertype = t.xusertype 
left join sys.extended_properties ETP on ETP.major_id = c.id and ETP.minor_id = c.colid and ETP.name ='MS_Description' 
left join syscomments CM on c.cdefault=CM.id
where c.id = object_id('表名')

 

转自:http://www.cnblogs.com/sydeveloper/archive/2012/12/10/2811544.html

评论(0) 引用(0) 浏览(1406)

如何在Visual Studio中开发自己的代码生成器插件

作者:freethy 发布于:2015-12-24 18:14 Thursday

   Visual Studio是美国微软公司开发的一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等,且所写的目标代码适用于微软支持的所有平台.可以说.NET开发人员离不开它,它可以极大的提高编写软件的效率. Visual Studio作为一个世界级开发工具,当然支持通过插件方式对其功能进行扩展,开发人员可以定制自己的插件来进一步提升Visual Studio的功能.

1 什么是Add In?

  所谓的add-in就是一些被Visual Studio加载到内存中运行的,能给用户提供特定功能的DLL动态链接库. 对于一般的开发情景来说,最常见的add-in用法就是可以通过.NET语言访问 DTE2 对象. DTE2是Visual Studio Automation Model的顶层对象,它具有一组接口和对象可以与 Visual Studio进行交互.DTE2可以做以下这些事情:

  • 访问和调用Visual Studio内置的函数和对象
  • 执行编译
  • 遍历解决方案中的项目
  • 在Visual Studio IDE中定制UI
  • 扩展Visual Studio功能...

2 创建VS Add In项目

  用Visual Studio 2012创建名为MyVisualStudioAddin的项目(根据向导进行设置,这里不赘述),界面如下:

3 核心 Connect 类

  插件入口就是Connect 类,先看一下Connect的类图:

  • Connect 实现外接程序对象的构造函数。请将您的初始化代码置于此方法内。
  • OnConnection 实现 IDTExtensibility2 接口的 OnConnection 方法。接收正在加载外接程序的通知。
  • OnDisconnection 实现 IDTExtensibility2 接口的 OnDisconnection 方法。接收正在卸载外接程序的通知。
  • OnAddInsUpdate 实现 IDTExtensibility2 接口的 OnAddInsUpdate 方法。当外接程序集合已发生更改时接收通知。
  • OnStartupComplete 实现 IDTExtensibility2 接口的 OnStartupComplete 方法。接收宿主应用程序已完成加载的通知。
  • OnBeginShutdown 实现 IDTExtensibility2 接口的 OnBeginShutdown 方法。接收正在卸载宿主应用程序的通知。
  • QueryStatus 实现 IDTCommandTarget 接口的 QueryStatus 方法。此方法在更新该命令的可用性时调用。
  • Exec 实现 IDTCommandTarget 接口的 Exec 方法。此方法在调用该命令时调用。
  • _applicationObject 是DTE2实例,是宿主应用程序的根对象。
  • _addInInstance是当前插件实例,表示此外接程序的对象。

   首先定义一些内部的对象,主要是自定义的命令,如下所示:


相关代码请参考原作者连接!!!

  

关于如何根据数据库结构生成C# Code代码,可以参加此文章.

4 插件发布

  创建了外接程序后,必须先向 Visual Studio 注册此外接程序,然后才能在“外接程序管理器”中激活它。 使用具有 .addin 文件扩展名的 XML 文件来完成此操作。.addin 文件描述了 Visual Studio 在“外接程序管理器”中显示外接程序所需的信息。 在 Visual Studio 启动时,它会查找 .addin 文件位置,获取任何可用的 .addin 文件。 如果找到相应文件,则会读取 XML 文件并向“外接程序管理器”提供在单击外接程序进行启动时所需的信息。使用外接程序向导创建外接程序时,会自动创建一个 .addin 文件。 你也可以使用本主题中的信息手动创建 .addin 文件。我是用Visual Studio2012 所以将.addin文件和对应的dll拷贝到C:\Users\wangming\Documents\Visual Studio 2012\Addins文件下:

  如果发布没有错误,那么重新启动Visual Studio2012后,在项目文件上右击弹出菜单,可以看到下面的界面:

  同时在菜单栏创建了一个JackWang的命令按钮和工具菜单下还添加了一个MyVS外接程序的命令按钮,如下图:

5 代码生成器

  代码生成器(此处用的是yuvalsol的工程,我将其整合到插件中)可以根据用户选择的数据库,选择对应的表,然后生成表结构对应的C#类:

 6 插件卸载

  如果自己定义的插件想卸载怎么办?可参见https://msdn.microsoft.com/en-us/library/ms228765.aspx.

  • 删除插件对应的.addin文件. 默认路径为..\Users\username\My Documents\Visual Studio 2012\Addins\(请根据实际情况查看具体路径)

  • 在 Visual Studio开发人员命令行中, 输入devenv /resetaddin MyVisualStudioAddin.Connect  进行卸载(MyVisualStudioAddin.Connect 是MyVisualStudioAddin.AddIn文件中的FullClassName;

  • 至此, add-in 不会出现在IDE中,卸载完成. 但是要完整去除必须手动删除插件对应的项目文件(如果你再次调试,可能会再次进行注册);

 7 总结

  通过插件机制可以方便的定制VS IDE, 一般软件公司都有自己的一套框架,其代码也有一定的封装,且各不相同,可以通过扩展VS,通过定制的代码生成工具来快速生成符合本公司所需的代码,从而从重复机械的劳动中解放出来(虽然完全自动生成的代码不可能直接能用,但是人工在此基础上进行调整,也提升了代码的编写效率,而且减少类似于拼写/标点等人为的错误点等.

  虽然我们不生产代码,是代码的搬运工,但是正确的打开方式是用代码去帮我们搬运代码!!!

水平有限,望各位园友不吝赐教!如果觉得不错,请点击推荐和关注! 
出处:http://www.cnblogs.com/isaboy/ 
声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

在此向原作者致敬~

评论(0) 引用(0) 浏览(1346)

在windows xp 上执行mono,跳出了“无法定位程序输入点InterlockedCompareExchange64于动态链接库KER”错误。

作者:freethy 发布于:2015-10-23 15:54 Friday

在windows xp 上执行mono,跳出了“无法定位程序输入点InterlockedCompareExchange64于动态链接库KER”错误。



--解决方案:
版本问题已经不支持xp了,但是2.0的分支任然支持着xp,V2.0.6是最新也是最后一个新版本支持xp  下这个版本就好了

评论(0) 引用(0) 浏览(1526)

火狐网页访问https提示安全连接失败

作者:freethy 发布于:2015-9-21 17:53 Monday

使用https访问网站提示错误:‘’在服务器密钥交换握手信息中 SSL 收到了一个弱临时 Diffie-Hellman 密钥。 (错误码: ssl_error_weak_server_ephemeral_dh_key)“
解决方法:
安装插件:https://addons.mozilla.org/en-us/firefox/addon/disable-dhe/ (英文)
 
                https://addons.mozilla.org/en-us/firefox/addon/disable-dhe/ (中文)
安装插件访问即可。

评论(0) 引用(0) 浏览(1938)

c# 获取程序相关目录

作者:freethy 发布于:2015-9-18 12:22 Friday

// 获取程序的基目录。
System.AppDomain.CurrentDomain.BaseDirectory

// 获取模块的完整路径,包含文件名
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

// 获取和设置当前目录(该进程从中启动的目录)的完全限定目录。
System.Environment.CurrentDirectory

// 获取应用程序的当前工作目录,注意工作目录是可以改变的,而不限定在程序所在目录
System.IO.Directory.GetCurrentDirectory()

// 获取和设置包括该应用程序的目录的名称。
System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase

// 获取启动了应用程序的可执行文件的路径。
System.Windows.Forms.Application.StartupPath

// 获取启动了应用程序的可执行文件的路径及文件名
System.Windows.Forms.Application.ExecutablePath

评论(0) 引用(0) 浏览(1409)

MYSQL 备份数据库

作者:freethy 发布于:2015-9-1 15:19 Tuesday

mysqldump -u用户名 -p密码 数据库名 --skip-lock-tables | gzip > c:\aa.sql.zip


评论(0) 引用(0) 浏览(1514)

WebClient 指定Cookies下载页面

作者:freethy 发布于:2015-7-18 15:29 Saturday


            string url = "http://www.xxxx.com/xxx.php?id=123456";
            string cookies = "PHPSESSID=xxx;xxxxxxxxxxxxxxxxxxxxxxxxxx";
           
            WebClient wc = new WebClient();
            wc.Headers.Add("Cookie", cookies);
            wc.Encoding = System.Text.Encoding.UTF8;
            string html = wc.DownloadString(url);

评论(0) 引用(0) 浏览(1520)

NSIS安装脚本

作者:freethy 发布于:2015-7-1 18:52 Wednesday

${PRODUCT_NAME}; 安装程序初始定义常量
!define PRODUCT_NAME "软件名"
!define PRODUCT_VERSION "1.0"
!define PRODUCT_WEB_SITE "http://www.google.com"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${PRODUCT_NAME}.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"


SetCompressor /SOLID lzma
SetCompressorDictSize 32


; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------
!include "MUI.nsh"


; MUI 预定义常量
!define MUI_ABORTWARNING ;当用户要关闭安装程序时, 显示一个警告消息框
!define MUI_UNABORTWARNING ;当用户要关闭卸载程序时, 显示一个警告消息框
!define MUI_ICON "install.ico" ;安装程序图标
!define MUI_UNICON "uninst.ico" ;卸载程序图标
!define MUI_FINISHPAGE_NOAUTOCLOSE ;不自动跳到完成页面, 允许用户检查安装记录
!define MUI_UNFINISHPAGE_NOAUTOCLOSE ;不自动跳到完成页面, 允许用户检查卸载记录
!define MUI_WELCOMEFINISHPAGE_BITMAP "welcome.bmp" ;用于欢迎页面和完成页面的位图(推荐尺寸: 164x314 象素).
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "welcome.bmp" ;用于卸载页面的位图(推荐尺寸: 164x314 象素).
!define MUI_COMPONENTSPAGE_SMALLDESC ;较小的页面底部的描述区域
!define MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO "鼠标移到组件上可查看相应说明" ;当没有选择区段时, 显示于描述框中的文本


; 欢迎页面
!insertmacro MUI_PAGE_WELCOME
; 组件选择页面
!insertmacro MUI_PAGE_COMPONENTS
; 安装目录选择页面
!insertmacro MUI_PAGE_DIRECTORY
; 开始菜单设置页面
var ICONS_GROUP
!define MUI_STARTMENUPAGE_NODISABLE
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "PRODUCTNAME"!define MUISTARTMENUPAGEREGISTRYROOT "{PRODUCT_NAME}" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "{PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "PRODUCTUNINSTKEY"!define MUISTARTMENUPAGEREGISTRYVALUENAME "{PRODUCT_UNINST_KEY}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "{PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
; 安装过程页面
!insertmacro MUI_PAGE_INSTFILES
; 安装完成页面
!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_NAME}.exe"
!define MUI_FINISHPAGE_RUN_NOTCHECKED ;默认不选中 '运行程序' 复选框
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\Readme.txt"
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED ;默认不选中 '自述文件' 复选框
!define MUI_FINISHPAGE_LINK "【欢迎访问作者主页】"
!define MUI_FINISHPAGE_LINK_LOCATION "${PRODUCT_WEB_SITE}"
!insertmacro MUI_PAGE_FINISH


; 安装卸载过程页面
!insertmacro MUI_UNPAGE_INSTFILES


; 安装界面包含的语言设置
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "English"


; 安装预释放文件
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; ------ MUI 现代界面定义结束 ------




Name "PRODUCTNAME{PRODUCT_NAME} {PRODUCT_VERSION}"
OutFile "Setup.exe"
InstallDir "PROGRAMFILES$PRODUCTNAME"InstallDirRegKey HKLM "PROGRAMFILES\${PRODUCT_NAME}" InstallDirRegKey HKLM "{PRODUCT_UNINST_KEY}" "UninstallString"
ShowInstDetails hide ;设置是否显示安装详细信息
ShowUnInstDetails hide
BrandingText "作者:"


Section "!主程序" SEC01
SectionIn RO ;必选组件灰色
  SetOutPath "$INSTDIR"
  SetOverwrite on
  File "Readme.txt"


; 创建开始菜单快捷方式
  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
  CreateShortCut "DESKTOP$PRODUCTNAME.lnk" "DESKTOP\${PRODUCT_NAME}.lnk" "INSTDIR\PRODUCTNAME.exe"  CreateDirectory "{PRODUCT_NAME}.exe"   CreateDirectory "SMPROGRAMS\ICONSGROUP"  CreateShortCut "ICONS_GROUP"   CreateShortCut "SMPROGRAMS\ICONSGROUP$PRODUCTNAME.lnk" "ICONS_GROUP\${PRODUCT_NAME}.lnk" "INSTDIR\${PRODUCT_NAME}.exe"
  !insertmacro MUI_STARTMENU_WRITE_END
SectionEnd


; 安装.NET Framework
Section "Microsoft .NET Framework 2.0" SEC02
  File "DotNet.exe"
  ExecWait '"DotNet.exe" /q:a /c:"install.exe /q"'
SectionEnd


Section -AdditionalIcons
  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
  WriteIniStr "INSTDIR$PRODUCTNAME.url" "InternetShortcut" "URL" "INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "{PRODUCT_WEB_SITE}"
  CreateShortCut "SMPROGRAMS$ICONSGROUP\欢迎访问作者主页.lnk" "SMPROGRAMS\$ICONS_GROUP\欢迎访问作者主页.lnk" "INSTDIR\PRODUCTNAME.url"  CreateShortCut "{PRODUCT_NAME}.url"   CreateShortCut "SMPROGRAMS\ICONSGROUP\卸载.lnk" "ICONS_GROUP\卸载.lnk" "INSTDIR\uninst.exe"
  !insertmacro MUI_STARTMENU_WRITE_END
SectionEnd


Section -Post
  WriteUninstaller "INSTDIR\uninst.exe"  WriteRegStr HKLM "INSTDIR\uninst.exe"   WriteRegStr HKLM "{PRODUCT_DIR_REGKEY}" "" "$INSTDIR\PRODUCTNAME.exe"  WriteRegStr{PRODUCT_NAME}.exe"   WriteRegStr {PRODUCT_UNINST_ROOT_KEY} "PRODUCTUNINSTKEY" "DisplayName" "{PRODUCT_UNINST_KEY}" "DisplayName" "(^Name)"
  WriteRegStr PRODUCTUNINSTROOTKEY "{PRODUCT_UNINST_ROOT_KEY} "{PRODUCT_UNINST_KEY}" "UninstallString" "INSTDIR\uninst.exe"  WriteRegStrINSTDIR\uninst.exe"   WriteRegStr {PRODUCT_UNINST_ROOT_KEY} "PRODUCTUNINSTKEY" "DisplayIcon" "{PRODUCT_UNINST_KEY}" "DisplayIcon" "INSTDIR\PRODUCTNAME.exe"  WriteRegStr{PRODUCT_NAME}.exe"   WriteRegStr {PRODUCT_UNINST_ROOT_KEY} "PRODUCTUNINSTKEY" "DisplayVersion" "{PRODUCT_UNINST_KEY}" "DisplayVersion" "{PRODUCT_VERSION}"
  WriteRegStr PRODUCTUNINSTROOTKEY "{PRODUCT_UNINST_ROOT_KEY} "{PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
SectionEnd


#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#


; 区段组件描述
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
  !insertmacro MUI_DESCRIPTION_TEXT SEC01 "必备组件"  !insertmacro MUIDESCRIPTIONTEXT{SEC01} "必备组件"   !insertmacro MUI_DESCRIPTION_TEXT {SEC02} "运行主程序必需的框架,如果确认已经安装,则不必勾选"
!insertmacro MUI_FUNCTION_DESCRIPTION_END


/******************************
 *  以下是安装程序的卸载部分  *
 ******************************/


Section Uninstall
  !insertmacro MUI_STARTMENU_GETFOLDER "Application" ICONSGROUP  Delete "ICONS_GROUP   Delete "INSTDIR\uninst.exe"


  Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
  
  SetShellVarContext current ;当前用户开始菜单
  Delete "SMPROGRAMS$ICONSGROUP\卸载.lnk"  Delete "SMPROGRAMS\$ICONS_GROUP\卸载.lnk"   Delete "SMPROGRAMS\ICONSGROUP$PRODUCTNAME.lnk"  Delete "ICONS_GROUP\${PRODUCT_NAME}.lnk"   Delete "SMPROGRAMS\ICONSGROUP\欢迎访问作者主页.lnk"  RMDir /r "ICONS_GROUP\欢迎访问作者主页.lnk"   RMDir /r "SMPROGRAMS\$ICONS_GROUP"
    SetShellVarContext all ;全部用户开始菜单
  Delete "SMPROGRAMS$ICONSGROUP\卸载.lnk"  Delete "SMPROGRAMS\$ICONS_GROUP\卸载.lnk"   Delete "SMPROGRAMS\ICONSGROUP$PRODUCTNAME.lnk"  Delete "ICONS_GROUP\${PRODUCT_NAME}.lnk"   Delete "SMPROGRAMS\ICONSGROUP\欢迎访问作者主页.lnk"    RMDir /r "ICONS_GROUP\欢迎访问作者主页.lnk"      RMDir /r "SMPROGRAMS\ICONSGROUP"  RMDir /r "ICONS_GROUP"    RMDir /r "INSTDIR"


  DeleteRegKey PRODUCTUNINSTROOTKEY "{PRODUCT_UNINST_ROOT_KEY} "{PRODUCT_UNINST_KEY}"
  DeleteRegKey HKLM "{PRODUCT_DIR_REGKEY}"   SetAutoClose false SectionEnd  #-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#  Function un.onInit   MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除{PRODUCT_DIR_REGKEY}"   SetAutoClose false SectionEnd  #-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#  Function un.onInit   MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 (^Name) ,及其所有的组件?" IDYES +2
  Abort
FunctionEnd


Function un.onUninstSuccess
  HideWindow
  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机移除。"
FunctionEnd

评论(0) 引用(0) 浏览(1804)

Powered by emlog 苏ICP备11068260号-3