2011年8月16日星期二

exe4j生成的exe文件的unpack

今天看到一个比较实用的Java软件,想知道它是如何实现的,但是这个软件已经使用exe4j封装成了可执行文件。通过搜索网络,看到下面的这篇文章:

http://www.blogjava.net/cnfree/archive/2010/08/22/329559.html

其中的关键:

  1. exe文件的解码(OR 88)
  2. 使用WinHex从解码后的文件中分离出jar文件

其中第一步在文中已经给出了源代码如下:

import java.io.*;
import java.util.*;
public class gen {
public static void main(String args[]) throws IOException {
        FileInputStream fin = new FileInputStream(args[0]); // 可以将整个exe文件解码
        FileOutputStream fout = new FileOutputStream(args[1]);
        BufferedInputStream bin = new BufferedInputStream(fin);
        BufferedOutputStream bout = new BufferedOutputStream(fout);
int in = 0;
do {
            in = bin.read();
if (in == -1)
break;
            in ^= 0x88;
            bout.write(in);
        } while (true);
        bin.close();
        fin.close();
        bout.close();
        fout.close();
    }
}

第二步在文章中是这样描述的:

分析提取出来的数据文件,使用WinHex查看其16进制代码。由于Jar文件的开头总是PK开头,并且总包含有manifest.mf文件,并且结尾总是有3个00,同时结尾段有整个Jar包文件的索引,我们可以根据这一特性来分析我们需要的片段。
1、搜索Jar的manifest,然后往前找,找到的第一个PK段,即为一个Jar的开头。
2、查看片段里Jar里的每个class信息,直到最后的文件索引片段。
3、一个Jar的结束片段位于索引片段之后,仍然包含着PK段,并且最后包含着3个00,且这3个00距离PK大概20个字节左右
根据以上3条准则,足以提取整个Jar数据段,然后导入新文件中,并且以zip字段命名,尝试用ZIP解压缩软件打开,看看是否抽取正确。

这个步骤需要不断尝试才能得到正确的文件,通过实践发现有更简单的方法:在解码后的文件中,如果包含多个jar文件,则之间用十六进制88分隔,每个jar文件均以PK开始,因此可以在WinHex中这样操作:

搜索十六进制串:88888888504B03040A00,其中前面的88分隔符可以根据需要调整数量,将找到的PK(504B)标注为块的开始,按F3再次搜索此特征串,从找到的下一个位置处往前搜索到第一个非88的字节作为块的结束,然后在Edit|Block中将选中的块插入到新文件即可,现在找到的PK的位置即为下一个jar文件的开始。依次类推,可分离出所有的jar文件,注意:最后一个jar文件的结束是PK200 (即jar文件所使用的压缩算法)。

经过实践,这个方法能快速地找到并分离exe4j打包的exe文件中的jar文件。

更简单的方法是:

打包成可执行文件的Java程序在运行时,会将jar全部解压然后调用java运行库执行,只要到系统temp文件夹中搜索*.jar即可得到。

2011年7月17日星期日

在X64系统中开发的Windows服务,如何连接数据库?

 

在使用ODBC连接数据库时,会出现如下问题:

1. 如果为Any CPU或者X64平台,则出现:The specified DSN contains an architecture mismatch between the Driver and Application
查阅资料,使用Wow64下的ODBCAD32.exe来添加系统DSN可解决问题,但实践下来无任何效果

2.如果为x86平台,则会出现:找不到数据源或者驱动程序

在使用JET OLEDB连接数据库时,出现问题如何解决:

1. 连接带有密码的ACCESS数据库时出现“无法启动应用程序。工作组信息文件丢失,或是已被其它用户以独占方式打开”的解决方法:


此问题是由数据库的连接串引起的,可用下面的串连接即可
"Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=true;Data Source=E:\data1.mdb;Jet OLEDB:Database Password=1111 "

2. The 'Microsoft.Jet.OLEDB.4.0' provider is not registered on the local machine 
未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序。


将系统编译目标改为X86即可,原因是未安装64bit的JET OLEDB驱动程序

2011年7月16日星期六

在应用程序中安装、卸载、启动和停止系统服务

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.ServiceProcess;

namespace TncsConfig
{
    class ServiceManager
    {
        private String serviceName;
        private String filepath;

        public ServiceManager(string serviceName,string filepath){
            this.serviceName = serviceName;
            this.filepath = filepath;
        }
       
