RSS 2.0 Feed

Wednesday, May 07, 2008

我们在应对网站的恶意请求时候,一个解决方法就是把有问题的请求IP封杀掉。

如果想快速处理这种问题,就需要编写一段代码,达到一定门槛,自动封杀。再复杂点就是不是永久封杀,还可以自动在一定时间后解封。

封杀的逻辑代码看后面提供的。

需要说明的是:IIS7时,情况发生了不同。

 

下面的代码,在处理封杀IP时候,不论IIS6还是IIS7 都可以把需要封杀的IP加入封杀列表。但是需要注意的是我们代码写的是全部替换原先的数据。但是在IIS7下,执行的效果是原先的不替换,新加一批封杀IP。当然IIS7下,如果新加的IP原来就有了,则会报如下异常:

System.Runtime.InteropServices.COMException was caught
  Message="当文件已存在时,无法创建该文件。 (异常来自 HRESULT:0x800700B7)"
  Source="System.DirectoryServices"
  ErrorCode=-2147024713
  StackTrace:
       在 System.DirectoryServices.DirectoryEntry.CommitChanges()
       在 IIS_Security_ConsoleApplication.Program.IPDeny() 位置 D:\MyCodes\IIS_Security_ConsoleApplication\IIS_Security_ConsoleApplication\Program.cs:行号 109
  InnerException:

这就是说,IIS7, 我们可以通过编程接口增加封杀IP名单,但是没发通过编程接口剔出封杀IP。

 

参考代码:

这里提供了两套参考代码,其实原理都是一样的。

在IIS 6 下,都没有任何问题, IIS 7 下都会有没发删除原先已有数据的问题。

代码一:


using System.DirectoryServices;
using System.Reflection;
using System;

class Program
{

static void IPDeny()
{

try
{
string serverName = "localhost";
// retrieve the directory entry for the root of the IIS server
System.DirectoryServices.DirectoryEntry IIS = new System.DirectoryServices.DirectoryEntry(
string.Format("IIS://{0}/w3svc/1/root", serverName));

// retrieve the list of currently denied IPs
Console.WriteLine("Retrieving the list of currently denied IPs.");

// get the IPSecurity property
Type typ = IIS.Properties["IPSecurity"][0].GetType();
object IPSecurity = IIS.Properties["IPSecurity"][0];


// retrieve the IPDeny list from the IPSecurity object
Array origIPDenyList = (Array)typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null);

// 罗列已经被拒绝的地址
foreach (string s in origIPDenyList)
Console.WriteLine("Before: " + s);

// check GrantByDefault. This has to be set to true,
// or what we are doing will not work.
bool bGrantByDefault = (bool)typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, IPSecurity, null);

Console.WriteLine("GrantByDefault = " + bGrantByDefault);
if (!bGrantByDefault)
{
// 必须设置 默认允许访问
typ.InvokeMember("GrantByDefault", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] { true });
}


// 更新被拒绝的IP列表
// 注意这里是完全替换
// 如果你想保留原先的拒绝列表,需要原先的拒绝列表也在这个数组中

Console.WriteLine("Updating the list of denied IPs.");

object[] newIPDenyList = new object[4];
newIPDenyList[0] = "192.168.1.21, 255.255.255.255";
newIPDenyList[1] = "192.168.1.22, 255.255.255.255";
newIPDenyList[2] = "192.168.1.23, 255.255.255.255";
newIPDenyList[3] = "192.168.1.24, 255.255.255.255";

Console.WriteLine("Calling SetProperty");

// add the updated list back to the IPSecurity object
typ.InvokeMember("IPDeny", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Instance | BindingFlags.SetProperty, null, IPSecurity, new object[] { newIPDenyList });



IIS.Properties["IPSecurity"][0] = IPSecurity;

Console.WriteLine("Commiting the changes.");

// commit the changes
IIS.CommitChanges();
IIS.RefreshCache();

