如何从Windows服务锁定工作站?

Bra*_*ews 3 .net windows-services locking

我需要从用VB.Net编写的Windows服务锁定工作站.我在Windows 7上编写应用程序,但它也需要在Vista和XP下运行.

User32 API LockWorkStation不起作用,因为它需要一个交互式桌面,我的返回值为0.

我尝试从进程和Shell中调用%windir%\ System32\rundll32.exe user32.dll,LockWorkStation,但仍然没有任何反应.

将服务设置为与桌面交互是不行的,因为我在管理员帐户下运行服务,因此它可以执行一些需要管理员权限的其他内容 - 例如禁用网络,并且您只能选择与桌面交互选项如果在本地系统帐户下运行.

这将是次要问题 - 如何在本地系统帐户下运行的服务中运行具有管理员权限的另一个应用程序而不会引起用户烦扰.

我正在编写一个应用程序来控制我的孩子计算机/互联网访问(我计划在完成后开源)所以我需要尽可能隐秘地发生一切.

我有一个UI来处理任务栏中的设置和状态通知,但这很容易被杀死,从而打败锁定.我可以制作另一个隐藏的Windows窗体应用程序来处理锁定,但这似乎是一个相当不优雅的解决方案.

谁有更好的想法?

Adr*_*dro 5

我一直在与这个斗争一周,在阅读了很多关于这个问题的信息后,终于得到了解决方案......

您必须使用CreateProcessAsUser函数,如下所示:

  Private Shared Sub Executer(ByVal content As String)
    Dim objProcess As System.Diagnostics.Process

    Dim filename As String
    filename = "e:\lock.bat" 
    'create a bat file with ''rundll32.exe user32.dll,LockWorkStation'' inside

    Dim UserTokenHandle As IntPtr = IntPtr.Zero
    WindowsApi.WTSQueryUserToken(WindowsApi.WTSGetActiveConsoleSessionId, UserTokenHandle)

    Dim ProcInfo As New WindowsApi.PROCESS_INFORMATION
    Dim StartInfo As New WindowsApi.STARTUPINFOW
    StartInfo.cb = CUInt(Marshal.SizeOf(StartInfo))

    WindowsApi.CreateProcessAsUser(UserTokenHandle, filename, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, StartInfo, ProcInfo)
    If Not UserTokenHandle = IntPtr.Zero Then
        WindowsApi.CloseHandle(UserTokenHandle)
    End If

End Sub
Run Code Online (Sandbox Code Playgroud)

这里获得大部分代码,您也可以找到与此功能一起使用的WindowsApi.我仍然试图找到是否可以避免蝙蝠文件,但至少是一个非常体面的解决方案.

编辑:为避免使用外部*.bat文件来执行代码,只需编辑WindowsApi类并用以下代码替换CreateProcessAsUser和advapi32.dll导入部分:

    <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 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
Run Code Online (Sandbox Code Playgroud)

现在你可以使用stringbuilder作为CreateProcessAsUser函数的thrid参数(comandline),并将第二个(applicationame)作为'Nothing',如下所示:

Dim cmdline As New StringBuilder
cmdline.Append("rundll32.exe user32.dll,LockWorkStation")
WindowsApi.CreateProcessAsUser(UserTokenHandle, Nothing, cmdline, IntPtr.Zero, IntPtr.Zero, False, 0, IntPtr.Zero, Nothing, StartInfo, ProcInfo)
Run Code Online (Sandbox Code Playgroud)

它会工作!!!!

此致,AP


Bra*_*ews 0

我对我的回答并不完全满意,但 Window 的安全性让我别无选择。服务中打开的任何内容(通过 Process、Shell 等)都将无法访问桌面。我了解微软造成的限制背后的原因,但仍然令人沮丧!

我的服务使用 IPC 告诉我的 UI 锁定计算机。这是执行此操作的基本链接:

http://anoriginidea.wordpress.com/2007/08/09/simple-inter-process-communication-in-vbnet/

有关其他数据,请参阅他的参考链接。

然而,这仍然不太有效。另请参阅此链接,了解如何在没有“访问被拒绝”消息的情况下执行此操作:

http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/ce968b5b-04fe-46d2-bb75-73e367a8b0c3

确保您的 URI 正确。服务器端的 portName 属性是 GetObject 方法调用中 IPC 路径的第一部分。第二部分映射到服务器端 RegisterWellKnownServiceType 调用的第二个参数。

显然,服务器和客户端的 portName 属性需要不同。

如果出现“无法连接到 IPC 端口:系统找不到指定的文件。” 在您的客户端上,服务器尚未启动,因此听不到您的尖叫声。