月度归档:2013年03月

SQLServer存储过程及参数查询

得到数据库存储过程列表:

select * from dbo.sysobjects where OBJECTPROPERTY(id, N'IsProcedure') = 1 order by name

得到某个存储过程的参数信息:(SQL方法)

select * from syscolumns where ID in    
  (SELECT id FROM sysobjects as a  
   WHERE OBJECTPROPERTY(id, N'IsProcedure') = 1    
   and id = object_id(N'[dbo].[mystoredprocedurename]'))

得到某个存储过程的参数信息:(Ado.net方法)

SqlCommandBuilder.DeriveParameters(mysqlcommand);

得到数据库所有表:

select * from dbo.sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1 order by name

得到某个表中的字段信息:

select c.name as ColumnName, c.colorder as ColumnOrder, c.xtype as DataType, typ.name as  DataTypeName, c.Length, c.isnullable from dbo.syscolumns c inner join dbo.sysobjects t 
on c.id = t.id 
inner join dbo.systypes typ on typ.xtype = c.xtype
where OBJECTPROPERTY(t.id, N'IsUserTable') = 1 
and t.name='mytable' order by c.colorder;

 

C# Ado.net代码示例:

 

1. 得到数据库存储过程列表:

using System.Data.SqlClient;
 
private void GetStoredProceduresList()
{
    string sql = "select * from dbo.sysobjects where OBJECTPROPERTY(id, N'IsProcedure') = 1 order by name";
    string connStr = @"Data Source=(local);Initial Catalog=mydatabase; Integrated Security=True; 

Connection Timeout=1;";

 
    SqlConnection conn = new SqlConnection(connStr);
    SqlCommand cmd = new SqlCommand(sql, conn);
    cmd.CommandType = CommandType.Text;
 
    try
    {
        conn.Open();
 
        using (SqlDataReader MyReader = cmd.ExecuteReader())
        {
            while (MyReader.Read())
            {
                //Get stored procedure name
                this.listBox1.Items.Add(MyReader[0].ToString());
            }
        }
    }
    finally
    {
        conn.Close();
    }
}

2. 得到某个存储过程的参数信息:(Ado.net方法)

using System.Data.SqlClient;
 
private void GetArguments()
{
    string connStr = @"Data Source=(local);Initial Catalog=mydatabase; Integrated Security=True; 

Connection Timeout=1;";

 
    SqlConnection conn = new SqlConnection(connStr);
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = conn;
    cmd.CommandText = "mystoredprocedurename";
    cmd.CommandType = CommandType.StoredProcedure;
 
    try
    {
        conn.Open();
 
        SqlCommandBuilder.DeriveParameters(cmd);
 
        foreach (SqlParameter var in cmd.Parameters)
        {
            if (cmd.Parameters.IndexOf(var) == 0) continue;//Skip return value
 
            MessageBox.Show((String.Format("Param: {0}{1}Type: {2}{1}Direction: {3}",
               var.ParameterName,
               Environment.NewLine,
               var.SqlDbType.ToString(),
               var.Direction.ToString())));
        }
    }
    finally
    {
        conn.Close();
    }
 
}

3. 列出所有数据库:

using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
 
private static string connString = 
            "Persist Security Info=True;timeout=5;Data Source=192.168.1.8;User ID=sa;Password=password";
 
/// <summary>
/// 列出所有数据库
/// </summary>
/// <returns></returns>
public string[] GetDatabases()
{
    return GetList("SELECT name FROM sysdatabases order by name asc");
}
 
private string[] GetList(string sql)
{
    if (String.IsNullOrEmpty(connString)) return null;
 
    string connStr = connString;
 
    SqlConnection conn = new SqlConnection(connStr);
    SqlCommand cmd = new SqlCommand(sql, conn);
    cmd.CommandType = CommandType.Text;
 
    try
    {
        conn.Open();
 
        List<string> ret = new List<string>();
 
        using (SqlDataReader MyReader = cmd.ExecuteReader())
        {
            while (MyReader.Read())
            {
                ret.Add(MyReader[0].ToString());
            }
        }
 
        if (ret.Count > 0) return ret.ToArray();
        return null;
    }
    finally
    {
        conn.Close();
    }
}
 

