Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从Windows服务以编程方式锁定工作站_C#_Visual Studio 2015_Windows Services - Fatal编程技术网

C# 从Windows服务以编程方式锁定工作站

C# 从Windows服务以编程方式锁定工作站,c#,visual-studio-2015,windows-services,C#,Visual Studio 2015,Windows Services,在我的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) } 但是上面的

在我的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)
}
但是上面的代码不起作用


有人对此有解决方案吗?

您不能从Windows服务中执行此操作,因为它清楚地说明,此API函数只能从交互式桌面中运行的进程调用。Windows服务未在交互式桌面中运行


若必须这样做,则应首先检查用户是否已登录,然后在要锁定的inpersonating用户下生成进程。但在我看来,这是一个相当老套的解决方案。也许更好的解决方案是在用户登录时启动隐藏或托盘应用程序,然后从该应用程序执行作业。

Windows服务不在桌面上运行,因此您无法从该服务调用它

从文档中,强调我的:

LockWorkStation功能只能由交互式桌面上运行的进程调用。此外,用户必须登录,并且工作站不能已经锁定

这可能是一种黑客行为,但您可以创建一个托盘应用程序,该应用程序可以响应来自服务的某种进程间调用,调用
LockWorkStation

如果您不喜欢托盘应用程序的可见性质,请考虑创建一个控制台应用程序,该程序生成线程等待调用,并在用户登录时运行无窗口。 另一种可能是创建一个从不创建UI窗口的Windows应用程序。如果您使用API,这绝对是您想要做的

这里的关键是,某些东西必须在用户的交互上下文中运行

作为参考,您可以查看。

您可以使用Windows API执行此操作,它将以与LockWorkStation相同的方式注销用户

但是,由于该服务处于特殊会话中,您不能仅断开WTS_当前_会话,而必须断开计算机上的每个活动会话

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);
    }
}
使用系统;
使用System.Runtime.InteropServices;
公营锁具工作站
{
[DllImport(“wtsapi32.dll”,SetLastError=true)]
静态外部bool-WTSDisconnectSession(IntPtr-hServer、int-sessionId、bool-bWait);
[DllImport(“wtsapi32.dll”,SetLastError=true)]
静态外部int WTSEnumeratessions(IntPtr hServer、int Reserved、int Version、ref IntPtr ppSessionInfo、ref int pCount);
[DllImport(“wtsapi32.dll”)]
静态外部无效WTSFreeMemory(IntPtr pMemory);
[StructLayout(LayoutKind.Sequential)]
私有结构WTS\u会话\u信息
{
公共Int32会话ID;
[Marshallas(UnmanagedType.LPStr)]
公共字符串pInstallationName;
公共WTS_CONNECTSTATE_CLASS State;
}
私有枚举WTS_信息_类
{
中国程序,
WTS应用程序名称,
WTSWorkingDirectory,
WTSOEMId,
WTSSessionId,
苏瑟南,
WTSWinStationName,
WTSDomainName,
WTS连接状态,
WTSClientBuildNumber,
WTSClientName,
WTSClientDirectory,
WTSClientProductId,
WTSClientHardwareId,
WTSClientAddress,
WTSClientDisplay,
WTSClientProtocolType
}
私有枚举WTS_连接状态_类
{
是的,
WTS连接,
WTSConnectQuery,
WTSShadow,
WTS断开连接,
西德尔,
WTSListen,
WTSReset,
WTSDown,
WTSInit
}
公共静态无效锁定工作站()
{
IntPtr ppSessionInfo=IntPtr.Zero;
Int32计数=0;
Int32 retval=WTSEnumerateSessions(IntPtr.Zero,0,1,ref-ppSessionInfo,ref-count);
Int32 dataSize=Marshal.SizeOf(typeof(WTS_SESSION_INFO));
IntPtr currentSession=ppSessionInfo;
如果(retval==0)返回;
for(int i=0;i
除了创建托盘应用程序,还有其他解决方案吗?如果可能,请给我一个链接。我用另一个选项更新了我的答案。我不认为你可以从服务中生成一个应用程序,如果可以的话,它可能会像Antonio提到的那样更加黑客。为了澄清,我可以在windows服务下调用控制台应用程序吗?你可以使用某种形式的IPC调用控制台应用程序或无头win32进程。搜索“windows进程间通信”以获得一些想法。更奇特的可能是消息总线或使用套接字,但这可能有些过分,因为您知道进程在同一台机器上。你可以做一些超级黑客的事情,比如在控制台应用程序中实现一个文件监视程序,监视服务删除文件,但这有点笨重。可能不是控制台应用程序,因为它们是可见的。(即使您立即隐藏控制台,它仍然会短暂弹出。)它们也会使用更多资源。最好将其配置为Windows应用程序,然后永远不要创建任何窗口。如果我没有将您的标记为正确答案,我很抱歉,但我会给您投票。在用户会话中启动进程以代表您工作是一项相当成熟的技术。我不会称之为黑客。(与使用在每个用户会话中永久运行的应用程序相比,有几个优点,最重要的可能是没有真正可靠的方法来做到这一点。)并不意味着在用户会话中启动过程是一种黑客行为。我说的是从服务中锁定用户会话,将更新我的回答你确定这与Windows+L相同吗?@JobaDiniz这与在每个打开的服务器上执行Windows+L相同