2016-06-06 11 views
9

Czy można to zrobić tak, że nawet po usunięciu pliku aplikacji aplikacja po uruchomieniu nadal będzie działać do końca?C# Jak sprawić, aby aplikacja nadal działała nawet po usunięciu pliku aplikacji

Mam przenośną aplikację konsoli, która działa na dysku wymiennym i chciałaby, aby nadal działała, nawet jeśli dysk zostanie przypadkowo usunięty, czy to możliwe?

Widziałem http://www.codeproject.com/Articles/13897/Load-an-EXE-File-and-Run-It-from-Memory, ale wygląda na to, że nie działa.

+4

chciałbym zrobić w tym sposób: po uruchomieniu aplikacji kopiuje plik wykonywalny i zależności w folderze tymczasowym, a następnie restartuje aplikację z kopii tymczasowej i zabija pierwszy inst ance. – ElmoDev001

+0

Rozwiązanie z codeproject wydaje się być innym rodzajem aplikacji: uruchamia drugi plik wykonywalny (z urządzenia wymiennego) z podstawowego pliku wykonywalnego, który utrzymuje się na dysku systemowym. – ElmoDev001

+0

Co się stanie teraz, jeśli usuniesz dysk? Moje założenie jest następujące: aby móc uruchomić plik wykonywalny, należy najpierw załadować. Nie wiem, jak dokładnie ładowanie się pojawia (możesz [zbadać] (http://reversingproject.info/wp-content/uploads/2009/05/an_in-depth_look_into_the_win32_portable_executable_file_format_part_2.pdf)), ale spodziewałbym się, że tylko zasoby (gdy są dostępne później) jest problem. Załaduj je wstępnie i użyj wersji buforowanej = nie musisz już mieć dostępu do dysku = nie ma problemu. Popraw mnie, jeśli się mylę (powiedz co się teraz stanie). – Sinatr

Odpowiedz

0

Komentarz przez ElmoDev001 doprowadził mnie do osiągnięcia pożądanych rezultatów.

Są błędy, ale tutaj jest ogólna idea:

Program.cs (klasa główna)

class Program { 
    static void Main(string[] args) 
    { 
     String Temp = System.IO.Path.GetTempPath(); 
     String tmpDir = Temp + @"tmp\"; 

     String fileName = String.Concat(Process.GetCurrentProcess().ProcessName, ".exe"); 
     String filePath = Path.Combine(Extension.AssemblyDirectory, fileName); 
     String tempFilePath = Path.Combine(tmpDir, fileName); 

     if (!Directory.Exists(tmpDir)) { Directory.CreateDirectory(tmpDir); } 

     if (!(string.Equals(filePath, tempFilePath))) // if the application is not running at temp folder 
     { 
      if (!(File.Exists(tempFilePath))) // if the application does not exist at temp folder 
      { 
       ext.initFile(); 
      } 
      else if (File.Exists(tempFilePath)) // if the application already exists at temp folder 
      { 
       File.Delete(tempFilePath); 
       ext.initFile(); 
      } 
     } 
     else if (string.Equals(filePath, tempFilePath)) // if the application is running at temp folder 
     { 
       //main code 
     } 
    } 
} 

Extension.cs

class Extension 
{ 

    String Temp = System.IO.Path.GetTempPath(); 
    String tmpDir = Temp + @"tmp\"; 

    String fileName = String.Concat(Process.GetCurrentProcess().ProcessName, ".exe"); 
    String filePath = Path.Combine(Extension.AssemblyDirectory, fileName); 
    String tempFilePath = Path.Combine(tmpDir, fileName); 

    public static string AssemblyDirectory 
    { 
     get 
     { 
      string codeBase = Assembly.GetExecutingAssembly().CodeBase; 
      UriBuilder uri = new UriBuilder(codeBase); 
      string path = Uri.UnescapeDataString(uri.Path); 
      return Path.GetDirectoryName(path); 
     } 
    } 

    public static void initFile() 
    { 
      File.Copy(filePath, tempFilePath); 
      Process.Start(tempFilePath); 
      System.Environment.Exit(0); 
    } 
} 
2

Jeśli aplikacja konsoli zawiera odwołania do złożeń, mogą one nie zostać załadowane, dopóki nie zostaną użyte.

Trzeba załadować wszystkie podobne zespoły w głównej metody lub gdzieś w inicjującego/uruchamiania:

var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList(); 
var loadedPaths = loadedAssemblies.Select(a => a.Location).ToArray(); 

var referencedPaths = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll"); 
var toLoad = referencedPaths.Where(r => !loadedPaths.Contains(r, StringComparer.InvariantCultureIgnoreCase)).ToList(); 
toLoad.ForEach(path => loadedAssemblies.Add(AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path)))); 
1

Problem z podejściem w artykule (z Twojego punktu widzenia) jest to, że trzeba go uruchomić z innej aplikacji i plik binarny tej aplikacji musi być cały czas obecny, więc nie możesz go uruchomić z tej samej lokalizacji lub nie pozbyłeś się problemu.

Jeden mechanizm mógłby być:

  1. użytkownik uruchamia app
  2. sama kopie aplikacji do folderu temp.
  3. Aplikacja uruchamia kopię tymczasową za pomocą parametru Process.Start i a/nocopy
  4. Aplikacja się zamyka.
  5. Aplikacja Temp uruchamia się, odczytuje parametr/nocopy i pomija kopię i uruchamia.
+0

W jaki sposób zamierzasz wykonać parametr/nocopy? – pleasega

+1

To tylko niestandardowy parametr wiersza poleceń, który można zarządzać w aplikacji. Podobnie jak w moim komentarzu ("Innym rozwiązaniem jest uruchomienie aplikacji z odpowiednim wierszem poleceń, który pozwala sprawdzić przy uruchomieniu aplikacji"). – ElmoDev001

+0

W bardzo prostych terminach, w 'void Main (string [] args)', wystarczy przetestować, czy jeden z ciągów w 'args' jest"/nocopy ". Najlepiej sprawdzić bez uwzględniania wielkości liter. –

Powiązane problemy