4. 得到Table表格列表:

private static string connString = 
  "Persist Security Info=True;timeout=5;Data Source=192.168.1.8;Initial Catalog=myDb;User ID=sa;Password=password";
 
/* select name from sysobjects where xtype='u'  ---
   C = CHECK 约束
   D = 默认值或 DEFAULT 约束
   F = FOREIGN KEY 约束
   L = 日志
   FN = 标量函数
   IF = 内嵌表函数
   P = 存储过程
   PK = PRIMARY KEY 约束(类型是 K)
   RF = 复制筛选存储过程
   S = 系统表
   TF = 表函数
   TR = 触发器
   U = 用户表
   UQ = UNIQUE 约束(类型是 K)
   V = 视图
   X = 扩展存储过程
   */
 
public string[] GetTableList()
{
    return GetList("SELECT name FROM sysobjects WHERE xtype='U' AND name   <>   'dtproperties' order by name asc");
}

5. 得到View视图列表:

public string[] GetViewList()
{
     return GetList("SELECT name FROM sysobjects WHERE xtype='V' AND name   <>   'dtproperties' order by name asc");
}

6. 得到Function函数列表:

public string[] GetFunctionList()
{
    return GetList("SELECT name FROM sysobjects WHERE xtype='FN' AND name   <>   'dtproperties' order by name asc");
}

7. 得到存储过程列表:

public string[] GetStoredProceduresList()
{
    return GetList("select * from dbo.sysobjects where OBJECTPROPERTY(id, N'IsProcedure') = 1 order by name asc");
}

8. 得到table的索引Index信息:

public TreeNode[] GetTableIndex(string tableName)
{
    if (String.IsNullOrEmpty(connString)) return null;
 
    List<TreeNode> nodes = new List<TreeNode>();
 
    string connStr = connString;
 
    SqlConnection conn = new SqlConnection(connStr);
    SqlCommand cmd = new SqlCommand(String.Format("exec sp_helpindex {0}", tableName), conn);
    cmd.CommandType = CommandType.Text;
 
    try
    {
        conn.Open();
 
        using (SqlDataReader MyReader = cmd.ExecuteReader())
        {
            while (MyReader.Read())
            {
                TreeNode node = new TreeNode(MyReader[0].ToString(), 2, 2);/*Index name*/
                node.ToolTipText = String.Format("{0}{1}{2}", MyReader[2].ToString()/*index keys*/, Environment.NewLine,
                    MyReader[1].ToString()/*Description*/);
                nodes.Add(node);
            }
        }
    }
    finally
    {
        conn.Close();
    }
 
    if(nodes.Count>0) return nodes.ToArray ();
    return null;
}

9. 得到Table,View,Function,存储过程的参数,Field信息:

public string[] GetTableFields(string tableName)
{
    return GetList(String.Format("select name from syscolumns where id =object_id('{0}')", tableName));
}

10. 得到Table各个Field的详细定义:

public TreeNode[] GetTableFieldsDefinition(string TableName)
{
    if (String.IsNullOrEmpty(connString)) return null;
 
    string connStr = connString;
 
    List<TreeNode> nodes = new List<TreeNode>();
 
    SqlConnection conn = new SqlConnection(connStr);
    SqlCommand cmd = new SqlCommand(String.Format("select a.name,b.name,a.length,a.isnullable from syscolumns a,systypes b,sysobjects d where a.xtype=b.xusertype and a.id=d.id and d.xtype='U' and a.id =object_id('{0}')",
                  TableName), conn);
    cmd.CommandType = CommandType.Text;
              
    try
    {
        conn.Open();
 
        using (SqlDataReader MyReader = cmd.ExecuteReader())
        {
            while (MyReader.Read())
            {
                TreeNode node = new TreeNode(MyReader[0].ToString(), 2, 2);
                node.ToolTipText = String.Format("Type: {0}{1}Length: {2}{1}Nullable: {3}", MyReader[1].ToString()/*type*/, Environment.NewLine,
                    MyReader[2].ToString()/*length*/, Convert.ToBoolean(MyReader[3]));
                nodes.Add(node);
            }
        }
 
        if (nodes.Count > 0) return nodes.ToArray();
        return null;
    }
    finally
    {
        conn.Close();
    }
 
}

