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

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

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

Re[4]: PCロック中にシャットダウンができない


(過去ログ 86 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■51324 / inTopicNo.1)  PCロック中にシャットダウンができない
  
□投稿者/ はっちゃん (1回)-(2010/07/02(Fri) 00:32:27)

分類:[C#] 

Windows7 Ultimate、VisualStudio2008ProfessionalEdition(C#)という環境で、タイマーを使用して時間がきたらシャットダウンするプログラムをWindowsアプリで作っています。

フォーム上には、現在の時刻を表示するTextBoxとセット時間を表示するTextBox、セット時間を入力するためのInputBoxを表示するためのタイマーセットボタンと時間を待たずにシャットダウンするシャットダウンボタンで構成されています。

Windowsアプリではコンピュータがロックしているときは動作しないので、独自にWindowsサービス(ShutdownTimerServise)を作成しロックされていてもシャットダウンができるようにと考えました。

動作は、
@セット時間を入力
Aセット時間を表示するTextBoxのTextChangeでエラーチェック
B正しい書式だったらWindowsサービスを開始(この時、セット時間をサービスへ渡す)
CWindowsサービス内で現在時刻とセット時間を比較し、等しくなったらOnShutdown()を呼び出す
DOnShutdown()で詳細なシャットダウン情報を与えて、シャットダウンさせる。同時にOnStop()を呼び出す

以上の手順でシャットダウンさせようと思っています。

実際動作させてみると、InputBoxでセット時間を入力し【OK】をクリックすると下記のようなエラーで止まってしまいます。

Windowsサービスを作成するのは今回が初めてでどこが間違っているのかわかりません。
どなたか教えてください。
よろしくお願いします。


【エラーメッセージ】
アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました。
[続行]をクリックすると、アプリケーションはこのエラーを無視し、続行しようとします。
[終了]をクリックすると、アプリケーションは直ちに終了します。
'.'コンピュータで ShutdownTimerServise サービスを開けません。


【ソースコード】
@ShutdownTimer.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic;
using System.ServiceProcess;

namespace ShutdownTimer
{
    public partial class frmShutdownTimer : Form
    {
        private ServiceController sc = new ServiceController("ShutdownTimerService");

        public frmShutdownTimer()
        {
            InitializeComponent();
        }

        private void btnShutdown_Click(object sender, EventArgs e)
        {
            Shutdown();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;
            txtThisTime.Text = dt.ToString("HH:mm:ss");
            
            if (txtThisTime.Text == txtTimer.Text)
            {
                MessageBox.Show("シャットダウン開始");
            }
        }

        private void frmAutoShutdown_Load(object sender, EventArgs e)
        {

        }

        private void btnSetTimer_Click(object sender, EventArgs e)
        {
            string strInput = "";
            string[] strs=new string[1];
            
            strInput = Interaction.InputBox("セット時間を入力してください。\n\n書式:【hhmmss】", "タイマー時間セット", "", -1, -1);

            if (strInput != "")
            {
                if (strInput.Length != 6)
                {
                    MessageBox.Show("書式:【hhmmss】で入力して下さい。", "書式違反");
                    txtTimer.Text = "";
                }
                else
                {
                    txtTimer.Text = strInput.Substring(0, 2) + ":" + strInput.Substring(2, 2) + ":" + strInput.Substring(4, 2);
                    strs[0] = txtTimer.Text;

                    if (sc.Status == ServiceControllerStatus.Stopped)
                    {
                        sc.Start(strs);
                    }
                }
            }

        }

        private void Shutdown()
        {
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
            psi.FileName = "shutdown.exe";

            //コマンドラインを指定
            psi.Arguments = "/r /t 20";

            //ウィンドウを表示しないようにする
            psi.CreateNoWindow = true;

            //起動
            System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
        }
    }
}


AShutdownTimerService.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;

namespace ShutdownTimerService
{
    public partial class ShutdownTimerService : ServiceBase
    {
        private string[] _strs = new string[1];
        
        public ShutdownTimerService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            _strs[0] = args[0];
            EventLog.WriteEntry("ShutdownTimerServiceを開始しました。", "Infomation");
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        }

        protected override void OnStop()
        {
            EventLog.WriteEntry("ShutdownTimerServiceを終了しました。", "Infomation");
        }

        protected override void OnShutdown()
        {
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
            psi.FileName = "shutdown.exe";

            //コマンドラインを指定
            psi.Arguments = "/r /t 20";

            //ウィンドウを表示しないようにする(こうしても表示される)
            psi.CreateNoWindow = true;

            //起動
            System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);

            base.OnStop();
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            DateTime dtTimer = Convert.ToDateTime(_strs[0]);
            string strTimer = dtTimer.ToLongDateString();

            DateTime dtThisTime = DateTime.Now;
            string strThisTime = dtThisTime.ToLongDateString();

            if (strTimer == strThisTime)
            {
                base.OnShutdown();
            }
        }
    }
}

BProjectInstaller.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Windows.Forms;

namespace ShutdownTimerService
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }

        private void serviceInstaller_AfterInstall(object sender, InstallEventArgs e)
        {
            MessageBox.Show("サービスが正常にインストールされました。");
        }
    }
}

