让PostgreSQL数据库和移动硬盘一起移动

来源:互联网 发布:网络信息安全注意事项 编辑:程序博客网 时间:2024/05/15 16:15

让PostgreSQL数据库和移动硬盘一起移动


 

摘  要:通过分析PostgreSQL安装成功后在windows注册表上所注册的条目,依此编写相关配置程序,当安装了PostgreSQL数据库的移动硬盘通过USB口插入其它PC机,通过运行此程序能够马上启动移动硬盘上的数据库,避免重装PostgreSQL数据库的费时费力的麻烦。

关键词:PostgreSQL;移动硬盘

由于PostgreSQL数据库知识太过繁复,需要长期的学习和实操。如果PostgreSQL能够安装在移动硬盘上,在任何有PC机的地方(比如公共图书馆),插上移动硬盘,执行必要的程序后,就能使用(当然能够通过编辑autorun.inf文件做到插上就能启动),是一个不错的主意。下面是经过多次尝试达到此目的经过检验的制作过程。

1 在移动硬盘上安装PostgreSQL数据库

首先保证移动硬盘有一个固定的盘符,尽量选择较大的字符,比如G以免与PC机上的盘符产生冲突(一般选择G盘比较好)。

将移动硬盘插入PC机后,查看盘符是否为G,不为G通过【计算机管理】下【磁盘管理】中选择移动硬盘,鼠标右键,选择菜单【更改驱动器名和路径】将其改为G。

然后按照常规的PostgreSQL安装方法将PostgreSQL安装在移动硬盘上。

我们假定数据库实例名为MY11.

2 复制PostgreSQL应用程序快捷方式

假定PostgreSQL安装在G:\0PostgreSQL下,在此目录下创建一个子目录比如dbstart,再在此子目录下创建下一级子目录比如9.3用于存放各种用于配置PostgreSQL的各种文件.这一级目录可以有多个,比如9.3用于存放与一个PostgreSQL9.3数据库相关的文件,而9.2用于存放与一个PostgreSQL9.2数据库相关的文件等(如果你准备在移动硬盘上安装各种版本的PostgreSQL数据库的话)。

将安装PostgreSQL后产生的PostgreSQL应用程序的菜单目录(例如C:\Documents andSettings\All Users\「开始」菜单\程序\PostgreSQL9.3)复制到上述子目录下(这个目录下是一些PostgreSQL程序的快捷方式),以便当此移动硬盘插入其他PC机时可以方便的使用PostgreSQL的相关程序。

3 导出及编制PostgreSQL注册表的相关条目文件

导出[HKEY_LOCAL_MACHINE\SOFTWARE\PostgreSQL],将文件命名为PostgreSQL.reg。

导出[HKEY_LOCAL_MACHINE\SOFTWARE\PostgreSQL Global Development Group],将文件命名为PostgreSQL_Global_Development_Group.reg。

导出[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\postgresql-9.3],将文件命名为PostgreSQL_CurrentControlSet.reg,复制此文件为PostgreSQL_ControlSet001.reg、PostgreSQL_ControlSet002.reg、PostgreSQL_ControlSet003.reg、PostgreSQL_ControlSet004.reg,并将各文件中的CurrentControlSet分别改为ControlSet001、ControlSet002、ControlSet003、ControlSet004。然后将这些文件放在目录G:\0PostgreSQL\dbstart\9.3下。

4 编写相关自动配置程序

编写下列批处理程序PostgreSQL_start.bat和PostgreSQL_stop.bat,并存放在目录G:\0PostgreSQL\dbstart\9.3下

启动PostgreSQL的批处理程序PostgreSQL_start.bat如下:

rem 创建、注册并启动PostgreSQL企业管理服务

 

rem 先创建服务,服务中的服务执行程序是否完整无所谓

%systemroot%\system32\sc createpostgresql-9.3 binPath= "G:\0PostgreSQL\9.3\bin\pg_ctl.exe"

rem 将PostgreSQL相关信息导入注册表

reg import PostgreSQL.reg

reg importPostgreSQL_Global_Development_Group.reg

 

rem 用正确的带参数的执行程序替换占位的服务执行程序,并用完整的服务参数导入注册表中

reg importPostgreSQL_ControlSet001.reg

reg importPostgreSQL_ControlSet002.reg

reg importPostgreSQL_ControlSet003.reg

reg import PostgreSQL_ControlSet004.reg

reg importPostgreSQL_CurrentControlSet.reg

 

rem 启动PostgreSQL企业管理服务

%systemroot%\system32\sc startpostgresql-9.3

 

关闭PostgreSQL的批处理程序PostgreSQL_stop.bat如下:

%systemroot%\system32\scstop postgresql-9.3

Exit

 

5 如何自动修改移动硬盘的盘符

为了解决当移动硬盘通过USB口插入PC机后,其盘符可能不为G这一问题,可以通过编写下列批处理start_g.bat将移动硬盘的新的盘符改成G。此批处理程序存放在目录Ж:\ 0PostgreSQL\dbstart\9.3下(其中Ж为移动硬盘当前的盘符)。它只有下列一条语句:

changediskdriver.exeG

其中changediskdriver.exe 用VC开发,代码如下:

 

#define _WIN32_WINNT 0x0501

 

#include <windows.h>

#include <stdio.h>

#include <ctype.h>

#include <string.h>

//系统函数执行错误时,打印具体错误并退出程序

DWORD printLastError(LPTSTRlpszFunction)

{

   LPVOID lpMsgBuf;

   DWORD dw = GetLastError();

FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM,NULL,dw,

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf,0, NULL );

   printf("%s failed with error %d:%s", lpszFunction, dw, lpMsgBuf);

   LocalFree(lpMsgBuf);

     exit(dw);

     return dw;

}

 

//判断给定盘符是否已经被占用,并顺便求出未被占用的第一个盘符

bool isExist(char cDiskLetter,char & cFirstUnDL)

{

     int DiskCount = 0;

     bool bExist=false;

     cFirstUnDL=0;

//利用GetLogicalDrives()函数可以获取系统中逻辑驱动器的数量,函数返回的是一个位无符号整型数据。

     DWORDDiskInfo = GetLogicalDrives();

     char cCount='A';

     while(DiskInfo)//通过循环操作查看每一位数据是否为,如果为则相应盘符被使用,否则未用。

     {

         if(DiskInfo&1)//通过位运算的逻辑与操作,判断是否为1

         {

              if(cCount==cDiskLetter)bExist=true;

            ++DiskCount;

         }

         else

         {

              if(cCount>'B'&& 0==cFirstUnDL)cFirstUnDL=cCount;

         }

         DiskInfo= DiskInfo >> 1;//通过位运算的右移操作保证每循环一次所检查的位置向右移动一位。

         cCount++;

     }

     return bExist;

}

 

//删除原盘符,绑定新盘符

int changeDL(char * sdriver,char * ddriver)

{

     char vn[MAX_PATH];

     DWORDiret=GetVolumeNameForVolumeMountPoint( TEXT(sdriver), vn, _countof(vn) );

     if(0==iret)

     {

         return printLastError("GetVolumeNameForVolumeMountPoint");

     }

     iret=DeleteVolumeMountPoint(TEXT(sdriver) );//删除当前盘符

     if(0==iret)

     {

         return printLastError("DeleteVolumeMountPoint");

     }

     iret=SetVolumeMountPoint(TEXT(ddriver), vn );//将当前盘符改为目的盘符

     if(0==iret)

     {

         return printLastError("SetVolumeMountPoint");

     }

     return iret;

}

 

 

int main(int argc,char *argv[])