11. 得到存储过程内容:

类似“8. 得到table的索引Index信息”,SQL语句为:EXEC Sp_HelpText '存储过程名'

 

12. 得到视图View定义:

类似“8. 得到table的索引Index信息”,SQL语句为:EXEC Sp_HelpText '视图名'

 

(以上代码可用于代码生成器,列出数据库的所有信息)

vpn 网关&出口

VPN的英文全称是“Virtual Private Network”,翻译过来就是“虚拟专用网络”。顾名思义,虚拟专用网络可以把它理解成是虚拟出来的企业内部专线。

在公司外部internet,通过vpn拨号连接到单位的VPN后,就相当于这台电脑连接在了企业内部局域网中

单位的VPN 专用拨号,拨号链接正常,就是上不了网
每次新建这个拨号都正常,也能连到公司内部网上

这个问题的原因是默认情况下,连接VPN后,电脑的网关就会被修改成VPN设备那头的网关
所有上网的数据都默认通过VPN如果VPN设备没有设置转发外网数据的话,你就上不了网

所以启用本地默认网关,不使用“远程网络上的默认网关”就能访问远程局域网的同时,还能通过本地计算机访问Internet。

VPN连接-->属性--> 网络--> Internet协议--> 高级--> 勾掉“在远程网络上使用网关”

集群系统 heartbeat & lvs

一般我们用到的集群系统主要有2种:

1、高可用(High Availability)HA集群, 使用Heartbeat实现;也会称为”双机热备”, “双机互备”, “双机”。

2、负载均衡群集(Load Balance Cluster),使用Linux Virtual Server(LVS)实现;

 

heartbeat (Linux-HA)的工作原理:heartbeat最核心的包括两个部分,心跳监测部分和资源接管部分,心跳监测可以通过网络链路和串口进行,而且支持冗 余链路,它们之间相互发送报文来告诉对方自己当前的状态,如果在指定的时间内未受到对方发送的报文,那么就认为对方失效,这时需启动资源接管模块来接管运 行在对方主机上的资源或者服务。

另一种参考:  Keepalived

 

LVS详解:http://www.linuxidc.com/Linux/2012-09/71474.htm

http://linux.chinaunix.net/techdoc/net/2009/07/21/1125256.shtml

 

基于heartbeat v2和ldirectord实现director高可用

一、环境拓扑介绍

点击查看原图

说明:前端两台调度服务器Director1和Director2,两者之间可以实现故障转移,例如当Director1节点出现故障时Director2节点可以自动接管调度服务器的资源,能够继续为为客户端转发请求到后端Real Server;而且当后台的node1或着node2出现故障时能够把故障节点自动踢出列表,当恢复正常时能够自动加入。
注意:
      1、设置各个节点间的时间同步
      2、基于hosts文件实现能够互相用主机名访问
      3、使用uname -n执行结果要和主机名相同
      4、确保ipvsadm服务和httpd服务关闭开机启动
 
二、安装相关软件包
需要的软件:
 ipvsadm
 heartbeat                                        
 heartbeat-ldirectord                  
 heartbeat-pils                                
 heartbeat-stonith                    
 libnet          
 perl-MailTools                
 libtool-ltdl                
 openhpi-libs            
 perl-Compress-Zlib              
 perl-HTML-Parser            
 perl-HTML-Tagset            
 perl-TimeDate    
 perl-libwww-perl 
 
三、配置Director节点之间高可用
1、复制配置文件样例
[root@director1 ~]# cd /usr/share/doc/heartbeat-2.1.4/
[root@director1 heartbeat-2.1.4]# cp authkeys ha.cf haresources /etc/ha.d/
 
2、编辑配置文件
[root@director1 heartbeat-2.1.4]# cd /etc/ha.d/
[root@director1 ha.d]# vim ha.cf 
--------------------------添加如下行------------------------------------
bcast  eth1   //定义发送心跳信息的广播接口,我这里是eth1
node    director1 //定义节点
node    director2
-------------------------结束--------------------------------------------
 
