用VS2008安装项目如何生成文件和写入文件?

时间:2021-07-25 08:54:57
第一次做安装程序,有些问题不懂,想请教下做过这方面的朋友,我要做一个安装程序,这个安装程序可以改名,比如setup_1234.exe,setup_4321.exe,当程序安装完成时在目录下生成一个setup.bat的文件,在文件里写入setup_1234或setup_4321,用VS2008安装项目应该怎么来做?当然也可以写入注册表,我的目标是当程序运行时要获取安装程序的名字。或者有其它的制做安装程序的方法能实现这个功能的。

20 个解决方案

#1


安装程序运行的时候也不是以名字来定进程名的。不然也可以在安装的时候启动另一个程序来获取调用程序的名字。

#2


installsheild行不行

#3


安装程序自己安装的时候GetModuleFileName获取自己的名字,然后写入注册表记录一下,以后其他程序就可以读取注册表来获取

#4


引用 3 楼 oyljerry 的回复:
安装程序自己安装的时候GetModuleFileName获取自己的名字,然后写入注册表记录一下,以后其他程序就可以读取注册表来获取

问题是安装程序如何调用GetModuleFileName,以及写入注册表,好像安装项目不能调用windows API函数。

#5


引用 2 楼 buyong 的回复:
installsheild行不行

这应该是Installsheild的升级版。

#6


可以考虑在自定义操作里调用一个小程序来实现你要的功能

#7


引用 6 楼 xianglitian 的回复:
可以考虑在自定义操作里调用一个小程序来实现你要的功能

这个小程序应该怎么做?安装程序的进程名叫msiexec.exe,而不是以名字来命名的。应该怎样获取运行的名字?

#8


引用 7 楼 vanssanyc 的回复:
引用 6 楼 xianglitian 的回复:
可以考虑在自定义操作里调用一个小程序来实现你要的功能

这个小程序应该怎么做?安装程序的进程名叫msiexec.exe,而不是以名字来命名的。应该怎样获取运行的名字?

这个安装程序会是什么名字一点规律都没有么
那你这个需求无法实现啊

#9


可以考虑,直接在安装包里包含一个setup.bat文件就可以了。

安装完后,在安装目录自然就有了,没必要生成吧。

#10


引用 8 楼 xianglitian 的回复:
这个安装程序会是什么名字一点规律都没有么
那你这个需求无法实现啊

就是因为安装程序可以随便改,所以要取得安装程序的名字,我刚试了下,我把安装程序改成setup_1235.msi或其它名字,在程序运行的时获取的进程名都是misexec.exe,而无法获取setup_1234这样的名字,比较困惑,其它exe程序改名字的话进程名也会随之更改。

#11


是不是setup_1235.msi调用了misexec.exe

#12


引用 9 楼 ladingwen3 的回复:
可以考虑,直接在安装包里包含一个setup.bat文件就可以了。

安装完后,在安装目录自然就有了,没必要生成吧。

因为想要获取setup_1234.msi这个名字,所以要在安装的时候获取,有其它方法也行,只要能获取安装程序的名字。

#13


引用 11 楼 xianglitian 的回复:
是不是setup_1235.msi调用了misexec.exe

这应该是msi安装程序特有的,每次打开系统都会生成一个msiexec.exe的进程,并且不止一个,还有一个是system用户的。

#14


用GetModuleFileName获取msiexec.exe的路径得到的是什么呢

#15


不懂绑顶

#16


引用 14 楼 xianglitian 的回复:
用GetModuleFileName获取msiexec.exe的路径得到的是什么呢


c:\windows\system32\msiexec.exe

#17


引用 16 楼 vanssanyc 的回复:
引用 14 楼 xianglitian 的回复:
用GetModuleFileName获取msiexec.exe的路径得到的是什么呢


c:\windows\system32\msiexec.exe
那就获取它的启动命令行看看

#18


引用 17 楼 xianglitian 的回复:
c:\windows\system32\msiexec.exe
那就获取它的启动命令行看看

怎么获取的?

#19


以下代码引自windows核心编程
也许你不能直接调用
不过基本方法应该就是这样了
当然这里只是获取其他进程的命令行参数
不一定能解决你的问题