CserviceInstallerのプロパティ

Discription:設定時間によってシャットダウンを実行します。
DisplayName:ShutdownTimerService
Parent:ProjectInstaller
ServiceName:ShutdownTimerService
StartType:Automatic
(Name):serviceInstaller
その他の項目はデフォルト

DserviceProcessInstallerのプロパティ

Account:LocalService
Parent:ProjectInstaller
(Name):serviceProcessInstaller
その他の項目はデフォルト

EProjectInstallerのプロパティ
(Name):ProjectInstaller
その他の項目はデフォルト

FShutdownTimerServiceのプロパティ

CanPauseAndContinue:True
CanShutdown:True
ServiceName:ShutdownTimerService
(Name):ShutdownTimerService
その他の項目はデフォルト

Gtimerのプロパティ

(Name):timer
Interval:1000
その他の項目はデフォルト

HeventLogのプロパティ

(Name):eventLog
その他の項目はデフォルト

引用返信 編集キー/
■51325 / inTopicNo.2)  Re[1]: PCロック中にシャットダウンができない
□投稿者/ 渋木宏明 (10回)-(2010/07/02(Fri) 04:15:53)
渋木宏明 さんの Web サイト
> Windowsアプリではコンピュータがロックしているときは動作しないので、

そんなはずはないです。ロック画面が表示されている状態でも、アプリケーションは実行されています。
そう判断した根拠はなんでしょう?

もし「ロック」というのがいわゆる「スリープ」や「休止状態」のことを指しているのであれば、確かにアプリケーションの実行は凍結されています。
ですが、その場合は Windows サービスの実行も凍結されています。目的の処理を Windows サービスで処理を実行しても、「スリープ」や「休止状態」による実行の凍結を回避することにはなりません。

> (4) Windowsサービス内で現在時刻とセット時間を比較し、等しくなったらOnShutdown()を呼び出す

NG です。

OnShutdown() は、Windows サービスをシャットダウンさせるためのメソッドではありません。
同様に、OnStop() メソッドは、Windows サービスを停止させるためのメソッドではありません。

これらのメソッドは、Windows サービスがサービスコントロールマネージャから

・システムがシャットダウンされようとしていることの通知
・Windows サービスが停止されようとしていることの通知

を受け取るために用意されたメソッドなので、ユーザコードでこれらのメソッドを直接呼び出すべきではありません。


引用返信 編集キー/
■51370 / inTopicNo.3)  Re[2]: PCロック中にシャットダウンができない
□投稿者/ はっちゃん (3回)-(2010/07/02(Fri) 23:11:03)
渋木さん、返信が遅れましてすみません。

>>Windowsアプリではコンピュータがロックしているときは動作しないので、
>
> そんなはずはないです。ロック画面が表示されている状態でも、アプリケーションは実行されています。
> そう判断した根拠はなんでしょう?

Windowsアプリと書いてしまったのが間違いです。
最初はサービスはなしで、フォームのみで作成しました。
その場合、ログオンした状態でシャットダウンできましたが
タイマー動作後、【Ctrl+Alt+Del】でコンピュータをロックしてセット時間になるのを待っていましたが、シャットダウンされませんでした。

>
> もし「ロック」というのがいわゆる「スリープ」や「休止状態」のことを指しているのであれば、確かにアプリケーションの実行は凍結されています。
> ですが、その場合は Windows サービスの実行も凍結されています。目的の処理を Windows サービスで処理を実行しても、「スリープ」や「休止状態」による実行の凍結を回避することにはなりません。

「スリープ」や「休止状態」のことではありません。
スクリーンセーバーを解除した後にすぐデスックトップではセキュリティ上問題があるので、パスワードを入力しないとデスックトップが表示できないようにする為の【ロック】です。

>>(4) Windowsサービス内で現在時刻とセット時間を比較し、等しくなったらOnShutdown()を呼び出す
>
> NG です。
>
> OnShutdown() は、Windows サービスをシャットダウンさせるためのメソッドではありません。
> 同様に、OnStop() メソッドは、Windows サービスを停止させるためのメソッドではありません。
>
> これらのメソッドは、Windows サービスがサービスコントロールマネージャから
>
> ・システムがシャットダウンされようとしていることの通知
> ・Windows サービスが停止されようとしていることの通知
>
> を受け取るために用意されたメソッドなので、ユーザコードでこれらのメソッドを直接呼び出すべきではありません。

OnStart()、OnStop()、OnShutdown() それぞれの意味もわからずにコーディングしていました。
とても勉強になりました。
これから、プログラムを改修してみます。
後ほどまたアップしますので、その時はよろしくお願いします。
引用返信 編集キー/
■51373 / inTopicNo.4)  Re[3]: PCロック中にシャットダウンができない
□投稿者/ 渋木宏明 (15回)-(2010/07/03(Sat) 00:36:02)
渋木宏明 さんの Web サイト
> Windowsアプリと書いてしまったのが間違いです。
> 最初はサービスはなしで、フォームのみで作成しました。
> その場合、ログオンした状態でシャットダウンできましたが
> タイマー動作後、【Ctrl+Alt+Del】でコンピュータをロックしてセット時間になるのを待っていましたが、シャットダウンされませんでした。