编辑配置文件authkeys
[root@director1 ha.d]# vim authkeys    
-------------------------添加如下行---------------------------------
auth 1
1 md5 124hddhu56d8yd8  //后边的为随机数值
--------------------------结束-------------------------------------
[root@director1 ha.d]# chmod 600 authkeys  //设置权限为600 
 
编辑配置文件haresources
[root@director1 ha.d]# vim haresources    //编辑资源配置文件添加如下行
director1      192.168.56.200/32/eth1/192.168.56.200 ldirectord //定义资源VIP,ldirectord服务
 
编辑ldriectord配置文件
[root@director1 ha.d]# vim ldirectord.cf 
--------------------------------修改为以下内容----------------------------
checktimeout=3    //检测超时时间
checkinterval=1    //检测间隔
autoreload=yes    //该配置文件修改后能够自动重载
quiescent=yes 
virtual=192.168.56.200:80 //定义VIP地址和端口
        real=192.168.56.103:80 gate //定义real server的IP和端口
        real=192.168.56.104:80 gate //定义第二个real server
        fallback=127.0.0.1:80 gate //如果所有后端节点不可用时请求连接的转发位置,此处设置转发给director自身的80端口
        service=http    //定义服务类型
        request=".test.html" //检测后端节点时使用的页面
        receive="ok"    //检测的关键字,这里的设置表示测试访问.test.html页面是否包含ok关键字,如果有则说明该节点正常,否则认定为故障
        scheduler=wlc //指定算法
        protocol=tcp //定义协议为tcp
        checktype=negotiate //检测类型
        checkport=80    //检测的端口
-----------------------------------结束------------------------------------------
 
3、把配置文件拷贝到director2节点
[root@director1 ha.d]# scp -p ha.cf authkeys ldirectord.cf haresources director2:/etc/ha.d/

四、配置后端服务节点
 
安装apache配置测试主页
[root@node1 ~]# yum -y install httpd
[root@node1 ~]# echo node1 > /var/www/html/index.html
[root@node1 ~]# echo ok > /var/www/html/.test.html
配置节点的其他参数请参看LVS的文档介绍,这里执行在LVS文档中介绍的real server上执行的脚本(参见另外一篇博客:LVS负载均衡集群详解):
[root@node1 ~]# bash realserver.sh start
 
在node2上执行与node1节点相同的操作,为了演示方便可以看出效果在node2节点上的index.html页面输入与node1不同的内容以示区分。
 
五、启动heartbeat服务测试
[root@director1 ha.d]# service heartbeat start
[root@director1 ha.d]# ssh director2 'service heartbeat start' //director节点通过SSH启动heartbeat服务
 
测试Director1节点故障
[root@director1 ha.d]# /usr/lib/heartbeat/hb_standby //该脚本为heartbeat自带的脚本可以使该节点转为备用节点。

点击查看原图
 
测试node1节点故障
[root@node1 ~]# service httpd stop

点击查看原图

在director2节点上使用ipvsadm -Ln命令可以看到已经自动把node1节点相关条目移除

测试node1和node2节点同时故障,由于在ldirectord配置文件中设置了当所有后端节点故障时请求转发至director本身的80端口,所以这里需要director也安装httpd服务,或者修改该配置文件转向其他Web服务器。
 
总结:至此一个高可用的Director调度服务器集群已经完成,同时也要注意在现实环境中至少要2条线路来同时广播节点心跳信息,避免因为线路的故障造成节点间的资源争夺。

北京 DNS

北京联通DNS服务器地址:
202.106.196.115
202.106.0.20
202.106.46.151(ADSL)
北京电信DNS服务器地址:
219.141.136.10
219.141.146.10

俄罗斯 / Russian :

Yandex.Dns Basic
77.88.8.8
77.88.8.1

Yandex.Dns Safe
77.88.8.88
77.88.8.2

Yandex.Dns Family
77.88.8.7
77.88.8.3

罗杰斯通信公司,加拿大 / ClearCloud:
174.118.212.1
174.118.212.2

