[转载]asp.net mvc2网站部署在IIS6的方法 - 我思故我在... - 博客园

mikel阅读(1000)

[转载]asp.net mvc2网站部署在IIS6的方法 – 我思故我在… – 博客园.

部署环境: Server 2003 +IIS6

1.先安装好IIS6,再安装.net framework 4.0和ASP.NET mvc 安装包(主要是里面的一个dll,不安装也可以,只需要找到这个dll,将mvc.dll 放入网站bin目录下,这个dll文件的默认路径是C:\Program Files\Microsoft ASP.NET\ASP.NET MVC 2\Assemblies\System.Web.Mvc.dll)

 

2.在IIS中新建网站设置web主目录,这个不详细说了,接着说重点

 

3.在发布的网站上右击【属性】—【主目录】—-【配置】,在弹出的【应用程序配置】窗口中点击【添加】,点击【浏览】将“可执行文件”设置为“C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll”,“扩展名”设置为”.mvc”,取消【确认文件是否存在

然后在下面点击【插入】,同样选择aspnet_isapi.dll,取消【确认文件是否存在】。

在发布的网站上右击【属性】–【APS.NET】,将【ASP.NET version】设置为4.0.30319

 

4.在【Web服务扩展】中设置ASP.NET v4.0.30319 为允许

 

以上配置完成后就大功告成了,以上亲测成功,若有问题欢迎留言一起探讨!

 

PS:若先装的.net framework 4.0,后装的IIS,需要注册aspnet到IIS,方法如下:

注意:要以管理员的身份运行

启动cmd窗口 (win键+R )  ,找到 4.0所在的目录,本人机器目录是
C:\Windows\Microsoft.NET\Framework\v4.0.30319

启动CMD进入上面的目录C:\Windows\Microsoft.NET\Framework\v4.0.30319

运行  aspnet_regiis.exe -i

稍等一会, aspnet_regiis 注册成功

[转载]C# 生成随机数 - 许明吉博客 - 博客园

mikel阅读(1036)

[转载]C# 生成随机数 – 许明吉博客 – 博客园.

private static char[] constant =
{
'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
};
public static string GenerateRandomNumber(int Length)
{
System.Text.StringBuilder newRandom = new System.Text.StringBuilder(62);
Random rd = new Random();
for (int i = 0; i < Length; i++)
{
newRandom.Append(constant[rd.Next(62)]);
}
return newRandom.ToString();
}

     随机数的使用很普遍,可用它随机显示图片,用它防止无聊的人在论坛灌水还可以用来加密信息等等。本文讨论如何在一段数字区间内随机生成若干个互不相同的随机数,比如在从1到20间随机生成6个互不相同的整数,并通过此文介绍Visual C#中随机数的用法。
.net.Frameword中提供了一个专门产生随机数的类System.Random,此类默认情况下已被导入,编程过程中可以直接使用。我们知道, 计算机并不能产生完全随机的数字,它生成的数字被称为伪随机数,它是以相同的概率从一组有限的数字中选取的,所选的数字并不具有完全的随机性,但就实用而 言,其随机程度已经足够了。

我们可以用以下两种方法初始化一个随机数发生器;

函数是这样用,比如100至999的随机数

Random ran=new Random();
int RandKey=ran.Next(100,999);

不过这样会有重复,可以给Random一个系统时间做为参数,以此产生随机数,就不会重复了

第一种方法不指定随机种子,系统自动选取当前时前作随机种子:

Random ra=new Random();

第二种方法是指定一个int型的参数作为随机种子:

int iSeed=6;
Random ra
=new Random(iSeed);

下面我们要用到Random.Next()方法产生随机数。

ra.Next();

它返回一个大于或等于零而小于2,147,483,647的数,这并不满足我们的需要,下面我们介绍它的重载函数和其它一些方法。

publicvirtualint Next(int);

用法:ra.next(20)
返回一个小于所指定最大值(此处为20)的正随机数。

publicvirtualint Next(int minValue, int maxValue);

用法:ra.next(1,20)
返回一个指定范围内(此处为1-20之间)的随机数,我们在下面的实例中会用到此函数。

类System.Random还有几个方法分别是:
公共方法:
NextBytes用随机数填充指定字节数组的元素。
NextDouble返回一个介于 0.0 和 1.0 之间的随机数。

受保护的方法:
Sample返回一个介于 0.0 和 1.0 之间的随机数,只允许子类对象访问。

以上介绍了随机数的基本用法,下面我们用一个实例来做更进一步的介绍。要在一段数字区间内随机生成若干个互不相同的随机数,比如在从1到20间随机生成6个互不相同的整数。

主要是下面两个函数getRandomNum与getNum:

public int[] getRandomNum(int num,int minValue,int maxValue)
{
Random ra=new Random(unchecked((int)DateTime.Now.Ticks));
int[] arrNum=new int[num];
int tmp=0;
for (int i=0;i<=num-1;i ){
tmp=ra.Next(minValue,maxValue); //随机取数
arrNum[i]=getNum(arrNum,tmp,minValue,maxValue,ra); //取出值赋到数组中
}
return arrNum;
}

getRandomNum即是在区间[minValue,maxValue]取出num个互不相同的随机数,返回的数组包含着结果。

其中随机数是这样创建的 Random ra=new Random(unchecked((int)DateTime.Now.Ticks));为什么不用Random ra=new Random();(系统自动选取当前时前作随机种子)呢?

用系统时间做随机种子并不保险,如果应用程序在一个较快的计算机上运行,则该计算机的系统时钟可能没有时间在此构造函数的调用之间进行更改,Random 的不同实例的种子值可能相同。这种情况下,我们就需要另外的算法来保证产生的数字的随机性。所以为了保证产生的随机数足够”随机”,我们不得不使用复杂一点的方法来获得随机种子。在上面的这段程序中,我们首先使用系统时间作为随机种子,然后将上一次产生的随机数跟循环变量和一个与系统时间有关的整型参数相乘,以之作为随机种子,从而得到了每次都不同的随机种子,保证了产生足够”随机”的随机数。

