所以我正在尝试创建一个包含以下步骤的安装程序:
在最后几个步骤中遇到了问题。以下是我目前正在使用的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
...
但是,根据此post,该指令仅在用户单击“完成”后生效。
因此设置会附加到路径:
...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的路径。
我认为必须有一种方法可以在单击完成之前通知进程,但是复制上述post中的代码甚至无法在inno中编译
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('Environment')), SMTO_ABORTIFHUNG, 5000, MsgResult);
要求用户第二次开始安装是不可能的,因为安装程序应该首先自动化......任何想法?
答案 0 :(得分:2)
如果要通知所有窗口有关环境更改,请执行以下代码(向导完成时InnoSetup内部使用,ChangesEnvironment
指令设置为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;