// 检查更新后的数据
Console.WriteLine("Checking to see if the update took.");

IPSecurity = IIS.Properties["IPSecurity"][0];
Array y = (Array)typ.InvokeMember("IPDeny",
BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
| BindingFlags.GetProperty, null, IPSecurity, null);

foreach (string s in y)
Console.WriteLine("After: " + s);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
}

}
}

 

代码二:

        using System.DirectoryServices;
using System.Reflection;
using System;



static void SetIPSecurityProperty(string metabasePath, string member, string item)
{
// metabasePath is of the form "IIS://<servername>/<path>"
// for example "IIS://localhost/SMTPSVC/1"
// member is of the form "IPGrant|IPDeny|DomainGrant|DomainDeny"
// item is of the form "<ipaddress|domain>", for example, 157.56.236.15 or domain.microsoft.com
Console.WriteLine("\nEnumerating the IPSecurity property at {0}:", metabasePath);

try
{
if (("IPGrant" != member) && ("IPDeny" != member) && ("DomainGrant" != member) && ("DomainDeny" != member))
{
Console.WriteLine(" Failed in SetIPSecurityProperty; second param must be one of IPGrant|IPDeny|DomainGrant|DomainDeny");
}
else
{
DirectoryEntry path = new DirectoryEntry(metabasePath);
path.RefreshCache();
object ipsecObj = path.Invoke("Get", new string[] { "IPSecurity" });
Type t = ipsecObj.GetType();
Array data = (Array)t.InvokeMember(member, BindingFlags.GetProperty, null, ipsecObj, null);
Console.WriteLine(" Old {0} =", member);
bool exists = false;
foreach (object dataItem in data)
{
Console.WriteLine(" {0}", dataItem.ToString());
if (dataItem.ToString().StartsWith(item))
{
exists = true;
}
}

if (exists)
{
Console.WriteLine(" {0} already exists in {1}", item, member);
}
else
{
object[] newData = new object[data.Length + 1];
data.CopyTo(newData, 0);
newData.SetValue(item, data.Length);

t.InvokeMember(member, BindingFlags.SetProperty, null, ipsecObj, new object[] { newData });

path.Invoke("Put", new object[] { "IPSecurity", ipsecObj });

path.CommitChanges();

path.RefreshCache();
ipsecObj = path.Invoke("Get", new string[] { "IPSecurity" });
data = (Array)t.InvokeMember(member, BindingFlags.GetProperty, null, ipsecObj, null);
Console.WriteLine(" New {0} =", member);
foreach (object dataItem in data)
Console.WriteLine(" {0}", dataItem.ToString());
Console.WriteLine(" Done.");
}
}
}
catch (Exception ex)
{
if ("HRESULT 0x80005006" == ex.Message)
Console.WriteLine(" Property IPSecurity does not exist at {0}", metabasePath);
else
Console.WriteLine("Failed in SetIPSecurityProperty with the following exception: \n{0}", ex.Message);
}
}

static void Main(string[] args)
{

// 获取目前服务器上有哪些站点
DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
foreach (DirectoryEntry dir in root.Children)
{
if (dir.SchemaClassName == "IIsWebServer")
{
string ww = dir.Properties["ServerComment"].Value.ToString();

Console.Write("IIS://localhost/W3SVC/{0}/ROOT/ {1}\r\n", dir.Name, ww);
}
}


// IPDeny();

SetIPSecurityProperty("IIS://localhost/w3svc/1/root", "IPDeny", "192.168.5.79");

Console.ReadLine();
}

 

参考资料:

Blocking IIS IP Addresses with ASP.NET
http://www.west-wind.com/WebLog/posts/59731.aspx

How to Programmatically add IP Addresses to IIS's Deny Access List
http://www.codeproject.com/KB/security/iiswmi.aspx

HOWTO: 通过 IP 地址或域名称限制站点访问
http://support.microsoft.com/default.aspx/kb/324066

