C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

単一インスタンスのアプリケーションを作成するを一時的に無効化 /コング (21/02/20(Sat) 13:35) #96867
Re[1]: 単一インスタンスのアプリケーションを作成するを一時.. /魔界の仮面弁士 (21/02/20(Sat) 16:58) #96868
  └ Re[2]: 単一インスタンスのアプリケーションを作成するを一時.. /とっちゃん (21/02/20(Sat) 17:40) #96869
    └ Re[3]: 単一インスタンスのアプリケーションを作成するを一時.. /コング (21/02/21(Sun) 11:23) #96874
      └ Re[4]: 単一インスタンスのアプリケーションを作成するを一時.. /とっちゃん (21/02/21(Sun) 13:39) #96875
        └ Re[5]: 単一インスタンスのアプリケーションを作成するを一時.. /コング (21/02/22(Mon) 12:17) #96883
          └ Re[6]: 単一インスタンスのアプリケーションを作成するを一時.. /とっちゃん (21/02/22(Mon) 15:00) #96885
            └ Re[7]: 単一インスタンスのアプリケーションを作成するを一時.. /コング (21/02/25(Thu) 21:08) #96902 解決済み


親記事 / ▼[ 96868 ]
■96867 / 親階層)  単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ コング (1回)-(2021/02/20(Sat) 13:35:30)

分類:[.NET 全般] 


VB.NETを使っていて
レジストリをいじるプログラムを書いています。

そのために、レジストリをいじる箇所だけ

http://bbs.wankuma.com/index.cgi?mode=al2&namber=77535&KLOG=131

このページを参考にして、自身を管理者権限で有りで実行するようにしてあります。


これは

[単一インスタンスのアプリケーションを作成する]にチェックが入っていない状態だとうまくいくのですが
チェックが入った状態だと、複数のプログラムを同時に起動できないため、
新規に起動することができません。

そのため、一時的に
単一インスタンスのアプリケーションを作成するを無効化
したいのですがどのようなコードでこのようなことが実現できますでしょうか?


[ □ Tree ] 返信 編集キー/

▲[ 96867 ] / ▼[ 96869 ]
■96868 / 1階層)  Re[1]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ 魔界の仮面弁士 (2974回)-(2021/02/20(Sat) 16:58:46)
2021/02/20(Sat) 17:55:07 編集(投稿者)

No96867 (コング さん) に返信
> そのため、一時的に
> 単一インスタンスのアプリケーションを作成するを無効化
> したいのですがどのようなコードでこのようなことが実現できますでしょうか?

一時的に無効化するという考え方にするのではなく、
「管理者モード」と「通常モード」それぞれで単一起動となるよう、
それぞれ別のミューテックスをつかうなどして
自前管理すれば良いのではないでしょうか。

https://dobon.net/vb/dotnet/process/checkprevinstance.html#section2
https://smdn.jp/programming/netfx/tips/singleinst_with_mutex/


あるいは自己起動を行うのではなく、アプリを 2 つ用意しておき、
一方は「レジストリ設定を行うだけの管理者権限専用の副アプリ」として、
それを主アプリから呼び出すような設計にしてみるとか。(未検証)
[ 親 96867 / □ Tree ] 返信 編集キー/

▲[ 96868 ] / ▼[ 96874 ]
■96869 / 2階層)  Re[2]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ とっちゃん (716回)-(2021/02/20(Sat) 17:40:38)
No96867 (コング さん) に返信

> [単一インスタンスのアプリケーションを作成する]にチェックが入っていない状態だとうまくいくのですが
> チェックが入った状態だと、複数のプログラムを同時に起動できないため、
> 新規に起動することができません。
>
> そのため、一時的に
> 単一インスタンスのアプリケーションを作成するを無効化
> したいのですがどのようなコードでこのようなことが実現できますでしょうか?
>
>
VBのアプリケーションフレームワークの機能を利用した、単一インスタンス実行の抑制は
アプリケーションのビルド時に決めるため一時的な抑制などはできません。

