MAC设置AndroidStudio初始环境

1、从Oracle下载MAC版本的JDK7

http://www.oracle.com/technetwork/java/javase/downloads/index.html

2、从Google下载MAC版本Android Studio和Android SDK Manager

http://developer.android.com/sdk/index.html

3、安装JDK7、Android Studio、Android SDK Manager,并下载需要版本的Android SDK

4、此时双击Android Studio会报错:

Android Studio was unable to find a valid JVM.

这是因为Android Studio默认使用JDK1.6.*的原因

在Finder中打开Application文件夹,在“Android Studio.app”上右键,显示程序包内容
编辑Content/Info.plist,修改属性JVMOptions->JVMVersion一行,从1.6.*修改为1.7.*

5、此时双击Android Studio会尝试从Google获取最新的Android SDK信息

Fetching Android SDK component information

当然你读不到啦,只好屏蔽初始化方法:

编辑Content/idea.properties/bin/idea.properties文件,添加一行
disable.android.first.run=true

6、现在Android Studio可以启动了,但是不能新建项目
需要告诉Android Studio,Android SDK在哪里:

主界面-》Configure-》Project Defaults-》Project Structure-》Android SDK location
填写Android SDK的绝对路径,保存,然后就能新建应用了

7、那就新建一个简单应用测试一下吧,当然先是虚拟机:

Starting emulator for AVD 'new'
emulator: ERROR: x86 emulation currently requires hardware acceleration!
Please ensure Intel HAXM is properly installed and usable.
CPU acceleration status: HAX kernel module is not installed!

这是因为HAXM模块没有安装,前往Android SDK根目录

安装下面的软件:
PATH_TO_SDK/extras/intel/Hardware_Accelerated_Execution_Manager/IntelHAXM_1.1.1_for_10_9_and_above.dmg

8、然后就是在设备上测试,Android SDK找不到我的设备

#添加adb路径
echo "export PATH=${PATH}:/PATH_TO_SDK/android-sdk-macosx/platform-tools/">>~/.bash_profile
#然后刷新一下
source .bash_profile 
#添加设备厂商ID(我的是小米),可以在系统报告中看到设备厂商ID信息
echo"0x2717">>~/.android/adb_usb.ini
#杀掉adb服务
adb kill-server
#重启adb服务
adb sever
#PTP模式连上手机,当然要开启手机调试咯,这样就能看到设备了
adb devices

9、连上设备了,运行时报错:

Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.neohope.testapp/.LoginActivity } from null (pid=29619, uid=2000) not exported from uid 10139

这个错误是因为Main Activity没有设置,在Manifest中对应的Activity中增加如下设置即可

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

Wireshark过滤规则

Wireshark是一个很好用的sniffer工具,插件十分强大。有时,为了判断问题,在日常工作中也会用到一些,现在记录一部分常用的过滤规则:

1、运算符

lt < 小于
le <= 小于等于
eq == 等于
gt > 大于
ge >= 大于等于
ne != 不等
and && 与操作
or || 或操作
not ! 非操作

2、ip、mac和port过滤

#过滤ip地址为192.168.1.102的全部数据包
ip.addr eq 192.168.1.102
#过滤从192.168.1.102发来的数据包 或 发往192.168.1.102的数据包
ip.src eq 192.168.1.102 or ip.dst eq 192.168.1.102

#过滤MAC地址为00:00:00:01:02:03的所有包
eth.add eq 00:00:00:01:02:03
#过滤MAC地址为00:00:00:01:02:03发送的包 或 发往00:00:00:01:02:03的包
eth.src eq 00:00:00:01:02:03 or eth.dst eq 00:00:00:01:02:03

#过滤8080端口全部tcp数据包(接收和发送)
tcp.port eq 8080
#过滤8080端口发送的全部tcp数据包 或 发送到8080端口全部tcp数据包
tcp.srcport eq 8080 or tcp.dstport eq 8080

#过滤21端口全部udp数据包(接收和发送)
upd.port eq 21
#过滤21端口发送的全部udp数据包 或 发送到21端口全部udp数据包
udp.srcport eq 21 or udp.dstport eq 21

#过滤1024以内端口数据包
tcp.port <= 1024

#去掉tcp数据包
!tcp
#或
not tcp

3、包长度过滤

#udp报文长度等于100
udp.length eq 100

#udp数据长度等于92
udp.len eq 92

#经常可以用到eth(farme),ip,arp,tcp,udp等协议的包长度
#注意区分包长度和payload长度

4、HTTP协议

#过滤GET方法的HTTP数据包
http.request.method == "GET"

#按URI过滤HTTP数据包
http.request.uri == "/image/logo.gif"

