スキップしてメイン コンテンツへ

 none
Windows10における、GetLastInputInfo関数(User32API)について RRS feed

  • 質問

  • はじめまして。
    Windows10(x64)、VB2010Expressの環境で、Windowsアプリケーションを開発しております。
    (対象プラットフォームはx86、.Net Framework3.5 Client Profile)

    その中で、アイドル時間を見て処理をする/しないを判断している部分があるのですが、GetLastInputInfo関数で取得できるLASTINPUTINFO構造体のdwTimeの値が、常にSystem.Environment.TickCountと同じ値を返しているようで、TickCountとdwTimeの差で経過時間を取得できずに困っています。
    自分なりに調べたところ、セッション0分離の情報はあったのですが、当方が作成しているのはサービスではなく、UIを持った単体のWindowsアプリなので、セッションIDは0ではありません。
    なお、Windows7(x86/x64)、WIndows8.1upd(x64)では正常に動作する(dwTimeを取得できる)ことを確認済みです。

    Windows10においては、Win32APIの使用に何か制限があったりするのでしょうか?
    32ビットアプリや、.Net Framework3.5についての制限はなさそうだったのですが・・・

    何かご存じな方、同様の現象を経験された方がいらっしゃれば、ご回答ください。
    現在、社内で新規に購入するPCについてはWindows10を選択し、順次移行していく方向になっており、この問題がWindows10の制限で、その制限がGetLastInputInfo関数に限った制限ではない場合は、配布済の他のアプリケーションにおいても見直しが必要ということになりそうです。

    なお、ソースコードは以下の通りとなっています。
    もしコードに問題があればご指摘下さい。
    よろしくお願い致します。

    Imports System.Runtime.InteropServices
    
    Namespace WinAPI
        Partial Public Class User32
            Public Const DLLName As String = "user32"
    
            <StructLayout(LayoutKind.Sequential)> _
            Structure LASTINPUTINFO
                Public cbSize As UInteger
                Public dwTime As UInteger
            End Structure
    
            <DllImport(DLLName)>
            Public Shared Function GetLastInputInfo( _
                ByRef plii As LASTINPUTINFO _
                ) As <MarshalAs(UnmanagedType.Bool)> Boolean
            End Function
        End Class
    End Namespace
    
    Public Class Form1
        Public Shared ReadOnly Property SystemTickSecconds As Integer
            Get
                Return (System.Environment.TickCount And Int32.MaxValue) \ 1000
            End Get
        End Property
    
        Public Shared ReadOnly Property ApplicationTickSecconds As Integer
            Get
                Return System.Convert.ToInt32(Now.Subtract(Process.GetCurrentProcess().StartTime).TotalSeconds)
            End Get
        End Property
    
        Public Shared ReadOnly Property CurrentUsersIdleSeccond As Integer
            Get
                Return SystemTickSecconds - (GetCurrentUserLastInputTickSeconds() \ 1000)
            End Get
        End Property
    
        Private Shared Function GetCurrentUserLastInputTickSeconds() As Integer
            Dim info As WinAPI.User32.LASTINPUTINFO
    
            info.cbSize = Marshal.SizeOf(info)
            If Not WinAPI.User32.GetLastInputInfo(info) Then Return 0
            Return info.dwTime Mod Int32.MaxValue
        End Function
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Try
                Timer1.Start()
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub
    
        Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
            Try
                TextBox1.Text = SystemTickSecconds
                TextBox2.Text = ApplicationTickSecconds
                TextBox3.Text = CurrentUsersIdleSeccond
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub
    End Class
    

        
    2016年6月26日 2:54

回答

  • 掲示のコードを手元の Windows 10(x64)で試しましたが、再現しません。

    おそらく、環境要因でしょう。仮想的なマウス入力・キー入力を与えるツールが常駐しているとか、ドライバーが悪いとか。(参考
    別の Windows 10 環境を用意して検証してみてください。

    ただ、そういった環境があると仮定した場合にもうまくいくアプローチと言われると難しいところはありますね。

    • 回答としてマーク do_minic 2016年6月26日 11:55
    2016年6月26日 10:56
    モデレータ

すべての返信

  • 掲示のコードを手元の Windows 10(x64)で試しましたが、再現しません。

    おそらく、環境要因でしょう。仮想的なマウス入力・キー入力を与えるツールが常駐しているとか、ドライバーが悪いとか。(参考
    別の Windows 10 環境を用意して検証してみてください。

    ただ、そういった環境があると仮定した場合にもうまくいくアプローチと言われると難しいところはありますね。

    • 回答としてマーク do_minic 2016年6月26日 11:55
    2016年6月26日 10:56
    モデレータ
  • Azulean様
    回答ありがとうございます。
     
    ご助言により以下を試したところ、原因が掴めました。
    ①マウスフック、キーフックでメッセージ監視⇒異常なし
    ②OSの動作に直接関係ないプロセスを順次kill⇒現象変わらず
    ③キーボード、マウスを含む接続機器を1つずつ外す⇒判明!
     
    EARINというワイヤレスイヤホンの、収納ケース兼充電器がUSB給電なので、常時接続状態にしていたのですが、これを外したら正しいdwTimeを取得できました。
    正直、考えもしませんでした・・・
    ワイヤレスマウスは誤検出を疑ってOFFにしてみたりしてたのですが。
     
    本当に助かりました。
    ドライバーというキーワードを頂いて、ハードを疑うことができました。
    ありがとうございました。
    2016年6月26日 11:54