使用ADSI来操作IIS的路径
http://blog.joycode.com/ghj/archive/2004/06/08/24047.aspx

Setting IP Security Using System.DirectoryServices
http://www.cnblogs.com/drw/articles/17951.html

如何通过WEB方式,来控制iis的禁用IP名单。
http://blog.joycode.com/ghj/archive/2004/06/08/24075.aspx

Setting IP Security Using System.DirectoryServices
http://msdn.microsoft.com/en-us/library/ms524322(VS.85).aspx

how to automate adding denied IPs for IIS

http://www.nukeforums.com/forums/viewtopic.php?p=54746&highlight=&sid=1176c746e2037ed24acac86dd53ca747

IIS 7.0: Configure IPv4 Address and Domain Name Allow Rules
http://technet2.microsoft.com/windowsserver2008/en/library/d0de9475-0439-4ec1-8337-2bcedacd15c71033.mspx?mfr=true

posted @ | Feedback (2) | Filed Under [ 技术随笔 网站开发管理相关内容 ]

Sunday, May 04, 2008

分类统计时候,我们可能经常会碰到这样的需求,每个分类按照一定顺序,取几条数据,然后在一起显示。

这个问题的解决方法,我们通过搜索引擎,可以找到很多中。但是不是SQL语句过于复杂,就是在数据量比较大时候,性能特别成问题。

今天我就碰到这样一个需求。而我自己的解决方案就是SQL过于复杂,或者性能比较差的。为此我在CSDN论坛发了个帖子,看有没有更好的解决方案。

http://topic.csdn.net/u/20080504/14/5c5866c3-8b91-45ef-ab17-f994f88f8e42.html

CSDN的 SQL Server 板块  不愧是高手云集,问题发出不到半小时,就获得了近10种解决方案。经过测试,我把性能最高,且SQL不复杂的方案整理出来。特别感谢 jinjazz 的解答。

 

问题详细描述如下:

比如,假设我们有下面这样结构的一张表,这张表的数据量非常巨大。

CREATE TABLE table1
(
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](128) NOT NULL,
[class] int not null,
[date] datetime not null
)

class 表示分类编号。 分类数不固定, 至少有上千种分类
date 表示该条记录被更新的时间
我们现在想获得每个分类最新被更新的5条记录。

 

解决方案

select id,name,class,date from(
select id,name,class,date ,row_number() over(partition by class order by date desc)
as rowindex from table1) a
where rowindex <= 5

 

解决方案简单说明:

这个解决方案的关键就是使用了SQL 2005 的 ROW_NUMBER 这个全新的函数。

ROW_NUMBER ( ) 函数的语法如下:
ROW_NUMBER ( )     OVER ( [ <partition_by_clause> ] <order_by_clause> )

OVER 子句中的 PARTITION BY 将结果集分为多个分区。
OVER 子句中的 ORDER BY 将对 ROW_NUMBER 进行排序。

下面是MSDN的几个简单例子:

 

以下示例将根据年初至今的销售额,返回 AdventureWorks 中销售人员的 ROW_NUMBER。

USE AdventureWorks; 
GO

SELECT c.FirstName, c.LastName ,
ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) AS 'Row Number' ,s.SalesYTD, a.PostalCode

FROM Sales.SalesPerson s INNER JOIN Person.Contact c ON s.SalesPersonID = c.ContactID
INNER JOIN Person.Address a ON a.AddressID = c.ContactID
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0;


以下示例将返回行号为 50 到 60 的行(包含这两行),并按 OrderDate 进行排序。

USE AdventureWorks; 
GO

WITH OrderedOrders AS ( SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader )

SELECT * FROM OrderedOrders WHERE RowNumber BETWEEN 50 AND 60;


 

以下示例说明了如何使用 PARTITION BY 参数。

USE AdventureWorks; 
GO