        public void InstallService(IDictionary stateSaver)
        {
            try
            {
                System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
                if (!ServiceIsExisted())
                {
                    //Install Service
                    string[] commandLineOptions = new string[1] { "/LogFile=TncsDataTransferService.log" };
                    System.Configuration.Install.AssemblyInstaller myAssemblyInstaller = new System.Configuration.Install.AssemblyInstaller(filepath,commandLineOptions);
                    myAssemblyInstaller.UseNewContext = true;
                    myAssemblyInstaller.Install(stateSaver);
                    myAssemblyInstaller.Commit(stateSaver);
                    myAssemblyInstaller.Dispose();
                    //--Start Service
                    service.Start();
                    service.WaitForStatus(ServiceControllerStatus.Running);
                }
                else
                {
                    if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
                    {
                        service.Start();
                        service.WaitForStatus(ServiceControllerStatus.Running);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Install Service Error: " + ex.Message);
            }
        }

        public void UnInstallService()
        {
            try
            {
                if (ServiceIsExisted())
                {
                    //UnInstall Service
                    System.Configuration.Install.AssemblyInstaller myAssemblyInstaller = new System.Configuration.Install.AssemblyInstaller();
                    myAssemblyInstaller.UseNewContext = true;
                    myAssemblyInstaller.Path = filepath;
                    myAssemblyInstaller.Uninstall(null);
                    myAssemblyInstaller.Dispose();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Uninstall Service Error: " + ex.Message);
            }
        }

        public bool ServiceIsExisted()
        {
            ServiceController[] services = ServiceController.GetServices();
            foreach (ServiceController s in services)
            {
                if (s.ServiceName == serviceName)
                {
                    return true;
                }
            }
            return false;
        }

        public Boolean ServiceIsRunning(){
            if (ServiceIsExisted())
            {
                System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
                if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                    return true;
                else
                    return false;
            }
            return false;
        }

        public void StartService()
        {
            if (ServiceIsExisted())
            {
                System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
                if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
                {
                    service.Start();
                    service.WaitForStatus(ServiceControllerStatus.Running);
                }
            }
        }

        public void StopService()
        {
            if (ServiceIsExisted())
            {
                System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
                if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
                {
                    service.Stop();
                    service.WaitForStatus(ServiceControllerStatus.Stopped);
                }
            }
        }
    }
}

Win7 X64中使用控制面板中的设置数据源无法读到系统ODBC数据源

 

应该使用 C:\Windows\SysWOW64\odbcad32.exe 来配置ODBC数据源

在Win7 X64中使用C#获取系统和用户ODBC数据源

 

需要注意的是,系统ODBC数据源保存在 HKLM\Software\Wow6432Node\ODBC\ODBC.INI\ODBC Data Sources键下

using System;
using System.Collections.Generic;
using System.Text;

namespace TncsConfig
{
    /// <summary>
    /// The types of data sources that can be set.
    /// </summary>
    public enum DataSourceType { System, User }

    /// <summary>
    /// Provides methods and tools to manage the Odbc data sources on the machine.
    /// </summary>
    public class OdbcDataSourceManager
    {
        // Returns a list of data source names from the local machine.
        public System.Collections.SortedList GetAllDataSourceNames()
        {
            // Get the list of user DSN's first.
            System.Collections.SortedList dsnList = GetUserDataSourceNames();

            // Get list of System DSN's and add them to the first list.
            System.Collections.SortedList systemDsnList = GetSystemDataSourceNames();
            for (int i = 0; i < systemDsnList.Count; i++)
            {
                string sName = systemDsnList.GetKey(i) as string;
                DataSourceType type = (DataSourceType)systemDsnList.GetByIndex(i);
                try
                {
                    // This dsn to the master list
                    dsnList.Add(sName, type);
                }
                catch
                {
                    // An exception can be thrown if the key being added is a duplicate so
                    // we just catch it here and have to ignore it.
                }
            }

            return dsnList;
        }

        /// <summary>
        /// Gets all System data source names for the local machine.
        /// </summary>
        public System.Collections.SortedList GetSystemDataSourceNames()
        {
            System.Collections.SortedList dsnList = new System.Collections.SortedList();

            // get system dsn's
            Microsoft.Win32.RegistryKey reg = (Microsoft.Win32.Registry.LocalMachine).OpenSubKey("Software");
            if (reg != null)
            {
                reg = reg.OpenSubKey("ODBC");
                if (reg != null)
                {
                    reg = reg.OpenSubKey("ODBC.INI");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC Data Sources");
                        if (reg != null)
                        {
                            // Get all DSN entries defined in DSN_LOC_IN_REGISTRY.
                            foreach (string sName in reg.GetValueNames())
                            {
                                dsnList.Add(sName, DataSourceType.System);
                            }
                        }
                        try
                        {
                            reg.Close();
                        }
                        catch { /* ignore this exception if we couldn't close */ }
                    }
                }
            }
            reg = (Microsoft.Win32.Registry.LocalMachine).OpenSubKey("Software");
            if(reg!=null){
                reg = reg.OpenSubKey("Wow6432Node");
                if(reg!=null){
                    reg = reg.OpenSubKey("ODBC");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC.INI");
                        if (reg != null)
                        {
                            reg = reg.OpenSubKey("ODBC Data Sources");
                            if (reg != null)
                            {
                                // Get all DSN entries defined in DSN_LOC_IN_REGISTRY.
                                foreach (string sName in reg.GetValueNames())
                                {
                                    dsnList.Add(sName, DataSourceType.System);
                                }
                            }
                            try
                            {
                                reg.Close();
                            }
                            catch { /* ignore this exception if we couldn't close */ }
                        }
                    }
                }
            }

            return dsnList;
        }

        /// <summary>
        /// Gets all User data source names for the local machine.
        /// </summary>
        public System.Collections.SortedList GetUserDataSourceNames()
        {
            System.Collections.SortedList dsnList = new System.Collections.SortedList();

            // get user dsn's
            Microsoft.Win32.RegistryKey reg = (Microsoft.Win32.Registry.CurrentUser).OpenSubKey("Software");
            if (reg != null)
            {
                reg = reg.OpenSubKey("ODBC");
                if (reg != null)
                {
                    reg = reg.OpenSubKey("ODBC.INI");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC Data Sources");
                        if (reg != null)
                        {
                            // Get all DSN entries defined in DSN_LOC_IN_REGISTRY.
                            foreach (string sName in reg.GetValueNames())
                            {
                                dsnList.Add(sName, DataSourceType.User);
                            }
                        }
                        try
                        {
                            reg.Close();
                        }
                        catch { /* ignore this exception if we couldn't close */ }
                    }
                }
            }

            return dsnList;
        }
    }
}

