1

そこで、次の手順を持つインストーラーを作成しようとしています。

  1. Python がインストールされているかどうかを確認する
  2. アプリ ファイルをコピーする
  3. Python インストール ディレクトリが Windows 環境パスにあるかどうかを確認します
  4. Python スクリプト フォルダーが Windows 環境パスにあるかどうかを確認します。
  5. scripts フォルダーが 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; がパスにある場合)、ファイルが見つからないという例外がスローされます。

ただし、何も変更せずにインストーラーを 2 回目に実行すると、Python の実行時に easy_install へのパスを検出できるようになったため、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 に答える