ここしばらく、WindowsServiceからWindowsをシャットダウンするソフトを作っていましたが。
シャットダウンではなくて画面ロックでできないか、ということでやってみました。
<DllImport("Advapi32.dll", EntryPoint:="CreateProcessAsUser",
ExactSpelling:=False, SetLastError:=True, CharSet:=CharSet.Unicode)>
Public Shared Function CreateProcessAsUser(ByVal hToken As IntPtr,
ByVal lpApplicationName As String,
<[In](), Out(), [Optional]()> ByVal lpCommandLine As System.Text.StringBuilder,
ByVal lpProcessAttributes As IntPtr,
ByVal lpThreadAttributes As IntPtr,
<MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandles As Boolean,
ByVal dwCreationFlags As Integer,
ByVal lpEnvironment As IntPtr,
ByVal lpCurrentDirectory As String,
<[In]()> ByRef lpStartupInfo As STARTUPINFOW,
<Out()> ByRef lpProcessInformation As PROCESS_INFORMATION) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("Wtsapi32.dll", EntryPoint:="WTSQueryUserToken", SetLastError:=True)>
Public Shared Function WTSQueryUserToken(ByVal SessionId As UInteger,
ByRef phToken As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("kernel32.dll", EntryPoint:="WTSGetActiveConsoleSessionId", SetLastError:=True)>
Public Shared Function WTSGetActiveConsoleSessionId() As UInteger
End Function
<StructLayout(LayoutKind.Sequential)>
Public Structure STARTUPINFOW
Public cb As UInteger
<MarshalAs(UnmanagedType.LPWStr)>
Public lpReserved As String
<MarshalAs(UnmanagedType.LPWStr)>
Public lpDesktop As String
<MarshalAs(UnmanagedType.LPWStr)>
Public lpTitle As String
Public dwX As UInteger
Public dwY As UInteger
Public dwXSize As UInteger
Public dwYSize As UInteger
Public dwXCountChars As UInteger
Public dwYCountChars As UInteger
Public dwFillAttribute As UInteger
Public dwFlags As UInteger
Public wShowWindow As UShort
Public cbReserved2 As UShort
Public lpReserved2 As IntPtr
Public hStdInput As IntPtr
Public hStdOutput As IntPtr
Public hStdError As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential)>
Public Structure PROCESS_INFORMATION
Public hProcess As IntPtr
Public hThread As IntPtr
Public dwProcessId As UInteger
Public dwThreadId As UInteger
End Structure
ここまでが関数のインポート等です。
これを
Dim UserTokenHandle As IntPtr = IntPtr.Zero
WTSQueryUserToken(WTSGetActiveConsoleSessionId, UserTokenHandle)
Dim ProcInfo As New PROCESS_INFORMATION
Dim StartInfo As New STARTUPINFOW
StartInfo.cb = CUInt(Runtime.InteropServices.Marshal.SizeOf(StartInfo))
Dim cmdline As New System.Text.StringBuilder
cmdline.Append("rundll32.exe user32.dll,LockWorkStation")
CreateProcessAsUser(UserTokenHandle, Nothing, cmdline, IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, StartInfo, ProcInfo)
のようにWindowsService上で呼び出すことにより、画面をロックすることができました。
実際やってみると、シャットダウンよりも安定して動作するようなので、今回はこちらを採用しようかと思っています。シャットダウンは、ふいに動作しないことがあったので、少し不安が残るのです。