2011年7月12日星期二

删除重复数据的存储过程

CREATE PROCEDURE deldup

AS
    declare @bid integer,@bbid integer,@bname varchar(200)
    declare name_cursor cursor for  SELECT distinct a.bname FROM BuyerTable a INNER JOIN BuyerTable b ON a.Bname = b.Bname AND a.BuyerID <> b.BuyerID
   
    open name_cursor

    FETCH   NEXT   FROM   name_cursor  INTO   @bname

    WHILE   @@FETCH_STATUS   =   0
    BEGIN
        select @bid=min(buyerid) from buyertable where bname=@bname
        declare id_cursor cursor for select buyerid from buyertable where bname=@bname
        open id_cursor
        fetch next from id_cursor into @bbid
        while @@fetch_status=0
        begin
            update ProductionSell set buyerid=@bid where buyerid=@bbid
            fetch next from id_cursor into @bbid
        end
        close id_cursor
        deallocate id_cursor

        update buyertable set buyerid=@bid where bname=@bname
       
        FETCH   NEXT   FROM   name_cursor  INTO   @bname
    end
    close name_cursor
    deallocate name_cursor
   
GO

2011年2月16日星期三

Code::Blocks 10.05与Comodo防火墙的冲突及解决方法

看到CB出了新版本,赶快试验了一下,结果发现在debug时出现问题,搜索网络找到了类似的问题

http://forums.comodo.com/empty-t47299.0.html

http://forums.codeblocks.org/index.php/topic,13666.0.html

最后的解决方法是将 guard32.dll    gdb.exe 和 project所在的目录一起加入到 Comodo D+ 的可执行文件控制的排除列表中

2011年2月3日星期四

QQ群共享空间无法上传文件的解决方法

装了IE8的你可能会发现,根本无法上传文件,即使你切换回旧版群共享文件也是如此。而在QQ校友的班级群页面上,上传文件也是只出现上传文件选择框,点击上传之后,什么也没有发生。

这种情况发生在基于IE内核、运行在安装了IE8的操作系统上的浏览器中,解决方法是打开Internet选项,将– 安全– 自定义级别   >>把“将文件上传到服务器时包含本地目录路径”这一项“启用”确定即可解决此问题。

2011年2月1日星期二

C#程序设置只允许一个实例

namespace VPNClient
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            bool createNew;
            using (System.Threading.Mutex mutex = new System.Threading.Mutex(true, Application.ProductName, out createNew))
            {

                if (createNew)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new MainForm());
                }else{
                    MessageBox.Show("应用程序已经在运行中...");
                    System.Threading.Thread.Sleep(1000);
                    System.Environment.Exit(1);
                }
            }
        }
    }
}

另一个实现的很好的IP Helper代码包

 

http://www.csharpfr.com//code.aspx?ID=50722

法国网站

一个IPHelper API的实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;