BOOL GetProcessCmdLine(HANDLE hProcess, LPTSTR szCmdLine, DWORD Size) {

   // Sanity checks
   if ((hProcess == NULL) || (szCmdLine == NULL) || (Size == 0))
      return(FALSE);

   // 0. Get the Process Environment Block address
   int   iReturn = 1;
   DWORD dwSize;
   SIZE_T size;

   PROCESS_BASIC_INFORMATION  pbi;
   // The PEB was supposed to always be at address 0x7ffdf000 in XP...
   // ... but, here is the "right" way to get it now in Vista.
   iReturn =
      _NtQueryInformationProcess(
         hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &dwSize);

   // NtQueryInformationProcess returns a negative value if it fails
   if (iReturn >= 0) {
      // 1. Find the Process Environment Block
      __PEB PEB;
  size = dwSize;
      if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &PEB, 
         sizeof(PEB), &size)) {
         // Call GetLastError() if you need to know why
         return(FALSE);
      }

      // 2. From this PEB, get the address of the block containing 
      // a pointer to the CmdLine
      __INFOBLOCK Block;
      if (!ReadProcessMemory(hProcess, (LPVOID)PEB.InfoBlockAddress, 
         &Block, sizeof(Block), &size)) {
         // Call GetLastError() if you need to know why
         return(FALSE);
      }

      // 3. Get the CmdLine
      wchar_t wszCmdLine[MAX_PATH+1];
      if (!ReadProcessMemory(hProcess, (LPVOID)Block.wszCmdLineAddress, 
         wszCmdLine, MAX_PATH*sizeof(wchar_t), &size)) {
         // Call GetLastError() if you need to know why
         return(FALSE);
      }

      // 4. Skip the application pathname
      //    it can be empty, "c:\...\app.exe" or c:\...\app.exe
      wchar_t* pPos = wszCmdLine;
      if (*pPos != L'\0') {
         if (*pPos == L'"') {
         // Find the next " character
            pPos = wcschr(&pPos[1], L'"');
         } else {
         // Find the next SPACE character
            pPos = wcschr(&pPos[1], L' ');
         }

         // Skip it
         if (pPos != NULL)
            pPos++;
      }

      // Copy it back
      if (pPos != NULL) {
         if (*pPos != L'\0') {
#ifdef UNICODE
            // Both strings are in UNICODE.
            _tcscpy_s(szCmdLine, Size, pPos);   
#else
            // from UNICODE to ANSI
            MultiByteToWideChar(CP_ACP, 0, szCmdLine, Size, 
               pPos, wcslen(pPos)); 
#endif
         }
         else
            szCmdLine[0] = TEXT('\0');
      }
      else
         szCmdLine[0] = TEXT('\0');
   }
   else {
      return(FALSE);
   }

   return(TRUE);
}


BOOL GetProcessCmdLine(DWORD PID, LPTSTR szCmdLine, DWORD Size) {

   // Sanity checks
   if ((PID <= 0) || (szCmdLine == NULL))
      return(FALSE);

   // Check if we can get information for this process
   HANDLE hProcess = 
      OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
   if (hProcess == NULL)
      return(FALSE);

   BOOL bReturn = GetProcessCmdLine(hProcess, szCmdLine, Size);

   // Don't forget to release the process handle
   CloseHandle(hProcess);

   return(bReturn);
}

#20


引用 19 楼 xianglitian 的回复:
以下代码引自windows核心编程
也许你不能直接调用
不过基本方法应该就是这样了
当然这里只是获取其他进程的命令行参数
不一定能解决你的问题

C/C++ code