2つ目以降の起動は、アプリケーションクラス(通常見えない<というより明示的に作らない)の
StartupNextInstance が呼ばれるので、そこで判断すればできる様です(知らなかった)。

でも、アプリが昇格実行の2回目なのか?なんて判断するのはかなり面倒なので
個人的には、昇格処理専用プログラムを用意して、昇格実行する必要のある処理は
全てその専用プログラムを通じて行う形が良いと思います。

専用プログラムであれば、アプリ自身が昇格実行の設定で作れるため起動時にOS側で問答無用で昇格してくれます。
そのため、昇格しているのか?なんてことは考えずに処理することができます。

呼び出す側も自分が昇格しているかどうかなんてことは考えずに単純に Process.Start を使って
実行するだけで済みます(パラメータでアプリからの要求で実行しているかどうかを判定する必要はある)。

と書いていたら、いつの間にか返答が...w

[ 親 96867 / □ Tree ] 返信 編集キー/

▲[ 96869 ] / ▼[ 96875 ]
■96874 / 3階層)  Re[3]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ コング (2回)-(2021/02/21(Sun) 11:23:26)
ありがとうございます。

これって
[単一インスタンスのアプリケーションを作成する]
を無効化した上で、


Private Sub Form0_Load(sender As Object, e As EventArgs) Handles MyBase.Load

Dim mutexName As String = "MyApplicationName"
'Mutex名の先頭に「Global\」を付けて、Global Mutexにする
mutexName = "Global\" & mutexName
'すべてのユーザーにフルコントロールを許可するMutexSecurityを作成する
Dim rule As New System.Security.AccessControl.MutexAccessRule(
New System.Security.Principal.SecurityIdentifier(
System.Security.Principal.WellKnownSidType.WorldSid, Nothing),
System.Security.AccessControl.MutexRights.FullControl,
System.Security.AccessControl.AccessControlType.Allow)

Dim mutexSecurity As New System.Security.AccessControl.MutexSecurity()
mutexSecurity.AddAccessRule(rule)
'Mutexオブジェクトを作成する
Dim createdNew As Boolean



' 初期所有権は与えず、名前付きミューテックスを作成
Using mutex As New System.Threading.Mutex(False, mutexName, createdNew, mutexSecurity)
' ミューテックスに入る
' (すでに他のプロセスがミューテックスの排他区間に入っている場合でも、待機せず即座に処理を返す)
If mutex.WaitOne(0, False) = False Then
' ミューテックスに入った
' (このプロセス以外にミューテックスの排他区間に入っているプロセスはない)



Environment.Exit(0)



End If
End Using

End Sub



のようにして使うのですよね??

なぜか多重にプログラムを起動できてしまうのですが
何が間違っていますでしょうか??

[ 親 96867 / □ Tree ] 返信 編集キー/

▲[ 96874 ] / ▼[ 96883 ]
■96875 / 4階層)  Re[4]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ とっちゃん (717回)-(2021/02/21(Sun) 13:39:07)
No96874 (コング さん) に返信
> ありがとうございます。
>
> これって
> [単一インスタンスのアプリケーションを作成する]
> を無効化した上で、
>
「これ」がどれを指してるのかいまいちよくわからないですが
「二重起動防止策を自分で組み込む」を指しているのであれば、
もっと早い段階(具体的には、Main関数を使うようにしてそこで)
行う必要があります。

VBでのMain関数の作り方については、ここの掲示板でも過去に何度も出ていますし
あちこちに記事があるので、詳しいことは丸っと省略しますが以下のような感じでメイン関数を書きます

> Sub Main()
> ' ここで、二重起動しているかを確認
> ' 2回目以降の起動であれば、すぐに「return」で終了する(Exitではない)
> ' 問題なければ、アプリケーションの起動シーケンス(Appliation.Run())に行く。
> End Sub


ちなみに、Load イベントは、今ウィンドウを作っていますよ(この場合はForm0かな?)というイベントです。
なので、ここでやっぱやめた!とする場合は、
Exit() ではなく Close()を呼び出し、その直後でReturnします。


