15

次の投稿を読みました。私のコードはまったく同じように見えますが、機能しません:
InnoSetup実行中のプロセスをチェックしています

http://www.vincenzo.net/isxkb/index.php?title=PSVinceから例をコピーしました

しかし、次のようにコードを変更しても、この例は機能しません。

[Code]
function IsModuleLoaded(modulename: AnsiString):  Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';

コードは常に返されますfalse(プログラムは実行されていても実行されていません)。Windows2008R2およびWindows7でテスト済み。

実際、が実行されているかどうかを確認したいと思いtomcat5.exeます。だから私はで作業することはできないと思いますAppMutex

https://code.google.com/p/psvince/source/detail?r=5も見
ましたが、そのDLLの互換性に関する事実は見つかりません。

完全なコード:

[Files]
Source: psvince.dll; Flags: dontcopy

[Code]
function IsModuleLoaded(modulename: AnsiString ):  Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';

function InitializeSetup(): Boolean;
begin
  if(IsModuleLoaded( 'notepad.exe' )) then
    begin
      MsgBox('Running', mbInformation, MB_OK);
      Result := false;
    end
  else
    begin
      MsgBox('Not running', mbInformation, MB_OK);
      Result := true;
    end
end;
4

5 に答える 5

54

WMIとを使用できますWin32_Process

この関数をInnoSetupスクリプトに追加してみてください。

function IsAppRunning(const FileName : string): Boolean;
var
    FSWbemLocator: Variant;
    FWMIService   : Variant;
    FWbemObjectSet: Variant;
begin
    Result := false;
    FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
    FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
    FWbemObjectSet :=
      FWMIService.ExecQuery(
        Format('SELECT Name FROM Win32_Process Where Name="%s"', [FileName]));
    Result := (FWbemObjectSet.Count > 0);
    FWbemObjectSet := Unassigned;
    FWMIService := Unassigned;
    FSWbemLocator := Unassigned;
end;
于 2012-03-30T21:37:22.003 に答える
8

RRUZの優れた回答にコメントを追加するのに十分な担当者ポイントがないため、ここに追加します。例外をキャッチするようにしてください。そうしないと、サービスにアクセスできないユーザーに対してインストーラーが失敗します。

try
      FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
      FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
      FWbemObjectSet := FWMIService.ExecQuery(Format('SELECT Name FROM Win32_Process Where Name="%s"',[FileName]));
      Result := (FWbemObjectSet.Count > 0);
except
end;
于 2014-08-27T02:30:31.840 に答える
2

これにはさらに簡単な解決策があります。RRUZによって提案されたコードを使用するかどうかは、インストールパスを知っているかどうかに依存します。インストーラーの初期化時に実行すると、これはわかりません。

最善の解決策は、FindWindowByClassNameを使用することです。常に開いているメインフォームがあるというわずかな前提条件がありますが、開いている可能性のあるさまざまなフォームがある場合は、いつでも複数のチェックを実行できます。言うまでもなく、クラス名をできるだけ一意にする必要があります。

関数の例:

function IsAppRunning(): Boolean;
begin                                                                
  Result := (FindWindowByClassName( '{#AppWndClassName}') <> 0) or (FindWindowByClassName( '{#AltAppWndClassName}') <> 0);
end;

#プリコンパイル参照は、インストールスクリプトの前に定義されています...

#define AppWndClassName "TMySplashScreen"
#define AltAppWndClassName "TMyMainForm"

次に、コードセクションで次のように呼び出します。

function InitializeUninstall(): Boolean;
begin
  // check if application is running
  if IsAppRunning() then
  begin
    MsgBox( 'An Instance of MyFantasticApp is already running. - Please close it and run the uninstall again.', mbError, MB_OK );
    Result := false;
  end
  else 
    Result := true;
End;

これよりも複雑なものが必要な場合は、ミューテックスを調べる必要がありますが、上記のコードの利点は、他のコードと同じように、適度に一意のクラス名がある限り、そのシンプルで迅速なことです。

(確かに、マルチユーザーシステムで実行している場合は、別のユーザーのセッションにある場合はウィンドウが見つからない可能性があります。ただし、前述したように、ほとんどの単純な状況では、これで問題ありません。)

于 2013-09-06T07:47:32.650 に答える
1

残念ながら、psvince.dllは私の観察に基づいて64ビットの実行中のプロセスをクエリできません。また、私はその開発者ではないため、Windowsx64で動作するように修正する方法がわかりません。

私の回避策は、自家製のコマンドラインユーティリティであるprocessviewer.exeを使用することです。

http://github.com/lextm/processviewer

これは、 TouchMouseMateのWindows7x64でテストされています

http://www.lextm.com/2012/03/new-inno-setup-installer-script-samples-version-compare-running-processes/

于 2012-03-30T11:48:23.530 に答える
1

簡単な解決策は、exeファイルを削除しようとすることです。とにかくそれを交換またはアンインストールするつもりだと思います。ファイルが存在し、削除に失敗した場合は、おそらく実行中です。

于 2014-05-21T13:29:06.327 に答える