none
Windows8.1タブレットでの、InstantGoの(スリープ?&レジュームの)検出について RRS feed

  • 質問

  • こんにちは。こちらでお世話になった者です。引き続きお世話になります。

    続きですが、Windowsタブレットの駆動時間を計る簡単なプログラムを作りたいとおもっております。タブレットの電源が入っている時間と、スリープ(InstantGo有効)時・レジューム時の時間とをバッテリーの残量と照らし合わせて算出するオリジナルの駆動時間計測ソフトです。

    そこで日時を知るために、InstantGoが有効なスリープに入るときと、それからの復帰(レジューム)時を検出できないものかと思って、調べました。ですが検討がつきません。通常のスリープ検出方法では、InstantGo時は検出できませんでした。

    環境は、VisualStudio Community 2015(またはcsc.exe)、東芝Windows8.1タブレットS38/26M(デスクトップはASUSの型落ち中古でWindows8.1)です。

    よろしくお願いいたします。






    2015年10月29日 5:29

回答

  • C++であれば以下で動くかなとは思いますが、これをC#に移植するのはInstantGoと本質的には無関係なのでやめておきます(メンドウ)。

    #include <stdio.h>
    #include <Windows.h>
    #include <SubAuth.h>
    #include <PowrProf.h>
    #pragma comment(lib, "PowrProf.lib")
    
    ULONG DeviceNotifyCallbackRoutine(PVOID Context, ULONG Type, PVOID Setting) {
    	const char* message =
    		Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
    		Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
    		Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC " : "other";
    	printf("notify: %s.\n", message);
    	return ERROR_SUCCESS;
    }
    
    int main() {
    	SYSTEM_POWER_CAPABILITIES spc;
    	auto r1 = CallNtPowerInformation(SystemPowerCapabilities, nullptr, 0, &spc, sizeof spc);
    	if (r1 != STATUS_SUCCESS) {
    		printf("CallNtPowerInformation failed: NTSTATUS %d.\n", r1);
    		return 1;
    	}
    	if (!spc.AoAc) {
    		printf("connected standby not supportted.\n");
    		return 1;
    	}
    
    	DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS parameters{ DeviceNotifyCallbackRoutine };
    	HPOWERNOTIFY notify;
    	auto r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, &parameters, &notify);
    	if (r2 != ERROR_SUCCESS) {
    		printf("PowerRegisterSuspendResumeNotification failed.\n");
    		return 1;
    	}
    
    	getchar();
    
    	r2 = PowerUnregisterSuspendResumeNotification(notify);
    	if (r2 != ERROR_SUCCESS) {
    		printf("PowerUnregisterSuspendResumeNotification failed.\n");
    		return 1;
    	}
    	return 0;
    }
    

    • 回答の候補に設定 星 睦美 2015年11月2日 6:28
    • 回答としてマーク HISSTORY_T 2015年11月7日 10:05
    2015年10月29日 6:31
  • これで動きますでしょうか?

    using System;
    using System.Runtime.InteropServices;
    
    namespace instantgo3cs {
        class Program {
            #region Interop
            const int STATUS_SUCCESS = 0x00000000;
            const int ERROR_SUCCESS = 0x00000000;
            const int PBT_APMSUSPEND = 0x0004;
            const int PBT_APMRESUMESUSPEND = 0x0007;
            const int PBT_APMRESUMEAUTOMATIC = 0x0012;
            const int DEVICE_NOTIFY_CALLBACK = 2;
    
            enum POWER_INFORMATION_LEVEL {
                SystemPowerPolicyAc,
                SystemPowerPolicyDc,
                VerifySystemPolicyAc,
                VerifySystemPolicyDc,
                SystemPowerCapabilities,
                SystemBatteryState,
                SystemPowerStateHandler,
                ProcessorStateHandler,
                SystemPowerPolicyCurrent,
                AdministratorPowerPolicy,
                SystemReserveHiberFile,
                ProcessorInformation,
                SystemPowerInformation,
                ProcessorStateHandler2,
                LastWakeTime,
                LastSleepTime,
                SystemExecutionState,
                SystemPowerStateNotifyHandler,
                ProcessorPowerPolicyAc,
                ProcessorPowerPolicyDc,
                VerifyProcessorPowerPolicyAc,
                VerifyProcessorPowerPolicyDc,
                ProcessorPowerPolicyCurrent,
                SystemPowerStateLogging,
                SystemPowerLoggingEntry,
                SetPowerSettingValue,
                NotifyUserPowerSetting,
                PowerInformationLevelUnused0,
                SystemMonitorHiberBootPowerOff,
                SystemVideoState,
                TraceApplicationPowerMessage,
                TraceApplicationPowerMessageEnd,
                ProcessorPerfStates,
                ProcessorIdleStates,
                ProcessorCap,
                SystemWakeSource,
                SystemHiberFileInformation,
                TraceServicePowerMessage,
                ProcessorLoad,
                PowerShutdownNotification,
                MonitorCapabilities,
                SessionPowerInit,
                SessionDisplayState,
                PowerRequestCreate,
                PowerRequestAction,
                GetPowerRequestList,
                ProcessorInformationEx,
                NotifyUserModeLegacyPowerEvent,
                GroupPark,
                ProcessorIdleDomains,
                WakeTimerList,
                SystemHiberFileSize,
                ProcessorIdleStatesHv,
                ProcessorPerfStatesHv,
                ProcessorPerfCapHv,
                ProcessorSetIdle,
                LogicalProcessorIdling,
                UserPresence,
                PowerSettingNotificationName,
                GetPowerSettingValue,
                IdleResiliency,
                SessionRITState,
                SessionConnectNotification,
                SessionPowerCleanup,
                SessionLockState,
                SystemHiberbootState,
                PlatformInformation,
                PdcInvocation,
                MonitorInvocation,
                FirmwareTableInformationRegistered,
                SetShutdownSelectedTime,
                SuspendResumeInvocation,
                PlmPowerRequestCreate,
                ScreenOff,
                CsDeviceNotification,
                PlatformRole,
                LastResumePerformance,
                DisplayBurst,
                ExitLatencySamplingPercentage,
                RegisterSpmPowerSettings,
                PlatformIdleStates,
                ProcessorIdleVeto,
                PlatformIdleVeto,
                SystemBatteryStatePrecise,
                ThermalEvent,
                PowerInformationLevelMaximum
            }
    
            enum SYSTEM_POWER_STATE {
                PowerSystemUnspecified = 0,
                PowerSystemWorking = 1,
                PowerSystemSleeping1 = 2,
                PowerSystemSleeping2 = 3,
                PowerSystemSleeping3 = 4,
                PowerSystemHibernate = 5,
                PowerSystemShutdown = 6,
                PowerSystemMaximum = 7
            }
    
            delegate int DEVICE_NOTIFY_CALLBACK_ROUTINE(IntPtr Context, int Type, IntPtr Setting);
    
            [StructLayout(LayoutKind.Sequential)]
            struct BATTERY_REPORTING_SCALE {
                public int Granularity;
                public int Capacity;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct SYSTEM_POWER_CAPABILITIES {
                [MarshalAs(UnmanagedType.U1)]
                public bool PowerButtonPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool SleepButtonPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool LidPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS1;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS2;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS3;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS4;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS5;
                [MarshalAs(UnmanagedType.U1)]
                public bool HiberFilePresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool FullWake;
                [MarshalAs(UnmanagedType.U1)]
                public bool VideoDimPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool ApmPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool UpsPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool ThermalControl;
                [MarshalAs(UnmanagedType.U1)]
                public bool ProcessorThrottle;
                public byte ProcessorMinThrottle;
                public byte ProcessorMaxThrottle;
                [MarshalAs(UnmanagedType.U1)]
                public bool FastSystemS4;
                [MarshalAs(UnmanagedType.U1)]
                public bool Hiberboot;
                [MarshalAs(UnmanagedType.U1)]
                public bool WakeAlarmPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool AoAc;
                [MarshalAs(UnmanagedType.U1)]
                public bool DiskSpinDown;
                public byte spare3_0;
                public byte spare3_1;
                public byte spare3_2;
                public byte spare3_3;
                public byte spare3_4;
                public byte spare3_5;
                public byte spare3_6;
                public byte spare3_7;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemBatteriesPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool BatteriesAreShortTerm;
                public BATTERY_REPORTING_SCALE BatteryScale_0;
                public BATTERY_REPORTING_SCALE BatteryScale_1;
                public BATTERY_REPORTING_SCALE BatteryScale_2;
                public SYSTEM_POWER_STATE AcOnLineWake;
                public SYSTEM_POWER_STATE SoftLidWake;
                public SYSTEM_POWER_STATE RtcWake;
                public SYSTEM_POWER_STATE MinDeviceWakeState;
                public SYSTEM_POWER_STATE DefaultLowLatencyWake;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            class DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {
                public DEVICE_NOTIFY_CALLBACK_ROUTINE Callback;
                public IntPtr Context;
            }
    
            [DllImport("PowrProf.dll")]
            static extern int CallNtPowerInformation(POWER_INFORMATION_LEVEL InformationLevel, IntPtr InputBuffer, int InputBufferLength, out SYSTEM_POWER_CAPABILITIES OutputBuffer, int OutputBufferLength);
            [DllImport("PowrProf.dll")]
            static extern int PowerRegisterSuspendResumeNotification(int Flags, DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Recipient, out IntPtr RegistrationHandle);
            [DllImport("PowrProf.dll")]
            static extern int PowerUnregisterSuspendResumeNotification(IntPtr RegistrationHandle);
            #endregion
    
            public static int DeviceNotifyCallbackRoutine(IntPtr Context, int Type, IntPtr Setting) {
                string message =
                    Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
                    Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
                    Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC" : "other";
                Console.WriteLine("notify: {0}.", message);
                return ERROR_SUCCESS;
            }
    
            static int Main(string[] args) {
                SYSTEM_POWER_CAPABILITIES spc;
                var r1 = CallNtPowerInformation(POWER_INFORMATION_LEVEL.SystemPowerCapabilities, IntPtr.Zero, 0, out spc, Marshal.SizeOf(typeof(SYSTEM_POWER_CAPABILITIES)));
                if (r1 != STATUS_SUCCESS) {
                    Console.WriteLine("CallNtPowerInformation failed: NTSTATUS {0:D}.", r1);
                    return 1;
                }
                if (!spc.AoAc) {
                    Console.WriteLine("connected standby not supportted.\n");
                    return 1;
                }
    
                var parameters = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS { Callback = DeviceNotifyCallbackRoutine };
                IntPtr notify;
                var r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, parameters, out notify);
                if (r2 != ERROR_SUCCESS) {
                    Console.WriteLine("PowerRegisterSuspendResumeNotification failed.");
                    return 1;
                }
    
                Console.ReadKey();
    
                r2 = PowerUnregisterSuspendResumeNotification(notify);
                if (r2 != ERROR_SUCCESS) {
                    Console.WriteLine("PowerUnregisterSuspendResumeNotification failed.");
                    return 1;
                }
                return 0;
            }
        }
    }
    

    気になる点は、
    HPOWERNOTIFYは本来SafeHandleなどを作る必要がありますが手抜きでIntPtrとしています。これについては安全でないだけで正しく互換動作します。
    DEVICE_NOTIFY_SUBSCRIBE_PARAMETERSは本来structにする必要がありますが事情があり手抜きでclassとしています。これについては確認できていません。
    DEVICE_NOTIFY_CALLBACK_ROUTINEはドキュメントが間違っていて実際の宣言はCALLBACK呼び出し規約ではありません。x64では影響ありませんがx86では正しく動作しないかもしれません。その場合は別の書き方が必要になります。

    • 回答としてマーク HISSTORY_T 2015年11月7日 10:04
    2015年11月4日 22:13

すべての返信

  • C++であれば以下で動くかなとは思いますが、これをC#に移植するのはInstantGoと本質的には無関係なのでやめておきます(メンドウ)。

    #include <stdio.h>
    #include <Windows.h>
    #include <SubAuth.h>
    #include <PowrProf.h>
    #pragma comment(lib, "PowrProf.lib")
    
    ULONG DeviceNotifyCallbackRoutine(PVOID Context, ULONG Type, PVOID Setting) {
    	const char* message =
    		Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
    		Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
    		Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC " : "other";
    	printf("notify: %s.\n", message);
    	return ERROR_SUCCESS;
    }
    
    int main() {
    	SYSTEM_POWER_CAPABILITIES spc;
    	auto r1 = CallNtPowerInformation(SystemPowerCapabilities, nullptr, 0, &spc, sizeof spc);
    	if (r1 != STATUS_SUCCESS) {
    		printf("CallNtPowerInformation failed: NTSTATUS %d.\n", r1);
    		return 1;
    	}
    	if (!spc.AoAc) {
    		printf("connected standby not supportted.\n");
    		return 1;
    	}
    
    	DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS parameters{ DeviceNotifyCallbackRoutine };
    	HPOWERNOTIFY notify;
    	auto r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, &parameters, &notify);
    	if (r2 != ERROR_SUCCESS) {
    		printf("PowerRegisterSuspendResumeNotification failed.\n");
    		return 1;
    	}
    
    	getchar();
    
    	r2 = PowerUnregisterSuspendResumeNotification(notify);
    	if (r2 != ERROR_SUCCESS) {
    		printf("PowerUnregisterSuspendResumeNotification failed.\n");
    		return 1;
    	}
    	return 0;
    }
    

    • 回答の候補に設定 星 睦美 2015年11月2日 6:28
    • 回答としてマーク HISSTORY_T 2015年11月7日 10:05
    2015年10月29日 6:31
  • コードありがとうございます。とてもきれいなコードですね。

    それが、いまの僕ではC++だめです。わかりません。

    ……お手上げです。コードはVS2015 C++コンソールプログラムでコンパイルでき、(Releaseでコンパイルすると)動きました。

    ……何とかなりませんか。

    C++を始めるには(よいコードと思いますが、)僕には少し早いです(いづれC++をと思っているのは確かです)。




    2015年10月30日 6:36
  • 前半のCallNtPowerInformation()のような単発のAPI呼び出しについていえば、まだ考慮する点も少なくなんとかなります。しかし、本題のDeviceNotifyCallbackRoutineコールバックとなるとC++言語で記述した内容とC#言語仕様・.NETランタイム仕様との整合性として考慮すべき点が増えます。当然ながらC++言語で記述できることが前提にあります。

    そのような点から目を反らし、完成形のみを求めるというのであれば、それは質問ではなく丸投げ、アプリケーションの開発依頼でしかありません。

    2015年10月30日 22:00
  • 前半のCallNtPowerInformation()のような単発のAPI呼び出しについていえば、まだ考慮する点も少なくなんとかなります。しかし、本題のDeviceNotifyCallbackRoutineコールバックとなるとC++言語で記述した内容とC#言語仕様・.NETランタイム仕様との整合性として考慮すべき点が増えます。当然ながらC++言語で記述できることが前提にあります。

    え、実際に聞き知ったのは初めてです。システムの設計はまだC++なのですか。コールバックですか……。

    そのような点から目を反らし、完成形のみを求めるというのであれば、それは質問ではなく丸投げ、アプリケーションの開発依頼でしかありません。

    このスレッドを立てるにあたってまず気になっていたのはそれでした。

    (また口が先に出ますが、)

    実際このコードが作動するのを見て、”これ公開しちゃっていいの?”って思いました。~ このコードが実現するもの、そのソフトは、在れば、タブレットのバッテリー駆動時間のデータとしての収集にとても重宝され、定番ソフトになるであろうと思うのです(主流になっていくタブレットのかなめが駆動時間です。iPadの最大の強みというのは実はそこ)。あって不思議じゃないのにも関わらずそれがない。その難関がこのコードが実現するものだったのではないかと思うものなのです。JEITAバッテリ動作時間測定法のJEITAの基準より(人力(じんりき)ですが)リアルな値を集積できるでしょう。できたらすごい。みんな使うでしょうし。必需品になる。なにせ普段使用の駆動時間データが得られるのですから。

    職業プログラマーにとってはこんな話はどうってこともないということですか?

    MSDNってライセンスが厳しいんですよね。確認ですが、ソースコードの再配布は禁止なのですよね。じゃあリンクならいいんですよね?

    このプログラムも活動も、ひとえにWindowsタブレットの真の実力・価値をスペック化しあらわすことによってユーザーに良いWindowsタブレットを手にしてもらい好評を得、さらなる進化・改善に貢献したいがためです。僕は初代iPadを持っていますが、それと比べて課題をズバリ言うと、最初から最後まで、1から10まで、バッテリー駆動時間であり、なかでもKeyは話題のInstantGoモードです。その改善に使えるモニタープログラムとしてあったらいいと思うわけです。このプログラムの存在意義はそういう種からのものです。

    どうか、このソフトに日の目を見させて下さい。

    ですが、これでもダメだというのなら無理にとは申しません。その際は目印か、放置かしてください。

    ---
    My Homepage:
    http://homepage2.nifty.com/tdg_alive/index.html







    2015年10月31日 7:33
  • 話が発散していていまいち何を伝えようとしているのかわかりませんでしたが、理解できた部分に個別に返信します。

    え、実際に聞き知ったのは初めてです。システムの設計はまだC++なのですか。コールバックですか……。

    何が「まだ」なのかわかりませんが、WindowsがInstantGoの動作状況を把握する方法として提供しているAPIはC言語ですから、その使用方法として想定されているのはC言語またはC++言語となります。他の言語を使用するのは自由ですが、それは利用者の責任になります。

    MSDNってライセンスが厳しいんですよね。確認ですが、ソースコードの再配布は禁止なのですよね。じゃあリンクならいいんですよね?

    私の書いたコードについてでしょうか? それについてはライセンスは明示していません。明示されていないものに対して「厳しい」とか「リンクならいい」などご自身の都合で勝手な判断をするのは法的に危険ですので、考え方を改めることをお勧めします。

    なお、本スレッドに張り付けたコードに関しては著作権を主張しませんので、ご自由にお使いください。

    2015年11月2日 5:47
  • C#へのコンバート、コンバーターの結果をベースに、ここまでしてみましたが、動きません。僕のコードは、めちゃくちゃ……かどうかすらわからないです。困難でいい訳はない。話にならないレベルですね。

    構造体?

    using System;
    using System.Runtime.InteropServices;
    
    namespace instantgo3cs
    {
        class Program
        {
            const int STATUS_SUCCESS = 0x00000000;
            const int ERROR_SUCCESS = 0x00000000;
            const int PBT_APMSUSPEND = 0x0004;
            const int PBT_APMRESUMESUSPEND = 0x0007;
            const int PBT_APMRESUMEAUTOMATIC = 0x0012;
    
            [DllImport("Powrprof.dll")]
            private extern static int CallNtPowerInformation(
                POWER_INFORMATION_LEVEL InformationLevel,
                string lpInputBuffer,
                UInt32 nInputBufferSize,
                string lpOutputBuffer,
                UInt32 nOutputBufferSize
            );
    
            [DllImport("Powrrof.dll")]
            private extern static int PowerRegisterSuspendResumeNotification(
                UInt32         Flags,
                IntPtr         Recipient,
                PHPOWERNOTIFY RegistrationHandle
            );
    
            [DllImport("Powrprof.dll")]
            private extern static int PowerUnregisterSuspendResumeNotification(
                HPOWERNOTIFY RegistrationHandle
            );
    
    
            //C++ TO C# CONVERTER TODO TASK: There is no equivalent to most C++ 'pragma' directives in C#:
            //#pragma comment(lib, "PowrProf.lib")
    
            public static uint DeviceNotifyCallbackRoutine(object Context, uint Type, object Setting)
            {
                string message =
                    Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
                    Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
                    Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC " : "other";
                Console.Write("notify: {0}.\n", message);
                return ERROR_SUCCESS;
            }
    
            static int Main(string[] args)
            {
                SYSTEM_POWER_CAPABILITIES spc = new SYSTEM_POWER_CAPABILITIES();
                var r1 = CallNtPowerInformation(SystemPowerCapabilities, null, 0, spc, sizeof(SYSTEM_POWER_CAPABILITIES));
                if (r1 != STATUS_SUCCESS)
                {
                    Console.Write("CallNtPowerInformation failed: NTSTATUS {0:D}.\n", r1);
                    return 1;
                }
                if (!spc.AoAc)
                {
                    Console.Write("connected standby not supportted.\n");
                    return 1;
                }
    
                DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS parameters = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS(DeviceNotifyCallbackRoutine);
                HPOWERNOTIFY notify = new HPOWERNOTIFY();
                var r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, parameters, notify);
                if (r2 != ERROR_SUCCESS)
                {
                    Console.Write("PowerRegisterSuspendResumeNotification failed.\n");
                    return 1;
                }
    
                Console.ReadKey();
    
                r2 = PowerUnregisterSuspendResumeNotification(notify);
                if (r2 != ERROR_SUCCESS)
                {
                    Console.Write("PowerUnregisterSuspendResumeNotification failed.\n");
                    return 1;
                }
                return 0;
            }
        }
    }
    
    // 2015H27/11/02 MON 20:13
    
    /*
    Bing Search Keywords is "C# API叩き方".
    */

    お手を煩わせてしまって、申し訳ありません。









    2015年11月2日 12:01
  • #pragma comment(lib, "PowrProf.lib")はリンカーに与えるオプションで、C#では[DllImport("Powrprof.dll")]が相当するため記述不要です。

    書かれているコードよりも省略されているDEVICE_NOTIFY_SUBSCRIBE_PARAMETERSの定義、コンストラクターの内容に問題がありそうです。その部分もあげてくれたら指摘できます。

    2015年11月3日 2:35
  • 長らくお付き合い感謝いたします。

    はちゃめちゃでしょう。まだ途中ですが経過報告までに。

    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace instantgo3cs
    {
        class Program
        {
            const uint STATUS_SUCCESS = 0x00000000;
            const uint ERROR_SUCCESS = 0x00000000;
            const uint PBT_APMSUSPEND = 0x0004;
            const uint PBT_APMRESUMESUSPEND = 0x0007;
            const uint PBT_APMRESUMEAUTOMATIC = 0x0012;
    
            [DllImport("Powrprof.dll", SetLastError = true)]        // interop.cs
            private extern static uint CallNtPowerInformation(
                POWER_INFORMATION_LEVEL InformationLevel,
                IntPtr lpInputBuffer,
                UInt32 nInputBufferSize,
                [Out] SYSTEM_POWER_CAPABILITIES lpOutputBuffer,
                UInt32 nOutputBufferSize
            );
    
            [DllImport("Powrrof.dll")]
            private extern static int PowerRegisterSuspendResumeNotification(
                uint Flags,
                DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Recipient,
                HPOWERNOTIFY RegistrationHandle
            );
    
            [DllImport("Powrprof.dll")]
            private extern static int PowerUnregisterSuspendResumeNotification(
                HPOWERNOTIFY RegistrationHandle
            );
    
            [StructLayout(LayoutKind.Sequential)]
            public class DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
            {
                public PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback;
                public string Context;
                public DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS(uint r)
                {
                    //
                }
    
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct PDEVICE_NOTIFY_CALLBACK_ROUTINE
            {
                //
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct HPOWERNOTIFY
            {
                //
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct DEVICE_NOTIFY_CALLBACK
            {
                //
            }
    
            public struct SYSTEM_POWER_CAPABILITIES
            {
                public bool PowerButtonPresent;
                public bool SleepButtonPresent;
                public bool LidPresent;
                public bool SystemS1;
                public bool SystemS2;
                public bool SystemS3;
                public bool SystemS4;
                public bool SystemS5;
                public bool HiberFilePresent;
                public bool FullWake;
                public bool VideoDimPresent;
                public bool ApmPresent;
                public bool UpsPresent;
                public bool ThermalControl;
                public bool ProcessorThrottle;
                public byte ProcessorMinThrottle;
                public byte ProcessorMaxThrottle;
                public bool FastSystemS4;
                public bool HiberBoot;
                public bool WakeAlarmPresent;
                public bool AoAc;
                public bool DiskSpinDown;
                public byte spare3;
                public bool SystemBatteriesPresent;
                public bool BatteriesAreShortTerm;
                public BATTERY_REPORTING_SCALE BatteryScale;
                public SYSTEM_POWER_STATE AcOnLineWake;
                public SYSTEM_POWER_STATE SoftLidWake;
                public SYSTEM_POWER_STATE RtcWake;
                public SYSTEM_POWER_STATE MinDeviceWakeState;
                public SYSTEM_POWER_STATE DefaultLowLatencyWake;
            }
    
            public struct BATTERY_REPORTING_SCALE
            {
                public UInt32 Granularity;
                public UInt32 Capacity;
    
            }
    
            public enum SYSTEM_POWER_STATE
            {
                PowerSystemUnspecified = 0,
                PowerSystemWorking = 1,
                PowerSystemSleeping1 = 2,
                PowerSystemSleeping2 = 3,
                PowerSystemSleeping3 = 4,
                PowerSystemHibernate = 5,
                PowerSystemShutdown = 6,
                PowerSystemMaximum = 7
            }
    
            public enum POWER_INFORMATION_LEVEL
            {
                SystemPowerPolicyAc,
                SystemPowerPolicyDc,
                VerifySystemPolicyAc,
                VerifySystemPolicyDc,
                SystemPowerCapabilities,
                SystemBatteryState,
                SystemPowerStateHandler,
                ProcessorStateHandler,
                SystemPowerPolicyCurrent,
                AdministratorPowerPolicy,
                SystemReserveHiberFile,
                ProcessorInformation,
                SystemPowerInformation,
                ProcessorStateHandler2,
                LastWakeTime,
                LastSleepTime,
                SystemExecutionState,
                SystemPowerStateNotifyHandler,
                ProcessorPowerPolicyAc,
                ProcessorPowerPolicyDc,
                VerifyProcessorPowerPolicyAc,
                VerifyProcessorPowerPolicyDc,
                ProcessorPowerPolicyCurrent,
                SystemPowerStateLogging,
                SystemPowerLoggingEntry,
                SetPowerSettingValue,
                NotifyUserPowerSetting,
                PowerInformationLevelUnused0,
                SystemMonitorHiberBootPowerOff,
                SystemVideoState,
                TraceApplicationPowerMessage,
                TraceApplicationPowerMessageEnd,
                ProcessorPerfStates,
                ProcessorIdleStates,
                ProcessorCap,
                SystemWakeSource,
                SystemHiberFileInformation,
                TraceServicePowerMessage,
                ProcessorLoad,
                PowerShutdownNotification,
                MonitorCapabilities,
                SessionPowerInit,
                SessionDisplayState,
                PowerRequestCreate,
                PowerRequestAction,
                GetPowerRequestList,
                ProcessorInformationEx,
                NotifyUserModeLegacyPowerEvent,
                GroupPark,
                ProcessorIdleDomains,
                WakeTimerList,
                SystemHiberFileSize,
                ProcessorIdleStatesHv,
                ProcessorPerfStatesHv,
                ProcessorPerfCapHv,
                ProcessorSetIdle,
                LogicalProcessorIdling,
                UserPresence,
                PowerSettingNotificationName,
                GetPowerSettingValue,
                IdleResiliency,
                SessionRITState,
                SessionConnectNotification,
                SessionPowerCleanup,
                SessionLockState,
                SystemHiberbootState,
                PlatformInformation,
                PdcInvocation,
                MonitorInvocation,
                FirmwareTableInformationRegistered,
                SetShutdownSelectedTime,
                SuspendResumeInvocation,
                PlmPowerRequestCreate,
                ScreenOff,
                CsDeviceNotification,
                PlatformRole,
                LastResumePerformance,
                DisplayBurst,
                ExitLatencySamplingPercentage,
                RegisterSpmPowerSettings,
                PlatformIdleStates,
                ProcessorIdleVeto,
                PlatformIdleVeto,
                SystemBatteryStatePrecise,
                ThermalEvent,
                PowerInformationLevelMaximum
            }
    
    
            [StructLayout(LayoutKind.Sequential)]
            public struct PHPOWERNOTIFY
            {
                //
            }
    
            //C++ TO C# CONVERTER TODO TASK: There is no equivalent to most C++ 'pragma' directives in C#:
    
            public static uint DeviceNotifyCallbackRoutine(string Context, uint Type, object Setting)
            {
                string message =
                    Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
                    Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
                    Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC " : "other";
                Console.Write("notify: {0}.\n", message);
                return ERROR_SUCCESS;
            }
    
            static int Main(string[] args)
            {
                SYSTEM_POWER_CAPABILITIES spc = new SYSTEM_POWER_CAPABILITIES();
                var r1 = CallNtPowerInformation(POWER_INFORMATION_LEVEL.SystemPowerCapabilities, IntPtr.Zero, 0, spc, (uint)Marshal.SizeOf(typeof(SYSTEM_POWER_CAPABILITIES)));// <SYSTEM_POWER_CAPABILITIES>(SYSTEM_POWER_CAPABILITIES));
                //var r1 = CallNtPowerInformation(SystemPowerCapabilities, null, 0, spc, System.Runtime.InteropServices.Marshal.SizeOf<SYSTEM_POWER_CAPABILITIES>);//(SYSTEM_POWER_CAPABILITIES));
                if (r1 != STATUS_SUCCESS)
                {
                    Console.Write("CallNtPowerInformation failed: NTSTATUS {0:D}.\n", r1);
                    return 1;
                }
                if (!spc.AoAc)
                {
                    Console.Write("connected standby not supportted.\n");
                    return 1;
                }
    
                DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS parameters = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS(DeviceNotifyCallbackRoutine(null,0,null));
                HPOWERNOTIFY notify = new HPOWERNOTIFY();
                var r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, parameters, notify);
                if (r2 != ERROR_SUCCESS)
                {
                    Console.Write("PowerRegisterSuspendResumeNotification failed.\n");
                    return 1;
                }
    
                Console.ReadKey();
    
                r2 = PowerUnregisterSuspendResumeNotification(notify);
                if (r2 != ERROR_SUCCESS)
                {
                    Console.Write("PowerUnregisterSuspendResumeNotification failed.\n");
                    return 1;
                }
                return 0;
            }
        }
    }
    
    // 2015H27/11/04 WED 15:13 
    // 2015H27/11/02 MON 20:13
    
    /*
    Bing Search Keywords is "C# API叩き方".
    C# API叩き方 - Bing
    http://www.bing.com/search?q=C%23+API%E5%8F%A9%E3%81%8D%E6%96%B9&qs=n&form=QBLH&scope=web&pq=c%23+api%E5%8F%A9%E3%81%8D%E6%96%B9&sc=0-6&sp=-1&sk=&cvid=ebcf4a85cd184a669ea35f25b4f1f290
    @IT:.NET TIPS Win32 APIやDLL関数を呼び出すには? - C#
    http://www.atmarkit.co.jp/fdotnet/dotnettips/024w32api/w32api.html
    CallNtPowerInformation function (Windows)
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa372675(v=vs.85).aspx
    PowerRegisterSuspendResumeNotification function (Windows)
    https://msdn.microsoft.com/en-us/library/windows/desktop/hh769080(v=vs.85).aspx
    PowerUnregisterSuspendResumeNotification function (Windows)
    https://msdn.microsoft.com/en-us/library/windows/desktop/hh769084(v=vs.85).aspx
    PVOID C# - Bing
    http://www.bing.com/search?q=PVOID+C%23&qs=n&form=QBLH&scope=web&pq=pvoid+c%23&sc=0-7&sp=-1&sk=&cvid=2dee2f1ae5f64520b9a339707379bdce
    Re[6]: void型へのポインタ
    http://bbs.wankuma.com/index.cgi?mode=al2&namber=57406&KLOG=96
    */
    
    /*
    StringBuilder
    C# Win32 API および DLL の利用 - MyMemoWiki
    http://typea.info/tips/wiki.cgi?page=C%23+Win32+API+%A4%AA%A4%E8%A4%D3+DLL+%A4%CE%CD%F8%CD%D1
    */

    ...


    2015年11月4日 13:27
  • これで動きますでしょうか?

    using System;
    using System.Runtime.InteropServices;
    
    namespace instantgo3cs {
        class Program {
            #region Interop
            const int STATUS_SUCCESS = 0x00000000;
            const int ERROR_SUCCESS = 0x00000000;
            const int PBT_APMSUSPEND = 0x0004;
            const int PBT_APMRESUMESUSPEND = 0x0007;
            const int PBT_APMRESUMEAUTOMATIC = 0x0012;
            const int DEVICE_NOTIFY_CALLBACK = 2;
    
            enum POWER_INFORMATION_LEVEL {
                SystemPowerPolicyAc,
                SystemPowerPolicyDc,
                VerifySystemPolicyAc,
                VerifySystemPolicyDc,
                SystemPowerCapabilities,
                SystemBatteryState,
                SystemPowerStateHandler,
                ProcessorStateHandler,
                SystemPowerPolicyCurrent,
                AdministratorPowerPolicy,
                SystemReserveHiberFile,
                ProcessorInformation,
                SystemPowerInformation,
                ProcessorStateHandler2,
                LastWakeTime,
                LastSleepTime,
                SystemExecutionState,
                SystemPowerStateNotifyHandler,
                ProcessorPowerPolicyAc,
                ProcessorPowerPolicyDc,
                VerifyProcessorPowerPolicyAc,
                VerifyProcessorPowerPolicyDc,
                ProcessorPowerPolicyCurrent,
                SystemPowerStateLogging,
                SystemPowerLoggingEntry,
                SetPowerSettingValue,
                NotifyUserPowerSetting,
                PowerInformationLevelUnused0,
                SystemMonitorHiberBootPowerOff,
                SystemVideoState,
                TraceApplicationPowerMessage,
                TraceApplicationPowerMessageEnd,
                ProcessorPerfStates,
                ProcessorIdleStates,
                ProcessorCap,
                SystemWakeSource,
                SystemHiberFileInformation,
                TraceServicePowerMessage,
                ProcessorLoad,
                PowerShutdownNotification,
                MonitorCapabilities,
                SessionPowerInit,
                SessionDisplayState,
                PowerRequestCreate,
                PowerRequestAction,
                GetPowerRequestList,
                ProcessorInformationEx,
                NotifyUserModeLegacyPowerEvent,
                GroupPark,
                ProcessorIdleDomains,
                WakeTimerList,
                SystemHiberFileSize,
                ProcessorIdleStatesHv,
                ProcessorPerfStatesHv,
                ProcessorPerfCapHv,
                ProcessorSetIdle,
                LogicalProcessorIdling,
                UserPresence,
                PowerSettingNotificationName,
                GetPowerSettingValue,
                IdleResiliency,
                SessionRITState,
                SessionConnectNotification,
                SessionPowerCleanup,
                SessionLockState,
                SystemHiberbootState,
                PlatformInformation,
                PdcInvocation,
                MonitorInvocation,
                FirmwareTableInformationRegistered,
                SetShutdownSelectedTime,
                SuspendResumeInvocation,
                PlmPowerRequestCreate,
                ScreenOff,
                CsDeviceNotification,
                PlatformRole,
                LastResumePerformance,
                DisplayBurst,
                ExitLatencySamplingPercentage,
                RegisterSpmPowerSettings,
                PlatformIdleStates,
                ProcessorIdleVeto,
                PlatformIdleVeto,
                SystemBatteryStatePrecise,
                ThermalEvent,
                PowerInformationLevelMaximum
            }
    
            enum SYSTEM_POWER_STATE {
                PowerSystemUnspecified = 0,
                PowerSystemWorking = 1,
                PowerSystemSleeping1 = 2,
                PowerSystemSleeping2 = 3,
                PowerSystemSleeping3 = 4,
                PowerSystemHibernate = 5,
                PowerSystemShutdown = 6,
                PowerSystemMaximum = 7
            }
    
            delegate int DEVICE_NOTIFY_CALLBACK_ROUTINE(IntPtr Context, int Type, IntPtr Setting);
    
            [StructLayout(LayoutKind.Sequential)]
            struct BATTERY_REPORTING_SCALE {
                public int Granularity;
                public int Capacity;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct SYSTEM_POWER_CAPABILITIES {
                [MarshalAs(UnmanagedType.U1)]
                public bool PowerButtonPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool SleepButtonPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool LidPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS1;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS2;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS3;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS4;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS5;
                [MarshalAs(UnmanagedType.U1)]
                public bool HiberFilePresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool FullWake;
                [MarshalAs(UnmanagedType.U1)]
                public bool VideoDimPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool ApmPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool UpsPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool ThermalControl;
                [MarshalAs(UnmanagedType.U1)]
                public bool ProcessorThrottle;
                public byte ProcessorMinThrottle;
                public byte ProcessorMaxThrottle;
                [MarshalAs(UnmanagedType.U1)]
                public bool FastSystemS4;
                [MarshalAs(UnmanagedType.U1)]
                public bool Hiberboot;
                [MarshalAs(UnmanagedType.U1)]
                public bool WakeAlarmPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool AoAc;
                [MarshalAs(UnmanagedType.U1)]
                public bool DiskSpinDown;
                public byte spare3_0;
                public byte spare3_1;
                public byte spare3_2;
                public byte spare3_3;
                public byte spare3_4;
                public byte spare3_5;
                public byte spare3_6;
                public byte spare3_7;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemBatteriesPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool BatteriesAreShortTerm;
                public BATTERY_REPORTING_SCALE BatteryScale_0;
                public BATTERY_REPORTING_SCALE BatteryScale_1;
                public BATTERY_REPORTING_SCALE BatteryScale_2;
                public SYSTEM_POWER_STATE AcOnLineWake;
                public SYSTEM_POWER_STATE SoftLidWake;
                public SYSTEM_POWER_STATE RtcWake;
                public SYSTEM_POWER_STATE MinDeviceWakeState;
                public SYSTEM_POWER_STATE DefaultLowLatencyWake;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            class DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {
                public DEVICE_NOTIFY_CALLBACK_ROUTINE Callback;
                public IntPtr Context;
            }
    
            [DllImport("PowrProf.dll")]
            static extern int CallNtPowerInformation(POWER_INFORMATION_LEVEL InformationLevel, IntPtr InputBuffer, int InputBufferLength, out SYSTEM_POWER_CAPABILITIES OutputBuffer, int OutputBufferLength);
            [DllImport("PowrProf.dll")]
            static extern int PowerRegisterSuspendResumeNotification(int Flags, DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Recipient, out IntPtr RegistrationHandle);
            [DllImport("PowrProf.dll")]
            static extern int PowerUnregisterSuspendResumeNotification(IntPtr RegistrationHandle);
            #endregion
    
            public static int DeviceNotifyCallbackRoutine(IntPtr Context, int Type, IntPtr Setting) {
                string message =
                    Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
                    Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
                    Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC" : "other";
                Console.WriteLine("notify: {0}.", message);
                return ERROR_SUCCESS;
            }
    
            static int Main(string[] args) {
                SYSTEM_POWER_CAPABILITIES spc;
                var r1 = CallNtPowerInformation(POWER_INFORMATION_LEVEL.SystemPowerCapabilities, IntPtr.Zero, 0, out spc, Marshal.SizeOf(typeof(SYSTEM_POWER_CAPABILITIES)));
                if (r1 != STATUS_SUCCESS) {
                    Console.WriteLine("CallNtPowerInformation failed: NTSTATUS {0:D}.", r1);
                    return 1;
                }
                if (!spc.AoAc) {
                    Console.WriteLine("connected standby not supportted.\n");
                    return 1;
                }
    
                var parameters = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS { Callback = DeviceNotifyCallbackRoutine };
                IntPtr notify;
                var r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, parameters, out notify);
                if (r2 != ERROR_SUCCESS) {
                    Console.WriteLine("PowerRegisterSuspendResumeNotification failed.");
                    return 1;
                }
    
                Console.ReadKey();
    
                r2 = PowerUnregisterSuspendResumeNotification(notify);
                if (r2 != ERROR_SUCCESS) {
                    Console.WriteLine("PowerUnregisterSuspendResumeNotification failed.");
                    return 1;
                }
                return 0;
            }
        }
    }
    

    気になる点は、
    HPOWERNOTIFYは本来SafeHandleなどを作る必要がありますが手抜きでIntPtrとしています。これについては安全でないだけで正しく互換動作します。
    DEVICE_NOTIFY_SUBSCRIBE_PARAMETERSは本来structにする必要がありますが事情があり手抜きでclassとしています。これについては確認できていません。
    DEVICE_NOTIFY_CALLBACK_ROUTINEはドキュメントが間違っていて実際の宣言はCALLBACK呼び出し規約ではありません。x64では影響ありませんがx86では正しく動作しないかもしれません。その場合は別の書き方が必要になります。

    • 回答としてマーク HISSTORY_T 2015年11月7日 10:04
    2015年11月4日 22:13
  • タブレットで休止(本来はないもので、InstantGoをレジストリで無効化したときに出現してそのままの)すると、復帰時に以下のように表示され例外が出て止まります。

    ==========

    notify: PBT_APMSUSPEND.

    ハンドルされていない例外: System.AccessViolationException: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。

    ==========

    PBTのイベントに何かないかと調べてみましたが空振りだったようです。C++ビルドの方は問題ないです。

    どうか、もう少々お付き合いくださいませ。

    (肝心なことを書き忘れました。タブレットは32ビットなのでx86ということに。)

    2015H27/11/06 FRI

    コンソールでデバッグを開始すると調子が出てきました。VisualStudioは今回インストールしたもので(今後、徐々に用途に応じて)。

    へんだな、try catch (Exception ex)ではだめです。

    7:52pm
    コンソールで調子が出てきたのでもう少しだけこのままにして置かせてください。

    11:10pm
    IntPtrをstringへ変更したところ、NullReferenceExceptionが出たので、ソース掲示および回答マークは明日夜まで様子を見させてください。





    2015年11月5日 9:50
  • C++版の方はReleaseで、C#版の方はDebugで動くということのようです。

    ともあれどうもありがとうございました。自己の限界をはるかに超えて成果を得、感謝のことばでは足りないくらいです。かなりの無理を聞いてくださったことを今後の人との関わり交流の勇気とし、糧と力にして自己に真に向かい、良いプログラムを書き、貢献していきたいと思います。本当にありがとうございました。










    2015年11月7日 10:03
  • 「これで動きますでしょうか?」に対する明確な返答がなかったので、書かれている文面からAccessViolationExceptionが発生することはわかりましたが、全体としてはいまいち状況がわからなかったのですが。

    Debug版では動作するとのことなので、Release版では動作しないということでしょうか? いろいろ断片的なために推測が交じり理解が難しいです。

    Debug版で動作するのであれば、Visual Studioでデバッグしながらスリープを試した場合はどうなるでしょうか? これは出力ウィンドウに何か表示されたりすることを期待しています。try-catchできないということはコールバック関数内に問題がある可能性があります。つまり既に指摘しているようにx86でコールバックが動作しないであろうという予想が正しいのかもしれません。

    2015年11月7日 11:03
  • 一般論として、ですが、C#とかの.NETで動くアプリでネイティブなコールバック登録をするときにありがちなのが、
    デリゲートオブジェクトが、ネイティブから実際にコールバックされる時にはすでにGCにより始末されていて死ぬ、という話です。
    特に、ネイティブなコールバック登録ではNET的な参照がないですから、メンバ変数にするとかGC.KeepAliveを呼ぶとかで明示的に保護してやる必要があります。

    具体的には、なんだかparametersの寿命が怪しい感じがします。



    jzkey

    2015年11月7日 14:35
  • 「これで動きますでしょうか?」に対する明確な返答がなかったので、書かれている文面からAccessViolationExceptionが発生することはわかりましたが、全体としてはいまいち状況がわからなかったのですが。

    Debug版では動作するとのことなので、Release版では動作しないということでしょうか? いろいろ断片的なために推測が交じり理解が難しいです。

    ごめんなさい。明確な答えが記されていませんでした。教えていただいたソースはそのままで動きました。ーただし、Debug版では動き、Releace版では、AccessViolationExceptionが発生いたします。(C++版はReleaceでは動き、DebugではVCRUNTIME140D.DLLがないと出ます)。

    Debug版で動作するのであれば、Visual Studioでデバッグしながらスリープを試した場合はどうなるでしょうか? これは出力ウィンドウに何か表示されたりすることを期待しています。

    申し訳ありません。容量不足でタブレットにはインストールできないので再現できないのです(VS Community2015は最小構成ならどれくらいの容量があればインストール可能でしょうか?)

    try-catchできないということはコールバック関数内に問題がある可能性があります。つまり既に指摘しているようにx86でコールバックが動作しないであろうという予想が正しいのかもしれません。
    そうです。try-catchができません。



    2015年11月8日 1:08
  • jzkeyさんの推測の通りだとしたら、PowerUnregisterSuspendResumeNotification()の終わった後にGC.KeepAlive(parameters);行を追加することで解決します。

    わたしの指摘通りだとしたら、

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    delegate int DEVICE_NOTIFY_CALLBACK_ROUTINE(IntPtr Context, int Type, IntPtr Setting);
    

    への変更で動作するかもしれません。引き続き問題が発生する場合は、この個所ではなかったということかもしれませんし、もっと厄介な回避策が必要ということかもしれません。

    2015年11月8日 6:12
  • 佐祐理さん、ありがとうございます。ん、結果はjzkeyさんの推測の通りでした。GCでした。

              :
              :
      Console.ReadKey();
      
      r2 = PowerUnregisterSuspendResumeNotification(notify);
      GC.KeepAlive(parameters);
    
      if (r2 != ERROR_SUCCESS)
      {
          Console.WriteLine("PowerUnregisterSuspendResumeNotification failed.");
          return 1;
      }
      return 0;	
             :
             :

    ここでよろしかったでしょうか?

    あと、プログラムに組み込んだ時に、どこかで(GC.Collect();で)明示的に手動で開放する必要があるのでしょうか?
    この答えは、

    https://msdn.microsoft.com/ja-jp/library/system.gc.keepalive(v=vs.110).aspx
    「パラメーターとして渡されるオブジェクトの有効期間を拡張する以外の副作用は生成されません。」

    でいいのでしょうか?拡張するって、伸ばしただけということですか?

    あと、VisualStudio Community 2015は、「4 GB のハード ディスク空き容量」ですか(夢なのかVC++は容量に入っていないとかどこかで見た気がする)。






    2015年11月8日 11:08
  • GC.KeepAlive()についてはドキュメントよりもソースコードおよびコメントを読んだ方が理解が進むかもしれません。
    2015年11月8日 12:03
  • ありがとうございます。またすごいページですねここは。重ね重ね感謝いたるものであります。

    僕はプロジェクトを立ち上げるのにいい機会がないかと思っているのです。いい案も作り手次第です。(ピラミッドのように)つなげていく才能みたいなものが必要なのでしょう。そちらでないことから…そういう点からいうと、ネットでないと生きられない僕は前に出ないほうがいいですね。『意見を述べる前にコードを書け』のようにコードが先なのでしょうが、アイデアを取り上げて具現するグループがあっていい。逆に、アイデアを埋もれさせることは先端分野にあって国家的損失に至ると思うのです。(著作権を整えた)プロジェクト方式への窓口を整備して、財産を生成する。国産のであればなおいい。ネットで生きる人を生かすことなんかにも通じるものです。

    僕はとてつもなく疲れやすいのが難点で。長い間起きていられないんで強く思うのですが、”愛とは惜しみなく労力を使うこと”(他意はありません)”心理を保ち、続けていく’答え’”だと思えてくるのです。

    それにしても、『意見を述べる前にコードを書け』であり、それには僕がいまWEBPAGEで行っているような、基礎的コードのパターンを増やしていくのでも(充足させることで)「やれるもんだけで毎日何かを頑張っていりゃ」(by 玉置浩二 田園)いいのですね。職業にするつもりがなくてもいい。そう思っていいものを残していく。’自己満足だろう'って言われるやもしれませんが、成果物が実在するならまったくそうではないはず。

    話を元に戻しますと、え~と、Windowsフォームで書き直すと、Console.ReadKey();で前半後半に分けて、前半をメインに、後半をClosedイベントに書けばいいのでしょうか?相変わらずでごめんなさい。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace instantgo5m03oop
    {
        public partial class Form1 : Form
        {
            #region Interop
            const int STATUS_SUCCESS = 0x00000000;
            const int ERROR_SUCCESS = 0x00000000;
            const int PBT_APMSUSPEND = 0x0004;
            const int PBT_APMRESUMESUSPEND = 0x0007;
            const int PBT_APMRESUMEAUTOMATIC = 0x0012;
            const int DEVICE_NOTIFY_CALLBACK = 2;
    
            enum POWER_INFORMATION_LEVEL
            {
                SystemPowerPolicyAc,
                SystemPowerPolicyDc,
                VerifySystemPolicyAc,
                VerifySystemPolicyDc,
                SystemPowerCapabilities,
                SystemBatteryState,
                SystemPowerStateHandler,
                ProcessorStateHandler,
                SystemPowerPolicyCurrent,
                AdministratorPowerPolicy,
                SystemReserveHiberFile,
                ProcessorInformation,
                SystemPowerInformation,
                ProcessorStateHandler2,
                LastWakeTime,
                LastSleepTime,
                SystemExecutionState,
                SystemPowerStateNotifyHandler,
                ProcessorPowerPolicyAc,
                ProcessorPowerPolicyDc,
                VerifyProcessorPowerPolicyAc,
                VerifyProcessorPowerPolicyDc,
                ProcessorPowerPolicyCurrent,
                SystemPowerStateLogging,
                SystemPowerLoggingEntry,
                SetPowerSettingValue,
                NotifyUserPowerSetting,
                PowerInformationLevelUnused0,
                SystemMonitorHiberBootPowerOff,
                SystemVideoState,
                TraceApplicationPowerMessage,
                TraceApplicationPowerMessageEnd,
                ProcessorPerfStates,
                ProcessorIdleStates,
                ProcessorCap,
                SystemWakeSource,
                SystemHiberFileInformation,
                TraceServicePowerMessage,
                ProcessorLoad,
                PowerShutdownNotification,
                MonitorCapabilities,
                SessionPowerInit,
                SessionDisplayState,
                PowerRequestCreate,
                PowerRequestAction,
                GetPowerRequestList,
                ProcessorInformationEx,
                NotifyUserModeLegacyPowerEvent,
                GroupPark,
                ProcessorIdleDomains,
                WakeTimerList,
                SystemHiberFileSize,
                ProcessorIdleStatesHv,
                ProcessorPerfStatesHv,
                ProcessorPerfCapHv,
                ProcessorSetIdle,
                LogicalProcessorIdling,
                UserPresence,
                PowerSettingNotificationName,
                GetPowerSettingValue,
                IdleResiliency,
                SessionRITState,
                SessionConnectNotification,
                SessionPowerCleanup,
                SessionLockState,
                SystemHiberbootState,
                PlatformInformation,
                PdcInvocation,
                MonitorInvocation,
                FirmwareTableInformationRegistered,
                SetShutdownSelectedTime,
                SuspendResumeInvocation,
                PlmPowerRequestCreate,
                ScreenOff,
                CsDeviceNotification,
                PlatformRole,
                LastResumePerformance,
                DisplayBurst,
                ExitLatencySamplingPercentage,
                RegisterSpmPowerSettings,
                PlatformIdleStates,
                ProcessorIdleVeto,
                PlatformIdleVeto,
                SystemBatteryStatePrecise,
                ThermalEvent,
                PowerInformationLevelMaximum
            }
    
            enum SYSTEM_POWER_STATE
            {
                PowerSystemUnspecified = 0,
                PowerSystemWorking = 1,
                PowerSystemSleeping1 = 2,
                PowerSystemSleeping2 = 3,
                PowerSystemSleeping3 = 4,
                PowerSystemHibernate = 5,
                PowerSystemShutdown = 6,
                PowerSystemMaximum = 7
            }
    
            delegate int DEVICE_NOTIFY_CALLBACK_ROUTINE(IntPtr Context, int Type, IntPtr Setting);
    
            [StructLayout(LayoutKind.Sequential)]
            struct BATTERY_REPORTING_SCALE
            {
                public int Granularity;
                public int Capacity;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            struct SYSTEM_POWER_CAPABILITIES
            {
                [MarshalAs(UnmanagedType.U1)]
                public bool PowerButtonPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool SleepButtonPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool LidPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS1;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS2;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS3;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS4;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemS5;
                [MarshalAs(UnmanagedType.U1)]
                public bool HiberFilePresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool FullWake;
                [MarshalAs(UnmanagedType.U1)]
                public bool VideoDimPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool ApmPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool UpsPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool ThermalControl;
                [MarshalAs(UnmanagedType.U1)]
                public bool ProcessorThrottle;
                public byte ProcessorMinThrottle;
                public byte ProcessorMaxThrottle;
                [MarshalAs(UnmanagedType.U1)]
                public bool FastSystemS4;
                [MarshalAs(UnmanagedType.U1)]
                public bool Hiberboot;
                [MarshalAs(UnmanagedType.U1)]
                public bool WakeAlarmPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool AoAc;
                [MarshalAs(UnmanagedType.U1)]
                public bool DiskSpinDown;
                public byte spare3_0;
                public byte spare3_1;
                public byte spare3_2;
                public byte spare3_3;
                public byte spare3_4;
                public byte spare3_5;
                public byte spare3_6;
                public byte spare3_7;
                [MarshalAs(UnmanagedType.U1)]
                public bool SystemBatteriesPresent;
                [MarshalAs(UnmanagedType.U1)]
                public bool BatteriesAreShortTerm;
                public BATTERY_REPORTING_SCALE BatteryScale_0;
                public BATTERY_REPORTING_SCALE BatteryScale_1;
                public BATTERY_REPORTING_SCALE BatteryScale_2;
                public SYSTEM_POWER_STATE AcOnLineWake;
                public SYSTEM_POWER_STATE SoftLidWake;
                public SYSTEM_POWER_STATE RtcWake;
                public SYSTEM_POWER_STATE MinDeviceWakeState;
                public SYSTEM_POWER_STATE DefaultLowLatencyWake;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            class DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
            {
                public DEVICE_NOTIFY_CALLBACK_ROUTINE Callback;
                public IntPtr Context;
            }
    
            [DllImport("PowrProf.dll")]
            static extern int CallNtPowerInformation(POWER_INFORMATION_LEVEL InformationLevel, IntPtr InputBuffer, int InputBufferLength, out SYSTEM_POWER_CAPABILITIES OutputBuffer, int OutputBufferLength);
            [DllImport("PowrProf.dll")]
            static extern int PowerRegisterSuspendResumeNotification(int Flags, DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Recipient, out IntPtr RegistrationHandle);
            [DllImport("PowrProf.dll")]
            static extern int PowerUnregisterSuspendResumeNotification(IntPtr RegistrationHandle);
            #endregion
    
            public int DeviceNotifyCallbackRoutine(IntPtr Context, int Type, IntPtr Setting)
            {
                string message =
                    Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
                    Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
                    Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC" : "other";
                textBox1.AppendText("notify: " + message + " in " + DateTime.Now + "\r\n");
                Console.Beep();
                return ERROR_SUCCESS;
            }
    
            DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS parameters = null;
            int r2;
            IntPtr notify;
    
            public Form1()
            {
                InitializeComponent();
    
                
                if (main() == 1) { textBox1.AppendText("ERROR" + "\r\n"); }
    
            }
    
            private int main()
            {
                SYSTEM_POWER_CAPABILITIES spc;
                var r1 = CallNtPowerInformation(POWER_INFORMATION_LEVEL.SystemPowerCapabilities, IntPtr.Zero, 0, out spc, Marshal.SizeOf(typeof(SYSTEM_POWER_CAPABILITIES)));
                if (r1 != STATUS_SUCCESS)
                {
                    textBox1.AppendText("CallNtPowerInformation failed: NTSTATUS " + r1 + "\r\n");
                    return 1;
                }
                if (!spc.AoAc)
                {
                    textBox1.AppendText("connected standby not supportted.\n");
                    return 1;
                }
    
                parameters = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS { Callback = DeviceNotifyCallbackRoutine };
                
                r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK, parameters, out notify);
                if (r2 != ERROR_SUCCESS)
                {
                    textBox1.AppendText("PowerRegisterSuspendResumeNotification failed." + "\r\n");
                    return 1;
                }
                //Console.ReadKey();
                return 0;
            }
    
            private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                r2 = PowerUnregisterSuspendResumeNotification(notify);
                //GC.KeepAlive(parameters);
                if (r2 != ERROR_SUCCESS)
                {
                    Console.WriteLine("PowerUnregisterSuspendResumeNotification failed.");
                    return;
                }
                return;
    
            }
        }
    }
    
    // 2015H27/11/09 MON
    // 2015H27/11/20 14:13

    フォームアプリケーションへの移植のとき、思考ループしました。タブレット上だけ、ウィンドウが出なくなり、苦慮しました。自分で付け加えたConsole.ReadKey();が原因で、キーを拾わず見た目応答なしでした。

    では。お世話になりました。





    2015年11月10日 5:40
  • あれ、スリープと休止の判別が…できません。次の新しいコールバックの発生時点で以前のがわかる形ですか?

    肝心なところでした。ごめんなさい、どこで捕まえればいいのかわかりません。

            public int DeviceNotifyCallbackRoutine(IntPtr Context, int Type, IntPtr Setting)
            {
                string message =
                    Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" :
                    Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" :
                    Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC" : "other";
                textBox1.AppendText("notify: " + message + " in " + DateTime.Now + "\r\n");
                if (Type == PBT_APMSUSPEND) { encount = 1; }
                if (Type == PBT_APMRESUMEAUTOMATIC) { encount = 2; }
                if (Type == PBT_APMRESUMESUSPEND) { encount = 3; }
                textBox1.AppendText("encount: " + encount.ToString() + "\n");
                Console.Beep();
                return ERROR_SUCCESS;
            }

    textBox1.AppendText("here: " + encount.ToString() + "\n");を書き込む場所を探しているのですが…。

    まさに『意見を述べる前に……コードを書け』ですね。我ながらつくづく、わかりなさいというはなしです。





    2015年11月11日 8:04
  • あれ、スリープと休止の判別が…できません。次の新しいコールバックの発生時点で以前のがわかる形ですか?

    これは「Windows8.1タブレットでの、InstantGoの(スリープ?&レジュームの)検出について」とは別の質問ですよね? InstantGoではない従来のスリープ・休止のイベントについては回答には含んでいません。

    意地悪で言っているのではなく、InstantGoを扱うAPIについてが議論の対象でしたし、(間接的ではありますが)前スレッドで通常のイベントとInstantGoのイベントを共通化できない旨を言及しています。

    2015年11月13日 8:13
  • >あれ、スリープと休止の判別が…できません。次の新しいコールバックの発生時点で以前のがわかる形ですか?

    これは「Windows8.1タブレットでの、InstantGoの(スリープ?&レジュームの)検出について」とは別の質問ですよね? InstantGoではない従来のスリープ・休止のイベントについては回答には含んでいません。

    意地悪で言っているのではなく、InstantGoを扱うAPIについてが議論の対象でしたし、(間接的ではありますが)前スレッドで通常のイベントとInstantGoのイベントを共通化できない旨を言及しています。

    返答感謝です。重ね重ね深く感謝いたす次第です。

    ”誤解です”、

    InstantGOでの、スリープと休止です。(休止に関して~ レジストリを書き換えるとInstantGOが無効になるんですが、そのときに休止状態という項目が電源メニューに出てきます。それがなんとレジストリを戻しても、出たままですし機能もする状態のままになるのです。で、ですが、その休止状態というメニューがあって、それを使わないでくださいというようにはいかないだろうということで、その”休止状態”という電源メニュー項目を使った時のコードを作成しています)。その(InstantGO有効時の)休止もきちんと検知できますが、…ん~と、詳しく書きますね。(日時が追加されています)

    (スリープから復帰時には:)
    notify: PBT_APMSUSPEND in 2015/11/13 21:53:51
    notify: PBT_APMRESUMEAUTOMATIC in 2015/11/13 21:53:53
    notify: PBT_APMRESUMESUSPEND in 2015/11/13 21:53:53

    (休止状態から復帰時には:)
    notify: PBT_APMSUSPEND in 2015/11/13 21:54:07
    notify: PBT_APMRESUMEAUTOMATIC in 2015/11/13 21:54:44

    それぞれ上記にように表示されます。ここで、初めのPBT_APMSUSPENDは同じです入る時ですか。そして復帰時に、PBT_APMRESUMEAUTOMATICが来て(2番目)、最後にPBT_APMRESUMESUSPENDです(3番目)。ここですが、スリープの時はPBT_APMRESUMESUSPENDが来るのですが、休止状態の時には、PBT_APMRESUMESUSPENDが来ないという違いがあります。この両者を判別する方法なのです。CallBackが発生した、

    public int DeviceNotifyCallbackRoutine(IntPtr Context, int Type, IntPtr Setting)
    {}
    この中でないと制御できるところはないですよね?次(3)が来ないことは次のCallBackの時にPBT_APMSUSPEND(1)が来てみてからしか、わからないのではないかということです。

    ん?あれ?なんで(3)が来ないんだろう……。そもそもそこを考えていませんでした……ん、



    2015年11月13日 13:58
  • 追記です。

    デスクトップ用でのプログラムは、

    // checkpowers1a_cs.cs
    
    class MyProgram { 
    
    	private System.DateTime _sleeptime;
    	private System.DateTime _waketime;
    	private System.TimeSpan _sleeps;			// this is total sleeps.
    
    	void vAdd()
    	{
    		Microsoft.Win32.SystemEvents.PowerModeChanged +=
    			new Microsoft.Win32.PowerModeChangedEventHandler(
    				SystemEvents_PowerModeChanged);
    
    	}
    
    	public void vDelete()
    	{
    		Microsoft.Win32.SystemEvents.PowerModeChanged -=
    			new Microsoft.Win32.PowerModeChangedEventHandler(
    				SystemEvents_PowerModeChanged);
    	}
    
    	private void SystemEvents_PowerModeChanged(object sender,
            Microsoft.Win32.PowerModeChangedEventArgs e)
        {
            switch (e.Mode)
            {
                case Microsoft.Win32.PowerModes.StatusChange:
                    System.Console.WriteLine("電源状態が変化。");
                    break;
                case Microsoft.Win32.PowerModes.Suspend:
        			_sleeptime = System.DateTime.Now;
                    System.Console.WriteLine("{0}に OSがサスペンド。", _sleeptime);
                    break;
                case Microsoft.Win32.PowerModes.Resume:
        			_waketime = System.DateTime.Now;
                    System.Console.WriteLine("{0}に OSがレジューム。", _waketime);
        			_sleeps = _sleeps + (_waketime - _sleeptime);
        			System.Console.WriteLine("_sleeps: {0}", _sleeps);
                    break;
            }
    	}
    
    	static void Main() { 
    		System.Console.WriteLine("スリープまたは休止をし、少し待って復帰してください. ctrl+c で終了します. ");
    		var vobj = new MyProgram();
    		vobj.vAdd();
    		System.Console.ReadKey();		
    		vobj.vDelete();
    		System.Console.ReadKey();
    	} 
    }

    上記コードをデスクトップ(InstantGOなし)で実行した結果です、

    (デスクトップでの’休止状態’の実行結果:)

    スリープまたは休止をし、少し待って復帰してください. ctrl+c で終了します.
    2015/11/14 12:36:51に OSがサスペンド。
    2015/11/14 12:37:34に OSがレジューム。
    _sleeps: 00:00:43.2166303


    となります。しかしこのプログラムをInstantGO有効のタブレットで走らせると、

    (このプログラムを、タブレットで(InstantGO有効時に)、’休止状態’を実行した結果:)

    スリープまたは休止をし、少し待って復帰してください. ctrl+c で終了します.
    2015/11/14 13:03:05に OSがレジューム。
    _sleeps: 735915.13:03:05.2473896

    このプログラムでは休止状態は、”OSがサスペンド。”の検出ができていないのです。

    前返信で記させていただいたInstantGO用の検出プログラムの結果から、あちらは休止の検出はできているといえるのですが、判別がしえないとも……。

    よろしくお願いします。





    2015年11月14日 4:21
  • 次のコールバック時に(前回が)休止だったかスリープだったかを判別するコードを(コンソールで)書いてみましたが、もっと良い方法がないものかと……

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace instantgo5m { class instantgo5me { #region Interop const int STATUS_SUCCESS = 0x00000000; const int ERROR_SUCCESS = 0x00000000; const int PBT_APMSUSPEND = 0x0004; const int PBT_APMRESUMESUSPEND = 0x0007; const int PBT_APMRESUMEAUTOMATIC = 0x0012; const int DEVICE_NOTIFY_CALLBACK = 2; enum POWER_INFORMATION_LEVEL { SystemPowerPolicyAc, SystemPowerPolicyDc, VerifySystemPolicyAc, VerifySystemPolicyDc, SystemPowerCapabilities, SystemBatteryState, SystemPowerStateHandler, ProcessorStateHandler, SystemPowerPolicyCurrent, AdministratorPowerPolicy, SystemReserveHiberFile, ProcessorInformation, SystemPowerInformation, ProcessorStateHandler2, LastWakeTime, LastSleepTime, SystemExecutionState, SystemPowerStateNotifyHandler, ProcessorPowerPolicyAc, ProcessorPowerPolicyDc, VerifyProcessorPowerPolicyAc, VerifyProcessorPowerPolicyDc, ProcessorPowerPolicyCurrent, SystemPowerStateLogging, SystemPowerLoggingEntry, SetPowerSettingValue, NotifyUserPowerSetting, PowerInformationLevelUnused0, SystemMonitorHiberBootPowerOff, SystemVideoState, TraceApplicationPowerMessage, TraceApplicationPowerMessageEnd, ProcessorPerfStates, ProcessorIdleStates, ProcessorCap, SystemWakeSource, SystemHiberFileInformation, TraceServicePowerMessage, ProcessorLoad, PowerShutdownNotification, MonitorCapabilities, SessionPowerInit, SessionDisplayState, PowerRequestCreate, PowerRequestAction, GetPowerRequestList, ProcessorInformationEx, NotifyUserModeLegacyPowerEvent, GroupPark, ProcessorIdleDomains, WakeTimerList, SystemHiberFileSize, ProcessorIdleStatesHv, ProcessorPerfStatesHv, ProcessorPerfCapHv, ProcessorSetIdle, LogicalProcessorIdling, UserPresence, PowerSettingNotificationName, GetPowerSettingValue, IdleResiliency, SessionRITState, SessionConnectNotification, SessionPowerCleanup, SessionLockState, SystemHiberbootState, PlatformInformation, PdcInvocation, MonitorInvocation, FirmwareTableInformationRegistered, SetShutdownSelectedTime, SuspendResumeInvocation, PlmPowerRequestCreate, ScreenOff, CsDeviceNotification, PlatformRole, LastResumePerformance, DisplayBurst, ExitLatencySamplingPercentage, RegisterSpmPowerSettings, PlatformIdleStates, ProcessorIdleVeto, PlatformIdleVeto, SystemBatteryStatePrecise, ThermalEvent, PowerInformationLevelMaximum } enum SYSTEM_POWER_STATE { PowerSystemUnspecified = 0, PowerSystemWorking = 1, PowerSystemSleeping1 = 2, PowerSystemSleeping2 = 3, PowerSystemSleeping3 = 4, PowerSystemHibernate = 5, PowerSystemShutdown = 6, PowerSystemMaximum = 7 } delegate int DEVICE_NOTIFY_CALLBACK_ROUTINE(IntPtr Context,
    int Type, IntPtr Setting); [StructLayout(LayoutKind.Sequential)] struct BATTERY_REPORTING_SCALE { public int Granularity; public int Capacity; } [StructLayout(LayoutKind.Sequential)] struct SYSTEM_POWER_CAPABILITIES { [MarshalAs(UnmanagedType.U1)] public bool PowerButtonPresent; [MarshalAs(UnmanagedType.U1)] public bool SleepButtonPresent; [MarshalAs(UnmanagedType.U1)] public bool LidPresent; [MarshalAs(UnmanagedType.U1)] public bool SystemS1; [MarshalAs(UnmanagedType.U1)] public bool SystemS2; [MarshalAs(UnmanagedType.U1)] public bool SystemS3; [MarshalAs(UnmanagedType.U1)] public bool SystemS4; [MarshalAs(UnmanagedType.U1)] public bool SystemS5; [MarshalAs(UnmanagedType.U1)] public bool HiberFilePresent; [MarshalAs(UnmanagedType.U1)] public bool FullWake; [MarshalAs(UnmanagedType.U1)] public bool VideoDimPresent; [MarshalAs(UnmanagedType.U1)] public bool ApmPresent; [MarshalAs(UnmanagedType.U1)] public bool UpsPresent; [MarshalAs(UnmanagedType.U1)] public bool ThermalControl; [MarshalAs(UnmanagedType.U1)] public bool ProcessorThrottle; public byte ProcessorMinThrottle; public byte ProcessorMaxThrottle; [MarshalAs(UnmanagedType.U1)] public bool FastSystemS4; [MarshalAs(UnmanagedType.U1)] public bool Hiberboot; [MarshalAs(UnmanagedType.U1)] public bool WakeAlarmPresent; [MarshalAs(UnmanagedType.U1)] public bool AoAc; [MarshalAs(UnmanagedType.U1)] public bool DiskSpinDown; public byte spare3_0; public byte spare3_1; public byte spare3_2; public byte spare3_3; public byte spare3_4; public byte spare3_5; public byte spare3_6; public byte spare3_7; [MarshalAs(UnmanagedType.U1)] public bool SystemBatteriesPresent; [MarshalAs(UnmanagedType.U1)] public bool BatteriesAreShortTerm; public BATTERY_REPORTING_SCALE BatteryScale_0; public BATTERY_REPORTING_SCALE BatteryScale_1; public BATTERY_REPORTING_SCALE BatteryScale_2; public SYSTEM_POWER_STATE AcOnLineWake; public SYSTEM_POWER_STATE SoftLidWake; public SYSTEM_POWER_STATE RtcWake; public SYSTEM_POWER_STATE MinDeviceWakeState; public SYSTEM_POWER_STATE DefaultLowLatencyWake; } [StructLayout(LayoutKind.Sequential)] class DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS { public DEVICE_NOTIFY_CALLBACK_ROUTINE Callback; public IntPtr Context; } [DllImport("PowrProf.dll")] static extern int CallNtPowerInformation(
    POWER_INFORMATION_LEVEL InformationLevel, IntPtr InputBuffer,
    int InputBufferLength, out SYSTEM_POWER_CAPABILITIES OutputBuffer,
    int OutputBufferLength); [DllImport("PowrProf.dll")] static extern int PowerRegisterSuspendResumeNotification(
    int Flags, DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS Recipient,
    out IntPtr RegistrationHandle); [DllImport("PowrProf.dll")] static extern int PowerUnregisterSuspendResumeNotification(
    IntPtr RegistrationHandle); #endregion static int encount = 0; static int previous = 0; static string msg, mode; public static int DeviceNotifyCallbackRoutine(
    IntPtr Context, int Type, IntPtr Setting) { string message = Type == PBT_APMSUSPEND ? "PBT_APMSUSPEND" : Type == PBT_APMRESUMESUSPEND ? "PBT_APMRESUMESUSPEND" : Type == PBT_APMRESUMEAUTOMATIC ? "PBT_APMRESUMEAUTOMATIC" : "other"; if (Type == PBT_APMSUSPEND)
    { msg = "\r\nnotify: " + message + " in " + DateTime.Now + "\r\n"; } else { msg = "notify: " + message + " in " + DateTime.Now + "\r\n"; } if (Type == PBT_APMSUSPEND)
    {
    previous = encount;
    if (previous == 2)
    {
    mode = "休止でした." + "\r\n"; Console.Write(mode);
    } else if (previous == 3)
    {
    mode = "スリープでした." + "\r\n"; Console.Write(mode);
    }
    encount = 1;
    } if (Type == PBT_APMRESUMEAUTOMATIC) { encount = 2; } if (Type == PBT_APMRESUMESUSPEND) { encount = 3; } Console.Write(msg); Console.Beep(); return ERROR_SUCCESS; } static DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS parameters = null; static int r2; static IntPtr notify; static int Main(string[] args) { SYSTEM_POWER_CAPABILITIES spc; var r1 = CallNtPowerInformation(
    POWER_INFORMATION_LEVEL.SystemPowerCapabilities, IntPtr.Zero, 0,
    out spc, Marshal.SizeOf(typeof(SYSTEM_POWER_CAPABILITIES))); if (r1 != STATUS_SUCCESS) { Console.WriteLine("CallNtPowerInformation failed: NTSTATUS {0:D}.",
    r1); return 1; } if (!spc.AoAc) { Console.WriteLine("connected standby not supportted.\n"); return 1; } parameters = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
    { Callback = DeviceNotifyCallbackRoutine }; //IntPtr notify; r2 = PowerRegisterSuspendResumeNotification(DEVICE_NOTIFY_CALLBACK,
    parameters, out notify); if (r2 != ERROR_SUCCESS) { Console.WriteLine("PowerRegisterSuspendResumeNotification failed."); return 1; } Console.ReadKey(); r2 = PowerUnregisterSuspendResumeNotification(notify); //GC.KeepAlive(parameters); if (r2 != ERROR_SUCCESS) { Console.WriteLine("PowerUnregisterSuspendResumeNotification failed."); return 1; } return 0; } } }









    2015年11月16日 11:21