BOOL GetProcessCmdLine(HANDLE hProcess, LPTSTR szCmdLine, DWORD Size) {

   // Sanity checks
   if (……

还是不行,不过还是要谢谢你~

#1


安装程序运行的时候也不是以名字来定进程名的。不然也可以在安装的时候启动另一个程序来获取调用程序的名字。

#2


installsheild行不行

#3


安装程序自己安装的时候GetModuleFileName获取自己的名字,然后写入注册表记录一下,以后其他程序就可以读取注册表来获取

#4


引用 3 楼 oyljerry 的回复:
安装程序自己安装的时候GetModuleFileName获取自己的名字,然后写入注册表记录一下,以后其他程序就可以读取注册表来获取

问题是安装程序如何调用GetModuleFileName,以及写入注册表,好像安装项目不能调用windows API函数。

#5


引用 2 楼 buyong 的回复:
installsheild行不行

这应该是Installsheild的升级版。

#6


可以考虑在自定义操作里调用一个小程序来实现你要的功能

#7


引用 6 楼 xianglitian 的回复:
可以考虑在自定义操作里调用一个小程序来实现你要的功能

这个小程序应该怎么做?安装程序的进程名叫msiexec.exe,而不是以名字来命名的。应该怎样获取运行的名字?

#8


引用 7 楼 vanssanyc 的回复:
引用 6 楼 xianglitian 的回复:
可以考虑在自定义操作里调用一个小程序来实现你要的功能

这个小程序应该怎么做?安装程序的进程名叫msiexec.exe,而不是以名字来命名的。应该怎样获取运行的名字?

这个安装程序会是什么名字一点规律都没有么
那你这个需求无法实现啊

#9


可以考虑,直接在安装包里包含一个setup.bat文件就可以了。

安装完后,在安装目录自然就有了,没必要生成吧。

#10


引用 8 楼 xianglitian 的回复:
这个安装程序会是什么名字一点规律都没有么
那你这个需求无法实现啊

就是因为安装程序可以随便改,所以要取得安装程序的名字,我刚试了下,我把安装程序改成setup_1235.msi或其它名字,在程序运行的时获取的进程名都是misexec.exe,而无法获取setup_1234这样的名字,比较困惑,其它exe程序改名字的话进程名也会随之更改。

#11


是不是setup_1235.msi调用了misexec.exe

#12


引用 9 楼 ladingwen3 的回复:
可以考虑,直接在安装包里包含一个setup.bat文件就可以了。

安装完后,在安装目录自然就有了,没必要生成吧。

因为想要获取setup_1234.msi这个名字,所以要在安装的时候获取,有其它方法也行,只要能获取安装程序的名字。

#13


引用 11 楼 xianglitian 的回复:
是不是setup_1235.msi调用了misexec.exe

这应该是msi安装程序特有的,每次打开系统都会生成一个msiexec.exe的进程,并且不止一个,还有一个是system用户的。

#14


用GetModuleFileName获取msiexec.exe的路径得到的是什么呢

#15


不懂绑顶

#16


引用 14 楼 xianglitian 的回复:
用GetModuleFileName获取msiexec.exe的路径得到的是什么呢


c:\windows\system32\msiexec.exe

#17


引用 16 楼 vanssanyc 的回复:
引用 14 楼 xianglitian 的回复:
用GetModuleFileName获取msiexec.exe的路径得到的是什么呢


c:\windows\system32\msiexec.exe
那就获取它的启动命令行看看

#18


引用 17 楼 xianglitian 的回复:
c:\windows\system32\msiexec.exe
那就获取它的启动命令行看看

怎么获取的?

#19


以下代码引自windows核心编程
也许你不能直接调用
不过基本方法应该就是这样了
当然这里只是获取其他进程的命令行参数
不一定能解决你的问题


BOOL GetProcessCmdLine(HANDLE hProcess, LPTSTR szCmdLine, DWORD Size) {

   // Sanity checks
   if ((hProcess == NULL) || (szCmdLine == NULL) || (Size == 0))
      return(FALSE);

   // 0. Get the Process Environment Block address
   int   iReturn = 1;
   DWORD dwSize;
   SIZE_T size;

   PROCESS_BASIC_INFORMATION  pbi;
   // The PEB was supposed to always be at address 0x7ffdf000 in XP...
   // ... but, here is the "right" way to get it now in Vista.
   iReturn =
      _NtQueryInformationProcess(
         hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &dwSize);

   // NtQueryInformationProcess returns a negative value if it fails
   if (iReturn >= 0) {
      // 1. Find the Process Environment Block
      __PEB PEB;
  size = dwSize;
      if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &PEB, 
         sizeof(PEB), &size)) {
         // Call GetLastError() if you need to know why
         return(FALSE);
      }

      // 2. From this PEB, get the address of the block containing 
      // a pointer to the CmdLine
      __INFOBLOCK Block;
      if (!ReadProcessMemory(hProcess, (LPVOID)PEB.InfoBlockAddress, 
         &Block, sizeof(Block), &size)) {
         // Call GetLastError() if you need to know why
         return(FALSE);
      }

      // 3. Get the CmdLine
      wchar_t wszCmdLine[MAX_PATH+1];
      if (!ReadProcessMemory(hProcess, (LPVOID)Block.wszCmdLineAddress, 
         wszCmdLine, MAX_PATH*sizeof(wchar_t), &size)) {
         // Call GetLastError() if you need to know why
         return(FALSE);
      }

      // 4. Skip the application pathname
      //    it can be empty, "c:\...\app.exe" or c:\...\app.exe
      wchar_t* pPos = wszCmdLine;
      if (*pPos != L'\0') {
         if (*pPos == L'"') {
         // Find the next " character
            pPos = wcschr(&pPos[1], L'"');
         } else {
         // Find the next SPACE character
            pPos = wcschr(&pPos[1], L' ');
         }

         // Skip it
         if (pPos != NULL)
            pPos++;
      }

      // Copy it back
      if (pPos != NULL) {
         if (*pPos != L'\0') {
#ifdef UNICODE
            // Both strings are in UNICODE.
            _tcscpy_s(szCmdLine, Size, pPos);   
#else
            // from UNICODE to ANSI
            MultiByteToWideChar(CP_ACP, 0, szCmdLine, Size, 
               pPos, wcslen(pPos)); 
#endif
         }
         else
            szCmdLine[0] = TEXT('\0');
      }
      else
         szCmdLine[0] = TEXT('\0');
   }
   else {
      return(FALSE);
   }

   return(TRUE);
}


BOOL GetProcessCmdLine(DWORD PID, LPTSTR szCmdLine, DWORD Size) {

   // Sanity checks
   if ((PID <= 0) || (szCmdLine == NULL))
      return(FALSE);

   // Check if we can get information for this process
   HANDLE hProcess = 
      OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
   if (hProcess == NULL)
      return(FALSE);

   BOOL bReturn = GetProcessCmdLine(hProcess, szCmdLine, Size);

   // Don't forget to release the process handle
   CloseHandle(hProcess);

   return(bReturn);
}

#20


引用 19 楼 xianglitian 的回复:
以下代码引自windows核心编程
也许你不能直接调用
不过基本方法应该就是这样了
当然这里只是获取其他进程的命令行参数
不一定能解决你的问题

C/C++ code



BOOL GetProcessCmdLine(HANDLE hProcess, LPTSTR szCmdLine, DWORD Size) {

   // Sanity checks
   if (……

还是不行,不过还是要谢谢你~

#21