10

.net 4 WPFアプリケーションを制限して、マシンごとに1回だけ実行できるようにする必要があります。セッションごとではなく、マシンごとに言ったことに注意してください。
これまで、単純なミューテックスを使用してシングルインスタンスアプリケーションを実装していましたが、残念ながら、そのようなミューテックスはセッションごとにあります。

マシン全体のミューテックスを作成する方法はありますか、それともマシンアプリケーションごとに単一のインスタンスを実装する他のソリューションはありますか?

4

7 に答える 7

14

これは、アプリケーションの存続期間中保持する必要があるグローバル Mutex オブジェクトを使用して行います。

MutexSecurity oMutexSecurity;

//Set the security object
oMutexSecurity = new MutexSecurity();
oMutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), MutexRights.FullControl, AccessControlType.Allow));

//Create the global mutex and set its security
moGlobalMutex = new Mutex(True, "Global\\{5076d41c-a40a-4f4d-9eed-bf274a5bedcb}", bFirstInstance);
moGlobalMutex.SetAccessControl(oMutexSecurity);

WherebFirstInstanceは、これがグローバルに実行されているアプリケーションの最初のインスタンスである場合に返されます。ミューテックスのグローバル部分を省略したり、ローカルに置き換えたりすると、ミューテックスはセッションごとにのみになります (これはおそらく、現在のコードがどのように機能しているかです)。

このテクニックは、ジョン スキートから最初に得たと思います。

Mutex オブジェクトに関する MSDN のトピックでは、Mutexオブジェクトの 2 つのスコープについて説明し、ターミナル サービスを使用するときにこれが重要である理由を強調しています (最後から 2 番目のメモを参照)。

于 2010-11-19T08:47:08.300 に答える
3

あなたがする必要があるのは、システムのセマフォを使用してアプリケーションのインスタンスを追跡することだと思います。

名前を受け入れるコンストラクターを使用して Semaphore オブジェクトを作成すると、その名前のオペレーティング システム セマフォに関連付けられます。

名前付きシステム セマフォは、オペレーティング システム全体で表示され、プロセスのアクティビティを同期するために使用できます。

編集:このアプローチがマシン上の複数のウィンドウセッションで機能するかどうかはわかりません。私はそれがOSレベルの構造であるべきだと思いますが、私はそのようにテストしていないので断言できません。

編集 2: 私はこれを知りませんでしたが、Stevo2000 の回答を読んだ後、私も調べてみました。オブジェクトをグローバル名前空間に適用できるようにするための "Global\" プレフィックスは、セマフォにも適用され、セマフォにも適用されると思います。このように作成された場合、動作するはずです。

于 2010-11-19T08:00:02.300 に答える
2

%PROGRAMDATA% のどこかで排他的な権限を持つファイルを開くことができます。開始される 2 番目のインスタンスは同じファイルを開こうとし、既に開いている場合は失敗します。

于 2010-11-19T07:59:05.593 に答える
1

レジストリを使用するのはどうですか?

  1. を作成できますregistry entry under HKEY_LOCAL_MACHINE
  2. flagアプリケーションが開始されているかどうかを値にします。
  3. Encrypt the keysymmetric key encryption他の誰も値を改ざんできないように、標準的な方法を使用します。
  4. On application start-up check for the keyそれに応じて中断\続行します。
  5. この暗号化/復号化の部分を行うを忘れないでくださいobfuscate your assembly。これにより、誰もリフレクターのコードを見てレジストリのキーをハッキングできなくなります。
于 2010-11-19T08:27:47.260 に答える
0

完全を期すために、今見つけた次の情報を追加したいと思います:
このWeb サイトには、Win32 メッセージを他のプロセスに送信する興味深いアプローチがあります。これにより、ユーザーがアセンブリの名前を変更してテストをバイパスする問題や、同じ名前の他のアセンブリの問題が修正されます。
彼らはメッセージを使用して他のプロセスのメインウィンドウをアクティブにしていますが、メッセージは、他のプロセスがそれに応答しているかどうかを確認して、それが私たちのプロセスであるかどうかを知るためにのみ使用されるダミーメッセージのようです。

まだテストしていないことに注意してください。

于 2010-11-19T08:39:59.313 に答える
0

I did something similar once.

When staring up the application list, I checked all running processes for a process with identical name, and if it existed I would not allow to start the program.

This is not bulletproof of course, since if another application have the exact same process name, your application will never start, but if you use a non-generic name it will probably be more than good enough.

于 2010-11-19T07:53:43.607 に答える
-1

WPF 3.5 で単一のインスタンス アプリを実行する方法の完全な例については、以下を参照してください。

public class SingleInstanceApplicationWrapper :
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
public SingleInstanceApplicationWrapper()
{
// Enable single-instance mode.
this.IsSingleInstance = true;
}
// Create the WPF application class.
private WpfApp app;
protected override bool OnStartup(
Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
app = new WpfApp();
app.Run();
return false;
}
// Direct multiple instances.
protected override void OnStartupNextInstance(
Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
{
if (e.CommandLine.Count > 0)
{
app.ShowDocument(e.CommandLine[0]);
}
}
}

第二部:

public class WpfApp : System.Windows.Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
WpfApp.current = this;
// Load the main window.
DocumentList list = new DocumentList();
this.MainWindow = list;
list.Show();
// Load the document that was specified as an argument.
if (e.Args.Length > 0) ShowDocument(e.Args[0]);
}
public void ShowDocument(string filename)
{
try
{
Document doc = new Document();
doc.LoadFile(filename);
doc.Owner = this.MainWindow;
doc.Show();
// If the application is already loaded, it may not be visible.
// This attempts to give focus to the new window.
doc.Activate();
}
catch
{
MessageBox.Show("Could not load document.");
}
}
}

三分の一:

 public class Startup
    {
    [STAThread]
    public static void Main(string[] args)
    {
    SingleInstanceApplicationWrapper wrapper =
    new SingleInstanceApplicationWrapper();
    wrapper.Run(args);
    }
    }

soem 参照を追加し、いくつかの using ステートメントを追加する必要があるかもしれませんが、うまくいくはずです。

ここから書籍のソース コードをダウンロードして、VS サンプルの完全なソリューションをダウンロードすることもできます。

「Pro WPF in C#3 2008 、Apress 、Matthew MacDonald」から取得した本は金です。やった。

于 2010-11-19T08:27:35.650 に答える