Я работаю на многопользовательском Windows Server, и ошибка rdpclip ежедневно укусывает нас всех. Обычно мы просто открываем диспетчер задач и убиваем, а затем перезапускаем rdpclip, но это уже неудобно. Я написал сценарий PowerShell для уничтожения, а затем перезапуска rdpclip, но никто его не использует, потому что это сценарий (не говоря уже о том, что политика выполнения ограничена для коробки). Я пытаюсь написать быстрое и грязное приложение для Windows, в котором вы нажимаете кнопку, чтобы убить rdpclip и перезапустить его. Но я хочу ограничить его доступ к текущему пользователю и не могу найти метод для класса Process, который делает это. Пока вот что у меня есть:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist)
{
if (theprocess.ProcessName == "rdpclip")
{
theprocess.Kill();
Process.Start("rdpclip");
}
}
Я не уверен, но думаю, что это убьет все процессы rdpclip. Я хотел бы выбрать по пользователю, как это делает мой сценарий PowerShell:
taskkill /fi "username eq $env:username" /im rdpclip.exe
& rdpclip.ex
Полагаю, я мог бы просто вызвать сценарий PowerShell из своего исполняемого файла, но это кажется довольно неуклюжим.
Заранее извиняюсь за любые проблемы с форматированием, я здесь впервые.
ОБНОВЛЕНИЕ: мне также нужно знать, как получить текущего пользователя и выбрать только эти процессы. Предлагаемое ниже решение WMI мне не помогает.
ОБНОВЛЕНИЕ 2: Хорошо, я понял, как получить текущего пользователя, но он не соответствует пользователю процесса через удаленный рабочий стол. Кто-нибудь знает, как получить имя пользователя вместо SID?
Ваше здоровье, fr0man





Прочтите следующую статью CodeProject, в ней есть вся необходимая информация:
Да ладно. Это поддерживается только в .NET 2.0 и ниже. Исправлено сейчас.
Лично я бы выбрал путь Win32 / PInvoke, а не WMI в этом случае. Однако это всего лишь предпочтение, я думаю, что метод WMI тоже подойдет.
Хорошо, вот что я в итоге сделал:
Process[] processlist = Process.GetProcesses();
bool rdpclipFound = false;
foreach (Process theprocess in processlist)
{
String ProcessUserSID = GetProcessInfoByPID(theprocess.Id);
String CurrentUser = WindowsIdentity.GetCurrent().Name.Replace("SERVERNAME\\","");
if (theprocess.ProcessName == "rdpclip" && ProcessUserSID == CurrentUser)
{
theprocess.Kill();
rdpclipFound = true;
}
}
Process.Start("rdpclip");
if (rdpclipFound)
{
MessageBox.Show("rdpclip.exe successfully restarted"); }
else
{
MessageBox.Show("rdpclip was not running under your username. It has been started, please try copying and pasting again.");
}
}
Мне пришлось заменить WindowsIdentity.GetCurrent (). Name на WindowsIdentity.GetCurrent (). User.Value, чтобы это работало.
Вместо использования GetProcessInfoByPID я просто беру данные из StartInfo.EnvironmentVariables.
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Security.Principal;
using System.Runtime.InteropServices;
namespace KillRDPClip
{
class Program
{
static void Main(string[] args)
{
Process[] processlist = Process.GetProcesses();
foreach (Process theprocess in processlist)
{
String ProcessUserSID = theprocess.StartInfo.EnvironmentVariables["USERNAME"];
String CurrentUser = Environment.UserName;
if (theprocess.ProcessName.ToLower().ToString() == "rdpclip" && ProcessUserSID == CurrentUser)
{
theprocess.Kill();
}
}
}
}
}
Вы можете открыть cmd в скрытом режиме и убить процесс, специфичный для пользователя. Здесь я пытаюсь убить процесс Excel, специфичный для текущего пользователя:
String CurrentUser = Environment.UserName;
Process[] allExcelProcesses = Process.GetProcessesByName("excel");
if (null != allExcelProcesses)
{
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C TASKKILL /F /FI \"USERNAME eq " + CurrentUser + "\" /IM EXCEL.EXE";
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
Выглядит хорошо, за исключением того, что я не могу заставить VS распознавать ObjectQuery даже с использованием System.Management. Я совершенно незнаком с этой областью.