1

所以我正在尝试创建一个具有以下步骤的安装程序:

  1. 检查是否安装了 Python
  2. 复制我的应用文件
  3. 检查 Python 安装目录是否在 Windows 环境路径中
  4. 检查 Python 脚本文件夹是否在 Windows 环境路径中
  5. 如果脚本文件夹不在 env 路径中,请添加它
  6. 安装easy_install
  7. 运行一个使用 easy_install 安装多个库的 python 脚本

在最后几个步骤中遇到了问题。这是我当前使用的 Inno 设置的相关代码:

begin
  case CurStep of
     ssInstall:       // File transfer is about to begin.
     begin
        // Note: Use abort(); to terminate the install during this step.
     end;

ssPostInstall:   // File transfer has finished.
  begin
     // Make sure Python is in the path.
     sPythonInstallDir := _PythonGetInstallDir();
     _PathAddToSystem( sPythonInstallDir )
     _PathAddToSystem( sPythonInstallDir + 'Scripts;' )

     // Run the bundled Python script.
     ExtractTemporaryFile( 'build_setup_script.py' );
     ExtractTemporaryFile( 'ez_setup.py'           );
     _LaunchApp( AddQuotes( sPythonInstallDir + 'python.exe' ), AddQuotes( ExpandConstant( '{tmp}\build_setup_script.py' ) ), ExpandConstant( '{tmp}' ), SW_SHOW, ewWaitUntilTerminated, 300, nTime, nResultCode );
  end;

ssDone :         // After the Finish dialog.
  begin
  end;
end;

这是python脚本:

def main(argv):
   ## Easy Install
   print("Installing easy_install")
   call(["Python", "ez_setup.py"])
...
   ## Installs server.py dependencies
   print("\nInstalling SQLAlchemy")
   call(["easy_install", "SQLAlchemy==0.7.8"])
...

在 inno 设置中,我还有以下指令

[Setup]
...
ChangesEnvironment=true
...   

但是,根据这篇文章,该指令仅在用户单击完成后才生效。

所以设置附加到路径:

...C:\Program Files (x86)\Git\cmd;;C:\Python27\;C:\Python27\Scripts;

但是,然后脚本运行(这有效,因为 inno 似乎知道路径已更改并且可以执行 Python 文件)然后脚本将安装 easy_install,它出于某种原因可以工作,但是当它尝试使用 easy_install 时(这就是为什么C:Python\Scripts; 在路径中)它抛出一个文件未找到异常。

但是,当我第二次运行安装程序时,不做任何更改,easy_install 步骤就会起作用,因为现在当 Python 运行时,它可以检测到 easy_install 的路径。

我认为必须有一种方法可以在单击完成之前通知进程,但是复制上述帖子中的代码甚至无法在 inno 中编译

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('Environment')), SMTO_ABORTIFHUNG, 5000, MsgResult);

要求用户第二次开始安装是不可能的,因为安装程序首先应该是自动化的......有什么想法吗?

4

1 回答 1

2

如果您想通知所有窗口有关环境更改,如下代码(在向导完成并且ChangesEnvironment指令设置为时由 InnoSetup 内部使用yes):

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
  LPARAM(PChar('Environment')), SMTO_ABORTIFHUNG, 5000, MsgResult);

您可以使用以下导入(使用最新的 ANSI 和 Unicode 版本的 InnoSetup 进行测试):

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
const
  SMTO_ABORTIFHUNG = 2;
  WM_WININICHANGE = $001A;
  WM_SETTINGCHANGE = WM_WININICHANGE;
type
  LONG_PTR = LongInt;
  LRESULT = LONG_PTR;  
  WPARAM = UINT_PTR;
  LPARAM = LONG_PTR;

function SendTextMessageTimeout(hWnd: HWND; Msg: UINT;
  wParam: WPARAM; lParam: string; fuFlags: UINT; 
  uTimeout: UINT; var lpdwResult: DWORD_PTR): LRESULT;
  external 'SendMessageTimeout{#AW}@user32.dll stdcall';

并在脚本中需要时像此伪代码中所示调用它:

var
  MsgResult: DWORD_PTR;
begin
  if SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
    'Environment', SMTO_ABORTIFHUNG, 5000, MsgResult) <> 0
  then
    MsgBox('Success!', mbInformation, MB_OK)
  else
    MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
end;
于 2013-03-20T21:59:39.777 回答