public static DialogResult LogoffUser(RemoteLogonSession windowsUser) { // LogoffUser() forces the selected user to logoff. // It returns a DialogResult which will be used to display the results. var dialog = new DialogResult(); bool didTaskSucceed = false; if (IsServerEdition) { try { IntPtr server = WtsApi.WTSOpenServer(ComputerName); if (WtsApi.LogOffUser(server, Convert.ToInt32(windowsUser.SessionId), windowsUser.Username) == true) { didTaskSucceed = true; } } catch { } } else { // Setup WMI query. var options = new ConnectionOptions(); if (GlobalVar.UseAlternateCredentials) { options.Username = GlobalVar.AlternateUsername; options.Password = GlobalVar.AlternatePassword; options.Authority = $"NTLMDOMAIN:{GlobalVar.AlternateDomain}"; } var scope = new ManagementScope($@"\\{ComputerName}\root\CIMV2", options); var query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem"); var searcher = new ManagementObjectSearcher(scope, query); try { foreach (ManagementObject m in searcher.Get()) { ManagementBaseObject inParams = m.GetMethodParameters("Win32Shutdown"); inParams["Flags"] = 4; ManagementBaseObject outParams = m.InvokeMethod("Win32Shutdown", inParams, null); int returnValue; bool isReturnValid = int.TryParse(outParams["ReturnValue"].ToString(), out returnValue); if (isReturnValid && returnValue == 0) { didTaskSucceed = true; } break; } } catch { } } if (didTaskSucceed) { // User has been logged off. Build DialogResult to reflect success. dialog.DialogTitle = "Success"; dialog.DialogBody = $"{windowsUser.Username} has been logged off. It might take a few minutes for the target user to be fully logged out."; dialog.DialogIconPath = "/Resources/success-48.png"; dialog.ButtonIconPath = "/Resources/checkmark-24.png"; dialog.ButtonText = "OK"; dialog.IsCancelVisible = false; } else { // Error logging off user. Build DialogResult to reflect failure. dialog.DialogTitle = "Error"; dialog.DialogBody = $"Failed to logoff {windowsUser.Username}."; dialog.DialogIconPath = "/Resources/error-48.png"; dialog.ButtonIconPath = "/Resources/checkmark-24.png"; dialog.ButtonText = "OK"; dialog.IsCancelVisible = false; } return(dialog); }
public static List <RemoteLogonSession> GetLogonSessions() { // GetProcesses() first uses WMI to determine if the target computer is running a desktop or server OS. // If running a server OS, it uses the Remote Desktop Service API to retrieve logon sessions. // If running a desktop OS, it uses WMI to retrieve logon sessions. // It returns a List of RemoteLogonSession which will be bound to a DataGrid on this UserControl. var logonSessions = new List <RemoteLogonSession>(); var taskResult = new TaskResult(); Result = taskResult; UInt32 productType = 1; // Determine whether operating system is server or desktop edition. var options = new ConnectionOptions(); if (GlobalVar.UseAlternateCredentials) { options.Username = GlobalVar.AlternateUsername; options.Password = GlobalVar.AlternatePassword; options.Authority = $"NTLMDOMAIN:{GlobalVar.AlternateDomain}"; } var scope = new ManagementScope($@"\\{ComputerName}\root\CIMV2", options); var query = new ObjectQuery("SELECT ProductType FROM Win32_OperatingSystem"); var searcher = new ManagementObjectSearcher(scope, query); try { foreach (ManagementObject m in searcher.Get()) { productType = (m["ProductType"] != null) ? (UInt32)m["ProductType"] : 1; break; } } catch { taskResult.DidTaskSucceed = false; return(logonSessions); } IsServerEdition = productType > 1 ? true : false; // If operating system is server edition, use Remote Desktop Services API to retrieve logon sessions. if (IsServerEdition) { try { using ( GlobalVar.UseAlternateCredentials ? UserImpersonation.Impersonate(GlobalVar.AlternateUsername, GlobalVar.AlternateDomain, GlobalVar.AlternatePassword) : null) { IntPtr server = WtsApi.WTSOpenServer(ComputerName); logonSessions.AddRange(WtsApi.GetWindowsUsers(server)); foreach (RemoteLogonSession logonSession in logonSessions) { query = new ObjectQuery($"SELECT CreationDate FROM Win32_Process WHERE SessionId = {logonSession.SessionId}"); searcher = new ManagementObjectSearcher(scope, query); DateTime logonTime = DateTime.Now; foreach (ManagementObject m in searcher.Get()) { DateTime procCreationDate = ManagementDateTimeConverter.ToDateTime(m["CreationDate"].ToString()); if (procCreationDate < logonTime) { logonSession.LogonTime = procCreationDate; } } } } taskResult.DidTaskSucceed = true; } catch { taskResult.DidTaskSucceed = false; } } // If operating system is desktop edition, query Win32_Process for explorer.exe to determine logged on users. else { query = new ObjectQuery("SELECT * FROM Win32_Process WHERE Name = 'explorer.exe'"); searcher = new ManagementObjectSearcher(scope, query); try { foreach (ManagementObject m in searcher.Get()) { var logonSession = new RemoteLogonSession(); logonSession.SessionId = (UInt32)m["SessionId"]; var dmtfDateTime = m["CreationDate"].ToString(); logonSession.LogonTime = ManagementDateTimeConverter.ToDateTime(dmtfDateTime); string[] argList = new string[] { string.Empty, string.Empty }; int returnVal = Convert.ToInt32(m.InvokeMethod("GetOwner", argList)); if (returnVal == 0) { logonSession.Username = argList[0]; logonSession.Domain = argList[1]; } else { logonSession.Username = string.Empty; } int index = logonSessions.FindIndex(item => item.SessionId == logonSession.SessionId); if (index >= 0) { continue; } else { logonSessions.Add(logonSession); } } taskResult.DidTaskSucceed = true; } catch { taskResult.DidTaskSucceed = false; } } return(logonSessions); }
public static DialogResult TaskGpupdate(string targetComputer) { // TaskGpupdate() uses WMI to execute the GPUpdate command. // It returns a DialogResult which will be used to display the results. var dialog = new DialogResult(); bool didTaskSucceed = false; const string gpupdateComputer = "cmd /c echo n | gpupdate /force"; // Setup WMI query. var options = new ConnectionOptions(); if (GlobalVar.UseAlternateCredentials) { options.Username = GlobalVar.AlternateUsername; options.Password = GlobalVar.AlternatePassword; options.Authority = $"NTLMDOMAIN:{GlobalVar.AlternateDomain}"; } var scope = new ManagementScope($@"\\{targetComputer}\root\CIMV2", options); try { scope.Connect(); var objectGetOptions = new ObjectGetOptions(); var managementPath = new ManagementPath("Win32_Process"); var managementClass = new ManagementClass(scope, managementPath, objectGetOptions); ManagementBaseObject inParams = managementClass.GetMethodParameters("Create"); inParams["CommandLine"] = gpupdateComputer; ManagementBaseObject outParams = managementClass.InvokeMethod("Create", inParams, null); int returnValue; bool isReturnValid = int.TryParse(outParams["ReturnValue"].ToString(), out returnValue); if (!isReturnValid || returnValue != 0) { throw new Exception(); } } catch { } try { // To apply user policies, gpupdate.exe MUST be run in the context of each logged in user. // In order to do so, a scheduled task is created on the target machine that is configured to run GPUpdate // as each currently logged in user. Prior to running the task, a simple .VBS script that calls gpupdate.exe is // written to C:\Windows\TEMP on the target computer. The scheduled task points to the .VBS script. This is done // to hide any console windows that would appear if the task were to directly run gpupdate.exe. The temporary // script file and task are then deleted once the execution has kicked off. const string gpupdateUser = "******"WScript.Shell\").Run \"cmd /c echo n | gpupdate /target:user /force\", 0"; string remotePathToGpupdateScript = $@"\\{targetComputer}\C$\Windows\Temp"; string localPathToGpupdateScript = @"C:\Windows\Temp"; RemoteLogonSession.ComputerName = targetComputer; var loggedOnUsers = RemoteLogonSession.GetLogonSessions(); if (loggedOnUsers.Count > 0 && Directory.Exists(remotePathToGpupdateScript)) { var rnd = new Random(); var rndNumber = rnd.Next(0, 1000); remotePathToGpupdateScript += $@"\splc-{rndNumber}.vbs"; localPathToGpupdateScript += $@"\splc-{rndNumber}.vbs"; var scheduledTaskName = "SpliceAdmin-Gpupdate-" + rndNumber; // Write temporary .vbs script file. File.WriteAllText(remotePathToGpupdateScript, gpupdateUser); if (File.Exists(remotePathToGpupdateScript)) { var fileInfo = new FileInfo(remotePathToGpupdateScript); var fileSecurity = fileInfo.GetAccessControl(); fileSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), FileSystemRights.ReadAndExecute, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow)); fileInfo.SetAccessControl(fileSecurity); var startInfo = new ProcessStartInfo(); startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; startInfo.FileName = "schtasks.exe"; foreach (var user in loggedOnUsers) { startInfo.Arguments = $"/create /f /s {targetComputer} /ru {user.Username} /sc once /st 00:00 /tn {scheduledTaskName} /tr \"wscript.exe //e:vbs //b \\\"{localPathToGpupdateScript}\\\"\" /it"; Process.Start(startInfo); Thread.Sleep(500); startInfo.Arguments = $"/run /tn {scheduledTaskName} /s {targetComputer}"; Process.Start(startInfo); Thread.Sleep(2000); } startInfo.Arguments = $"/delete /f /tn {scheduledTaskName} /s {targetComputer}"; Process.Start(startInfo); File.Delete(remotePathToGpupdateScript); } Thread.Sleep(7000); didTaskSucceed = true; } } catch { } if (didTaskSucceed) { // GPUpdate was successful. Build DialogResult to reflect success. dialog.DialogTitle = "Success"; dialog.DialogBody = $"{targetComputer} has successfuly refreshed all Group Policy Objects."; dialog.DialogIconPath = "/Resources/success-48.png"; dialog.ButtonIconPath = "/Resources/checkmark-24.png"; dialog.ButtonText = "OK"; dialog.IsCancelVisible = false; } else { // Failed to run GPUpdate. Build DialogResult to reflect failure. dialog.DialogTitle = "Error"; dialog.DialogBody = $"Failed to refresh Group Policy Objects on {targetComputer}."; dialog.DialogIconPath = "/Resources/error-48.png"; dialog.ButtonIconPath = "/Resources/checkmark-24.png"; dialog.ButtonText = "OK"; dialog.IsCancelVisible = false; } return(dialog); }