SELECT c.FirstName, c.LastName ,
ROW_NUMBER() OVER (PARTITION BY PostalCode ORDER BY SalesYTD DESC) AS 'Row Number' ,
s.SalesYTD, a.PostalCode

FROM Sales.SalesPerson s INNER JOIN Person.Contact c ON s.SalesPersonID = c.ContactID
INNER JOIN Person.Address a ON a.AddressID = c.ContactID
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0;

posted @ | Feedback (1) | Filed Under [ 数据库开发管理心得 ]

Thursday, April 24, 2008

CSDN 网友 zswang 组织了一个编程游戏比赛。划拳机器人比赛。类似“Robocode” 的游戏。

比赛相关帖子如下:

【编程游戏】编写一个会划拳的机器人参加擂台赛,规则内详。
http://topic.csdn.net/u/20080421/17/6a4d1c20-e1d1-4e9d-99ae-d648cb422ca6.html

【编程游戏】划拳机器人,前面一贴的机器人都集中来了,继续PK。谨慎路过。 
http://topic.csdn.net/u/20080423/21/cda52758-a06d-49e1-9db0-eda2b009da8c.html

很有意思的,为了让更多人能参与到这个很有趣的 .NET 编程比赛中来,我转了下面的内容:

 


划拳介绍

      划拳又叫豁拳、猜枚、猜拳、拇战,即饮酒时两人同时伸出手指并各说一个数,谁说的数目跟双方所伸手指的总数相符,谁就算赢,输的人喝酒。此乃我国
古传至今仍时尚流行的饮酒游戏,它增添酒兴,烘托喜庆,是一种民间的酒令。 其技巧性颇强,给玩者留有神机斗智的余地,且因玩时须喊叫,易让人兴奋,极富竞争性。
两人同时伸出一只手,用攥起的拳头和伸出一到五个手指,表示从零到五这几个数字,与此同时,嘴里喊出从零到10的数字,如果两人伸出的手指表示的数字相加与其中一个人嘴里喊出的数字相同,那么这个人就算赢了这一拳。举例说明:比如一个人伸出了三个手指,另一个人伸出了四个手指,一个人喊了七,另一个喊了六,那么这个人喊七的人就赢了;如一个人伸出攥紧的拳头(表示零),嘴里喊出了三,而另一个恰好伸出了三个手指可嘴里喊的七,那么喊三的就赢了。就这么简单。当然,如果自己喊的是“八仙过海”, 而自己仅伸出了一个手指,那么对方即使伸出五指也不可能凑成八,这种拳就叫臭拳,如果不是事先约定,是要罚酒的。


    划拳规则看完了,那我们就开始写一个会划拳的机器人吧!
    那么一个会划拳的机器会做什么事情呢?其实就是两件:


第一件、出拳,即:自己出几个手指?自己猜合计是多少。
第二件、知道划拳的结果,即:对方出几个手指,对方猜合计是多少,是否获胜还是平局还是其他。
   只要继承Drunkard这个类,重载Come()和Outcome()方法那么你就拥有了一个会划拳的机器人,参与这个游戏了!


【游戏规则】
1、比赛共1000局,即:出现胜负算一局,如出拳100次没有结果也算一局并双方均不得分;
2、赢一局得1分、输不扣分;
3、机器人执行中每出现一次异常,扣100分、对方加1分、记一局;
4、机器人执行中反应超时1000毫秒直接判负,每超时100毫秒,扣1分,超时10次以上直接判负;
5、自己得分高于对手并大于600分判胜;
6、自己得分为正数对手得分为负数判胜;
7、其他情况则判平。
具体执行的过程,算法的过程请参考Drunkery <T1, T2>类的实现


