众所周知 .Net中Random类生成的随机数是假随机数,关键要看构造函数里的种子
如果你做个实验

1
2
3
4
for (int i = 0; i > 100; i++)
{
    Console.WriteLine(new Random(i).Next());
}

就会看到很有规律的一串数

许多人想到时间,DateTime.Now.Ticks,首先这个属性是long,与Random构造函数的参数不符,你需要做一定处理,而且在机器很快的情况下,短时间内这个数字不会有变化,生成的“随机数”也就都是一样的。于是网上介绍的许多方法会用Ticks相乘、或者乘以i等做一些处理,让这个种子看上去随机一些,不过还是显得麻烦。

其实,在.Net中,说道随机,最先想到的就是Guid.NewGuid(),但Guid是Guid的格式,怎么转换成你自己的格式呢?

HashCode!

.Net中,所有类继承于object,而所有的object都会有Equals()和GetHashCode()两个方法,而GetHashCode()的返回值,正是Random类构造函数所需要的int,这么方便的东西,我们当然要利用一下,所以,很容易写下了如下代码。

1
2
3
4
5
6
7
8
9
10
static string GetCode(int num)
{
    string a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < num; i++)
    {
        sb.Append(a[new Random(Guid.NewGuid().GetHashCode()).Next(0, a.Length -1)]);
    }
    return sb.ToString();
}

转自:http://www.cnblogs.com/Mirricle/archive/2008/06/02/1212003.html

东软的C#编程规范,与大家分享。
点击下载

感觉挺有趣的,就转过来给大家看了。

紧耦合
  从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺。但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒。但是彼得又不想让老板呆在他的办公室里站在背后盯着他,于是就对老板做出承诺:无论何时,只要我的工作取得了一点进展我都会及时让你知道。彼得通过周期性地使用“带类型的引用”(原文为:“typed reference” 也就是delegate??)“回调”他的老板来实现他的承诺,如下:

class Worker {
public void Advise(Boss boss) { _boss = boss; }
public void DoWork() {
Console.WriteLine(“工作: 工作开始”);
if( _boss != null ) _boss.WorkStarted();
Console.WriteLine(“工作: 工作进行中”);
if( _boss != null ) _boss.WorkProgressing();
Console.WriteLine("“工作: 工作完成”");
if( _boss != null ) {
int grade = _boss.WorkCompleted();
Console.WriteLine(“工人的工作得分=” + grade);
}
}
private Boss _boss;
}
class Boss {
public void WorkStarted() { /* 老板不关心。 */ }
public void WorkProgressing() { /*老板不关心。 */ }
public int WorkCompleted() {
Console.WriteLine(“时间差不多!”);
return 2; /* 总分为10 */
}
}
class Universe {
static void Main() {
Worker peter = new Worker();
Boss boss = new Boss();
peter.Advise(boss);
peter.DoWork();
Console.WriteLine(“Main: 工人工作完成”);
Console.ReadLine();
}
}

接口
  现在,彼得成了一个特殊的人,他不但能容忍吝啬的老板,而且和他周围的宇宙也有了密切的联系,以至于他认为宇宙对他的工作进度也感兴趣。不幸的是,他必须也给宇宙添加一个特殊的回调函数Advise来实现同时向他老板和宇宙报告工作进度。彼得想要把潜在的通知的列表和这些通知的实现方法分离开来,于是他决定把方法分离为一个接口:

interface IWorkerEvents {
void WorkStarted();
void WorkProgressing();
int WorkCompleted();
}
class Worker {
public void Advise(IWorkerEvents events) { _events = events; }
public void DoWork() {
Console.WriteLine(“工作: 工作开始”);
if( _events != null ) _events.WorkStarted();
Console.WriteLine(“工作: 工作进行中”);
if(_events != null ) _events.WorkProgressing();
Console.WriteLine("“工作: 工作完成”");
if(_events != null ) {
int grade = _events.WorkCompleted();
Console.WriteLine(“工人的工作得分=” + grade);
}
}
private IWorkerEvents _events;
}
class Boss : IWorkerEvents {
public void WorkStarted() { /* 老板不关心。 */ }
public void WorkProgressing() { /* 老板不关心。 */ }
public int WorkCompleted() {
Console.WriteLine(“时间差不多!”);
return 3; /* 总分为10 */
}
}