namespace VPNClient
{
    class iphlpapi
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADDRESS_STRING
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string Address;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADDR_STRING
        {
            public IntPtr Next;
            public IP_ADDRESS_STRING IpAddress;
            public IP_ADDRESS_STRING IpMask;
            public Int32 Context;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDROW
        {
            public UInt32 dwForwardDest;        //destination IP address.
            public UInt32 dwForwardMask;        //Subnet mask
            public UInt32 dwForwardPolicy;      //conditions for multi-path route. Unused, specify 0.
            public UInt32 dwForwardNextHop;     //IP address of the next hop. Own address?
            public UInt32 dwForwardIfIndex;     //index of interface
            public UInt32 dwForwardType;        //route type
            public UInt32 dwForwardProto;       //routing protocol.
            public UInt32 dwForwardAge;         //age of route.
            public UInt32 dwForwardNextHopAS;   //autonomous system number. 0 if not relevant
            public int dwForwardMetric1;     //-1 if not used (goes for all metrics)
            public int dwForwardMetric2;
            public int dwForwardMetric3;
            public int dwForwardMetric4;
            public int dwForwardMetric5;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADAPTER_INFO
        {
            public IntPtr Next;
            public Int32 ComboIndex;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256 + 4)]
            public string AdapterName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128 + 4)]
            public string AdapterDescription;
            public UInt32 AddressLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] Address;
            public Int32 Index;
            public UInt32 Type;
            public UInt32 DhcpEnabled;
            public IntPtr CurrentIpAddress;
            public IP_ADDR_STRING IpAddressList;
            public IP_ADDR_STRING GatewayList;
            public IP_ADDR_STRING DhcpServer;
            public bool HaveWins;
            public IP_ADDR_STRING PrimaryWinsServer;
            public IP_ADDR_STRING SecondaryWinsServer;
            public Int32 LeaseObtained;
            public Int32 LeaseExpires;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDTABLE
        {
            public int dwNumEntries;            //number of route entries in the table.
            public MIB_IPFORWARDROW[] table;
        }

        [DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
        public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int CreateIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int DeleteIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int SetIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int GetIpForwardTable(byte[] pIpForwardTable, out int pdwSize, bool bOrder);


        public static int createIpForwardEntry(UInt32 destIPAddress, UInt32 destMask, UInt32 nextHopIPAddress, UInt32 ifIndex,int metric)
        {
            MIB_IPFORWARDROW mifr = new MIB_IPFORWARDROW();
            mifr.dwForwardDest = destIPAddress;
            mifr.dwForwardMask = destMask;
            mifr.dwForwardNextHop = nextHopIPAddress;
            mifr.dwForwardIfIndex = ifIndex;
            mifr.dwForwardPolicy = Convert.ToUInt32(0);
            mifr.dwForwardType = Convert.ToUInt32(3);
            mifr.dwForwardProto = Convert.ToUInt32(3);
            mifr.dwForwardAge = Convert.ToUInt32(0);
            mifr.dwForwardNextHopAS = Convert.ToUInt32(0);
            mifr.dwForwardMetric1 = metric;
            mifr.dwForwardMetric2 = -1;
            mifr.dwForwardMetric3 = -1;
            mifr.dwForwardMetric4 = -1;
            mifr.dwForwardMetric5 = -1;
            return CreateIpForwardEntry(ref mifr);
        }

        public static int deleteIpForwardEntry(UInt32 destIPAddress, UInt32 destMask, UInt32 nextHopIPAddress, UInt32 ifIndex)
        {
            MIB_IPFORWARDROW mifr = new MIB_IPFORWARDROW();
            mifr.dwForwardDest = destIPAddress;
            mifr.dwForwardMask = destMask;
            mifr.dwForwardNextHop = nextHopIPAddress;
            mifr.dwForwardIfIndex = ifIndex;
            mifr.dwForwardPolicy = Convert.ToUInt32(0);
            mifr.dwForwardType = Convert.ToUInt32(3);
            mifr.dwForwardProto = Convert.ToUInt32(3);
            mifr.dwForwardAge = Convert.ToUInt32(0);
            mifr.dwForwardNextHopAS = Convert.ToUInt32(0);
            mifr.dwForwardMetric1 = -1;
            mifr.dwForwardMetric2 = -1;
            mifr.dwForwardMetric3 = -1;
            mifr.dwForwardMetric4 = -1;
            mifr.dwForwardMetric5 = -1;
            return DeleteIpForwardEntry(ref mifr);
        }

        const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
        const int ERROR_BUFFER_OVERFLOW = 111;
        const int MAX_ADAPTER_NAME_LENGTH = 256;
        const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
        const int MIB_IF_TYPE_OTHER = 1;
        const int MIB_IF_TYPE_ETHERNET = 6;
        const int MIB_IF_TYPE_TOKENRING = 9;
        const int MIB_IF_TYPE_FDDI = 15;
        const int MIB_IF_TYPE_PPP = 23;
        const int MIB_IF_TYPE_LOOPBACK = 24;
        const int MIB_IF_TYPE_SLIP = 28;

        /// <summary>
        /// IPAddressToNumber
        /// </summary>
        /// <param name="IPaddress"></param>
        /// <returns></returns>
        public static double IPAddressToNumber(string IPaddress)
        {
            int i;
            string[] arrDec;
            double num = 0;
            if (IPaddress == "")
            {
                return 0;
            }
            else
            {
                arrDec = IPaddress.Split('.');
                for (i = arrDec.Length - 1; i >= 0; i = i - 1)
                {
                    num += ((int.Parse(arrDec[i]) % 256) * Math.Pow(256, (3 - i)));
                }
                return num;
            }
        }

        /// <summary>
        /// GetAdaptersIndex
        /// </summary>
        /// <returns></returns>
        public static string GetAdaptersIndex()
        {
            string result = string.Empty;
            long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));
            int ret = GetAdaptersInfo(pArray, ref structSize);

            if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
            {
                pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));
                ret = GetAdaptersInfo(pArray, ref structSize);
            }

            if (ret == 0)
            {
                IntPtr pEntry = pArray;
                do
                {
                    IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));
                    if (entry.AdapterDescription.IndexOf("PPP") >= 0 || entry.AdapterDescription.IndexOf("SLIP") >= 0 || entry.AdapterDescription.IndexOf("PPTP") >= 0 || entry.AdapterDescription.IndexOf("VPN") >= 0)
                    {
                        result += (result == string.Empty ? string.Empty : "|") + entry.Index.ToString();
                    }
                    pEntry = entry.Next;
                }
                while (pEntry != IntPtr.Zero);
                Marshal.FreeHGlobal(pArray);
                return result;
            }
            else
            {
                Marshal.FreeHGlobal(pArray);
                throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
            }

        }

        /// <summary>
        /// GetAdapters
        /// </summary>
        public static void GetAdapters()
        {
            long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));

            int ret = GetAdaptersInfo(pArray, ref structSize);

            if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
            {
                // Buffer was too small, reallocate the correct size for the buffer.
                pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));

                ret = GetAdaptersInfo(pArray, ref structSize);
            } // if

            if (ret == 0)
            {
                // Call Succeeded
                IntPtr pEntry = pArray;

                do
                {
                    // Retrieve the adapter info from the memory address
                    IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));

                    // ***Do something with the data HERE!***
                    Console.WriteLine("\n");
                    Console.WriteLine("Index: {0}", entry.Index.ToString());

                    // Adapter Type
                    string tmpString = string.Empty;
                    switch (entry.Type)
                    {
                        case MIB_IF_TYPE_ETHERNET: tmpString = "Ethernet"; break;
                        case MIB_IF_TYPE_TOKENRING: tmpString = "Token Ring"; break;
                        case MIB_IF_TYPE_FDDI: tmpString = "FDDI"; break;
                        case MIB_IF_TYPE_PPP: tmpString = "PPP"; break;
                        case MIB_IF_TYPE_LOOPBACK: tmpString = "Loopback"; break;
                        case MIB_IF_TYPE_SLIP: tmpString = "Slip"; break;
                        default: tmpString = "Other/Unknown"; break;
                    }

                    Console.WriteLine("Adapter Type: {0}", tmpString);
                    Console.WriteLine("Name: {0}", entry.AdapterName);
                    Console.WriteLine("Desc: {0}\n", entry.AdapterDescription);
                    Console.WriteLine("DHCP Enabled: {0}", (entry.DhcpEnabled == 1) ? "Yes" : "No");

                    if (entry.DhcpEnabled == 1)
                    {
                        Console.WriteLine("DHCP Server : {0}", entry.DhcpServer.IpAddress.Address);

                        // Lease Obtained (convert from "time_t" to C# DateTime)
                        DateTime pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseObtained).ToLocalTime();
                        Console.WriteLine("Lease Obtained: {0}", pdatDate.ToString());

                        // Lease Expires (convert from "time_t" to C# DateTime)
                        pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseExpires).ToLocalTime();
                        Console.WriteLine("Lease Expires : {0}\n", pdatDate.ToString());
                    } // if DhcpEnabled

                    Console.WriteLine("IP Address     : {0}", entry.IpAddressList.IpAddress.Address);
                    Console.WriteLine("Subnet Mask    : {0}", entry.IpAddressList.IpMask.Address);
                    Console.WriteLine("Default Gateway: {0}", entry.GatewayList.IpAddress.Address);

                    // MAC Address (data is in a byte[])
                    tmpString = string.Empty;
                    for (int i = 0; i < entry.AddressLength - 1; i++)
                    {
                        tmpString += string.Format("{0:X2}-", entry.Address[i]);
                    }

                    Console.WriteLine("MAC Address    : {0}{1:X2}\n", tmpString, entry.Address[entry.AddressLength - 1]);
                    Console.WriteLine("Has WINS: {0}", entry.HaveWins ? "Yes" : "No");

                    if (entry.HaveWins)
                    {
                        Console.WriteLine("Primary WINS Server  : {0}", entry.PrimaryWinsServer.IpAddress.Address);
                        Console.WriteLine("Secondary WINS Server: {0}", entry.SecondaryWinsServer.IpAddress.Address);
                    }

                    // Get next adapter (if any)
                    pEntry = entry.Next;

                }
                while (pEntry != IntPtr.Zero);
                Marshal.FreeHGlobal(pArray);
            }
            else
            {
                Marshal.FreeHGlobal(pArray);
                throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
            }

        }
    }
}

修改windows系统路由表

/// <summary>
        /// 添加靜態路由
        /// </summary>
        /// <returns></returns>
        private int AddIpRouteEntries(){
            HttpClient wc = new HttpClient();
            int res=AddIpRouteEntriesFromFile("http://61.155.18.16:81/cernet.txt");
             if(res!=0){
                 MessageBox.Show("不能下载路由列表,即将把常熟理工学院内部地址添加到系统路由表并通过VPN访问,其他地址继续通过原网络访问!");
                 return res;
             }
             res = AddIpRouteEntriesFromFile("http://61.155.18.16:81/userdefine.txt");
             if (res != 0)
             {
                 MessageBox.Show("不能下载路由列表,即将把常熟理工学院内部地址添加到系统路由表并通过VPN访问,其他地址继续通过原网络访问!");
                 return res;
             }
            res=AddIpRouteEntry("10.0.0.0","255.0.0.0");
            return res;
        }

        private int AddIpRouteEntriesFromFile(string url){
            int res = 0;
            HttpClient wc = new HttpClient();
            try
            {
                byte[] str = wc.DownloadData(url);
                String restext = Encoding.Default.GetString(str);
                String[] ads = restext.Split(new char[] { '\n' });
                for (int i = 0; i < ads.Length; i++)
                {
                    string ent = ads[i].Trim();
                    if (ent.Length != 0)
                    {
                        string[] xx = ent.Split(new char[] { ',' });
                        res = AddIpRouteEntry(xx[0], xx[1]);
                        if (res != 0)
                            return res;
                    }

                }
            }
            catch (Exception exp)
            {
                return 1976;
            }
            return res;
        }

        /// <summary>
        /// 添加靜態路由
        /// </summary>
        /// <param name="network"></param>
        /// <param name="netmask"></param>
        /// <returns></returns>
        private int AddIpRouteEntry(string network,string netmask){
            UInt32 dest = BitConverter.ToUInt32(IPAddress.Parse(network).GetAddressBytes(), 0);
            UInt32 mask = BitConverter.ToUInt32(IPAddress.Parse(netmask).GetAddressBytes(), 0);
            UInt32 nextHop = BitConverter.ToUInt32(IPAddress.Parse(this.ClientIp).GetAddressBytes(), 0);
            return iphlpapi.createIpForwardEntry(dest, mask, nextHop, Convert.ToUInt32(this.interfaceIndex), metric);
        }

        /// <summary>
        /// 獲取系統路由表中目標地址為0.0.0.0的路由項的metric
        /// </summary>
        private void GetMetric(){
            IEnumerable<RouteEntry> ienum=iphlp.GetRoutesTable();
            IEnumerator<RouteEntry> enums=ienum.GetEnumerator();
            enums.MoveNext();
            while(enums.Current!=null){
                RouteEntry ent = enums.Current;
                if (ent.Destination.Equals(IPAddress.Parse("0.0.0.0")))
                {
                    metric=ent.Metric1;
                    return;
                }
                enums.MoveNext();
            }
        }