【入门提示】
1、机器人的命名建议是: <自己的id> +  <第几个> + "号",如:Zswang一号、Zswang二号,当然你也可以用“长江七号”
2、不允许修改Drunkard和Drunkery <T1, T2>;
3、机器人必须从Drunkard继承;
4、分析擂主代码是战胜擂主的关键;
5、打擂容易守擂难,大家自由发挥吧!

 
【擂台赛规则】
1、第一个打败擂主的机器人奖励20分,并成为新的擂主;
2、自己不能挑战自己编写的机器人;
3、最后一个擂主获得200专家分,发帖另付;
4、其余分数酌情散掉。
标准代码和比赛规则有什么不妥或者建议欢迎讨论,谢谢关注
(调试代码参考后面两帖,-_-!!!代码有点多,先别抢沙发。。。。)

 

由于空间有限, 这里就不贴调试代码了, 调试代码,以及基类代码看上面给的两个帖子的链接。

posted @ | Feedback (0) | Filed Under [ .net 编程心得 ]

Friday, April 18, 2008

比如我们有下面的需求:

三台电脑:A,B,C。
我们在 B 和 C 上部署了同样的一个服务,电脑 A 需要根据客户端的选择,自动的切换到底是调用B的服务,还是C的服务。

要实现这个需求,核心就在客户端的调用上。下面我们用一个简单的演示这个功能的代码来说明如何实现。

 

首先:服务器段

服务器段逻辑,这是非常简单的,我们按照之前的.net编写规范,编写代码即可。熟悉.net Remoting 的完全可以跳过这部分。

下面是一段简单的服务器段逻辑代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace MyServiceComponent
{
public class MyComponent : MarshalByRefObject
{
public string GetString(short s)
{
// 返回信息中包含服务器IP,这样我们就知道客户端调用的是哪个服务器
if (s <= 10)
return string.Format("<=10 {0}", GetIP());
else
return string.Format("大于10 {0}", GetIP());
}

protected string GetIP() //获取本地IP
{
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = ipHost.AddressList[0];
return ipAddr.ToString();
}
}
}

服务器段的配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown mode="Singleton" type="MyServiceComponent.MyComponent, MyServiceComponent"
objectUri="HongjunguoRemotingService" />
</service>
<channels>
<!-- 这里的配置方法,请参看MSDN中 远程处理安全通道技术示例 -->
<channel ref="tcp" port="8088" secure="true" impersonate="true"
protectionLevel="EncryptAndSign" />
<serverProviders>
<formatter href="binary" typeFilterLevel="Full"/>
</serverProviders>
</channels>
</application>
<!--
只有把 customErrors 配置成 Off ,服务器端的详细错误异常,才能传递到客户端
默认是不传递完整的错误异常的。
-->

<customErrors mode ="Off" />
</system.runtime.remoting>
</configuration>

服务器段调用代码

RemotingConfiguration.Configure(
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);

 

客户端

客户端如果我们用以前常用的,把所有客户端的调用信息都写在一个配置文件中,期望简单的用下面代码就不可以了。

 RemotingConfiguration.Configure(configFile, true);

如果我们用上面的方法时,则会收到下面的异常:

远程处理配置失败,异常为“System.Runtime.Remoting.RemotingException:
试图重定向类型“MyServiceComponent.MyComponent, MyServiceComponent”的激活,而该类型已被重定向。
   在 System.Runtime.Remoting.RemotingConfigHandler.RemotingConfigInfo.AddWellKnownClientType(WellKnownClientTypeEntry entry)
   在 System.Runtime.Remoting.RemotingConfigHandler.RegisterWellKnownClientType(WellKnownClientTypeEntry entry)
   在 System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownClientType(WellKnownClientTypeEntry entry)
   在 System.Runtime.Remoting.RemotingConfigHandler.RemotingConfigInfo.StoreRemoteAppEntries(RemotingXmlConfigFileData configData)
   在 System.Runtime.Remoting.RemotingConfigHandler.ConfigureRemoting(RemotingXmlConfigFileData configData, Boolean ensureSecurity)”。