シャットダウンされなかったのは、アプリケーションの実行権限の問題じゃないですか?

ごく単純に、ボタン押下の10秒後にメッセージボックスを表示するだけのプログラムを作成して

・ボタン押下
・ロック
・10秒以上待つ
・ロック解除

したら、メッセージボックスが表示されてました。

なので、シャットダウンに失敗したからと言って、「ロック状態ではアプリケーション実行が凍結される」ということはないはずです。
引用返信 編集キー/
■51374 / inTopicNo.5)  Re[4]: PCロック中にシャットダウンができない
□投稿者/ はっちゃん (4回)-(2010/07/03(Sat) 01:03:12)
渋木さん、お待たせしてしまいました。
プログラムを改修したら、ロック状態でシャットダウンできました。
いろいろとありがとうございました。

>>Windowsアプリと書いてしまったのが間違いです。
>>最初はサービスはなしで、フォームのみで作成しました。
>>その場合、ログオンした状態でシャットダウンできましたが
>>タイマー動作後、【Ctrl+Alt+Del】でコンピュータをロックしてセット時間になるのを待っていましたが、シャットダウンされませんでした。
> 
> シャットダウンされなかったのは、アプリケーションの実行権限の問題じゃないですか?
> 
> ごく単純に、ボタン押下の10秒後にメッセージボックスを表示するだけのプログラムを作成して
> 
> ・ボタン押下
> ・ロック
> ・10秒以上待つ
> ・ロック解除
> 
> したら、メッセージボックスが表示されてました。
> 
> なので、シャットダウンに失敗したからと言って、「ロック状態ではアプリケーション実行が凍結される」ということはないはずです。

私もこの件は検証してみました。
渋木さんの言うとおりメッセージボックスが表示されていました。
自動的にシャットダウンできなかったのは、メッセージボックスが表示されていて【OK】ボタンの入力待ちだったからですね。
ということで、メッセージボックスの表示をやめたら自動でシャットダウンしました。
下記に改修後のプログラムを載せます。
ありがとうございました。

【改修後のプログラム】
@ShutdownTimer.cs

using System;
using System.ServiceProcess;
using System.Windows.Forms;
using Microsoft.VisualBasic;

namespace ShutdownTimer
{
    public partial class frmShutdownTimer : Form
    {
        private ServiceController sc = new ServiceController("ShutdownTimerService");

        public frmShutdownTimer()
        {
            InitializeComponent();
        }

        private void btnShutdown_Click(object sender, EventArgs e)
        {
            Shutdown();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;
            txtThisTime.Text = dt.ToString("HH:mm:ss");
            
            if (txtThisTime.Text == txtTimer.Text)
            {
                Shutdown();
            }
        }

        private void btnSetTimer_Click(object sender, EventArgs e)
        {
            string strInput = "";
            
            strInput = Interaction.InputBox("セット時間を入力してください。\n\n書式:【hhmmss】", "タイマー時間セット", "", -1, -1);

            if (strInput != "")
            {
                if (strInput.Length != 6)
                {
                    MessageBox.Show("書式:【hhmmss】で入力して下さい。", "書式違反");
                    txtTimer.Text = "";
                }
                else
                {
                    txtTimer.Text = strInput.Substring(0, 2) + ":" + strInput.Substring(2, 2) + ":" + strInput.Substring(4, 2);

                    if (sc.Status == ServiceControllerStatus.Stopped)
                    {
                        sc.Start();
                    }
                }
            }
        }

        private void Shutdown()
        {
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
            psi.FileName = "shutdown.exe";

            //コマンドラインを指定
            psi.Arguments = "/s /t 20";

            //ウィンドウを表示しないようにする
            psi.UseShellExecute = false;
            psi.CreateNoWindow = true;

            //起動
            System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
            Environment.Exit(0);
        }

        private void frmShutdownTimer_Load(object sender, EventArgs e)
        {

        }
    }
}


AShutdownTimerService.cs

using System.Diagnostics;
using System.ServiceProcess;

namespace ShutdownTimerService
{
    public partial class ShutdownTimerService : ServiceBase
    {
        public ShutdownTimerService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            EventLog.WriteEntry("ShutdownTimerServiceを開始しました。");
        }

        protected override void OnStop()
        {
            EventLog.WriteEntry("シャットダウンを終了しました。");
            EventLog.WriteEntry("ShutdownTimerServiceを終了します。");
        }

        protected override void OnShutdown()
        {
            EventLog.WriteEntry("シャットダウンを開始します。");
        }
   }
}


BProjectInstaller.cs

using System.ComponentModel;
using System.Configuration.Install;
using System.Windows.Forms;

namespace ShutdownTimerService
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }

        private void serviceInstaller_AfterInstall(object sender, InstallEventArgs e)
        {
            MessageBox.Show("サービスが正常にインストールされました。");
        }

        private void serviceInstaller_BeforeInstall(object sender, InstallEventArgs e)
        {
            MessageBox.Show("サービスのインストールを開始します。");
        }
    }
}

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -