2012年2月19日星期日

在InnoSetup中检测和安装.NET Framework和MySQL Connector/NET

 

[Files]
Source: "D:\VOS\share\tncs\dotnetfx.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall
Source: "D:\VOS\share\tncs\mysql-connector-net-6.4.3.msi"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall 
; 注意: 不要在任何共享系统文件上使用“Flags: ignoreversion”

[Run]
Filename: "{tmp}\dotnetfx.exe"; Parameters: “/Q /NORESTART”; Check: IsFramework20Installed; Flags: runhidden shellexec waituntilterminated hidewizard;
Filename: "msiexec.exe"; Parameters: "/i ""{tmp}\mysql-connector-net-6.4.3.msi"""; Check: IsMysqlConnectorNetInstalled; Flags: hidewizard

[Code]  
function IsFramework20Installed():Boolean;
begin
    Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\.NetFramework\Policy\v2.0');
end;

function IsMysqlConnectorNetInstalled():Boolean;
begin
    Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\MySQL AB\MySQL Connector/Net');
end;

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