参考我在论坛咨询的帖子

远程处理配置失败,异常为“RemotingException: 试图重定向类型“MySC.MyComponent, MyServiceComponent”的激活,而该类型已被重定向  
http://topic.csdn.net/u/20080418/10/a9b02fa0-a230-4fb6-abeb-b7407a6729c1.html

使用.net Remoting 客户端调用服务器段时,需要考虑两个东西:
1、信道的问题(Channel)

2、如何创建远程对象,也就是注册类型

 

先说信道的问题:

上面例子中, B 和 C 服务器,他们完全可能一个开放的是 TCP 信道,一个开放的是 HTTP 信道。 同时,访问他们服务时,身份验证完全可能是不同的。各自服务器自身的验证。

这就有一个需要解决的问题,如何实现客户端多信道。下面这篇博客对此有比较详细的介绍:

Remoting多个信道(Chennel)的注册问题
http://www.cnblogs.com/kriss/archive/2005/11/30/288177.html

 

创建远程对象的问题:

如果我们把需要创建的信息写在配置文件中,用 RemotingConfiguration.Configure(configFile, true); 来创建远程对象,就会出现下面的错误。

 

远程处理配置失败,异常为“System.Runtime.Remoting.RemotingException:
试图重定向类型“MyServiceComponent.MyComponent, MyServiceComponent”的激活,而该类型已被重定向。
   在 System.Runtime.Remoting.RemotingConfigHandler.RemotingConfigInfo.AddWellKnownClientType(WellKnownClientTypeEntry entry)
   在 System.Runtime.Remoting.RemotingConfigHandler.RegisterWellKnownClientType(WellKnownClientTypeEntry entry)
   在 System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownClientType(WellKnownClientTypeEntry entry)
   在  System.Runtime.Remoting.RemotingConfigHandler.RemotingConfigInfo.StoreRemoteAppEntries(RemotingXmlConfigFileData configData)
   在 System.Runtime.Remoting.RemotingConfigHandler.ConfigureRemoting (RemotingXmlConfigFileData configData, Boolean ensureSecurity)”。

 

解决方法,就是下面的演示代码,不写在配置文件中,改自己手工创建,如下面客户端演示代码。

编码创建对象可以使用 Activator.GetObject 或者 Activator.CreateInstance 。

下面就是我的演示代码

针对B服务器的配置文件(主要是通道的配置,注意这两个配置文件验证信息不一样)

注意,这个配置文件中我们可没有下面这样的信息:

    <client displayName="client01" >
        <wellknown
          displayName ="Wellknown1"
          type="MyServiceComponent.MyComponent,MyServiceComponent"
                url="tcp://192.168.5.2:8088/HongjunguoRemotingService" />
      </client>


s1.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<!--
这里的配置方法,请参看MSDN中 远程处理安全通道技术示例
这个技术请参看:

http://www.cnblogs.com/zhengyun_ustc/archive/2006/06/09/remoting_InvalidCredentialException.html
http://forums.asp.net/thread/1626741.aspx
-->

<channel name="Channel1" ref="tcp" port="8081" secure="true"
tokenImpersonationLevel="impersonation" protectionLevel="EncryptAndSign"
username="ghj1976" password="*****" domain="*****" />
<clientProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</clientProviders>
</channels>
</application>
<customErrors mode ="Off" />
</system.runtime.remoting>
</configuration>

 

针对C服务器的配置文件(主要是通道的配置,注意这两个配置文件验证信息不一样)
s2.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel name="Channel2" ref="tcp" port="8082" secure="true"
tokenImpersonationLevel="impersonation" protectionLevel="EncryptAndSign"
username="communityserver" password="****" domain="***"/>
<clientProviders>
<formatter ref="binary" typeFilterLevel="Full" />
</clientProviders>
</channels>
</application>
<customErrors mode ="Off" />
</system.runtime.remoting>
</configuration>

 

