У меня есть служба Windows, которую я хотел бы автоматически и без проблем обновлять. Я начал использовать wyBuild для реализации этого, но имел некоторые проблемы с ним, и решил попытаться построить свой собственный. Я написал автономный exe, который можно вызвать для выполнения процедуры обновления: проверяет наличие нового zip-файла с обновлением, загружает его, распаковывает, останавливает службу Windows, копирует файлы из zip и перезапускает службу. Этот exe отлично работает, когда я запускаю его из командной строки и писать не очень сложно.Как запустить exe из .NET Windows Service для обновления службы
Однако, теперь я хотел бы, чтобы служба (тот же самый обновлялась), чтобы выложить обновление для exe для обновления. Я впервые попробовал Process.Start:
var proc = Process.Start(pathToUpdaterExe);
proc.WaitForExit(60000);
Это называется Апдейтер, но когда программа обновления останавливает службу, что процесс был убит, и обновление прекращается. Я сделал некоторые поиски, и похоже, что решение заключается в использовании отдельного AppDomain. Это то, что я сейчас:
Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
Evidence objEvidence = new System.Security.Policy.Evidence(baseEvidence);
AppDomainSetup setup = new AppDomainSetup();
var updateDomain = AppDomain.CreateDomain("updateDomain", objEvidence, setup);
updateDomain.ExecuteAssembly(updater);
AppDomain.Unload(updateDomain);
Однако, теперь я получаю System.IO.IOException об ошибке: «Процесс не может получить доступ к файлу«C: \ Program Files (x86) \ Компания \ Service \ Service. dll ', потому что он используется другим процессом "при попытке скопировать поверх новой Service.dll
Опять же, у меня остановлен услуга на этом этапе. Я подтвердил это с помощью журнала. Я не могу себе представить, что бы Service.dll еще заперт, поэтому я добавил код, чтобы проверить, что запирая его:
public static IEnumerable<Process> GetProcessesLocking(string filePath)
{
var result = new List<Process>();
result.Clear();
var processes = Process.GetProcesses();
foreach (Process proc in processes)
{
try
{
if (proc.HasExited) continue;
foreach (ProcessModule module in proc.Modules)
{
if ((module.FileName.ToLower().CompareTo(filePath.ToLower()) == 0))
{
result.Add(proc);
break;
}
}
}
catch (Exception ex)
{
Log(ex.ToString());
Log("There was an error checking " + proc.ProcessName);
}
}
return result;
}
Однако этот код указывает на то, что ничего не имеет блокировку на DLL (результат пуст и ничего не регистрируется, показывая ошибку).
Я подозреваю, что я столкнулся с проблемой UAC, которая является реальной причиной IOException. Служба Windows работает как LocalSystem. Все, что задавать: Как должен Я запускаю обновление exe из службы Windows, чтобы он имел права копировать файлы в c: \ Program Files?
Update
В комментариях и ответ предполагает, Process.Start может работать, но есть некоторые нюансы. Вам необходимо запустить cmd.exe и использовать для его обновления. Я также обнаружил, что не могу использовать полный путь для exater updater и что мне нужно установить UseShellExecute = false. Это мой последний рабочий код, который запускает программу обновления из службы .NET:
var cmd = "/c start updater.exe";
var startInfo = new ProcessStartInfo("cmd.exe");
startInfo.Arguments = cmd;
startInfo.WorkingDirectory = AssemblyDirectory;
startInfo.UseShellExecute = false;
var proc = Process.Start(startInfo);
Полностью с головы, но почему бы не просто создать службу для запланированной задачи за 5 секунд? Таким образом, процесс, который инициирует обновление и фактическую обработку обновления, полностью отключен –
Когда это произойдет, вы можете найти имя DLL («find handle») в Process Explorer, чтобы узнать, кто еще имеет дескриптор, открытый для DLL? Или запишите такой сеанс в Process Monitor. Просто найдите настоящего преступника. Вы не знаете, будет ли более успешным запуск через 5 секунд. –
Ваше 1-е решение может работать. Прочтите http://stackoverflow.com/questions/1035213/process-start-and-the-process-tree, чтобы узнать, как сохранить обновление. –