注意:如果不获取系统路由表中目标地址为0的项的metric而直接添加路由项(metric1=-1),则CreateIpForwardEntry()函数会返回87(Invalid parameter)

获取VPN拨号后的IP地址

 

private void GetVpnClientIp(){
           GetMetric();
           foreach (RasConnection connection in RasConnection.GetActiveConnections())
           {
               if (connection.EntryName == entry.Name)
               {
                   RasIPInfo ipAddresses = (RasIPInfo)connection.GetProjectionInfo(RasProjectionType.IP);
                  
                   interfaceIndex =Convert.ToUInt32(iphlpapi.GetAdaptersIndex());
                   if (ipAddresses != null)
                   {
                       //this.ClientAddressTextBox.Text = ipAddresses.IPAddress.ToString();
                       //this.ServerAddressTextBox.Text = ipAddresses.ServerIPAddress.ToString();
                       this.Ipbar.Text = ipAddresses.IPAddress.ToString();
                       this.ClientIp = ipAddresses.IPAddress.ToString();
                       this.ServerIp = ipAddresses.ServerIPAddress.ToString();
                   }
               }
           }
       }

使用DotRas进行VPN拨号

 

/// <summary>
       /// 初始化VPN連接
       ///
       /// </summary>
       private void InitVpnEntry(){
           try
           {
               this.AllUsersPhoneBook.Open();
               entry = RasEntry.CreateVpnEntry(EntryName, "61.155.18.16", RasVpnStrategy.Default,
                   RasDevice.GetDeviceByName("(PPTP)", RasDeviceType.Vpn));
               entry.Options.RemoteDefaultGateway = bDefaultGw;
               entry.Options.NetworkLogOn = false;
               entry.Options.PreviewDomain = false;
               this.AllUsersPhoneBook.Entries.Remove(entry.Name);
               this.AllUsersPhoneBook.Entries.Add(entry);
               this.statusbar.Text = "VPN连接创建成功,程序初始化完成!";
               this.DisconnectButton.Enabled = false;
           }catch(Exception ex){
               //MessageBox.Show(ex.GetType()+":打开或创建电话簿时发生错误。请检查VPN连接是否已经存在!");
           }
       }

       /// <summary>
       /// 建立VPN連接
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void button2_Click(object sender, EventArgs e)
       {
           InitVpnEntry();
           this.Dialer.EntryName = EntryName;
           this.Dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);

           this.username = txtUsername.Text.Trim();
           this.password = txtPassword.Text.Trim();
           if (this.username.Length == 0 || this.password.Length == 0)
           {
               MessageBox.Show("请填写用户名和密码!");
               return;
           }

           try
           {
               this.Dialer.Credentials = new NetworkCredential(username,password);
               this.handle = this.Dialer.DialAsync();
               this.DisconnectButton.Enabled = true;
               this.BtnExit.Enabled = false;
               this.btnConnect.Enabled = false;
           }
           catch (Exception ex)
           {
               MessageBox.Show(ex.ToString());
           }
       }