#按内容过滤HTTP数据包
http contains "Content-Type: application/dicom"

5、匹配规则

\d 0-9的数字
\D \d的补集
\w 单词字符,即大小写字母、0-9的数字、下划线
\W \w的补集
\s 空白字符,包括换行符\n、回车符\r、制表符\t、垂直制表符\v、换页符\f
\S \s的补集
. 除换行符\n外的任意字符
.* 匹配任意文本
[…] 匹配[]内所列出的所有字符
[^…] 匹配非[]内所列出的字符
^ 表示其后的字符必须位于字符串的开始处
$ 表示其前面的字符必须位于字符串的结束处
\b 匹配一个单词的边界
\B 匹配一个非单词的边界
{n} 匹配前面的字符n次
{n,} 匹配前面的字符n次或多于n次
{n,m} 匹配前面的字符n到m次
? 匹配前面的字符0或1次
+ 匹配前面的字符1次或多于1次
* 匹配前面的字符0次或式于0次

6、包匹配

#字节匹配,比如匹配payload第一个字节0x14的UDP数据包
udp[8]==14

#范围匹配,经常使用到tcp[offset,n],比如匹配payload的前4个字节0x0004002a
udp[8:4]==00:04:00:2a

#正则匹配,要用match,比如匹配HTTP1.1协议的数据包
tcp[20:] matches "^GET [ -~]*HTTP/1.1\\x0d\\x0a"

7、示例

#DICOMClient 上抓取 DICOMServer
ip.dst eq 服务端ip &&  tcp.port eq 104

#DICOMServer 上抓取 DICOMClient
tcp.port eq 104

#HL7v2Client 上抓取 HL7v2Server
ip.dst eq 服务端ip &&  tcp.port eq 3306

#HL7v2Server上抓取 HL7v2Client 
tcp.port eq 3306

Windows服务程序访问NAS

由于服务程序授权与用户桌面授权互不影响,所以即使在用户桌面映射了NAS盘符,在Windows服务程序下仍然是不可以访问的。

一般来说有这样几种做法来访问NAS或共享盘:
1、加入域,通过“域用户认证”或“通过将NAS资源设置对某台计算机授权”来达到访问NAS的目的
2、不加域,在Windows中添加与NAS相同的用户名及密码,服务程序通过该用户名密码登录,可以访问NAS
3、不加域,通过调阅API的方式来获得访问NAS的权限
A、VC实现如下:

DWORD AcessNetDrtive(TCHAR* szRemotePath, TCHAR* szLocalDriver,  const TCHAR* szUsername, const TCHAR* szPassword)
{
	DWORD dwRetVal;
	DWORD dwFlags;

	NETRESOURCE nr;
	memset(&nr, 0, sizeof(NETRESOURCE));
	nr.dwScope = RESOURCE_GLOBALNET;
	nr.dwType = RESOURCETYPE_ANY;
	nr.lpLocalName = szLocalDriver;
	nr.lpRemoteName = szRemotePath;
	nr.lpProvider = NULL;

	//CONNECT_REDIRECT;CONNECT_UPDATE_PROFILE;
	dwFlags = 0;
	dwRetVal = WNetAddConnection2(&nr, szPassword, szUsername, dwFlags);

	retrun dwRetVal;
}

B、C#实现如下:

    public class NetworkDrive
    {
        public enum ResourceScope
        {
            RESOURCE_CONNECTED = 1,
            RESOURCE_GLOBALNET,
            RESOURCE_REMEMBERED,
            RESOURCE_RECENT,
            RESOURCE_CONTEXT
        }

        public enum ResourceType
        {
            RESOURCETYPE_ANY,
            RESOURCETYPE_DISK,
            RESOURCETYPE_PRINT,
            RESOURCETYPE_RESERVED
        }

        public enum ResourceUsage
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,
            RESOURCEUSAGE_CONTAINER = 0x00000002,
            RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
            RESOURCEUSAGE_SIBLING = 0x00000008,
            RESOURCEUSAGE_ATTACHED = 0x00000010,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        }

        public enum ResourceDisplayType
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN,
            RESOURCEDISPLAYTYPE_SERVER,
            RESOURCEDISPLAYTYPE_SHARE,
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        }

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public ResourceScope dwScope = 0;
            public ResourceType dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage dwUsage = 0;
            public string lpLocalName = null;
            public string lpRemoteName = null;
            public string lpComment = null;
            public string lpProvider = null;
        }

        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

        public static int MapNetworkDrive(string remotePath, string localDrive, string userName, string passWord)
        {
            NETRESOURCE myNetResource = new NETRESOURCE();
            myNetResource.lpLocalName = localDrive;
            myNetResource.lpRemoteName = remotePath;
            myNetResource.lpProvider = null;
            int result = WNetAddConnection2(myNetResource, passWord, userName, 0);
            return result;
        }
    }