{

     if(argc<2)

     {

         exit(1);

         return 1;

     }

     DWORDiret=0;

     char szCurPath[MAX_PATH];

     char szPath[MAX_PATH];

     char sdriver[]="?:\\";

     char ddriver[]="?:\\";

     ddriver[0]=toupper(argv[1][0]);

     DWORDdw=GetLogicalDrives();

     int size=GetCurrentDirectory(0,NULL);

     if(0==size)

     {

         return printLastError("GetCurrentDirectory");

     }

     if(0 != GetCurrentDirectory(size,szCurPath) )

     {

         sdriver[0]=toupper(szCurPath[0]);

         if(sdriver[0]==ddriver[0])//如果当前盘符与目的盘符一致则什么都不做,幸运成功完成任务

         {

              printf("你很幸运!当前盘符与目的盘符一致。");

              goto LabelBat;

         }

         size=GetSystemDirectory(NULL,0);

         if(0==size)

         {

              return printLastError("GetSystemDirectory");

         }

         if (0 != GetSystemDirectory(szPath,size) )

         {

              char vn[MAX_PATH];

              iret=GetVolumeNameForVolumeMountPoint(TEXT(sdriver), vn, _countof(vn) );

              if(0==iret)

              {

                   return printLastError("GetVolumeNameForVolumeMountPoint");

              }

              if(toupper(szPath[0])==ddriver[0])//不妙,目的盘符已被操作系统占用

              {

                   //既然被操作系统占用,不能删除原盘符,

                   printf("大事不妙!目的盘符已被操作系统占用。");

                   printf("此时要启动Oracle数据库的话,\r\n"

                       "你只好将Oracle必要的目录复制到操作系统所占用的分区上再执行相关的设置批处理程序.\r\n"

                       "等到关机之前,将相关的Oracle复制回移动硬盘上.\r\n"

                       "或者通过将Oracle恢复到当前盘的方式来启动Oracle,不过不建议这样做,"

                       "因为回到过去能用的PC机又要进行一次类似的处理.\r\n"

                       );

                   exit(2);

                   return 2;

              }

              else//运气不错,目的盘符未被操作系统占用

              {

                   char cFirstUnDL;

                   if(isExist(ddriver[0],cFirstUnDL))//目的盘符已被占用

                   {

                       char ddriver_new[]="?:\\";

                       ddriver_new[0]=cFirstUnDL;

                       changeDL(ddriver,ddriver_new);//既然你没有被操作系统占用,我就不客气了

                   }

                   changeDL(sdriver,ddriver);

              }

         }

         else

         {

              return printLastError("GetSystemDirectory");

         }

     }

     else

     {

         return printLastError("GetCurrentDirectory");

     }

     LabelBat:

     char * szpos=szCurPath+strlen(szCurPath);

     while(szpos<=szCurPath)

     {

         szpos--;

         if('\\'==szpos[0])

         {

              szpos[0]='\0';

              break;

         }

     }

     szCurPath[0]=ddriver[0];

    //为了避免由于改变当前盘符所造成的问题,特在C盘生成批处理并执行之

     FILE* fp=fopen("C:\\psql_start.bat","w");

     char szTemp[MAX_PATH];

     strcpy(szTemp,ddriver);

     szTemp[2]='\0';

     fputs(szTemp,fp);

     fputs("\r\n",fp);

     sprintf(szTemp,"cd %s\r\n",szCurPath);

     fputs(szTemp,fp);

     sprintf(szTemp,"start %s\\PostgreSQL_start.bat\r\n",szCurPath);

     printf(szTemp);

     fputs(szTemp,fp);

     fclose(fp);

     system("C:\\psql_start.bat");

     exit(0);

  return 0;

}

6 结语

本文通过摸索,找到了使移动硬盘上安装的PostgreSQL数据库可以在任何安装了Windows操作系统的PC上复活的方法,避免了重装PostgreSQL数据库系统的麻烦。如果当移动硬盘插入PC机后,如果盘符与原来安装时的盘符相同,此时直接运行PostgreSQL_start.bat即可启动移动硬盘上的PostgreSQL数据库,否则运行start_g.bat通过自动修改盘符的方式也可以启动移动硬盘上的PostgreSQL数据库。


参考文献

Oracle数据库和移动硬盘一起移动

0 0
原创粉丝点击