/// <summary>
        /// 斷開VPN連接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DisconnectButton_Click(object sender, EventArgs e)
        {
            if (entry == null)
                return;
            if (this.Dialer.IsBusy)
            {
                this.Dialer.DialAsyncCancel();
            }
            else
            {
                RasConnection connection = RasConnection.GetActiveConnectionByHandle(this.handle);
                if (connection != null)
                {
                    connection.HangUp();
                }
            }
            this.BtnExit.Enabled = true;
            this.btnConnect.Enabled = true;
            this.DisconnectButton.Enabled = false;
            this.statusbar.Text = "VPN连接已断开!";
        }

/// <summary>
       /// 異步VPN連接過程回調函數
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void Dialer_StateChanged(object sender, StateChangedEventArgs e)
       {
           this.statusbar.Text = e.State.ToString();
       }

       /// <summary>
       /// 異步VPN連接過程回調函數
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void Dialer_DialCompleted(object sender, DialCompletedEventArgs e)
       {
           if (e.Cancelled)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = "拨号已被取消!";
           }
           else if (e.TimedOut)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = "连接超时!";
           }
           else if (e.Error != null)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = e.Error.ToString();
           }
           else if (e.Connected)
           {
               this.DisconnectButton.Enabled = true;
               this.BtnExit.Enabled = false;
               this.btnConnect.Enabled = false;
               this.statusbar.Text = "VPN拨号成功!";
               WriteSettings();
               GetVpnClientIp();
           }

           if (!e.Connected)
           {
               this.DisconnectButton.Enabled = false;
               this.BtnExit.Enabled = true;
               this.btnConnect.Enabled = true;
               this.statusbar.Text = "未能成功连接VPN服务器!";
               MessageBox.Show("VPN拨号失败!请检查服务器是否正常,用户名和密码是否正确。");
           }
       }

C#中保存和装载配置文件(ini)的类及使用示例代码

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Windows.Forms;

namespace VPNClient
{
    public class Settings
    {
        XmlDocument doc;
        string fileName;
        string rootName;

        public Settings(string fileName, string rootName)
        {
            this.fileName = fileName;
            this.rootName = rootName;

            doc = new XmlDocument();

            try
            {
                doc.Load(fileName);
            }
            catch (System.IO.FileNotFoundException)
            {
                CreateSettingsDocument();
            }
        }

        public Settings(string fileName)
            : this(fileName, "Settings")
        {
        }

        //Deletes all entries of a section
        public void ClearSection(string section)
        {
            XmlNode root = doc.DocumentElement;
            XmlNode s = root.SelectSingleNode('/' + rootName + '/' + section);

            if (s == null)
                return;  //not found

            s.RemoveAll();
        }

        //initializes a new settings file with the XML version
        //and the root node
        protected void CreateSettingsDocument()
        {
            doc.AppendChild(doc.CreateXmlDeclaration("1.0", null, null));
            doc.AppendChild(doc.CreateElement(rootName));
        }