IIS程序访问NAS

IIS程序访问NAS,一般有两种情况,加域和没加域
1、加域后,什么都好办,可以通过两种方式认证
A、采用域帐户认证
B、NAS资源可以直接授权给指定计算机访问

2、不加域,那一般有三种方式设置访问权限
A、通过指定程序的用户名和密码访问(这里指定的不是本地的用户名和密码,而是NAS的用户名和密码)
B、不指定用户名和密码,直接通过pass-through authentication方式访问,其规则为:
首先通过用户的真实id进行验证
如果用户没有授权,会尝试使用应用池的账户进行验证
如果应用池账号为NetworkService或LocalSystem,将使用计算机账号进行验证
采取这样的方式IIS会提出警告,因为IIS只有在运行之后,才知道能否访问NAS
C、通过代码实现

    //NAS访问封装类
    public class NetworkDrive
    {
        public enum ResourceScope
        {
            RESOURCE_CONNECTED = 1,
            RESOURCE_GLOBALNET,
            RESOURCE_REMEMBERED,
            RESOURCE_RECENT,
            RESOURCE_CONTEXT
        }

        public enum ResourceType
        {
            RESOURCETYPE_ANY,
            RESOURCETYPE_DISK,
            RESOURCETYPE_PRINT,
            RESOURCETYPE_RESERVED
        }

        public enum ResourceUsage
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,
            RESOURCEUSAGE_CONTAINER = 0x00000002,
            RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
            RESOURCEUSAGE_SIBLING = 0x00000008,
            RESOURCEUSAGE_ATTACHED = 0x00000010,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        }

        public enum ResourceDisplayType
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN,
            RESOURCEDISPLAYTYPE_SERVER,
            RESOURCEDISPLAYTYPE_SHARE,
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        }

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public ResourceScope dwScope = 0;
            public ResourceType dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage dwUsage = 0;
            public string lpLocalName = null;
            public string lpRemoteName = null;
            public string lpComment = null;
            public string lpProvider = null;
        }

        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

        public static int MapNetworkDrive(string remotePath, string localDrive, string userName, string passWord)
        {
            NETRESOURCE myNetResource = new NETRESOURCE();
            myNetResource.lpLocalName = localDrive;
            myNetResource.lpRemoteName = remotePath;
            myNetResource.lpProvider = null;
            int result = WNetAddConnection2(myNetResource, passWord, userName, 0);
            return result;
        }
    }

    //调用示例
    NetworkDrive.MapNetworkDrive("NAS paht with ip", "Local Driver Letter", "user", "password");

参考资料:
What is “pass-through authentication” in IIS 7?

不支持一个STA线程上针对多个句柄的WaitAll

最近项目中用了COM控件,同时也用了多线程,在等待线程退出的地方,使用了

AutoResetEvent[] tEevents;
//...
WaitHandle.WaitAll(tEevents);

程序运行到这里,就会报错:

不支持一个STA线程上针对多个句柄的WaitAll

当时事情很急,将其调整为

AutoResetEvent[] tEevents;
//...
foreach(var tEvent in tEevents)
{
    tEvent.WaitOne();
}

就将这个问题绕了过去。

后来,在Stackoverflow上面,查了STA和MTA的区别。COM线程模型称为Apartment模型,分为STA和MTA两种。
STA(Single Thread Apartment)
STA是非线程安全的,常用于UI界面,其他线程要访问STA模式的COM组件,需要通过STA线程进行访问(其实就变成了单线程调用)
MTA(Multi Thread Apartment)
MTA是线程安全的,COM的程序员自己处理了并发的问题,其他线程可以直接访问COM组件

参考资料:
Could you explain STA and MTA?

2014版MAC分区失败(后记)

等了一个月,MAC一直卡在“加密已暂停,连接电源适配器”,当然不管插不插电,结果是一样的。
重启到command+r,关闭FileVault,还是不行。

好吧,这是逼着我干掉你了。
1、将MAC备份为移动硬盘上的映像文件。
2、重启进入MAC,用Time Mashine同样备份到移动硬盘上。
3、重启到command+r
4、磁盘工具,干掉当前分区
5、重建分区(不带加密的那个)
6、Time Mashine还原
7、重启进入MAC
8、Bootcamp分区,安装Win7,搞定!

2014版MAC分区失败