iPhone消息推送机制实现与探讨

.NET 开源项目:

https://github.com/Redth/APNS-Sharp

Push的原理:

Push 的工作机制可以简单的概括为下图

点击查看原图

图中,Provider是指某个iPhone软件的Push服务器,这篇文章我将使用.net作为Provider。

APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的服务器。

上图可以分为三个阶段。

第一阶段:.net应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。

第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone。

第三阶段:iPhone把发来的消息传递给相应的应用程序, 并且按照设定弹出Push通知。

 点击查看原图

从上图我们可以看到。

1、首先是应用程序注册消息推送。

2、 IOS跟APNS Server要deviceToken。应用程序接受deviceToken。

3、应用程序将deviceToken发送给PUSH服务端程序。

4、 服务端程序向APNS服务发送消息。

5、APNS服务将消息发送给iPhone应用程序。

无论是iPhone客户端跟APNS,还是Provider和APNS都需要通过证书进行连接的。下面我介绍一下几种用到的证书。

几种证书:

一、*.certSigningRequest文件

1、生成Certificate Signing Request (CSR):

点击查看原图

2、填写你的邮箱和Common Name,这里填写为PushChat。选择保存到硬盘。

点击查看原图

这样就在本地生成了一个PushChat.certSigningRequest文件。

二、生成*.p12文件

1、导出密钥,并输入你的密码。

点击查看原图

输入你的密码:

点击查看原图

这样就生成了一个PushChatKey.p12文件。

三、新建一个App ID 和SSL certificate文件

1、用你的付过费的apple帐号登录到iOS Provisioning Portal。新建一个App ID。

Description:中输入PushChat

Bundle Seed ID:默认选择Generate New

Bundle Identifier:输入com.mysoft.PushChat

点击提交

点击查看原图

这样就会生成下面这条记录:

点击查看原图

点击配置:

点击查看原图

出现下面界面,点击继续:

点击查看原图

这里我们选择前面生成好的PushChat.certSigningRequest文件,点击生成。

点击查看原图

正在生成

点击查看原图

生成完毕,我们把它下载下来。命名为aps_developer_identity.cer

点击查看原图

点击完成,你会发现状态变成Enabled。

点击查看原图

到现在为止,我们已经生成了3个文件。

1、PushChat.certSigningRequest

2、PushChatKey.p12

3、aps_developer_identity.cer

现在我们创建一个简单的iPhone应用程序。

1、打开Xcode,选择创建一个View-based Application。命名如下图:

点击查看原图

2、在PushChatAppDelegate中的didFinishLaunchingWithOptions方法中加入下面代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; // Let the device know we want to receive push notifications [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; return YES; }

通过registerForRemoteNotificationTypes方法,告诉应用程序,能接受push来的通知。

3、在xcode中运行,会弹出下面的提示框:

点击查看原图

选择OK。表示此应用程序开启消息通知服务。

在 PushChatAppDelegate.m代码中添加下面方法获取deviceToken :

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { NSLog(@"My token is: %@", deviceToken); } - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { NSLog(@"Failed to get token, error: %@", error); }

获取到的deviceToken,我们可以通过webservice服务提交给.net应用程序,这里我简单处理,直接打印出来,拷贝到.net应用环境中使用。

发送通知的.net应用程序出来需要知道deviceToken之外,还需要一个与APNS连接的证书。

这个证书可以通过我们前面生成的两个文件中得到。

使用OpenSSL生成.net和APNS通信的证书文件。

1、将aps_developer_identity.cer转换成 aps_developer_identity.pem格式。

openssl x509 -in aps_developer_identity.cer -inform DER -out aps_developer_identity.pem -outform PEM

2、将p12格式的私钥转换成pem,需要设置4次密码,这里密码都设置为:abc123。

openssl pkcs12 -nocerts -out PushChat_Noenc.pem -in PushChat.p12

3、用certificate和the key 创建PKCS#12格式的文件。

openssl pkcs12 -export -in aps_developer_identity.pem -inkey PushChat_Noenc.pem -certfile PushChat.certSigningRequest -name "aps_developer_identity" -out aps_developer_identity.p12

