Как заблокировать рабочую станцию ​​от службы Windows? - PullRequest
3 голосов
/ 18 марта 2010

Мне нужно заблокировать рабочую станцию ​​из службы Windows, написанной на VB.Net.Я пишу приложение для Windows 7, но оно также должно работать в Vista и XP.

User32 API LockWorkStation не работает, так как для него требуется интерактивный рабочий стол, и я получаю возвращаемое значение 0.

Я пытался вызвать% windir% \ System32 \ rundll32.exe user32.dll, LockWorkStation как из процесса, так и из оболочки, но все равно ничего не происходит.

Настройка службы для взаимодействия с рабочим столом не требуется.Если я запускаю службу под учетной записью администратора, она может выполнять некоторые другие действия, требующие прав администратора, например отключение сети, и вы можете выбрать только вариант взаимодействия с рабочим столом, если он работает под учетной записью локальной системы.

Это был бы второстепенный вопрос - как запустить другое приложение с правами администратора из службы, работающей под учетной записью локальной системы, без ошибок пользователя.

Я пишу приложение для управления доступом моих детей к компьютеру / интернету (который япланирую открыть исходники, когда закончу), поэтому мне нужно, чтобы все происходило как можно более незаметно.

У меня есть пользовательский интерфейс, который обрабатывает настройки и уведомления о состоянии на панели задач, но его легко убить и, таким образом, снять блокировку.Я мог бы сделать еще одно скрытое приложение Windows Forms, чтобы справиться с блокировкой, но это кажется довольно неуместным решением.

У кого-нибудь получше?

Ответы [ 5 ]

5 голосов
/ 15 января 2015

Я боролся с этим в течение недели, и после прочтения большого количества информации об этой проблеме, наконец-то получил решение для этого ...

Вы должны использовать функцию 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

Получил большую часть кода из здесь , где вы также можете найти WindowsApi для использования с этой функцией. Я все еще пытаюсь найти, если можно избежать файла bat, но по крайней мере это очень приличное решение.

EDIT: Чтобы не использовать внешний файл * .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

И теперь вы можете использовать stringbuilder в качестве аргумента thrid (comandline) для функции CreateProcessAsUser и поместить второй (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)

И это будет РАБОТАТЬ !!!!

С уважением, AP

2 голосов
/ 18 марта 2010

То, что вы пытаетесь сделать, активно блокируется Microsoft - если вы все же заработаете, это будет использовать лазейку, которая наверняка скоро закроется.

Что вы можете сделать, так это решение Friar Tuck / Robin Hood - запустить две программы и контролировать друг друга. Когда один из них убит, другой обнаруживает это и перезапускает (или просто выводит текущего пользователя из строя в качестве наказания, в зависимости от того, насколько серьезным вы хотите, чтобы это было).

1 голос
/ 18 марта 2010

Другое не элегантное решение (но без недостатков сигнализации вашего приложения пользовательского интерфейса) состоит в том, чтобы установить другую службу для взаимодействия с рабочим столом, задачей которой является прослушивание сигнала для блокировки рабочего стола.

Я согласен с тем, что не очень хорошо работать с учетными данными локальной системы, но если все, что делает служба, это блокирует рабочий стол, то это довольно маленькая площадь, требующая защиты.

0 голосов
/ 20 марта 2010

Я не полностью удовлетворен своим ответом, но безопасность Окна оставляет мне небольшую альтернативу. Все, что открыто в сервисе (через Process, Shell и т. Д.), Не будет иметь доступа к рабочему столу. Я понимаю причины ограничений, которые Microsoft создала, но все же расстраивает!

Моя служба использует IPC, чтобы сообщить моему пользовательскому интерфейсу о блокировке компьютера. Вот основная ссылка на это:

http://anoriginalidea.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 на стороне сервера является первой частью пути IPC в вызове метода GetObject. Вторая часть сопоставляется со вторым параметром вызова RegisterWellKnownServiceType на стороне сервера.

И, очевидно, свойства portName должны быть РАЗЛИЧНЫМИ на стороне сервера и на стороне клиента.

Если вы получили сообщение «Не удалось подключиться к порту IPC: система не может найти указанный файл». на вашем клиенте сервер еще не запущен, так что вам нечего кричать.

0 голосов
/ 18 марта 2010

Вы можете попытаться запустить заставку из службы Windows, которая автоматически блокирует рабочую станцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...