通过 Windows 服务以编程方式锁定工作站

Pol*_*lar 3 c# windows-services visual-studio-2015

从我的 Windows 服务中,我尝试使用以下代码锁定我的工作站:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LockWorkStation();

if (!LockWorkStation()){
 //Workstation was unable to lock(Write this on event log)
}
Run Code Online (Sandbox Code Playgroud)

但上面的代码不起作用。

有人有解决方案吗?

小智 5

您可以使用WTSDisconnectSession Windows API 来完成此操作,它将以与 LockWorkStation 相同的方式注销用户。

但是,由于该服务处于特殊会话中,因此您不能仅断开 WTS_CURRENT_SESSION 的连接,而必须断开计算机上每个活动会话的连接。

using System;
using System.Runtime.InteropServices;

public class LockWorkstation
{
    [DllImport("wtsapi32.dll", SetLastError = true)]
    static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);

    [DllImport("wtsapi32.dll", SetLastError = true)]
    static extern int WTSEnumerateSessions(IntPtr hServer, int Reserved, int Version, ref IntPtr ppSessionInfo, ref int pCount);

    [DllImport("wtsapi32.dll")]
    static extern void WTSFreeMemory(IntPtr pMemory);

    [StructLayout(LayoutKind.Sequential)]
    private struct WTS_SESSION_INFO
    {
        public Int32 SessionID;

        [MarshalAs(UnmanagedType.LPStr)]
        public String pWinStationName;

        public WTS_CONNECTSTATE_CLASS State;
    }

    private enum WTS_INFO_CLASS
    {
        WTSInitialProgram,
        WTSApplicationName,
        WTSWorkingDirectory,
        WTSOEMId,
        WTSSessionId,
        WTSUserName,
        WTSWinStationName,
        WTSDomainName,
        WTSConnectState,
        WTSClientBuildNumber,
        WTSClientName,
        WTSClientDirectory,
        WTSClientProductId,
        WTSClientHardwareId,
        WTSClientAddress,
        WTSClientDisplay,
        WTSClientProtocolType
    }

    private enum WTS_CONNECTSTATE_CLASS
    {
        WTSActive,
        WTSConnected,
        WTSConnectQuery,
        WTSShadow,
        WTSDisconnected,
        WTSIdle,
        WTSListen,
        WTSReset,
        WTSDown,
        WTSInit
    }

    public static void LockWorkStation()
    {
        IntPtr ppSessionInfo = IntPtr.Zero;
        Int32 count = 0;
        Int32 retval = WTSEnumerateSessions(IntPtr.Zero, 0, 1, ref ppSessionInfo, ref count);
        Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
        IntPtr currentSession = ppSessionInfo;

        if (retval == 0) return;

        for (int i = 0; i < count; i++)
        {
            WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure(currentSession, typeof(WTS_SESSION_INFO));
            if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive) WTSDisconnectSession(IntPtr.Zero, si.SessionID, false);
            currentSession += dataSize;
        }
        WTSFreeMemory(ppSessionInfo);
    }
}
Run Code Online (Sandbox Code Playgroud)