        public void Flush()
        {
            try
            {
                doc.Save(fileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //removes a section and all its entries
        public void RemoveSection(string section)
        {
            XmlNode root = doc.DocumentElement;
            XmlNode s = root.SelectSingleNode('/' + rootName + '/' + section);

            if (s != null)
                root.RemoveChild(s);
        }

        public void Save()
        {
            Flush();
        }


        #region Read methods

        public bool ReadBool(string section, string name, bool defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == Boolean.TrueString)
                return true;
            else if (s == Boolean.FalseString)
                return false;
            else
                return defaultValue;
        }

        public DateTime ReadDateTime(string section, string name, DateTime defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    DateTime dt = Convert.ToDateTime(s);
                    return dt;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public double ReadDouble(string section, string name, double defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    double d = Convert.ToDouble(s);
                    return d;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public float ReadFloat(string section, string name, float defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    float f = Convert.ToSingle(s);
                    return f;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public int ReadInt(string section, string name, int defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    int n = Convert.ToInt32(s);
                    return n;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public long ReadLong(string section, string name, long defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    long l = Convert.ToInt64(s);
                    return l;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public short ReadShort(string section, string name, short defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    short n = Convert.ToInt16(s);
                    return n;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public string ReadString(string section, string name, string defaultValue)
        {
            XmlNode root = doc.DocumentElement;
            XmlNode s = root.SelectSingleNode('/' + rootName + '/' + section);

            if (s == null)
                return defaultValue;  //not found

            XmlNode n = s.SelectSingleNode(name);

            if (n == null)
                return defaultValue;  //not found

            XmlAttributeCollection attrs = n.Attributes;

            foreach (XmlAttribute attr in attrs)
            {
                if (attr.Name == "value")
                    return attr.Value;
            }

            return defaultValue;
        }

        public uint ReadUInt(string section, string name, uint defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    uint n = Convert.ToUInt32(s);
                    return n;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public ulong ReadULong(string section, string name, ulong defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    ulong l = Convert.ToUInt64(s);
                    return l;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        public ushort ReadUShort(string section, string name, ushort defaultValue)
        {
            string s = ReadString(section, name, "");

            if (s == "")
                return defaultValue;
            else
            {
                try
                {
                    ushort n = Convert.ToUInt16(s);
                    return n;
                }
                catch (FormatException)
                {
                    return defaultValue;
                }
            }
        }

        #endregion


        #region Write methods

        public void WriteBool(string section, string name, bool value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteDateTime(string section, string name, DateTime value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteDouble(string section, string name, double value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteFloat(string section, string name, float value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteInt(string section, string name, int value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteLong(string section, string name, long value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteShort(string section, string name, short value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteString(string section, string name, string value)
        {
            XmlNode root = doc.DocumentElement;
            XmlNode s = root.SelectSingleNode('/' + rootName + '/' + section);

            if (s == null)
                s = root.AppendChild(doc.CreateElement(section));

            XmlNode n = s.SelectSingleNode(name);

            if (n == null)
                n = s.AppendChild(doc.CreateElement(name));

            XmlAttribute attr = ((XmlElement)n).SetAttributeNode("value", "");
            attr.Value = value;
        }

        public void WriteUInt(string section, string name, uint value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteULong(string section, string name, ulong value)
        {
            WriteString(section, name, value.ToString());
        }

        public void WriteUShort(string section, string name, ushort value)
        {
            WriteString(section, name, value.ToString());
        }

        #endregion

    }
}

使用示例代码

private void LoadSettings(){
            Settings s = new Settings("config.xml");
            bPasswdRemeber = s.ReadBool("Data1", "RemeberPassword", false);
            bDefaultGw = s.ReadBool("Data1", "UseDefaultGateway", false);
            username = s.ReadString("Data1", "Username", "");
            password = s.ReadString("Data1","Password","");
            this.txtUsername.Text = username;
            this.txtPassword.Text = password;
            this.cbxDefaultGW.Checked = bDefaultGw;
            this.cbxPassword.Checked = bPasswdRemeber;
        }

        private void WriteSettings(){
            username = this.txtUsername.Text.Trim();
            password = this.txtPassword.Text.Trim();
            bDefaultGw = this.cbxDefaultGW.Checked;
            bPasswdRemeber = this.cbxPassword.Checked;

            Settings s = new Settings("config.xml");
            s.WriteBool("Data1", "RemeberPassword", bPasswdRemeber);
            s.WriteBool("Data1", "UseDefaultGateway", bDefaultGw);
            if(bPasswdRemeber){
                s.WriteString("Data1", "Username", username);
                s.WriteString("Data1", "Password", password);
            }else{
                s.WriteString("Data1", "Username", "");
                s.WriteString("Data1", "Password", "");
            }
            s.Save();
        }

生成的config.xml数据文件

<?xml version="1.0"?>
<Settings>
  <Data1>
    <RemeberPassword value="True" />
    <UseDefaultGateway value="False" />
    <Username value="jimshen" />
    <Password value=jimshen!#$%%^ />
  </Data1>
</Settings>