委托
  不幸的是,每当彼得忙于通过接口的实现和老板交流时,就没有机会及时通知宇宙了。至少他应该忽略身在远方的老板的引用,好让其他实现了IWorkerEvents的对象得到他的工作报告。(”At least he'd abstracted the reference of his boss far away from him so that others who implemented the IWorkerEvents interface could be notified of his work progress” 原话如此,不理解到底是什么意思 )
  他的老板还是抱怨得很厉害。“彼得!”他老板吼道,“你为什么在工作一开始和工作进行中都来烦我?!我不关心这些事件。你不但强迫我实现了这些方法,而且还在浪费我宝贵的工作时间来处理你的事件,特别是当我外出的时候更是如此!你能不能不再来烦我?”
  于是,彼得意识到接口虽然在很多情况都很有用,但是当用作事件时,“粒度”不够好。他希望能够仅在别人想要时才通知他们,于是他决定把接口的方法分离为单独的委托,每个委托都像一个小的接口方法:

delegate void WorkStarted();
delegate void WorkProgressing();
delegate int WorkCompleted();
class Worker {
public void DoWork() {
Console.WriteLine(“工作: 工作开始”);
if( started != null ) started();
Console.WriteLine(“工作: 工作进行中”);
if( progressing != null ) progressing();
Console.WriteLine("“工作: 工作完成”");
if( completed != null ) {
int grade = completed();
Console.WriteLine(“工人的工作得分=” + grade);
}
}
public WorkStarted started;
public WorkProgressing progressing;
public WorkCompleted completed;
}
class Boss {
public int WorkCompleted() {
Console.WriteLine("Betterhttp://www.cnblogs.com/Images/dot.gif");
return 4; /* 总分为10 */
}
}
class Universe {
static void Main() {
Worker peter = new Worker();
Boss boss = new Boss();
peter.completed = new WorkCompleted(boss.WorkCompleted);
peter.DoWork();
Console.WriteLine(“Main: 工人工作完成”);
Console.ReadLine();
}
}

静态监听者
  这样,彼得不会再拿他老板不想要的事件来烦他老板了,但是他还没有把宇宙放到他的监听者列表中。因为宇宙是个包涵一切的实体,看来不适合使用实例方法的委托(想像一下,实例化一个“宇宙”要花费多少资源…..),于是彼得就需要能够对静态委托进行挂钩,委托对这一点支持得很好:

class Universe {
static void WorkerStartedWork() {
Console.WriteLine("Universe notices worker starting work");
}
static int WorkerCompletedWork() {
Console.WriteLine("Universe pleased with worker's work");
return 7;
}
static void Main() {
Worker peter = new Worker();
Boss boss = new Boss();
peter.completed = new WorkCompleted(boss.WorkCompleted);
peter.started = new WorkStarted(Universe.WorkerStartedWork);
peter.completed = new WorkCompleted(Universe.WorkerCompletedWork);
peter.DoWork();
Console.WriteLine(“Main: 工人工作完成”);
Console.ReadLine();
}
}

事件
  不幸的是,宇宙太忙了,也不习惯时刻关注它里面的个体,它可以用自己的委托替换了彼得老板的委托。这是把彼得的Worker类的的委托字段做成public的一个无意识的副作用。同样,如果彼得的老板不耐烦了,也可以决定自己来激发彼得的委托(真是一个粗鲁的老板):
// Peter's boss taking matters into his own hands
if( peter.completed != null ) peter.completed();
  彼得不想让这些事发生,他意识到需要给每个委托提供“注册”和“反注册”功能,这样监听者就可以自
己添加和移除委托,但同时又不能清空整个列表也不能随意激发彼得的事件了。彼得并没有来自己实现这些功能,相反,他使用了event关键字让C#编译器为他构建这些方法:

class Worker {
//http://www.cnblogs.com/Images/dot.gif
public event WorkStarted started;
public event WorkProgressing progressing;
public event WorkCompleted completed;
}

  彼得知道event关键字在委托的外边包装了一个property,仅让C#客户通过+= 和 -=操作符来添加和移除,强迫他的老板和宇宙正确地使用事件。

static void Main() {
Worker peter = new Worker();
Boss boss = new Boss();
peter.completed += new WorkCompleted(boss.WorkCompleted);
peter.started += new WorkStarted(Universe.WorkerStartedWork);
peter.completed += new WorkCompleted(Universe.WorkerCompletedWork);
peter.DoWork();
Console.WriteLine(“Main: 工人工作完成”);
Console.ReadLine();
}

“收获”所有结果
  到这时,彼得终于可以送一口气了,他成功地满足了所有监听者的需求,同时避免了与特定实现的紧耦合。但是他注意到他的老板和宇宙都为它的工作打了分,但是他仅仅接收了一个分数。面对多个监听者,他想要“收获”所有的结果,于是他深入到代理里面,轮询监听者列表,手工一个个调用:

public void DoWork() {
http://www.cnblogs.com/Images/dot.gif
Console.WriteLine("“工作: 工作完成”");
if( completed != null ) {
foreach( WorkCompleted wc in completed.GetInvocationList() ) {
int grade = wc();
Console.WriteLine(“工人的工作得分=” + grade);
}
}
}

异步通知:激发 & 忘掉
  同时,他的老板和宇宙还要忙于处理其他事情,也就是说他们给彼得打分所花费的事件变得非常长:

class Boss {
public int WorkCompleted() {
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Betterhttp://www.cnblogs.com/Images/dot.gif"); return 6; /* 总分为10 */
}
}
class Universe {
static int WorkerCompletedWork() {
System.Threading.Thread.Sleep(4000);
Console.WriteLine("Universe is pleased with worker's work");
return 7;
}
http://www.cnblogs.com/Images/dot.gif
}

  很不幸,彼得每次通知一个监听者后必须等待它给自己打分,现在这些通知花费了他太多的工作事件。于是他决定忘掉分数,仅仅异步激发事件:

public void DoWork() {
http://www.cnblogs.com/Images/dot.gif
Console.WriteLine("“工作: 工作完成”");
if( completed != null ) {
foreach( WorkCompleted wc in completed.GetInvocationList() )
{
wc.BeginInvoke(null, null);
}
}
}

异步通知:轮询
  这使得彼得可以通知他的监听者,然后立即返回工作,让进程的线程池来调用这些代理。随着时间的过去,彼得发现他丢失了他工作的反馈,他知道听取别人的赞扬和努力工作一样重要,于是他异步激发事件,但是周期性地轮询,取得可用的分数。

public void DoWork() {
http://www.cnblogs.com/Images/dot.gif
Console.WriteLine("“工作: 工作完成”");
if( completed != null ) {
foreach( WorkCompleted wc in completed.GetInvocationList() ) {
IAsyncResult res = wc.BeginInvoke(null, null);
while( !res.IsCompleted ) System.Threading.Thread.Sleep(1);
int grade = wc.EndInvoke(res);
Console.WriteLine(“工人的工作得分=” + grade);
}
}
}

异步通知:委托
  不幸地,彼得有回到了一开始就想避免的情况中来,比如,老板站在背后盯着他工作。于是,他决定使用自己的委托作为他调用的异步委托完成的通知,让他自己立即回到工作,但是仍可以在别人给他的工作打分后得到通知:

 public void DoWork() {
http://www.cnblogs.com/Images/dot.gif
Console.WriteLine("“工作: 工作完成”");
if( completed != null ) {
foreach( WorkCompleted wc in completed.GetInvocationList() ) {
wc.BeginInvoke(new AsyncCallback(WorkGraded), wc);
}
}
}
private void WorkGraded(IAsyncResult res) {
WorkCompleted wc = (WorkCompleted)res.AsyncState;
int grade = wc.EndInvoke(res);
Console.WriteLine(“工人的工作得分=” + grade);
}

宇宙中的幸福
  彼得、他的老板和宇宙最终都满足了。彼得的老板和宇宙可以收到他们感兴趣的事件通知,减少了实现的负担和非必需的往返“差旅费”。彼得可以通知他们,而不管他们要花多长时间来从目的方法中返回,同时又可以异步地得到他的结果。彼得知道,这并不*十分*简单,因为当他异步激发事件时,方法要在另外一个线程中执行,彼得的目的方法完成的通知也是一样的道理。但是,迈克和彼得是好朋友,他很熟悉线程的事情,可以在这个领域提供指导。
  他们永远幸福地生活下去……

引言:
  微软的新的.NET平台为开发者带来了许多新的诸如GDI+、Globalization之类的编程机制,同时还发明了一门全新的类似Java的编程语言-C#。对于这些新知识,我们应尽快了解、掌握并试图运用到实践项目中去,而通过实例学习的方法无疑是一个非常有效的途径。本文就通过一个简单的实例,向大家展示了在Visual C#中如何运用GDI+和Unsafe代码类等技术以实现简单的数字图像处理。

  一.概述:
  本文的实例是一个数字图像处理的应用程序,它完成的功能包括对图像颜色的翻转、对图像进行灰度处理和对图像进行增亮处理。该程序对图像进行处理部分的代码包含在一个专门的Filters类里面,通过调用该类里的静态成员函数,我们就可以实现相应的图像处理功能了。为实现图像处理,我们要对图像进行逐个象素处理。我们知道图像是由一个个的象素点组成的,对一幅图像的每个象素进行了相应的处理,最后整个图像也就处理好了。在这个过程中,我们只需对每个象素点进行相应的处理,在处理过程中却不需要考虑周围象素点对其的影响,所以相对来说程序的实现就变得简单多了。
  由于GDI+中的BitmapData类不提供对图像内部数据的直接访问的方法,我们唯一的办法就是使用指针来获得图像的内部数据,这时我们就得运用unsafe这个关键字来指明函数中访问图像内部数据的代码块了。在程序中,我还运用了打开文件和保存文件等选项,以使我们的辛勤劳动不付之东流。
  二.程序的实现:
  1.打开Visual Studio.net,新建一个Visual C#的项目,在模板中选择"Windows 应用程序"即可,项目名称可自定(这里为ImageProcessor)。
  2.为使窗体能显示图像,我们需要重载窗体的OnPaint()事件函数,在该函数中我们将一个图像绘制在程序的主窗体上,为了使窗体能显示不同尺寸大小的图像,我们还将窗体的AutoScroll属性设置为true。这样,根据图像的尺寸,窗体两边就会出现相应的滚动条。该函数的实现如下:
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(m_Bitmap, new Rectangle(this.AutoScrollPosition.X, this.AutoScrollPosition.Y,
(int)(m_Bitmap.Width), (int)(m_Bitmap.Height)));
}
3.给主窗体添加一个主菜单,该主菜单完成了一些基本的操作,包括"打开文件"、"保存文件"、"退出"、"翻转操作"、"灰度操作"、"增亮操作"等。前面三个操作完成图像文件的打开和保存以及程序的退出功能,相应的事件处理函数如下:
private void menuItemOpen_Click(object sender, System.EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Bitmap文件(*.bmp)|*.bmp|
Jpeg文件(*.jpg)|*.jpg|
所有合适文件(*.bmp/*.jpg)|*.bmp/*.jpg";
openFileDialog.FilterIndex = 2 ;
openFileDialog.RestoreDirectory = true ;
if(DialogResult.OK == openFileDialog.ShowDialog())
{
m_Bitmap = (Bitmap)Bitmap.FromFile(openFileDialog.FileName, false);
this.AutoScroll = true;
this.AutoScrollMinSize=new Size ((int)(m_Bitmap.Width),(int)
m_Bitmap.Height));
this.Invalidate();
}
}
  其中,m_Bitmap为主窗体类的一个数据成员,声明为private System.Drawing.Bitmap m_Bitmap;(注:因为程序中用到了相关的类,所以在程序文件的开始处应添加using System.Drawing.Imaging;)同时,在该类的构造函数中,我们必须先给它new一个Bitmap对象:m_Bitmap = new Bitmap(2,2);上述代码中的this.Invalidate();完成主窗体的重绘工作,它调用了主窗体的OnPaint()函数,结果就将打开的图像文件显示在主窗体上。
private void menuItemSave_Click(object sender, System.EventArgs e)
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Bitmap文件(*.bmp)|*.bmp|
Jpeg文件(*.jpg)|*.jpg|
所有合适文件(*.bmp/*.jpg)|*.bmp/*.jpg";
saveFileDialog.FilterIndex = 1 ;
saveFileDialog.RestoreDirectory = true ;
if(DialogResult.OK == saveFileDialog.ShowDialog())
{
m_Bitmap.Save(saveFileDialog.FileName);
}
}
  其中m_Bitmap.Save(saveFileDialog.FileName);一句完成了图像文件的保存,正是运用了GDI+的强大功能,我们只需这么一条简单的语句就完成了以前很大工作量的任务,所以合理运用.NET中的新机制一定会大大简化我们的工作的。
private void menuItemExit_Click(object sender, System.EventArgs e)
{
this.Close();
}
  接下来,三个主要操作的事件处理函数如下:
private void menuItemInvert_Click(object sender, System.EventArgs e)
{
if(Filters.Invert(m_Bitmap))
this.Invalidate();
}
private void menuItemGray_Click(object sender, System.EventArgs e)
{
if(Filters.Gray(m_Bitmap))
this.Invalidate();
}
private void menuItemBright_Click(object sender, System.EventArgs e)
{
Parameter dlg = new Parameter();
dlg.nValue = 0;
if (DialogResult.OK == dlg.ShowDialog())
{
if(Filters.Brightness(m_Bitmap, dlg.nValue))
this.Invalidate();
}
}
  三个函数中分别调用了相应的图像处理函数Invert()、Gray()、Brightness()等三个函数。这三个函数Filters类中的三个类型为public的静态函数(含有static关键字),它们的返回值类型均是bool型的,根据返回值我们可以决定是否进行主窗体的重绘工作。
  Invert()、Gray()、Brightness()等三个函数均包含在Filters类里面,Invert()函数的算法如下:
public static bool Invert(Bitmap b)
{
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y
  该函数以及后面的函数的参数都是Bitmap类型的,它们传值的对象就是程序中所打开的图像文件了。该函数中的BitmapData类型的bmData包含了图像文件的内部信息,bmData的Stride属性指明了一条线的宽度,而它的Scan0属性则是指向图像内部信息的指针。本函数完成的功能是图像颜色的翻转,实现的方法即用255减去图像中的每个象素点的值,并将所得值设置为原象素点处的值,对每个象素点进行如此的操作,只到整幅图像都处理完毕。函数中的unsafe代码块是整个函数的主体部分,首先我们取得图像内部数据的指针,然后设置好偏移量,同时设置nWidth为b.Width*3,因为每个象素点包含了三种颜色成分,对每个象素点进行处理时便要进行三次处理。接下来运用两个嵌套的for循环完成对每个象素点的处理,处理的核心便是一句:p[0] = (byte)(255-p[0]);。在unsafe代码块后,便可运用b.UnlockBits(bmData)进行图像资源的释放。函数执行成功,最后返回true值。注:由于是要编译不安全代码,所以得将项目属性页中的"允许不安全代码块"属性设置为true,图示如下:
http://www.yesky.com/image20010518/53286.jpg
该函数实现的程序效果如下:
http://www.yesky.com/image20010518/53287.jpg
http://www.yesky.com/image20010518/53288.jpg
 Gray()函数的算法如下:
public static bool Gray(Bitmap b)
{
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
byte red, green, blue;
for(int y=0;y
  本函数完成的功能是对图像进行灰度处理,我们的基本想法可是将每个象素点的三种颜色成分的值取平均值。然而由于人眼的敏感性,这样完全取平均值的做法的效果并不好,所以在程序中我取了三个效果最好的参数:.299,.587,.114。不过在这里要向读者指明的是,在GDI+中图像存储的格式是BGR而非RGB,即其顺序为:Blue、Green、Red。所以在for循环内部一定要设置好red、green、blue等变量的值,切不可颠倒。函数执行成功后,同样返回true值。
  该函数实现的程序效果如下:
http://www.yesky.com/image20010518/53289.jpg
http://www.yesky.com/image20010518/53293.jpg
 Brightness()函数的算法如下:
public static bool Brightness(Bitmap b, int nBrightness)
{
if (nBrightness 255)
return false;
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width,
b.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
int nVal = 0;
unsafe
{
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
int nWidth = b.Width * 3;
for(int y=0;y 255) nVal = 255;
p[0] = (byte)nVal;
++p;
}
p += nOffset;
}
}
b.UnlockBits(bmData);
return true;
}
  本函数完成的功能是对图像进行增亮处理,它比上面两个函数多了一个增亮参数-nBrightness,该参数由用户输入,范围为-255~255。在取得了增亮参数后,函数的unsafe代码部分对每个象素点的不同颜色成分进行逐个处理,即在原来值的基础上加上一个增亮参数以获得新的值。同时代码中还有一个防止成分值越界的操作,因为RGB成分值的范围为0~255,一旦超过了这个范围就要重新设置。函数最后执行成功后,同样得返回true值。
  该函数实现的程序效果如下:
http://www.yesky.com/image20010518/53295.jpg
三.小结:
  本文通过一个简单的实例向大家展现了用Visual C#以及GDI+完成数字图像处理的基本方法,通过实例,我们不难发现合理运用新技术不仅可以大大简化我们的编程工作,还可以提高编程的效率。不过我们在运用新技术的同时也得明白掌握基本的编程思想才是最主要的,不同的语言、不同的机制只是实现的具体方式不同而已,其内在的思想还是相通的。对于上面的例子,掌握了编写图像处理函数的算法,用其他的方式实现也应该是可行的。同时,在上面的基础上,读者不妨试着举一反三,编写出更多的图像处理的函数来,以充实并完善这个简单的实例。

摘要
本文讨论了如何使用Windows Installer技术发布.NET程序,以及如何使用native代码判断目标机器上是否安装有.NET Framework; 如果没有,将自动安装.NET Framework然后安装作者自己的.NET程序。

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

目录

本文内容

制作自己的安装程序

发布.NET Framework

制作自己的native安装程序

使用方法

总结

作者

本文内容

 
1. 使用VS.NET来制作安装程序。

2. 如何把.NET Framework 部署到目标机器。

3. 如何使用Native代码把.NET Framework和自己的安装程序制作为一个统一的安装程序。该程序做到如果目标机器上没有.NET Framework,将自动安装.NET Framework然后再自动安装作者自己的程序。

 
制作自己的安装程序

 
在VS.NET中,我们可以通过建立"Setup and Deployment Projects"项目,非常灵活方便的把自己的.NET程序制作为Windows Installer文件。比如,我们可以很方便的定制下面这些选项:
1. 是否在桌面上放置快捷方式。
2. 注册自己的文件类型,可以通过双击该文件来使用自己的程序打开。
3. 注册表的处理
在下面的MSDN站点,我们可以获得在VS.NET中通过Setup and Deployment Projects来制作自己的安装程序的示例:
http://msdn.microsoft.com/library/en-us/vsintro7/html/vbconDeploymentScenarios.asp

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

发布.NET Framework
 
.NET Framework 1.0提供一个用来重新部署.NET的exe文件:Dotnetfx.exe. 它包含了Common Language Runtime和其它.NET程序运行时必不可少的内容。
我们可以从下面的站点下载该exe文件:
http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/829/msdncompositedoc.xml
同时,我们也可以在VS.NET安装CD或者DVD中找到该文件。
我们可以通过多种方式来通过运行Dotnetfx.exe把.NET Framework部署到目标机器上:
1. 通过Microsoft Systems Management Server部署。
2. 通过Active Directory部署。
3. 使用第三方工具。
具体的信息,我们可以参阅下面的文章:
http://msdn.microsoft.com/library/en-us/dnnetdep/html/redistdeploy.asp

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

制作自己的native安装程序
 
如果我们要把自己的.NET程序发布到目标机器上,同时我们不确定该目标机器是否已经安装了.NET Framework, 那我们就需要自己设计一段unmanaged代码,来判断目标机器是否安装了.NET Framework, 如果没有,则运行Dotnetfx.exe安装.NET Framework, 然后利用Windows Installer安装自己的程序。
在MSDN的下面网页上,我们可以获得一个使用unmanaged C++实现的安装程序和它的源代码:
http://msdn.microsoft.com/downloads/default.asp?URL=/code/sample.asp?url=/msdn-files/027/001/830/msdncompositedoc.xml
1. 在CSettings class中,通过读取"settings.ini",获得您自己的MSI安装文件和dotnetfx.exe的路径,以及其他您自己的设置。(比如.NET Framework的语言版本)
GetCaptionText(void)
GetDialogText(void)
GetErrorCaptionText(void)
GetIniName(void)
GetProductName(void)
 
Parse()函数用来解析settings.ini文件。
2. 在Main.cpp文件中,全局函数FxInstallRequired()判断是否要在目标机器上安装.NET Framework. FxInstallRequired()会检测下面的注册表键值和dotnetfx.exe的版本和语言设置。
HKLM\SOFTWARE\Microsoft\.NETFramework\policy\v1.0
3.如果需要安装.NET Framework, 在全局函数ExecCmd()中调用下面的命令silent安装dotnetfx.exe:
dotnetfx.exe /q:a /c:"install /l /q"
4。 在ExecCmd()全局函数中调用下面的命令安装您自己的MSI文件:
msiexec /i <your MSI file> REBOOT=ReallySuppress

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

使用方法
 
如果我们使用上面的native代码作为自己的安装程序,那么我们可以通过下面的步骤把自己的.NET程序和它结合在一起:
1.把您自己的.NET程序制作成为Windows Installer (.MSI)文件。
2.打开"settings.ini"文件,在"Msi" key中设置您自己的.NET程序的MSI文件路径和文件名;在"FxInstallerPath" Key中,设置dotnetfx.exe的路径。具体的参数信息,您可以从下面文章中得到:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetdep/html/redistdeploy.asp
3. 把"setup.exe", "settings.ini", "dotnetfx.exe"和您自己的MSI安装文件,发送到目标机器上,然后运行"setup.exe", 安装程序会自动检测是否有.NET Framwork, 如果没有,将首先运行dotnetfx.exe。
通过上述步骤,您可以将自己的.NET程序成功的部署到没有安装.NET Framwork环境的机器上。

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

总结
 
通过上述步骤,您可以将自己的.NET程序成功的部署到没有安装.NET Framwork环境的机器上。

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

作者
 
张广辉
2002年10月22日

一、最小化窗口

点击“X”或“Alt+F4”时,最小化窗口,
如:
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
if (m.Msg == WM_SYSCOMMAND && (int) m.WParam == SC_CLOSE)
{
// User clicked close button
this.WindowState = FormWindowState.Minimized;
return;
}
base.WndProc(ref m);
}

二、如何让Foreach 循环运行的更快
foreach是一个对集合中的元素进行简单的枚举及处理的现成语句,用法如下例所示:
using System;
using System.Collections;
namespace LoopTest
{
class Class1
{
static void Main(string[] args)
{
// create an ArrayList of strings
ArrayList array = new ArrayList();
array.Add("Marty");
array.Add("Bill");
array.Add("George");
// print the value of every item
foreach (string item in array)
{
Console.WriteLine(item);
}
}
}
你可以将foreach语句用在每个实现了Ienumerable接口的集合里。如果想了解更多foreach的用法,你可以查看.NET Framework SDK文档中的C# Language Specification。

在编译的时候,C#编辑器会对每一个foreach 区域进行转换。IEnumerator enumerator = array.GetEnumerator();
try
{
string item;
while (enumerator.MoveNext())
{
item = (string) enumerator.Current;
Console.WriteLine(item);
}
}
finally
{
IDisposable d = enumerator as IDisposable;
if (d != null) d.Dispose();
}
这说明在后台,foreach的管理会给你的程序带来一些增加系统开销的额外代码。

三、将图片保存到一个XML文件
WinForm的资源文件中,将PictureBox的Image属性等非文字内容都转变成文本保存,这是通过序列化(Serialization)实现的,
例子://
using System.Runtime.Serialization.Formatters.Soap;
Stream stream = new FileStream("E:\\Image.xml",FileMode.Create,FileAccess.Write,FileShare.None);
SoapFormatter f = new SoapFormatter();
Image img = Image.FromFile("E:\\Image.bmp");
f.Serialize(stream,img);
stream.Close();

四、屏蔽CTRL-V
在WinForm中的TextBox控件没有办法屏蔽CTRL-V的剪贴板粘贴动作,如果需要一个输入框,但是不希望用户粘贴剪贴板的内容,可以改用RichTextBox控件,并且在KeyDown中屏蔽掉CTRL-V键,例子:

private void richTextBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
if(e.Control && e.KeyCode==Keys.V)
e.Handled = true;
}

一、判断文件或文件夹是否存在
使用System.IO.File,要检查一个文件是否存在非常简单:
bool exist = System.IO.File.Exists(fileName);

如果需要判断目录(文件夹)是否存在,可以使用System.IO.Directory:
bool exist = System.IO.Directory.Exists(folderName);

二、使用delegate类型设计自定义事件
在C#编程中,除了Method和Property,任何Class都可以有自己的事件(Event)。定义和使用自定义事件的步骤如下:
(1)在Class之外定义一个delegate类型,用于确定事件程序的接口
(2)在Class内部,声明一个public event变量,类型为上一步骤定义的delegate类型
(3)在某个Method或者Property内部某处,触发事件
(4)Client程序中使用+=操作符指定事件处理程序

例子: // 定义Delegate类型,约束事件程序的参数
public delegate void MyEventHandler(object sender, long lineNumber) ;

public class DataImports
{
// 定义新事件NewLineRead
public event MyEventHandler NewLineRead ;

public void ImportData()
{
long i = 0 ; // 事件参数
while()
{
i++ ;
// 触发事件
if( NewLineRead != null ) NewLineRead(this, i);
//...
}
//...
}
//...
}

// 以下为Client代码

private void CallMethod()
{
// 声明Class变量,不需要WithEvents
private DataImports _da = null;
// 指定事件处理程序
_da.NewLineRead += new MyEventHandler(this.DA_EnterNewLine) ;
// 调用Class方法,途中会触发事件
_da.ImportData();
}
// 事件处理程序
private void DA_EnterNewLine(object sender, long lineNumber)
{
// ...
}

三、IP与主机名解析
使用System.Net可以实现与Ping命令行类似的IP解析功能,例如将主机名解析为IP或者反过来: private string GetHostNameByIP(string ipAddress)
{
IPHostEntry hostInfo = Dns.GetHostByAddress(ipAddress);
return hostInfo.HostName;
}
private string GetIPByHostName(string hostName)
{
System.Net.IPHostEntry hostInfo = Dns.GetHostByName(hostName);
return hostInfo.AddressList[0].ToString();
}

In some scenarios, you may wish to ensure that a user can run only one instance of your application at a time. Besides ensuring that only a single instance of your application is running, you may also want to bring the instance already running to the front and restore it, if it is minimized.
First, to ensure that only one instance of your application is running at a time, the best method I've found is to create a mutex that is held by the operating system (thanks to Michael Covington). This will put a request to the operating system that a mutex be created if one does not already exist. Only one mutex can ever be created at a time, so if you request a new one and it cannot be created, you can safely assume that your application is already running.

using System.Threading
using System.Runtime.InteropServices;

public class Form1 : Form
{
[STAThread]
static void Main()
{
bool createdNew;

Mutex m = new Mutex(true, "YourAppName", out createdNew);

if (! createdNew)
{
// app is already running...
MessageBox.Show("Only one instance of this application is allowed at a time.");
return;
}

Application.Run(new Form1());

// keep the mutex reference alive until the normal termination of the program
GC.KeepAlive(m);
}
}

The above code will work for the vast majority of your needs. It will also run under scenarios where your code is executing with less than FullTrust permissions (see Code Access Security in MSDN for further information).

If your application can run with Full Trust permissions, we can take this a step further and find the window of the application instnace already running and bring it to the front for the user:

public class Form1 : Form
{
[STAThread]
static void Main()
{
bool createdNew;

System.Threading.Mutex m = new System.Threading.Mutex(true, "YourAppName", out createdNew);

if (! createdNew)
{
// see if we can find the other app and Bring it to front
IntPtr hWnd = FindWindow("WindowsForms10.Window.8.app3", "YourAppName");

if(hWnd != IntPtr.Zero)
{
Form1.WINDOWPLACEMENT placement = new Form1.WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);

GetWindowPlacement(hWnd, ref placement);

if(placement.showCmd != SW_NORMAL)
{
placement.showCmd = SW_RESTORE;

SetWindowPlacement(hWnd, ref placement);
SetForegroundWindow(hWnd);
}
}

return;
}

Application.Run(new Form1());

// keep the mutex reference alive until the normal termination of the program
GC.KeepAlive(m);
}

private const int SW_NORMAL = 1; // see WinUser.h for definitions
private const int SW_RESTORE = 9;

[DllImport("User32",EntryPoint="FindWindow")]
static extern IntPtr FindWindow(string className, string windowName);

[DllImport("User32",EntryPoint="SendMessage")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("User32",EntryPoint="SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("User32",EntryPoint="SetWindowPlacement")]
private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

[DllImport("User32",EntryPoint="GetWindowPlacement")]
private static extern bool GetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

private struct POINTAPI
{
public int x;
public int y;
}

private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}

private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public POINTAPI ptMinPosition;
public POINTAPI ptMaxPosition;
public RECT rcNormalPosition;
}
}

As you can see, with minimal effort, you can easily add a polished touch to your application. This might even help you avoid some extra legwork in ensuring that there are no issues with running multiple instances of your app at the same time that you might have to address.

For more information about the Platform Invoke mechanisms to call Win32 API functions, I recommend that you check out .NET Framework Solutions: In Search of the Lost Win32 API by John Mueller and Charles Petzold's seminal classic Programming Windows.

Until Longhorn comes out and more of the Windows platform becomes managed, platform invokes and interop will remain a key technology to understand and use to your advantage to fill the gaps left by the Windows Forms framework.

UPDATE:
Visual Studio .NET 2005 (aka. “Whidbey”) will let you specify Single Instance behavior for Visual Basic .NET projects through the Project Properties page. Curious as to why this option is available for VB projects and not for C# projects, as this seems to instruct the runtime or some framework library not to load more than one instance.

北理代理助手是专为北京理工大学开发的代理设置软件。使用该软件可以快速的切换、验证代理,并可随时下载网协提供的最新的代理列表。

http://www.felixwoo.com/wp-content/uploads/attachments/old/20041092068694.jpg

特色:
1、专为北理校园网设计 可以随时从网协服务器下载最新代理列表,列表数据由服务器每小时自动验证更新
2、快速切换代理 双击代理列表中的代理或在悬浮窗菜单中选择即可切换,无需重启IE
3、快速启用/禁用代理 通过主界面上选择或使用热键(Alt+F1)即可方便的启用或禁用代理,无需重启IE
4、自动启用最快代理 勾选此选项后即可在下载或验证结束后自动启用最快的代理
5、本地代理列表管理方便 除了可以从服务器下载最新的代理列表,您还可以在本地手动进行验证,验证结果按照由快到慢的顺序自动排列。您也可以手动的添加或删除代理。
6、添加代理方便 直接将代理文本拖动到悬浮窗即可添加到代理列表
7、绿色软件 免安装、不更改注册表、程序小巧(不到200K)

使用说明

http://www.felixwoo.com/wp-content/uploads/attachments/old/200410920650941.jpg

下载地址:
/download/北理代理助手.exe
.NET Framework /dotnetfx.exe (运行前请先安装)

Felix
2004.10.9

For performance test, it is very important to measure code execution time. Without measurement, there is no way to tell if we meet performance goal.

System.Environment.TickCount is not suitable for high resolution timing. Its resolution cannot be less than 500 milliseconds.

System.Datetime.Now returns the current time of type DateTime. With start datetime and end datetime, we can get the interval as a value of TimeSpan by (end - start ) . TimeSpan.TotalMilliseconds or TimeSpan.Ticks may be used to read interval. From MSDN, the resolution of System.Datetime.Now depends on the system timer.

System Approximate Resolution

Windows NT 3.5 and later 10 milliseconds

Windows 98 55 milliseconds

So it is better but not high resolution at all.

In .NET framework v1 and v1.1, we have to use P/Invoke to get high resolution reading. The class below is commonly used in performance test measurement. It is querying hardware to get high resolution performance counter. For more information (including what happens if the hardware does not support high resolution performance counter) please check MSDN for QueryPerformanceCounter and QueryPerformanceFrequency.

public class HighResolutionTimer

{

private long start;

private long stop;

private long frequency;

public HighResolutionTimer()

{

QueryPerformanceFrequency (ref frequency);

}

public void Start ()

{

QueryPerformanceCounter (ref start);

}

public void Stop ()

{

QueryPerformanceCounter (ref stop);

}

public float ElapsedTime

{

get{

float elapsed = (((float)(stop - start)) / ((float) frequency));

return elapsed;

}

}

[System.Runtime.InteropServices.DllImport("KERNEL32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]

private static extern bool QueryPerformanceCounter( [In, Out] ref long performanceCount);

[System.Runtime.InteropServices.DllImport("KERNEL32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]

private static extern bool QueryPerformanceFrequency( [In, Out] ref long frequency);

}

To illustrate the use of this class, check the code below.

HighResolutionTimer timer = new HighResolutionTimer();

timer.Start();

//Perf Test

timer.Stop();

Console.WriteLine(timer.ElapsedTime);

(This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm)

作者:孙展波

来源: http://blogs.gotdotnet.com/ZHANBOS

BIT Google 3.0更新日志
=================================
1.增加悬浮窗,把您想要搜索的文本拖动到悬浮窗即可搜索,搜索时悬浮窗会自动变为红色
2.增加"搜索剪贴板"功能,即可搜索您刚刚复制的文本内容
3.增加天气预报小栏目,同步MSN的北京天气预报
4.主界面最小化时缩小到系统托盘,单击系统托盘图标或双击悬浮窗即可恢复主界面

http://www.felixwoo.com/wp-content/uploads/attachments/old/200492817266477.jpg

http://www.felixwoo.com/wp-content/uploads/attachments/old/2004928172614734.jpg

http://www.felixwoo.com/wp-content/uploads/attachments/old/2004928172621354.jpg

而完成以上所有的功能您都无需连接外网

BIT Google 2.0 更新日志
=================================
1.增加网页模式查看搜索结果
2.列表模式增加鼠标右键菜单,可以选择打开网页和复制地址
3.修改了一些小bug..

  BIT Google是专为北京理工大学校园网提供的Google搜索服务软件。使用该软件无需连接外网即可搜索Google。
  BIT Google每页显示10个搜索条目,单击条目可显示网页内容简介,双击直接打开网页。BIT Google全面支持Google的搜索表达式,如“中国+北京”、“水果-苹果”等等...
  这个软件是我第一个使用WebService的软件,实现方法就是在在校内的一台可以访问外网的服务器上架设了Google搜索的WebService,该WebService又调用了Google提供的WebService。校内的用户使用软件时远程调用校内的WebService,也就是说用校内的服务器做中转代理,从而实现了不连接外网进行Google的搜索。
  这个软件也是使用C#开发的,所以使用前需要先安装.NET Framework。

下载地址:www.felixwoo.com/download/BITGoogle.exe

http://www.felixwoo.com/wp-content/uploads/attachments/old/2004928172650486.jpg

京ICP备05053527号
经过26次查询历时0.470秒终于生成了此页面
Powered by WordPress & Designed by Felix © 2012