客户端程序的调用代码

    public partial class ClientForm : Form
{
public ClientForm()
{
InitializeComponent();
}

private Dictionary<string, MyServiceComponent.MyComponent> dict =
new Dictionary<string, MyServiceComponent.MyComponent>(2);


private void button1_Click(object sender, EventArgs e)
{
short ss = 0;

if (!short.TryParse(this.textBox1.Text, out ss))
return;

string key = string.Empty;
string url = string.Empty;
if (radioButton1.Checked)
{
key = "s1.config";
url = "tcp://192.168.5.2:8088/HongjunguoRemotingService";
}
else if (radioButton2.Checked)
{
key = "s2.config";
url = "tcp://192.168.5.7:8088/HongjunguoRemotingService";
}
else
return;

MyServiceComponent.MyComponent com = null;
if (!dict.TryGetValue(key, out com))
{
string configFile = Path.Combine(
Path.GetDirectoryName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), key);

RemotingConfiguration.Configure(configFile, true);

//com = new MyServiceComponent.MyComponent();
com = (MyServiceComponent.MyComponent)Activator.GetObject(
typeof(MyServiceComponent.MyComponent), url);

dict.Add(key, com);
}
else
{
if (com == null) return;
}


string www = com.GetString(ss);
MessageBox.Show(www);

}
}

 

参考资料

 

客户端提示 信道 http 已注册
http://topic.csdn.net/t/20051219/15/4468126.html

如何取消RemotingConfiguration.RegisterActivatedClientType的注册类型
http://topic.csdn.net/t/20050116/16/3729762.html

 

RemotingConfiguration.Configure (String, Boolean) 中隐藏的秘密
http://blog.csdn.net/blue_sky_blue_heart/archive/2006/08/28/1130914.aspx

Remoting给远程对象属性赋值
http://topic.csdn.net/u/20070614/15/1d5a7738-e676-489e-978a-b194579d560b.html

posted @ | Feedback (1) | Filed Under [ .net 编程心得 技术随笔 网站开发管理相关内容 .net 3.0 .net 3.5 ]

Thursday, April 10, 2008

我坐公交车的历史,已经有10多年了。今天早上坐852上班的路上,碰到了一个我非常佩服的售票员。佩服她的原因是因为这趟车上,我正好看到2件事情。而她对这两件事情的处理,让我非常有感触,非常有心得。

 

第一件事情是在望京时,有个乘客下车时,这个售票员走到一个乘客跟前,小声地跟他说了一些话。当时我还觉得很怪异。虽然我就离那个乘客不到2米的地方。但是我只能断断续续的听到几个词。并不明白在说啥。那个乘客下车后,另外一个售票员也觉得很怪异,问她时,她才说那个乘客拿的是学生卡。

那个乘客看起来,老大不小了。估计三、四十了。看起来一点也不可能是学生。按照北京市的规定,发现非学生使用学生卡,卡当时没收,同时罚款不知道多少。违法使用学生卡的事情,我在其他公交车上也看到,但是这个售票员能用这种方式来解决,我是第一次看到。以前最多看到的是:大声地指责,没收卡,或者根本就当这件事情没有发生。

从跟人沟通的角度来看这个问题:争吵,或者视若不见。都不能帮人解决问题。跟他心平气和的沟通。同时一定不要在公众场合批评他,不能让他觉得自己在被公审。这才是督促他解决问题得最好沟通方式。

反面的教材就多了,比如之前的最牛秘书的事情;公司最忌讳的一些事情,就是说某个事情时候,抄送邮件给很多人;公交车上很多时候乘客跟售票员的吵架,就是沟通方式不当导致,我们管理团队时,跟手下沟通方式不当,也会带来很多麻烦等等。

这是我佩服这个售票员的第一个理由。

 