函数getNum是一递归,用它来检测生成的随机数是否有重复,如果取出来的数字和已取得的数字有重复就重新随机获取。值得注意的是要用一同一个随机数实例生成,所以ra要作为参数传入getNum中,否则生成的数字会有重复。

public int getNum(int[] arrNum,int tmp,int minValue,int maxValue,Random ra){
int n=0;
while (n<=arrNum.Length-1)
{
if (arrNum[n]==tmp) //利用循环判断是否有重复
{
tmp=ra.Next(minValue,maxValue); //重新随机获取。
getNum(arrNum,tmp,minValue,maxValue,ra);//递归:如果取出来的数字和已取得的数字有重复就重新随机获取。
}
n ;
}
return tmp;
}

最后就是要显示出来,当点击一个button时取出的数字显示在一个label中。

private void button1_Click(object sender, System.EventArgs e)
{
int[] arr=getRandomNum(6,1,20); //从1至20中取出6个互不相同的随机数
int i=0;
string temp="";
while (i<=arr.Length-1){
temp =arr[i].ToString() " ";
i ;
}
label1.Text=temp; //显示在label1中
}

[转载]ASP.NET MVC 的Action的返回值类型总结 - Creater - 博客园

mikel阅读(1459)

[转载]Action的返回值类型总结 – Creater – 博客园.

Action的返回值

 

MVC 中的 ActionResult是其他所有Action返回类型的基类,下面是我总结的返回类型,以相应的帮助方法:

下面是这些方法使用的更详细的例子

一、返回View     View()方法的几种重载:

public ViewResult Index() {
    return View();
}
 
public ViewResult Index() {
    return View("Index", "_AlternateLayoutPage");
}
 
public ViewResult Index() {
    return View("~/Views/Other/Index.cshtml");
}

二、返回partialView

public ActionResult PartialViewResult()
        {
            return PartialView();
        }
 
        //禁止直接访问的ChildAction
        [ChildActionOnly]
        public ActionResult ChildAction()
        {
            return PartialView();
        }

我们直接右键当前的Action名称就可以创建与Action同名的View,无参数的情况下,PartialView返回的就是与Action同名的View。

三、跳转的几种实现方式

1、通过静态URL进行跳转:
public RedirectResult Redirect() {
    return Redirect("/Example/Index");
}
 
2、通过RedirectToRoute方法跳转:
public RedirectToRouteResult Redirect() {
   return RedirectToRoute(new {
        controller = "Example",
        action = "Index",
        ID = "MyID"
   });
}
 
3、通过RedirectToAction方法跳转:
public RedirectToRouteResult Redirect() {
    return RedirectToAction("Index", "Basic");                       //如果只有action名称的话,Controller默认为当前Controller
}

四、返回json字符串

public ActionResult Json() 
{
        Dictionary<string,object> dic = new Dictionary<string, object>(); 
        dic.Add("id",100); 
        dic.Add("name","hello"); 
        return Json(dic, JsonRequestBehavior.AllowGet); 
}

主要用于返回json格式对象,可以用ajax操作;
注意:需要设置参数,JsonRequestBehavior.AllowGet,否则会提示错误:此请求已被阻止,因为当用在GET 请求中时,会将敏感信息透漏给第三方网站

若要允许 GET 请求,请将JsonRequestBehavior设置为AllowGet。

五、返回ContentResult

public ActionResult Content() 
{ 
       return  Content("Test Content", "text/html"); // 可以指定文本类型 
} 

页面输出“Test Content”;此类型多用于在ajax操作中需要返回的文本内容

六、返回JavaScriptResult

public ActionResult JavaScript() 
{ 
       string str =string.Format("alter('{0}');", "弹出窗口"); 
       return JavaScript(str); 
} 

这里并不会直接响应弹出窗口,需要用页面进行再一次调用。这个可以方便根据不同逻辑执行不同的js操作但

七、返回FileResult

public ActionResult File() 
{ 
       string fileName ="~/Content/test.zip"; // 文件名 
        string downFileName ="文件显示名称.zip"; // 要在下载框显示的文件名 
         return File(fileName,"application/octet-stream", downFileName); 
}

直接下载test.zip后保存到本地则为”文件显示名称.zip”

八、返回404、401

返回404public HttpStatusCodeResult StatusCode() {
     return HttpNotFound();
}


返回401
public HttpStatusCodeResult StatusCode() {
    return new HttpUnauthorizedResult();
}

[转载]ASP.net mvc Json使用学习+实例 - 竹青+ - 博客园

mikel阅读(1065)

[转载].net mvc Json使用学习+实例 – 竹青+ – 博客园.

最近刚开始接触 .net mvc,由于项目需要就学习一下。 记录一下,复习温故以便以后使用!

1、 .net MVCController

   mvc中所有的controller类都必须使用“Controller”后缀来命名

   并且对Action也有一定的要求:

 

  • 必须是一个public方法
  • 必须是实例方法
  • 没有标志NonActionAttribute特性的(NoAction)
  • 不能被重载
  • 必须返回ActionResult

2、 返回JsonResult序列化的Json对象

public class MyController : Controller
{
// 必须返回ActionResult类型
public ActionResult HelloWorld()
{
ViewData["Message"] = "Hello World!";
return View();
}

public ActionResult Json()
{
Dictionary&lt;string, object&gt; dic = new Dictionary&lt;string, object&gt;();
dic.Add("id", 100);
dic.Add("name", "hello");
return Json(dic, JsonRequestBehavior.AllowGet);
}
}

  注意:需要设置参数,JsonRequestBehavior.AllowGet
否则会提示错误:此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站
若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet 3、View层 接受页面 使用JQuery

$.ajax({
url: "/My/Json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
/*
//接受数据
当 data 为拼接字符串时,需要下面方法转换成 json对象
var json = jQuery.parseJSON(data);
*/
alert(data.id+","+data.name); // data 为json对象
},
error: function ErrorCallback(XMLHttpRequest, textStatus, errorThrown) {
alert(errorThrown + ":" + textStatus);
}
});

[转载]C#开发微信公众平台-就这么简单(附Demo) - 田园里的蟋蟀 - 博客园

mikel阅读(1076)

[转载]C#开发微信公众平台-就这么简单(附Demo) – 田园里的蟋蟀 – 博客园.

写在前面

  1. 服务号和订阅号
  2. URL配置
  3. 创建菜单
  4. 查询、删除菜单
  5. 接受消息
  6. 发送消息(图文、菜单事件响应)
  7. 示例Demo下载
  8. 后记

  最近公司在做微信开发,其实就是接口开发,网上找了很多资料,当然园友也写了 很多教程,但都是理论说了一大堆,实用指导或代码很少。如果你自己仔细研究下,其实就那么点东西,C#实现起来也很简单,原本不想写这篇文章的,但是本人 当时摸索走了很多弯路,这边总结下,希望初次接触微信公众平台的朋友别像当时的我一样。

  自己动手,丰衣足食。

服务号和订阅号

  服务号是公司申请的微信公共账号,订阅号是个人申请的,我个人也申请了一个,不过没怎么用。

  服务号

  1. 1个月(30天)内仅可以发送1条群发消息。
  2. 发给订阅用户(粉丝)的消息,会显示在对方的聊天列表中。
  3. 在发送消息给用户时,用户将收到即时的消息提醒。
  4. 服务号会在订阅用户(粉丝)的通讯录中。
  5. 可申请自定义菜单。

  订阅号

  1. 每天(24小时内)可以发送1条群发消息。
  2. 发给订阅用户(粉丝)的消息,将会显示在对方的订阅号文件夹中。
  3. 在发送消息给订阅用户(粉丝)时,订阅用户不会收到即时消息提醒。
  4. 在订阅用户(粉丝)的通讯录中,订阅号将被放入订阅号文件夹中。
  5. 订阅号不支持申请自定义菜单。

URL配置

  启用开发模式需要先成为开发者,而且编辑模式和开发模式只能选择一个,进入微信公众平台-开发模式,如下:

  需要填写url和token,当时本人填写这个的时候花了好久,我本以为填写个服务器的url就可以了(80端口),但是不行,主要是没有仔细的阅读提示信息,所以总是提示

  从上面可以看出,点击提交后微信会向我们填写的服务器发送几个参数,然后需要原样返回出来,所以在提交url的时候,先在服务器创建接口测试返回echostr参数内容。代码:

//成为开发者url测试,返回echoStr
public void InterfaceTest()
{
string token = "填写的token";
if (string.IsNullOrEmpty(token))
{
return;
}

string echoString = HttpContext.Current.Request.QueryString["echoStr"];
string signature = HttpContext.Current.Request.QueryString["signature"];
string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
string nonce = HttpContext.Current.Request.QueryString["nonce"];

if (!string.IsNullOrEmpty(echoString))
{
HttpContext.Current.Response.Write(echoString);
HttpContext.Current.Response.End();
}
}

  在一般处理程序ashx的ProcessRequest的方法内调用上面的方法,url填写的就是这个ashx的服务器地址,token是一个服务器标示,可以随便输入,代码中的token要和申请填写的一致,成为开发者才能做开发。

创建菜单

  我们添加一些微信服务号,聊天窗口下面有些菜单,这个可以在编辑模式简单配置,也可以在开发模式代码配置。微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口,可以看到创建菜单的一些要点,下面的使用网页调试工具调试该接口,只是调试接口是否可用,并不是直接创建菜单的,菜单分为两种:

  • click: 用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互。
  • view: 用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的url值 (即网页链接),达到打开网页的目的,建议与网页授权获取用户基本信息接口结合,获得用户的登入个人信息。

  click菜单需要填一个key,这个是在我们菜单点击事件的时候会用到,view只是一个菜单超链接。菜单数据是json格式,官网是php示例,其实C#实现起来也很简单,就是post发送一个json数据,示例代码:

public partial class createMenu : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
FileStream fs1 = new FileStream(Server.MapPath(".")+"\\menu.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs1, Encoding.GetEncoding("GBK"));
string menu = sr.ReadToEnd();
sr.Close();
fs1.Close();
GetPage("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=access_token", menu);
}
public string GetPage(string posturl, string postData)
{
Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
byte[] data = encoding.GetBytes(postData);
// 准备请求...
try
{
// 设置参数
request = WebRequest.Create(posturl) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
outstream = request.GetRequestStream();
outstream.Write(data, 0, data.Length);
outstream.Close();
//发送请求并获取相应回应数据
response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
string err = string.Empty;
Response.Write(content);
return content;
}
catch (Exception ex)
{
string err = ex.Message;
return string.Empty;
}
}
}

 menu.text里面的内容就是json示例菜单,大家可以从示例复制下来,按照你的需要修改一些就行了。

  关于access_token,其实就是一个请求标示,获取方式:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=appid&secret=secretappidsecret是开发者标示,在你的信息里面可以看到,通过这个链接返回一个json数据,就可以得到access_token值。

  需要注意的是:access_token 有一定的时效性,失效的话就需要重新获取下,这个在本机就可以创建,不需要上传到服务器,创建菜单正确,返回 {“errcode”:0,”errmsg”:”ok”}提示信息。这边就不截图了,大家试下就可以看到效果,一般创建菜单是一到两分钟生效,实在不行就 重新关注下。

查询、删除菜单

  查询和删除菜单也很简单,只不过是get请求,不需要传数据,看下示例代码:

