2016-07-26 3 views
0

С моей службы Windows я пытаюсь заблокировать свою рабочую станцию, используя следующий код:Программной Блокировка рабочей станции от службы 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) 
} 

но выше код не работает.

У кого-нибудь есть решение для этого?

ответ

1

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

Из документации LockWorkStation, внимание шахта:

Функция LockWorkStation является отозваны только процессами, запущенными на интерактивном рабочем столе. Кроме того, пользователь должен войти в систему, а рабочая станция уже не может быть заблокирована.

Это может быть хак, но, может быть, вы могли бы создать приложение лоток, который может, в ответ на какой-то межпроцессного звонок от службы, позвоните LockWorkStation.

Если вам не нравится, видимая природа приложения в трее, рассмотреть вопрос о создании консольного приложения, которое порождает поток ждать вызова, и работает без окон, когда пользователь входит в системе.

Другой возможность создания приложение Windows, которое никогда не создает окно пользовательского интерфейса. Это определенно то, что вы хотите сделать, если используете API data copy.

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

Для справки вы можете посмотреть Microsoft's MSDN topic on IPC.

+0

есть ли какое-либо решение для этого, кроме создания приложения в лотке? пожалуйста, дайте мне ссылку, если это возможно. – Polar

+0

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

+0

Для уточнения, могу ли я вызвать консольное приложение под службой Windows? – Polar

3

Вы не можете сделать это из службы Windows, четко изложив в documentation, что эту функцию API можно вызывать только из процесса, запущенного на интерактивном рабочем столе. Службы Windows не работают в интерактивном рабочем столе.

Если вы должны сделать это, вы должны сначала проверить, вошел ли пользователь в систему, а затем запустить процесс под именем пользователя, который вы хотите заблокировать. Но это кажется мне довольно хакерским решением. Возможно, лучшим решением будет запуск скрытого или лот-приложения при входе пользователя в систему, а затем выполнение задания из этого приложения.

+0

Прошу прощения, если я не поставил ваше мнение как правильный ответ, но я дам вам свой голос. – Polar

+0

Запуск процесса на сеансе пользователя для работы от вашего имени - довольно устоявшийся метод. Я бы не назвал это взломом. (Существует несколько преимуществ перед использованием приложения, которое работает постоянно на каждом сеансе пользователя, причем наиболее важным, вероятно, является то, что нет действительно надежного способа сделать это.) –

+0

не означает, что запуск процесса в сеансе пользователя является взломом.Я говорил о блокировке сеанса пользователя из службы, будет обновлять мой ответ –

1

Вы можете сделать это с помощью Windows API WTSDisconnectSession, он выйдет из системы так же, как это делает 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)); 
     Int32 currentSession = (int)ppSessionInfo; 

     if (retval == 0) return; 

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

спасибо. ваше решение работает идеально. – mannan

Смежные вопросы