おまけ…

> Dim mutexName As String = "MyApplicationName"
> 'Mutex名の先頭に「Global\」を付けて、Global Mutexにする
> mutexName = "Global\" & mutexName

アプリ起動中に同一マシン内でほかのユーザーも同時に利用する場面があるのでしょうか?
その場合は、Globalを付けて、マシン全体で一意な識別子とする必要がありますが
そうではない(ユーザーが異なるなら同時に動いてもよい、すなわちほかのマシンであれば同時に動いてもよいと同じ)なら
わざわざつける必要はありません(後続のいろいろな権限の部分も、特に権限設定は必要ない)。

[ 親 96867 / □ Tree ] 返信 編集キー/

▲[ 96875 ] / ▼[ 96885 ]
■96883 / 5階層)  Re[5]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ コング (4回)-(2021/02/22(Mon) 12:17:53)
ありがとうございます。

うまくいきました。



> ちなみに、Load イベントは、今ウィンドウを作っていますよ(この場合はForm0かな?)というイベントです。
> なので、ここでやっぱやめた!とする場合は、
> Exit() ではなく Close()を呼び出し、その直後でReturnします。

これに関してなのですが、

Close()を呼び出すと
Form_Close()が呼び出されてしまうため、
本来ならフォームが起動した場合に実行するはずのコードが実行されてしまいます。

ブーリアン変数を使って、
Form_Close()内のコードを実行するかどうか分岐すれば問題ないわけなのですが、
Environment.Exit(0)
を使ったデメリットはあるのでしょうか?
こちらを使っていて、特に問題も発生していませんし
コードもシンプルになるので、こちらを使いたいのですが
メモリーが解放されていないなど
何か目に見えない問題が発生しているのでしょうか?



[ 親 96867 / □ Tree ] 返信 編集キー/

▲[ 96883 ] / ▼[ 96902 ]
■96885 / 6階層)  Re[6]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ とっちゃん (718回)-(2021/02/22(Mon) 15:00:19)
No96883 (コング さん) に返信
>>ちなみに、Load イベントは、今ウィンドウを作っていますよ(この場合はForm0かな?)というイベントです。
>>なので、ここでやっぱやめた!とする場合は、
>>Exit() ではなく Close()を呼び出し、その直後でReturnします。
>
> これに関してなのですが、
>
> Close()を呼び出すと
> Form_Close()が呼び出されてしまうため、
> 本来ならフォームが起動した場合に実行するはずのコードが実行されてしまいます。
>
本質的な面で言えば、Loadされるよりも前に二重起動チェックするべきなので、Loadでやるのはどうなの?
という別の面はありますが…

基本的にLoad中に閉じるのは、何らかの理由で画面表示されたらこまるということなので
Close処理もそれに応じて作る必要はあると思います。

> Environment.Exit(0)
> を使ったデメリットはあるのでしょうか?
> こちらを使っていて、特に問題も発生していませんし

Exit のリファレンスに書いてありますが、Exit 呼び出し以後のcatch(finaly)が呼ばれません(usingも同様)。
Exit は、プロセスの強制終了コマンドです。
そのため、ライブラリの中も含め、何かの途中の処理があれば、それも全部放棄してプロセスを終了します。

見た目的には問題ないように見えても、実はどこかにほころびがあるかもしれません。
もし、そういったほころびがあれば、それが原因でどこかのタイミングでOSが動かなくなる
なんてことがあってもおかしくありません(発生率はほぼ0ですが絶対にないとは言えない)。

[ 親 96867 / □ Tree ] 返信 編集キー/

▲[ 96885 ] / 返信無し
■96902 / 7階層)  Re[7]: 単一インスタンスのアプリケーションを作成するを一時的に無効化
□投稿者/ コング (5回)-(2021/02/25(Thu) 21:08:10)
見た目上は問題無くても
問題がある場合もあるというはなかなか困りますね
どうもありがとうございました。

解決済み
[ 親 96867 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -