- PR -

WindowsサービスはOnStart内で止められる?

1
投稿者投稿内容
anonymous
会議室デビュー日: 2007/05/23
投稿数: 4
投稿日時: 2007-05-23 15:11
皆様、初めてお目にかかります。

さっそくですが、
VS2005のVB.NETでサービスを作成しています。
インストールの延長でサービスを起動しているのですが、
その際、ある条件を満たしていなければ開始しないという処理を実現したいと思っています。

Protected Overrides Sub OnStart(ByVal args() As String)
On Error GoTo Err_OnStart

中略

Exit_OnStart:
Exit Sub

Err_OnStart:
EventLog.WriteEntry("サービス","強制終了します", EventLogEntryType.Error)
Dim sc As New ServiceController("サービス")
If sc.Status = ServiceControllerStatus.StartPending Or_
sc.Status = ServiceControllerStatus.Paused Then
sc.Stop()
End If
Resume Next
End Sub

としているのですが、エラー時Err_OnStartになぜか2回入ってきてイベントログが2回出力されてしまいます。
sc.WaitForStatus(ServiceControllerStatus.Stopped)なども追加してみましたが、
同じでした。
良い方法があればご教授お願いします。m(__)m
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2007-05-23 16:11
ServiceControllerとかは使わなくても、
普通に継承元のServiceBaseクラスの
Stop()を実行すれば、停止したと思います。
ExitCodeにゼロを入れておけば、正常終了になったかと。


[ メッセージ編集済み 編集者: サトウ 編集日時 2007-05-23 16:12 ]
anonymous
会議室デビュー日: 2007/05/23
投稿数: 4
投稿日時: 2007-05-23 16:39
サトウさま、回答ありがとうございます。

早速やってみました。
が、どうも思った動きと違うようです。
以下ソース
Public Class サービス Inherits System.ServiceProcess.ServiceBase

以下、元スレと同じ

Err_OnStart:
Dim sb As ServiceBase = New サービス
sb.Stop()
Resume Next
End sub
とすると、今度はサービスが一回停止した後に開始してしまいました???
Resume Nextを取っても開始してしまいます。
そのまま終わって欲しいのですが...どこかおかしいでしょうか。
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2007-05-23 17:08
Class サービスはServiceBaseの派生クラスなので、
ServiceBaseクラスのメソッドは継承しています。
ですので、
引用:

anonymousさんの書き込み (2007-05-23 16:39) より:
Dim sb As ServiceBase = New サービス
sb.Stop()


のようにわざわざnewしなくても、
Stop()
あるいは、
Me.Stop()
で、OKです。

anonymous
会議室デビュー日: 2007/05/23
投稿数: 4
投稿日時: 2007-05-23 17:22
>サトウ様

指摘の通り修正したところ、正常に終了することができました。<(__)>
ありがとうございます。
もしご存知であれば教えていただきたいのですが、
強制終了の際、警告ダイアログ「ローカルコンピュータ上のサービスは起動して停止しました・・・」が表示されてしまいます。
なるべくならユーザには見せたくないので、できれば表示させずに済ますことはできないでしょうか?
サトウ
会議室デビュー日: 2006/01/17
投稿数: 17
投稿日時: 2007-05-23 18:23
引用:

anonymousさんの書き込み (2007-05-23 17:22) より:

もしご存知であれば教えていただきたいのですが、
強制終了の際、警告ダイアログ「ローカルコンピュータ上のサービスは起動して停止しました・・・」が表示されてしまいます。
なるべくならユーザには見せたくないので、できれば表示させずに済ますことはできないでしょうか?




おそらく、それはサービスコントロールマネージャの機能なので、無理だと思います。
もし、やるとしたら、一旦正常に開始したことにして、すぐに正常終了させるかですね。

一旦正常に開始したことにするには、OnStart()の途中でStop()せずに、
最後まで実行させます。同時にOnStart()からスレッドタイマーかなんかを仕掛けて、
OnStart()が終了した頃に、別スレッドから、(最初にanonymousさんがやってたように)
ServiceController経由でサービスを停止させます。
ちなみに、このとき、OnStop()が自動コールされます。

こうすると、サービスコントロールマネージャから見ると、
「開始してすぐ停止された」という動作であり、異常終了ではないので、
警告ダイアログは表示されないと思います。
仮に、「回復」の設定で再起動を指定していても、
異常終了ではないので、勝手に再起動されることもありません。


ただ、これだと、当然ユーザから見ても「開始してすぐ停止した」という状態になってしまい、
なぜ停止したのかがユーザには伝わりません。
せっかちなユーザさんだったら、開始中のプログレスバーだけ見て、起動したと思い、
起動したつもりが起動してなかった という事態になるかもしれません。
そう考えると、起動できなかった旨を表示してあげる方が、親切設計かもしれませんよ。
anonymous
会議室デビュー日: 2007/05/23
投稿数: 4
投稿日時: 2007-05-23 20:07
>サトウ様

ありがとうございます。
そうなのですね。
タイマーは確かに使っていますが、それは正常動作でして。
まあ強制的に終了させるのは異常系の話なので、
ダイアログが出たら出たで大丈夫だと思います。
(そのためにイベントログにも出力してますので...)


最後までお付き合いいただきありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)