public partial class selectMenu : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
GetPage("https://api.weixin.qq.com/cgi-bin/menu/get?access_token=access_token");
//GetPage("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=access_token");
}
public string GetPage(string posturl)
{
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
// 准备请求...
try
{
// 设置参数
request = WebRequest.Create(posturl) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
//发送请求并获取相应回应数据
response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
string err = string.Empty;
Response.Write(content);
return content;
}
catch (Exception ex)
{
string err = ex.Message;
return string.Empty;
}
}
}

  access_token获取方式上面已经讲过了,查询菜单返回的是json数据,其实就是我们创建菜单的menu.txt里面的内容。

  删除成功返回信息提示:{“errcode”:0,”errmsg”:”ok”},这个也只要在本地运行就可以了。

接受消息

  微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/index.php?title=接收普通消息,我们使用微信就是要对用户发送的信息进行处理,这边以接受普通消息为例,语音、图片消息等,举一反三可得。

  从文档上可以看出接受消息获得的是一个xml格式文件,当时有点犯傻的是,我要在哪边进行接受消息啊?还郁闷了半天,其实就是你一开始填写的url,是不是很汗颜啊,哈哈。


<![CDATA[toUser]]>
<![CDATA[fromUser]]>
1348831860
<![CDATA]>
<![CDATA[this is a test]]>
1234567890123456

我们在ashx添加下面代码:

public void ProcessRequest(HttpContext param_context)
{
string postString = string.Empty;
if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
{
using (Stream stream = HttpContext.Current.Request.InputStream)
{
Byte[] postBytes = new Byte[stream.Length];
stream.Read(postBytes, 0, (Int32)stream.Length);
postString = Encoding.UTF8.GetString(postBytes);
Handle(postString);
}
}
}

///
/// 处理信息并应答
///

private void Handle(string postStr)
{
messageHelp help = new messageHelp();
string responseContent = help.ReturnMessage(postStr);

HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;
HttpContext.Current.Response.Write(responseContent);
}

messageHelp是消息处理帮助类,这边提供下部分代码,完整的可以下载来,获取的postString是xml,格式如上,我们这边只需要转换成XmlDocument进行解析就行了:

