CMD常用命令17常用软件注册为Widows服务

1、Apache注册为Widows服务

httpd -k install

2、MySQL注册为Widows服务

mysqld --install MySQL --defaults-file="D:\MySQL\MySQL Server 5.1\my.ini"

3、PostgreSQL注册为Widows服务

pg_ctl.exe register -N "postgresql-8.4" -D "D:/PostgreSQL/8.4/data" -w

4、SVN注册为Widows服务

sc create svnserve binPath= "\"D:\Subversion\bin\svnserve.exe\" --service -r \"D:\Subversion\repository\"" displayname= "Subversion Service" depend= Tcpip start= auto 
sc start svnserve 
sc stop svnserve 
sc delete svnserve

5、redis注册为Widows服务

#loglevel 分为debug, notice, warning三级
redis-server.exe --service-install D:\Database\Redis2.8\db\redis.windows.conf --loglevel notice
redis-server --service-start
redis-server --service-stop
redis-server --service-uninstall

6、mongodb注册为Widows服务

mongod --dbpath=D:\Database\MongoDB3\db --logpath=D:\Database\MongoDB3\log\mongo.log --port 27027 --noauth --install -serviceName MongoDB01 --serviceDisplayName MongoDB01 
net start MongoDB01

Hadoop Windows Native 编译说明

1、首先,下载hadoop-2.5.2-src源码

拷贝文件夹hadoop-2.5.2-src\hadoop-common-project\hadoop-common\src\main\native
拷贝文件夹from hadoop-2.5.2-src\hadoop-common-project\hadoop-common\src\main\winutils

2、设置JAVA_HOME及PATH环境变量

3、生成javah的头文件
解压hadoop-common-2.5.1.jar,然后运行

javah org.apache.hadoop.util.NativeCrc32
javah org.apache.hadoop.io.compress.lz4.Lz4Compressor
javah org.apache.hadoop.io.compress.lz4.Lz4Decompressor
javah org.apache.hadoop.io.nativeio.NativeIO
javah org.apache.hadoop.security.JniBasedUnixGroupsMapping
javah org.apache.hadoop.security.JniBasedUnixGroupsMapping

4、打开winutils.sln,修改输出路径到../bin,编译

5、打开native.sln,修改输出路径到../bin,修改winutils.lib引用地址,编译

6、拷贝exe及dll文件到HADOOP_HOME/bin,搞定

常见问题:
1、编译的硬件平台要与java位数一致(x86,x64),否则dll无法加载
2、出问题时,先运行winutils.exe,无法运行时,要安装对应VS版本的vcredist可再发行包就好了
3、如果提示”unable to load native hadoop-library for your platform”的话,那只需要在JVM启动参数中制定native library的路径,就可以了

如果比较着急的话,可以到我的github上下载2.5.2版本的native binary:hadoop-windows-native

QT实现自动启动(Windows)

QString NMyUtils::getExeFullPathWithArgs()
{
    QString exePath = QCoreApplication::applicationFilePath().replace("/","\\").replace("Reminder.exe","QTLoader.exe");
    QString argPath = "\""+exePath+"\" TrayIcon";
    qDebug()<<argPath;
    return argPath;
}

bool NMyUtils::isAutoStart()
{
    QSettings reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN", QSettings::NativeFormat);
    QString val = reg.value("NReminder").toString();
    if(val.length()>0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void NMyUtils::setAutoStart()
{
    QSettings reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN", QSettings::NativeFormat);
    reg.setValue("NReminder",NMyUtils::getExeFullPathWithArgs());
}

void NMyUtils::removeAutoStart()
{
    QSettings reg("HKEY_LOCAL_MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN", QSettings::NativeFormat);
    reg.remove("NReminder");
}

Winform多行标题TabControl

今天写示例程序的时候,遇到了需要多行标题TabControl的情况。
整体流程很简单,就是将标题拆分,然后根据行数和最大行宽设置每一Page标题的高度及宽度即可。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace UITabControlTest
{
    public partial class SubForm : Form
    {
        private Dictionary<TabPage, TabPageInfo> allTabMap = new Dictionary<TabPage, TabPageInfo>();

        public SubForm()
        {
            InitializeComponent();
            tabMain.DrawMode = TabDrawMode.OwnerDrawFixed;
        }

        private void SubForm_Load(object sender, EventArgs e)
        {
            tabPage1.Text = "line1\nline2\nline3\nline4\nlin5";
            tabPage2.Text = "line1\nline2\nline3\nline4";
            tabPage3.Text = "line1\nline2\nline3";
            tabPage4.Text = "line1\nline2";

            int lineNum = 0;
            foreach (TabPage tab in this.tabMain.TabPages)
            {
                TabPageInfo pInfo = new TabPageInfo(tab.Text,"\n");
                allTabMap.Add(tab, pInfo);
                lineNum = lineNum>pInfo.LineNum?lineNum:pInfo.LineNum;
            }

            foreach (TabPage tab in this.tabMain.TabPages)
            {
                TabPageInfo pInfo = allTabMap[tab];
                tab.Text = pInfo.MaxLine;
            }

            //some thing is wrong, the font height is 14, the padding height is around 9, why?
            tabMain.Padding = new Point(0, Convert.ToInt32(tabMain.Font.Height * (lineNum - 1) * 0.65));
        }

        private void tabMain_DrawItem(object sender, DrawItemEventArgs e)
        {
            TabControl tabControl = (TabControl)sender;
            TabPage currentTab = tabControl.TabPages[e.Index];
            TabPageInfo info = allTabMap[currentTab];
            string tabText = info.AllLine;
            
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            RectangleF tabRect = (RectangleF)e.Bounds;
            RectangleF textRect = tabRect;
            if (e.Index == tabControl.SelectedIndex)
            {
                tabRect.Inflate(1, 1);
            }

            Graphics g = e.Graphics;
            g.Clip = new Region(tabRect);
            g.Clear(Control.DefaultBackColor);
            g.ResetClip();
            g.DrawString(tabText, e.Font, SystemBrushes.ControlText, textRect, sf);
        }
    }

    class TabPageInfo
    {
        public int LineNum
        {
            get
            {
                return nLineNum;
            }
        }

        public String MaxLine
        {
            get
            {
                //prevent auto wrap
                return szMaxLine+"  ";
            }
        }

        public String getLine(int index)
        {
            if (index < nLineNum)
            { 
                return szLines[index];
            }
            else
            {
                return "";
            }
        }

        public String AllLine
        {
            get
            {
                return szAllLine;
            }
        }

        private int nLineNum = 0;
        private String[] szLines;
        private String szAllLine;
        private String szMaxLine;

        public TabPageInfo(String pageTitle, String splitString)
        {
            szAllLine = pageTitle.Replace(splitString, "\n");
            String [] separators = new String[]{splitString};
            szLines = pageTitle.Split(separators,StringSplitOptions.RemoveEmptyEntries);
            nLineNum = szLines.Length;

            int nMaxLineWidth = 0;
            foreach(String line in szLines)
            {
                if (nMaxLineWidth < line.Length)
                {
                    nMaxLineWidth = line.Length;
                    szMaxLine = line;
                }
            }
        }
    }
}

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;
        }
    }

不支持一个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?

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;
        }
    }