vlary
Platinum Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору blackCbI4 Дабы не прослыть безответственным человеком, вот программа: Код: using System; using System.Diagnostics; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace TSShut { class Program { [DllImport("wtsapi32.dll")] static extern IntPtr WTSOpenServer([MarshalAs(UnmanagedType.LPStr)] String pServerName); [DllImport("wtsapi32.dll")] static extern void WTSCloseServer(IntPtr hServer); [DllImport("wtsapi32.dll")] static extern void WTSLogoffSession(IntPtr hServer, int sessionId, bool wait); [DllImport("wtsapi32.dll")] static extern Int32 WTSEnumerateSessions( IntPtr hServer, [MarshalAs(UnmanagedType.U4)] Int32 Reserved, [MarshalAs(UnmanagedType.U4)] Int32 Version, ref IntPtr ppSessionInfo, [MarshalAs(UnmanagedType.U4)] ref Int32 pCount); [DllImport("wtsapi32.dll")] static extern void WTSFreeMemory(IntPtr pMemory); [DllImport("Wtsapi32.dll")] static extern bool WTSQuerySessionInformation( System.IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned); [StructLayout(LayoutKind.Sequential)] private struct WTS_SESSION_INFO { public Int32 SessionID; [MarshalAs(UnmanagedType.LPStr)] public String pWinStationName; public WTS_CONNECTSTATE_CLASS State; } public enum WTS_INFO_CLASS { WTSInitialProgram, WTSApplicationName, WTSWorkingDirectory, WTSOEMId, WTSSessionId, WTSUserName, WTSWinStationName, WTSDomainName, WTSConnectState, WTSClientBuildNumber, WTSClientName, WTSClientDirectory, WTSClientProductId, WTSClientHardwareId, WTSClientAddress, WTSClientDisplay, WTSClientProtocolType } public enum WTS_CONNECTSTATE_CLASS { WTSActive, WTSConnected, WTSConnectQuery, WTSShadow, WTSDisconnected, WTSIdle, WTSListen, WTSReset, WTSDown, WTSInit } public static IntPtr serverHandle = IntPtr.Zero; static void Main(string[] args) { if (args.Length == 0 ) { Console.WriteLine("No server specified!"); return; } string tsserv = args[0]; if (tsserv.Length < 2) { Console.WriteLine("No server specified!"); return; } serverHandle = OpenServer(tsserv); if (serverHandle == IntPtr.Zero) { Console.WriteLine("Cannot find server " + tsserv); return; } if(GetActiveUsers()==0) Process.Start("shutdown.exe", "-s -t 00"); } public static IntPtr OpenServer(String Name) { IntPtr server = WTSOpenServer(Name); return server; } public static void CloseServer(IntPtr ServerHandle) { WTSCloseServer(ServerHandle); } public static int GetActiveUsers() { int activeusers =-1; try { IntPtr SessionInfoPtr = IntPtr.Zero; IntPtr userPtr = IntPtr.Zero; IntPtr domainPtr = IntPtr.Zero; Int32 sessionCount = 0; Int32 retVal = WTSEnumerateSessions(serverHandle, 0, 1, ref SessionInfoPtr, ref sessionCount); Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); Int32 currentSession = (int)SessionInfoPtr; uint bytes = 0; if (retVal != 0) { activeusers = 0; for (int i = 0; i < sessionCount; i++) { string user; WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(WTS_SESSION_INFO)); currentSession += dataSize; WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes); WTSQuerySessionInformation(serverHandle, si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes); user = Marshal.PtrToStringAnsi(userPtr); if (user.Length == 0 ) continue; if(si.State == WTS_CONNECTSTATE_CLASS.WTSActive) activeusers++; else WTSLogoffSession(serverHandle, si.SessionID, false); // Console.WriteLine("Domain and User: " + Marshal.PtrToStringAnsi(domainPtr) + "\\" + user); } WTSFreeMemory(SessionInfoPtr); } } finally { CloseServer(serverHandle); } return activeusers; } } } | Копируешь ее в файл с названием tssutdown.cs Для ее компиляции создаешь батничег: Код: @echo off set NETCF_PATH=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 if DEFINED REF ( set REF= ) set REF=%REF% "/r:%NETCF_PATH%\Mscorlib.dll" set REF=%REF% "/r:%NETCF_PATH%\System.dll" set REF=%REF% "/r:%NETCF_PATH%\System.Security.dll" %NETCF_PATH%\csc -nostdlib -noconfig /target:exe /out:tsshutdown.exe %REF% tsshutdown.cs | Называешь его, скажем, compile.bat, и кладешь в ту же директорию. Ищешь на компе (можно сразу на сервере компилить) где Microsoft.NET Framework 2.0, и поправляешь батник, если она не там, как написано в нем. Заходишь в директорию с батником и прогой, запускаешь батник, в результате имеешь файл tsshutdown.exe Его ставишь в планировщик, в качестве параметра указываешь айпи сервера. Запускаешь под юзером с административными правами.
---------- Заслуженный SCOтовод, почетный SUNтехник и любитель Кошек |
|