这样我们就得到了在.net应用程序中使用的证书文件:aps_developer_identity.p12

在.net应用程序中发送通知。

有个开源的类库:apns-sharp。

地址是:http://code.google.com/p/apns-sharp/

我们下载源代码,对里面的JdSoft.Apple.Apns.Notifications做相应的调整就能用了。

我们根据DeviceToken和p12File对JdSoft.Apple.Apns.Notifications.Test代码做相应的调整,如下图。

点击查看原图

这样就OK了。

效果:

通知的代码:

for (int i = 1; i <= count; i++) { //Create a new notification to send Notification alertNotification = new Notification(testDeviceToken); alertNotification.Payload.Alert.Body = string.Format("Testing {0}...", i); alertNotification.Payload.Sound = "default"; alertNotification.Payload.Badge = i; //Queue the notification to be sent if (service.QueueNotification(alertNotification)) Console.WriteLine("Notification Queued!"); else Console.WriteLine("Notification Failed to be Queued!"); //Sleep in between each message if (i < count) { Console.WriteLine("Sleeping " + sleepBetweenNotifications + " milliseconds before next Notification..."); System.Threading.Thread.Sleep(sleepBetweenNotifications); } }

用手机拍的ipad上面的显示:

点击查看原图点击查看原图

总结:这篇文章主要是详细的讲述了ios消息推送机制的实现,如何通过.net应用程序发送消息给ios应用程序。

 

附:

   摘自网上的一短代码: pingguo-C#.zip

在Windows下安装BIND作为DNS服务器

1、下载BIND

http://ftp.isc.org/isc/bind9/9.4.3/BIND9.4.3.zip

2、安装
下载回来是zip的压缩包,解压以后直接双击BINDInstall.exe安装,默认安装路径是C:\WINDOWS\system32\dns。bind在win32下将自己注册成服务,服务名叫ISC BIND,程序名为named.exe,启动服务需要用一专有帐户,默认名称为named,密码由安装者自定义。点击install以后,程序便安装在C:\WINDOWS\system32\dns下,这时还不能启动bind服务,会报代号1067的错,得先经过配置。

3、配置
先运行命令行cmd,cd 至 C:\WINDOWS\system32\dns\bin下,运行rndc-confgen.exe -a,会自动在C:\WINDOWS\system32\dns\etc\下生成rndc.key。此rndc.key是在是bind 9.x版本的新功能,是有关DNS更新以及更新时加密处理的,跟我们个人用户无太大关系,不过基于兼容性,还是照做。接下来,在C:\WINDOWS\system32\dns\etc\下建立named.conf,即bind的配置文件,文件内容如下:

include "c:\windows\system32\dns\etc\rndc.key";
zone "." {
type hint;
file "c:\windows\system32\dns\etc\named.root";
};

include一行主要是将rndc.key包含进去,zone "."一行是设置根节点,我们做自己个人的DNS服务器,只要设置这个足够,其他的各个参数可以自己上网去搜索了解,够用就好接下来从http://www.internic.net/下载named.root文件,里面定义了全球的根DNS服务器,下载地址是http://www.internic.net/zones/named.root,需要定期更新,不过用dig工具也可以实时查得根DNS服务器的地址,只不过win32下没有直接将输出结果存为named.root文件的功能,所以还是下载比较方便。named.root文件也是放在etc目录下。如果C盘是NTFS格式的话,还要记得定义启动bind的named用户c:\windows\system32\dns\etc这个目录的完全控制权,不然,还是会报1067的错(如果bind不作为服务启动,直接在cmd里启动,权限不必放行,因为是直接用当前用户的权限嘛)

4、启动

从“计算机管理--》服务”启动ISC BIND服务。

5、测试

把网络上的任意一台机器的DNS设置到安装了BIND的机器IP。Ping一下www.google.com。如果通了,恭喜你,做对了。

Android ADT 离线下载

网上很多的Android在IDE eclipse的开发环境教程,ADT的就安装肯定也在里面啦

ADT的安装都是一个在线安装地址

  https://dl-ssl.google.com/android/eclipse/

但是发现是这种在线安装方法不好,麻烦,时间长,所以都去找离线安装包啦,根据关键词,你可以找到ADT 12的zip下载地址:

http://dl.google.com/android/ADT-12.0.0.zip

但是我的eclipse 是最新版本的3.7.1,开发环境也要跟上吧,那现在ADT的最新版本是什么呢?

这里有一个技巧,那就是,可以利用在线安装地址获取当前适合eclipse 3.7.1的ADT版本,

点击查看原图

 

可以看到,当前在线安装的版本是16.0.1,最近更新时间是2011-12-15的,所以我们就下载最新的ADT ZIP包吧,

下载地址是什么?这个你应该可以猜出来了,我也算说的直白了。

http://dl.google.com/android/ADT-16.0.1.zip

有什么新版本你就可以用这个

http://dl.google.com/android/ADT-xx.x.x.zip来进行下载了

http://dl.google.com/android/ADT-20.0.3.zip

VMWare Mac.OSX.10.6

介绍一下使用VMWare安装MAC OS X时,无需转换成ISO格式,直接使用MAC OS X的DMG镜像文件进行安装的方法。
安装必备:

硬件:一台拥有支持虚拟技术的64位双核处理器和2GB以上内存的PC。
VMware软件:太大我就不上传了,如需要请联系我!
DMG光盘镜像文件:太大我就不上传了,如需要请联系我!
引导镜像文件:http://u.115.com/file/e6rt4q7s darwin_snow_legacy.iso

http://u.115.com/file/dn9mb5ap 苹果引导darwin.iso

首先安装好VMWare Workstation 7.13。使用File->New->Virtual Machine创建一个虚拟机,在选择操作系统时选择Other->FreeBSD 64-bit。
点击查看原图

2011-8-15 22:03

CPU设置1核可以,2核也可以,如果你是双核CPU,建议你分配1个核;内存建议设置为1024MB,如果你的物理内存够大也可以多给些;硬盘最少分配15GB,太小则无法进行安装,如果你还想多装些软件,建议多分配一些。最后一步可以在Customize Hardware选项里把软驱删除,因为这个用不上。
创建好之后,需要你在刚建立的虚拟机目录下找到一个扩展名为.vmx的文件,用记事本打开,找到guestOS = "freebsd-64"一行,将引号里的freebsd-64改为darwin10,改完是guestOS = "darwin10",保存修改后的文件。 如下图:
点击查看原图

2011-8-15 22:03

做了这一步,在这个虚拟机的Options->General选项下就可以看到操作系统版本显示为:MAC OS X Server 10.6,如下图所示。仍显示为FreeBSD 64-bit的需要重启一下VMWare。
点击查看原图

2011-8-15 22:03

引导成功,现在是更换Mac镜像,然后按F5
点击查看原图

2011-8-15 22:03

添加镜像后,回车
点击查看原图

2011-8-15 22:03

经过一阵准备阶段就进入了苹果系统的安装过程,如下图所示:选择语言种类
点击查看原图

2011-8-15 22:03

在这里特别提一下,有的同学在进行到选择安装盘的步骤时看不到硬盘选项
点击查看原图

2011-8-15 22:03

不要着急,在屏幕上方的菜单中找到“实用工具”->“磁盘工具”,如图所示:
点击查看原图

2011-8-15 22:03

对你的虚拟硬盘执行“抹掉”操作,如图所示:
点击查看原图

2011-8-15 22:03

操作完成后关闭“磁盘工具”窗口就OK了,如图所示:
点击查看原图

2011-8-15 22:03

根据你的电脑配置不同,大概进行几十分钟的安装,你就可以用上苹果操作系统了。
点击查看原图

2011-8-15 22:03

点击查看原图

2011-8-15 22:03

点击查看原图

2011-8-15 22:03


看到下图的界面,表示你的系统已经安装完成,需要重新启动。
点击查看原图

2011-8-15 22:03

重新启动前你要特别注意,先要去掉安装时在CD/DVD(IDE)设备上加载的苹果DMG镜像,换上Darwin或者Rebel EFI引导镜像,否则你将不能成功引导安装好的MAC OS X系统。