第二件事情发生在西八间房(广顺南大街南口)这一站。有个乘客在下车刷卡时发现扣了自己8毛。按照正常,应该是扣6毛。这个乘客就为了这2毛钱。大发雷霆,说了很多难听的话。这个乘客是在后门下车的,当时后门的那个售票员已经有点发懵了。显然后门这个售票员经验不足。不知道如何处理这件事情。我佩服的这个售票员,飞快地从中门售票员位置上跑到后门,追上那个乘客,然后又很快的跑回自己位置。

当时我们都觉得很奇怪,这个售票员就这么飞快的过去一趟,就再没听见那个乘客之前的大声门骂骂咧咧了。超级神奇。

大家能猜到这个售票员追上那个乘客干了啥事情么?

当然这事情后门的售票员也很奇怪,也替我们问了。

这个我最佩服的售票员,追上这个乘客,给了他2毛硬币。

坐公交多扣2毛,我自己都碰到过十多次。原因很简单,司机如果在每站的时候,按站号不及时,乘客刷卡时,刷的就是上一站的站号。系统当然按照上一站来计算费用,这样在一些多一站就要多交钱的情况时,就可能会多扣2毛。

由于时刷卡系统扣掉了,想从刷卡系统讨回这两毛,非常困难,而售票员买票的所得又是以5毛为最小单位的。显然这个售票员自己备了一些零钱。而且这些钱很可能是需要从自己工资中扣除,但是上面的行动,让有意见的乘客顿时觉得自己为了这2毛而进行的行为非常不对。对缓和矛盾非常有帮助。

这种事情其他公交车上也看到过,由于上面的原因,大多售票员采用的是道歉的方式,并且说这是刷卡系统扣的,他们也无能为力。

这个售票员用这种超级神奇的方式缓和了矛盾,这是我佩服这个售票员的第二个理由。

 

从这两件事情,我看到了在跟有矛盾,或者需要批评的人沟通时,选择的方式非常非常重要。方式不对,只能矛盾越来越对立。对解决问题一点都没有帮助。要想做好一个管理者,如果不具备这个售票员所具有的素质,是很难带领手下同甘共苦的。

 

最后,这趟公交车的车号是  京AC5933。 非常感谢这个售票员给我上了这么一节生动的跟人沟通的课程。

posted @ | Feedback (1) | Filed Under [ 非技术随笔 ]

Wednesday, April 09, 2008

由于我之前装的英文版本的IE8,现在想换成中文版本的, 所以就需要写在原先的IE8 Beta1 英文版,但是按照正常的思路去找卸载的地方,竟然没有找到。考虑到很多人可能会有我类似的问题。特意写了这篇博客帮助大家。

卸载的位置:

控制面板 --> 程序和功能 --> 查看已安装的更新(注意,是在这里)

MIcrosoft Windows 分类下面有一个 Windows Internet Explorer 8 ,卸载它即可。
IE8 是以更新的方式安装的,而不是一个普通的程序。这点是要需要注意的。

另外,英文版本的IE8 ,版本号是:8.0.6001.17184。

中文版版本是:8.0.6001.17193 。比英文版稍稍新一点。

posted @ | Feedback (0) | Filed Under [ 网站开发管理相关内容 Vista 相关 win2008 ]

Wednesday, March 26, 2008

这几天,我家宝宝一直赖在老妈肚子里面,不出来。害得我每天上班都提心吊胆的,也没有工作热情。就等着宝宝出生,可是他就是赖着不出来。

于是,就把公司电脑重装成了中文版的Win2008。 安装一些软件过程中碰到了不少问题,特意整理成这篇博客,让后来着少走弯路。

 

一、显卡驱动的问题

我电脑的显卡是:NVIDIA GeForce 6200 TurboCache。

GeForce 系列的显卡,在Window2008 下,最新的驱动反而不能用。 安装了最新的驱动后,你的显示器就会黑屏,没有任何治了。最新版本的 169.32,虽然说通过了Vista 的WHQL