2013-05-12 2 views
0

Следующий код должен заменить исполняемый файл и перезапустить приложение, которое должно работать, потому что содержание должно быть заменено, но не в текущем запущенном экземпляре:File.Replace не ведет себя, как и ожидалось

Dim tmppath As String = System.IO.Path.GetTempFileName 

Private Sub YesBtn_Click(sender As Object, e As EventArgs) Handles YesBtn.Click 
    Dim client As New WebClient() 
    AddHandler client.DownloadProgressChanged, AddressOf client_ProgressChanged 
    AddHandler client.DownloadFileCompleted, AddressOf client_DownloadFileCompleted 
    client.DownloadFileAsync(New Uri("https://github.com/Yttrium-tYcLief/Scrotter/raw/master/latest/scrotter.exe"), tmppath) 
End Sub 

Public Sub client_DownloadFileCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs) 
    File.Replace(tmppath, Application.ExecutablePath, Nothing) 
    Application.Restart() 
End Sub 

Согласно MSDN,

Pass ничего параметру destinationBackupFileName, если вы не хотите, чтобы создать резервную копию файла заменяются.

Однако, что на самом деле происходит то, что он делает создать резервную копию (если .exe является scrotter.exe, то новая резервная scrotter.exe~RF729c1fe9.TMP). Кроме того, в корневом каталоге создается новая пустая папка с именем «False».

Все, что я хочу, это заменить исполняемый файл исполняемым файлом и не иметь никаких резервных копий или дополнительных папок. Есть идеи?

+0

Вы проверили, происходит ли это только при запуске исполняемого файла? Я тестировал с помощью простого текстового файла, и то, что вы описываете, не происходит – Steve

ответ

1

Довольно трудно объяснить это с помощью размещенного кода, это пахнет каким-то сторонним утилизатором, который входит в систему и избегает проблем, которые имеет ваш код. Он никогда не будет работать, когда вы передадите Nothing для имени файла резервной копии. требуется, если вы хотите заменить исполняемый файл, который также загружен в память. CLR создает объект для сопоставления памяти для сборки, поэтому Windows может запрашивать данные из сборки в ОЗУ по требованию. С большим преимуществом, что это не занимает места в файле подкачки. Этот MMF также помещает жесткий файл в файл, поэтому никто не может изменять содержимое файла. Это было бы катастрофой.

Это блокировка данных файла, а не запись в каталоге для файла. Поэтому переименование файла по-прежнему работает. Это то, что File.Replace() делает, когда вы предоставляете ненужное имя файла резервной копии, он переименовывает сборку, чтобы вы все равно могли создать файл с тем же именем и не иметь проблем с блокировкой. Вы можете удалить резервную копию впоследствии, считая, что ваша программа по-прежнему имеет достаточные права для фактического удаления файла при его резервном копировании. В наши дни это необычно для UAC. Или просто не беспокоиться, дисковое пространство дешево и иметь резервную копию для борьбы с несчастными случаями - это то, что вы можете назвать функцией.

Итак, заходите и используйте File.Replace() правильно, используйте 3-й аргумент. Не забудьте удалить этот файл резервной копии, прежде чем вы вызовете Replace().

+0

Я собираюсь в итоге просто создать резервную копию в% temp% с неслучайным именем файла и проверить этот файл каждый раз, когда начнется мое приложение - если он есть, он будет удален. – yttrium

+0

Будьте осторожны с этим. Очень важно, чтобы файл резервной копии находился на одном диске, поэтому его можно просто перемещать, а не копировать. % temp% не предоставляет эту гарантию. Boilerplate - это тот же самый каталог, с добавлением расширения расширения .bak. Кроме того, гораздо проще найти резервный файл обратно, когда вы хотите его удалить или восстановить, еще одна вещь, которую% temp% не может гарантировать, поскольку она может измениться. –

+0

Так было бы лучше создать файл .bak в каталоге, в котором находится мой исполняемый файл, а затем проверить его и удалить при запуске? Я обеспокоен тем, что пользователь может вмешиваться в это или иметь другой файл. Могу ли я создать имя временного файла, используя System.IO.Path.GetRandomFilename, а затем сохранить это имя файла в реестре или что-то еще? Это было бы безопаснее, чем просто предположить, что файл .bak в каталоге является резервной копией моего приложения (это приложение переносимо, оно не устанавливается в каталог, хотя я должен подумать об этом) – yttrium

0

Я думаю, что .exe заблокирован до тех пор, пока ваш процесс запускается - экземпляр экземпляра не вызывает беспокойства. Чтобы избежать этого, я бы поместил программу обновления в отдельный файл .exe и выключил вашу основную аппликацию при обновлении.

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