最近帮朋友在新买的MBA上分区安装widows,但无论是bootcamp还是磁盘管理工具,都提示无法分区。
用磁盘管理工具直接分区的时候,提示“不允许此Core Storage操作在稀疏逻辑宗卷组上进行”。

不知道为什么,打电话问了Apple的客服,发现是默认开启了“FileVault”功能,压力山大。
到选项-》安全与隐私-》FileVault里关掉就可以了(FileVault要加密完毕后,才能关闭,所以现在用的是虚拟机)。

鄙视Apple,一点儿提示都没有,不就是SSD盘吗,有啥了不起的,哼。

另外,这台新版MBA,重启后按option,没有Recovery选项,客服小妹妹说新版MBA要按住command+r才有这个选项。
压力山大。

这台电脑是定制的i7+8G+128G的定制版本,不知道是不是MAC OS安装时是否和普通版本是一样的,还是客服小妹妹在忽悠我啊。

CS获取可执行文件所在文件夹

        //Form程序
        private static String getExeFileFolder()
        {
            String strExeFolder = System.Reflection.Assembly.GetExecutingAssembly().Location;
            int nPos = strExeFolder.LastIndexOf("\\");
            if (nPos >= 0)
            {
                strExeFolder = strExeFolder.Substring(0, nPos + 1);
            }
            else
            {
                strExeFolder = strExeFolder + "\\";
            }

            return strExeFolder;
        }

        //IIS程序
        String rootPath = Request.PhysicalApplicationPath;
        String strExeFolder = getExeFileFolder(rootPath);
        private static String getExeFileFolder(String strExeFolder)
        {
            int nPos = strExeFolder.LastIndexOf("\\");
            if (nPos >= 0)
            {
                strExeFolder = strExeFolder.Substring(0, nPos + 1);
            }
            else
            {
                strExeFolder = strExeFolder + "\\";
            }

            return strExeFolder;
        }

多线程处理

        int nMaxThreadNum = 5;
        List<List<JobParam>> jobQueue = new List<List<JobParam>>();
        //...
        for (int i = 0; i < nMaxThreadNum;i++)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncDoRetrieve), jobQueue&#91;i&#93;);
        }

        static void AsyncDoRetrieve(object state)
        {
            if (!(state == null && state is List<JobParam>)) return;
            List<JobParam> jobParams= state as List<JobParam> ;
            foreach(JobParam param in jobParams)
            {
                param.delegateDoSomeThing.BeginInvoke(param,null,null);
            }
        }

DBHelperSQLLite

1.IDBHelper.cs

    interface IDBHelper
    {
        void initDB();
        void closeDB();
        void ExecSQL(String execSql);
        DataTable ExecQuery(String querySql);
    }

2.ZDBHelperSQLLite.cs

    class ZDBHelperSQLLite : IDBHelper
    {
        String dataSource = "";
        SQLiteConnection connection = null;
        public void initDB(String dbPath)
        {
            dataSource = "Data Source =" + dbPath();
            connection = new SQLiteConnection(dbFile);
            connection.Open();
            initTables();
            CreateFileInfoTable();
        }
        
        public void closeDB()
        {
            connection.Close();
        }

        private void initTables()
        {
            String sqlCreate01 = "CREATE TABLE IF NOT EXISTS visitlog(user_id varchar(64), visit_path varchar(256), visit_time integer);";
            SQLiteCommand cmdCreateTable = new SQLiteCommand(connection);
            cmdCreateTable.CommandText = sqlCreate01;
            cmdCreateTable.ExecuteNonQuery();
        }
  
        public void ExecSQL(String execSql)
        {
            SQLiteTransaction transaction = connection.BeginTransaction();
            SQLiteCommand cmdExec = new SQLiteCommand(execSql, connection, transaction );
            cmdExec.ExecuteNonQuery();
            transaction.Commit();
        }

        public DataTable ExecQuery(String querySql)
        {
            SQLiteCommand cmdQuery = new SQLiteCommand(querySql, connection);
            SQLiteDataReader reader = cmdQuery.ExecuteReader();

            DataTable datatable = new DataTable();
            DataTable schemaTable = reader.GetSchemaTable();
            foreach (DataRow myRow in schemaTable.Rows)
            {
                DataColumn myDataColumn = new DataColumn();
                myDataColumn.DataType = myRow.GetType();
                myDataColumn.ColumnName = myRow[0].ToString();
                datatable.Columns.Add(myDataColumn);
            }
            schemaTable = null;

            while (reader.Read())
            {
                DataRow myDataRow = datatable.NewRow();
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    myDataRow[i] = reader[i].ToString();
                }
                datatable.Rows.Add(myDataRow);
                myDataRow = null;
            }
            reader.Close();

            return datatable;
        }
    }