//接受文本消息
public string TextHandle(XmlDocument xmldoc)
{
string responseContent = "";
XmlNode ToUserName = xmldoc.SelectSingleNode("/xml/ToUserName");
XmlNode FromUserName = xmldoc.SelectSingleNode("/xml/FromUserName");
XmlNode Content = xmldoc.SelectSingleNode("/xml/Content");
if (Content != null)
{
responseContent = string.Format(ReplyType.Message_Text,
FromUserName.InnerText,
ToUserName.InnerText,
DateTime.Now.Ticks,
"欢迎使用微信公共账号,您输入的内容为:" + Content.InnerText+"\r\n<a href="\&quot;http://www.cnblogs.com\&quot;">点击进入</a>");
}
return responseContent;
}
///
/// 普通文本消息
///

public static string Message_Text
{
get { return @"
<![CDATA[{0}]]>
<![CDATA[{1}]]>
{2}
<![CDATA]>
<![CDATA[{3}]]>
"; }
}

  上面的代码就是接受消息,并做一些处理操作,返回消息。

发送消息(图文、菜单事件响应)

  这边发送消息我分为三种:普通消息、图文消息和菜单事件响应。普通消息其实上面说接受消息的时候讲到了,完整的代码下边下载来看。

  我们先看下图文消息和菜单事件响应微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/index.php?title=回复图文消息#.E5.9B.9E.E5.A4.8D.E5.9B.BE.E6.96.87.E6.B6.88.E6.81.AF,xml格式为:


<![CDATA[toUser]]>
<![CDATA[fromUser]]>
12345678
<![CDATA[news]]>
2
<![CDATA[title1]]>
<![CDATA[description1]]>
<![CDATA[picurl]]> <![CDATA[url]]>

<![CDATA[title]]>
<![CDATA[description]]>
<![CDATA[picurl]]> <![CDATA[url]]>

 图文消息分为两种,我们先看下效果,找的圆通速递的微信服务号做示例:

  刚开始做的时候,我以为这两种应该不是用的同一个接口,但是在文档中找了半天也没有找到除这个之外的,就试了下两个图文消息,发现就是这个接口发送的,如果多个的话,item中的Description会失效,只会显示Title,大家试下就知道了,示例代码:

//事件
public string EventHandle(XmlDocument xmldoc)
{
string responseContent = "";
XmlNode Event = xmldoc.SelectSingleNode("/xml/Event");
XmlNode EventKey = xmldoc.SelectSingleNode("/xml/EventKey");
XmlNode ToUserName = xmldoc.SelectSingleNode("/xml/ToUserName");
XmlNode FromUserName = xmldoc.SelectSingleNode("/xml/FromUserName");
if (Event!=null)
{
//菜单单击事件
if (Event.InnerText.Equals("CLICK"))
{
if (EventKey.InnerText.Equals("click_one"))//click_one
{
responseContent = string.Format(ReplyType.Message_Text,
FromUserName.InnerText,
ToUserName.InnerText,
DateTime.Now.Ticks,
"你点击的是click_one");
}
else if (EventKey.InnerText.Equals("click_two"))//click_two
{
responseContent = string.Format(ReplyType.Message_News_Main,
FromUserName.InnerText,
ToUserName.InnerText,
DateTime.Now.Ticks,
"2",
string.Format(ReplyType.Message_News_Item,"我要寄件","",
"http://www.soso.com/orderPlace.jpg",
"http://www.soso.com/")+
string.Format(ReplyType.Message_News_Item, "订单管理", "",
"http://www.soso.com/orderManage.jpg",
"http://www.soso.com/"));
}
else if (EventKey.InnerText.Equals("click_three"))//click_three
{
responseContent = string.Format(ReplyType.Message_News_Main,
FromUserName.InnerText,
ToUserName.InnerText,
DateTime.Now.Ticks,
"1",
string.Format(ReplyType.Message_News_Item, "标题", "摘要",
"http://www.soso.com/jieshao.jpg",
"http://www.soso.com/"));
}
}
}
return responseContent;
}
///
/// 图文消息主体
///

public static string Message_News_Main
{
get
{
return @"
<![CDATA[{0}]]>
<![CDATA[{1}]]>
{2}
<![CDATA[news]]>
{3} {4}
";
}
}
///
/// 图文消息项
///

public static string Message_News_Item
{
get
{
return @"
<![CDATA[{0}]]>
<![CDATA[{1}]]>
<![CDATA[{2}]]> <![CDATA[{3}]]>
";
}
}

  需要注意的是:XmlNode Event = xmldoc.SelectSingleNode(/xml/Event)表示获取的是事件类型,XmlNode EventKey = xmldoc.SelectSingleNode(/xml/EventKey)表示事件标示,就是我们创建菜单添加click的key,通过key我们就可以判断出是点的哪个菜单。

 

  还有一点是回复超链接,有时候在服务号会发送一些链接,我们打开直接就会链接到相关网址,只需要在回复内容中添加:<a href=”http://www.baidu.com”>点击进入</a>,就可以了。

 

示例Demo下载

 

  下载地址:http://pan.baidu.com/s/1i3kMpwh

 

后记

 

关于微信公众平台当然还有许多其他的东西,本篇只是一些经验之谈,希望可以起到抛砖引玉的作用。有时候我们发现一些新鲜事物,觉得很难,就远远的看着,如果你用心的去感受它,其实也就这么回事。

 

不要高估别人,低估自己,其实深入内心,很多你自以为很了不起的人,其实也没什么,真是这样。

 

[转载]老程序员的下场_IT新闻_博客园

mikel阅读(762)

[转载]老程序员的下场_IT新闻_博客园.

英文原文:What happens to older developers?

长期从事编程活动的程序员都期望在 50 多岁时能爬到一个足够高的职位,或者能顺利的退休。

但我在这里讨论的可能是一个你还没有想过的问题:如果到那时你失业了呢?

50 多岁时你的职业仕途会成为一个问题。如果你有很好的技术,有人雇你,你会有一个很高的职衔,或你是一个专家,或有很好的人际关系,你都有可能找到一个新的职务。

否则,你会从衣食无忧沦落为无家可归。这是真的。我 55 岁,我的简历会让你感觉非常优秀,10 年前我能挣到多达 100 万美元。现在我是一个流浪汉。我身体不是很好,没有医险,没有牙医。能找到的工作只是一些基本不需要技术的体力劳动,我也干不了。

我在试着做家教。然而,这点钱基本上不够付燃气费的。一个行政助理公司的老总拒绝了我,他们只要有经验的。

有两个人考虑让我去照料他们更老的亲属,但我没去。我去那里后将有一个职责是伺候拉屎撒尿。

不希望你们也变成我这样。我能给你们的是我的一些建议:

1. 职场上往上爬,不要停。

2. 成为某一方面的专家——虽然保持足够宽的技术面也很重要,这样你才不会被淘汰。

3. 建立一个人际圈。扩大它。

4. 多样化你的投资。

5. 有工作时医疗保险一定要上,这方面不要出问题。如果你没了工作,没了钱,医疗保险也没有,这将会成为一个严重的问题。

6. 与人为善。但也不要犯傻。大部分你帮助过的人不会回报你。

关于成为某一方面的专家,我在 2011 年做了一段招聘工作,我敢肯定,市场上并不太喜欢全才/通才技术人员。

技术上我做全能选手做了 35 年。工作要求我这样。大部分任何项目只要来了我都做,包括任何类型的编程开发。互联网泡沫出现时,公司钱都花完了,我承担了所有的技术角色;IT,网站,开发,技术支持,文档编写,等等。所有工作我都会一点。

后来,这些经历没有给我带来任何改变。很少有招聘启事上写“需要一个什么都会一点”的人。

2003 年,互联网泡沫破灭时,我的持股收入有 1 百万美元。之后大部分都损失掉了,我只好重新到人才市场求职。这才认识到,招聘单位对大龄的技术通才需求并不多。

就我个人的情况,有些事情跟你们不太一样,这是另外一个故事,下回再说。但如果你是一个技术通才,而且在中年失业,你很可能会遇到这样的情况:

“有这样的经验阅历,你应该是一个 CTO 呀?为什么连个工作都没有?”

他们会问你一下算法问题——你有 30 年没思考过的问题。或要求你进行编码考试——在这种不利的情况下你根本发挥不出特长。

提早打算。人生不如意十有八九。

这是我的简历:

http://oldcoder.org/general/misc/Kiraly_Resume.pdf

Regards, Robert (the Old Coder)

[转载]nginx File not found 错误 – 运维与架构

mikel阅读(797)

[转载]nginx File not found 错误 – 运维与架构.

使用php-fpm解析PHP,”No input file specified”,”File not found”是令nginx新手头疼的常见错误,原因是php-fpm进程找不到SCRIPT_FILENAME配置的要执行的.php文件,php- fpm返回给nginx的默认404错误提示。

比如我的网站doucument_root下没有test.php,访问这个文件时通过抓包可以看到返回的内容。

HTTP/1.1 404 Not Found
Date: Fri, 21 Dec 2012 08:15:28 GMT
Content-Type: text/html
Proxy-Connection: close
Server: nginx/1.2.5
X-Powered-By: PHP/5.4.7
Via: 1.1 c3300 (NetCache NetApp/6.0.7)
Content-Length: 16

File not found.

 

很多人不想用户直接看到这个默认的404错误信息,想自定义404错误.

 

给出解决办法前我们来先分析下如何避免出现这类404错误,然后再说真的遇到这种情况(比如用户输入一个错误不存在的路径)时该怎么办,才能显示自定义的404错误页。

一、错误的路径被发送到php-fpm进程

出现这类错误,十个有九个是后端fastcgi进程收到错误路径(SCRIPT_FILENAME),而后端fastcgi收到错误路径的原因大都是配置错误。

常见的nginx.conf的配置如下:

 

server {
    listen   [::]:80;
    server_name  example.com www.example.com;
    access_log  /var/www/logs/example.com.access.log;  

    location / {
        root   /var/www/example.com;
        index  index.html index.htm index.pl;
    }

    location /images {
        autoindex on;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/example.com$fastcgi_script_name;
        include fastcgi_params;
    }
}

这个配置中有很多不合理的地方,其中一个明显的问题就是root指令被放到了location / 块。如果root指令被定义在location块中那么该root指令只能对其所在的location生效。其它locaiont中没有root指令,像 location /images块不会匹配任何请求,需要在每个请求中重复配置root指令来解决这个问题。因此我们需要把root指令放在server块,这样各个 location就会继承父server块定义的$document_root,如果某个location需要定义一个不同 的$document_root,则可以在location单独定义一个root指令。

另一个问题就是fastCGI参数SCRIPT_FILENAME 是写死的。如果修改了root指令的值或者移动文件到别的目录,php-fpm会返回“No input file specified”错误,因为SCRIPT_FILENAME在配置中是写死的并没有随着$doucument_root变化而变化,我们可以修改 SCRIPT_FILENAME配置如下:

fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

 

所以我们不能忘记在server块中配置root指令,不然$document_root的值为空,只会传$fastcgi_script_name到php-fpm,这样就会导致“No input file specified”错误。

 

二、请求的文件真的不存在

当nginx收到一个不在的.php文件的请求时,因为nginx只会检查$uri是否是.php结尾,不会对文件是否存在进行判断,.php结尾 的请求nginx会直接发给php-fpm处理。php-fpm处理时找不到文件就会返回“No input file specified”带着“404 Not Found”头。

解决办法

我们在nginx拦截不存在的文件,请求并返回自定义404错误

使用 try_files 捕捉不存在的urls并返回错误。

location ~ .php$ {
 try_files $uri =404;
 fastcgi_pass 127.0.0.1:9000;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME ....
 ...................................
 ...................................
}

上面的配置会检查.php文件是否存在,如果不存在,会返回404页面。

[转载]C#开发微信门户及应用(3)--文本消息和图文消息的应答 - 伍华聪 - 博客园

mikel阅读(1060)

[转载]C#开发微信门户及应用(3)–文本消息和图文消息的应答 – 伍华聪 – 博客园.

微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下、学习下微信的相关开发,也就 成为计划的安排事情之一了。本系列文章希望从一个循序渐进的角度上,全面介绍微信的相关开发过程和相关经验总结,希望给大家了解一下相关的开发历程。

在前面两篇两篇随笔《C#开发微信门户及应用(1)–开始使用微信接口》和《C#开发微信门户及应用(2)–微信消息的处理和应答》里面,大致介绍了我微信应用的框架构建,本随笔继续介绍这一主题,介绍消息应答里面的文本应答和图文应答的过程。

我们知道,给手机用户发送响应消息,它可以分为好多种方式,如回复文本消息、回复图片消息、回复语音消息、回复视频消息、回复音乐消息、回复图文消息等,如下所示。

而其中图片、视频、语音这三种方式,是需要开通微信认证才可以向用户发送存在微信服务器上的媒体信息,一般没有认证的公众号或者服务号,是不能发送这几种内容的。

1、实体信息关系及定义

在上一篇微信开发的随笔中,我展示了对接收消息和回复消息的应用实体类,这些实体类是我根据需要,根据开发需要,在应用层面对它们进行了封装,如回复的消息关系如下所示。

消息基类BaseMessage的实体类定义如下所示,它对日期构造了一个整形数值,并具备了一些常规的属性,并且还有一个重要的ToXML方法,用来给方法传递这些XML数据的。

///
/// 基础消息内容
///

[XmlRoot(ElementName = "xml")]
public class BaseMessage
{
///
/// 初始化一些内容,如创建时间为整形,
///

public BaseMessage()
{
this.CreateTime = DateTime.Now.DateTimeToInt();
}

///
/// 开发者微信号
///

public string ToUserName { get; set; }

///
/// 发送方帐号(一个OpenID)
///

public string FromUserName { get; set; }

///
/// 消息创建时间 (整型)
///

public int CreateTime { get; set; }

///
/// 消息类型
///

public string MsgType { get; set; }

public virtual string ToXml()
{
this.CreateTime = DateTime.Now.DateTimeToInt();//重新更新
return MyXmlHelper.ObjectToXml(this);
}

}

回复的文本消息实体类代码如下所示,我们可以看到,它继承了很多通用的实体属性,并且还具备了一个ToXml的通用方法,我们需要把它转换为响应的XML的时候,就使用这个方法就可以了。

///
/// 回复文本消息
///

[System.Xml.Serialization.XmlRoot(ElementName = "xml")]
public class ResponseText : BaseMessage
{
public ResponseText()
{
this.MsgType = ResponseMsgType.Text.ToString().ToLower();
}

public ResponseText(BaseMessage info) : this()
{
this.FromUserName = info.ToUserName;
this.ToUserName = info.FromUserName;
}

///
/// 内容
///

public string Content { get; set; }
}

而图文消息对象类ResponseNews,它包含更多的信息定义

///
/// 回复图文消息
///

[System.Xml.Serialization.XmlRoot(ElementName = "xml")]
public class ResponseNews : BaseMessage
{
public ResponseNews()
{
this.MsgType = ResponseMsgType.News.ToString().ToLower();

this.Articles = new List();
}
public ResponseNews(BaseMessage info) : this()
{
this.FromUserName = info.ToUserName;
this.ToUserName = info.FromUserName;
}

///
/// 图文消息个数,限制为10条以内
///

public int ArticleCount
{
get
{
return this.Articles.Count;
}
set
{
;//增加这个步骤才出来XML内容
}
}

///
/// 图文列表。
/// 多条图文消息信息,默认第一个item为大图,注意,如果图文数超过10,则将会无响应
///

[System.Xml.Serialization.XmlArrayItem("item")]
public List Articles { get; set; }

}

而其中的图文列表集合中的对象,它也是一个实体类型,包含了一些图文的链接,标题等信息,不在赘述。
2、消息的回复处理

如对于文本消息,我们可以用以下的方式进行处理。

ResponseText response = new ResponseText(info);
response.Content = "抱歉,此功能暂未开通。";
result = response.ToXml();

对于图文消息,我们可能需要录入更多的消息才能返回更好的效果。

注意图文的消息,图片的尺寸最好按照官方的标准,否则在手机上看起来不好看,官方的标准好像是宽高是(360,200)像素

///
/// 订阅或者显示公司信息
///

//////
private string ShowCompanyInfo(BaseMessage info)
{
string result = "";
//使用在微信平台上的图文信息(单图文信息)
ResponseNews response = new ResponseNews(info);
ArticleEntity entity = new ArticleEntity();
entity.Title = "广州爱奇迪软件科技有限公司";
entity.Description = "欢迎关注广州爱奇迪软件--专业的单位信息化软件和软件开发框架提供商,我们立志于为客户提供最好的软件及服务。\r\n";
entity.Description += "我们是一家极富创新性的软件科技公司,从事研究、开发并销售最可靠的、安全易用的技术产品及优质专业的服务,帮助全球客户和合作伙伴取得成功。\r\n......(此处省略1000字,哈哈)";
entity.PicUrl = "http://www.iqidi.com/WeixinImage/company.png";
entity.Url = "http://www.iqidi.com";

response.Articles.Add(entity);
result = response.ToXml();

return result;
}

我们来看看我公司的微信门户菜单,看起来是不是很酷呢。

对于这两种(文本消息、图文消息)用的地方是最多,很多微信门户,都主要是使用这两种方式进行响应。当然,我们还可以根据客户手机提交上来的各种消息进行不同的处理,请求消息的类型我在上一篇的随笔有介绍,如下所示。

需要关注了解整体效果,可以使用微信直接扫描二维码即可。

[转载]Android中的基类—抽取出来公共的方法 - Jacky_Chen-Fight - 博客园

mikel阅读(846)

[转载]Android中的基类—抽取出来公共的方法 – Jacky_Chen-Fight – 博客园.

Android中,一般来说一个应用会存在几十个页面,并且一个应用一般也会使用一个特定的主题,其中的页面的风格也是一致的,并且页面中的动画效果、页面的切换效果等也应该保持同样的风格,那么就需要一个基类,来完成页面的基础设置,这就是所谓的基类。

 

界面统一管理原因

 

  1. 当应用中的界面达到一定数量级时,如几十个界面,便于项目管理
  2. 提高界面的处理速度
  3. 避免由于多Activity导致的问题

 

界面统一管理的基础
当应用中的界面达到一定数量级时,为了能够让用户更容易操作上手,产品设计时会将界面显示风格进行统一。

案例驱动:


public abstract class BaseSetupActivity extends Activity {
     // 该抽象类,作为四个设置向导的基类,定义共同的方法
     private SharedPreferences mSharedPreferences;
     private static String TAG = "BaseSetupActivity";
 
     // 声明一个手势识别器
     private GestureDetector mGestureDetector;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        mSharedPreferences = getSharedPreferences("config", MODE_PRIVATE);
 
        // 初始化手势识别器
        // 2.初始化手势识别器
        // Basic Default Base Simple
        mGestureDetector = new GestureDetector(this,
               new GestureDetector.SimpleOnGestureListener() {
 
                   /**
                    * 划屏对应的方法. e1 手指第一次触摸屏幕 e2 手指离开屏幕瞬间 velocityX 水平方向移动的速度
                    * <span style="text-decoration: underline;">px</span>/s velocityY 竖直方向移动的速度
                    */
                   @Override
                   public boolean onFling(MotionEvent e1, MotionEvent e2,
                          float velocityX, float velocityY) {
                      if (Math.abs(velocityX) < 100) {
                          Log.i(TAG, "移动的太慢,动作不合法");
                          return true;
                      }
 
                      if ((e2.getRawX() - e1.getRawX()) > 200) {
                          showPre(null);
                          return true;
                      }
                      if ((e1.getRawX() - e2.getRawX()) > 200) {
                          showNext(null);
                          return true;
                      }
                      // 其实返回的就是false
                      return super.onFling(e1, e2, velocityX, velocityY);
                   }
 
               });
 
        // 子类中初始化布局
        initView();
 
     }
 
     // 设置当前的view布局
     public abstract void initView();
 
     // 显示下一个界面
     public abstract void showNext(View view);
 
     // 显示上一个界面
     public abstract void showPre(View view);
 
     // 3.activity被触摸的时候调用的方法 , 需要在这个里面让手势识别器 生效
     @Override
     public boolean onTouchEvent(MotionEvent event) {
        // 让手势识别器 生效
        mGestureDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
     }
 
 }

分析:
案例中主要实现的就是在同一主题下的页面的切换效果进行统一,初始化了手势识别器,并且让手势识别器生效。接下来看一下继承自这个基类的一个页面的设置


public class Mobile_safeActivity1 extends BaseSetupActivity {
 
     private static String <span style="text-decoration: underline;">TAG</span> = "Mobile_safeActivity1";
 
     @Override
     public void initView() {
        setContentView(R.layout.mobile_safeactivity1);
     }
 
     @Override
     public void showNext(View view) {
        Intent intent = new Intent(this, Mobile_safeActivity2.class);
        startActivity(intent);
        finish();
 
        // 设置切换的动画效果,该方法将会在程序执行startActivity以及finish()方法的时候进行调用
        overridePendingTransition(R.anim.tran_next_in, R.anim.tran_next_out);
     }
 
     @Override
     public void showPre(View view) {
 
     }
 
 }

分析:
非常明显这个Mobile_safeActivity1继承自前面的基类BaseSetupActivity,因此当手指在屏幕上进行滑动的时候,将会触发showNext()和showPre()两个方法,并且在切换时通过overriderPendingTransition()产生屏幕滑动的切换效果,这里可以根据实际需求进行设置,并且这个方法将会在执行finish()方法后自行调用。而在showPre()中没有写任何的内容是因为没有上一页。

也欢迎大家来本文首发地址:http://jackyonline.org/archives/152,欢迎点评和留言。如果有不妥之处,欢迎指教~

[转载]Genymotion配置及使用教程(最新最完整版附各部分下载地址) - 代码改变世界 - 博客频道 - CSDN.NET

mikel阅读(1319)

[转载]Genymotion配置及使用教程(最新最完整版附各部分下载地址) – 代码改变世界 – 博客频道 – CSDN.NET.

早都听说了Genymotion好用,今天才抽空把他配置出来,过程算是很曲折啊,不过好在完成了。而且我发现网上的教程都不怎么全,我还是找了好几篇文章才把他完整的配置出来,这篇是我从下载到项目运行成功的所有过程,希望对大家有所帮助。闲话到此结束。

 

首先第一步:注册Genymotion账号,要记下账号密码后面使用。

注册地址:http://www.genymotion.com/

 

第二步:一般情况下教程上会让先安装VirtualBox,但是根据我的经验,我的建议是先下载安装Genymotion。

下载地址:

https://cloud.genymotion.com/page/customer/login/?next=/page/launchpad/download/

注意想要下载必须先登录。

下载好之后就可以安装了,与普通软件安装过程没有太大的区别,安装目录随意,下一步下一步就OK。

 

安装好Genymotion之后要安装Microsoft Visual C++ 2008 Redistributable Package,所以建议各位看官们,最好也把Microsoft Visual C++ 2010 Redistributable Package以及.net 4.0环境也一并安装了,以免夜长梦多并减少后面的报错(已经安装过的可以自行忽略本步骤)

下载地址1:Microsoft Visual C++ 2008 Redistributable Package

X64:https://www.microsoft.com/zh-cn/download/details.aspx?id=15336

X86:https://www.microsoft.com/zh-cn/download/details.aspx?id=29

下载地址2:Microsoft Visual C++ 2010 Redistributable Package

X64:https://www.microsoft.com/zh-cn/download/details.aspx?id=14632

X86:https://www.microsoft.com/zh-cn/download/details.aspx?id=5555

下载地址3:Microsoft.NET Framework 4(独立安装程序)

https://www.microsoft.com/zh-cn/download/details.aspx?id=17718.

 

第三步:安装好Genymotion之后,下载安装Oracle的VirtulBox,(Genymotion需要虚拟环境才能运行)

下载地址:https://www.virtualbox.org/wiki/Downloads

根据你的实际情况自行选择。下载之后安装,安装过程也没有什么不同,下一步下一步就OK了。这里特别注意的是VirtulBox的安装路径,要是不 对,那么Genymotion就没法打开,现在你打开C:\Users\Administrator\AppData\Local\Genymobile 路径下的genymotion.log文件,文件中比较乱,你找到VBoxManage path (found by reg.exe)这句话,他后面的路径就是你需要安装VirtulBox的路径,这点是非常重要的,切记

 

第四步:启动Gentmoyion,进行一些相关的配置

第一次使用会问你是否添加一个新的虚拟机,选择yes.

进入如上界面,此时便填上你注册Genymoyion账户时的账号和密码,然后点击connect。

连接上之后他会出现设备列表,你可以大致浏览下,然后选择你想创建的一个,点击右下角的add。

然后他会列出一些设备的参数,你大致浏览下,然后点击next。

此时便会开始下载模拟器了。不支持断点续传,所以过程中不要断网,整个过程还是挺快的。

下载完毕后就可以创建了,点击右下角的create。

在这个界面就可以看到你所创建的模拟器的列表,在这个界面play是打开一个模拟器,add是创建一个模拟器,setting自然就是能对模拟器进 行一些设置。这里一步需要特别注意;这个步骤是为模拟器配置SDK,只有配置过的模拟器才能正常的运行程序。选择一个模拟器,点击setting。

在出现的setting界面中

勾选第一条,然后浏览sdk的路径,路径名到sdk为止,如果路径正确,下方的提示会打上粉红色的勾,然后点击OK。

然后回到设备列表,选择一个设备,点击play,就可以启动模拟器了。

关于模拟器的使用方法和一些配置可以再自行百度。因为我也不会,我以后也是要靠google哥哥的。哈哈。

Genymotion的安装过程到这就结束了,接下来讲Eclipse中Genymotion查件的配置与使用。

 

首先第一步:安装Eclipse Genymotion插件,我用的是在线安装的方法,

在线安装的地址为:http://plugins.genymotion.com/eclipse

如果没有被墙或者RP还行的话应该没问题。至于插件安装过程就不是这里该讲的东西了,不会的度娘吧。也可以下载离线包安装。

 

第二步:首次使用配置

安装好插件后你会在Eclipse面板中发现Genymotion的按钮,在sdk manager的隔壁,图标是:,点击他,第一次是不能直接使用的,然后他会指引你去配置Genymotion的directory,

出现如下界面。

此时要填的是Genymotion的安装路径,我的路径如上图所示。路径名到Genymotion为止,添加好后apply,然后OK。

 

第三步:使用它运行项目,配置上第二步之后返回Eclipse,再次点击Genymotion的图标,

他就会出现设备列表了,选择一个点击start就OK,此时你就能发现运行的模拟器了。

 

第四步:运行程序

运行程序之前也要进行配置,在你需要运行的工程处右键,Run as —>Run config……

进入运行设置界面。

选择上图所标注的选项,然后Apply,然后点击Run运行项目,这样就能看到你的项目在Genymotion上顺利运行了,当然我希望是顺利运行哈。

附:Genymotion中文官方手册供大家参阅

地址:http://www.app-edu.net/article-60414-1.html

到此,整个过程也结束了,大家终于可以解放自己的手机了。