|
You last visited: Today at 16:57
Advertisement
[C#] Chronoglisches Update
Discussion on [C#] Chronoglisches Update within the .NET Languages forum part of the Coders Den category.
04/11/2015, 10:36
|
#1
|
elite*gold: 0
Join Date: Mar 2015
Posts: 776
Received Thanks: 313
|
[C#] Chronoglisches Update
Hallo Elitepvpers,
ich brauche mal etwas Rat. Ich komme nicht weiter (obwohl ich erfahren bin, wahrscheinlich irgendein dummer Fehler.  ).
Situation: Ich habe eine Anwendung. Diese sucht zu Beginn nach neuen Updates, wenn eins oder mehr vorhanden ist, soll es das runterladen. Die Dateien heißen auf dem Server update_x.zip. Da eventuell in Update 10 eine wichtige neue Datei ist, die auch in Update 1337 gebraucht wird, muss natürlich jedes Update einzeln heruntergeladen werden.
Code:
Client (Version): 15
Server (Version): 20
install update 16
install update 17
install update 18
install update 19
install update 20
launch application
Das ihr euch das vorstellen könnt. Allerdings habe ich das Problem, dass das Programm dann noch update 21 (das nicht vorhanden ist) herunterladen möchte, dann ein leeres Zip-Archiv entpacken will (0KB) und dann eine Fehlermeldung gibt (verständlich!).
Hat jemand einen Sourcecode dafür, oder könnte über meinen mal drüberschauen?
Marco
|
|
|
04/11/2015, 11:39
|
#2
|
elite*gold: 2932
Join Date: Oct 2009
Posts: 6,966
Received Thanks: 1,097
|
Quote:
Originally Posted by *static_cast
Allerdings habe ich das Problem, dass das Programm dann noch update 21 (das nicht vorhanden ist) herunterladen möchte
|
hört sich nach ner fehlerhaften abbruchbedingung in einer schleife an.
Quote:
Originally Posted by *static_cast
Hat jemand einen Sourcecode dafür, oder könnte über meinen mal drüberschauen?
|
dafür müsstest du ihn posten oder linken
|
|
|
04/11/2015, 12:13
|
#3
|
elite*gold: 0
Join Date: Mar 2015
Posts: 776
Received Thanks: 313
|
Quote:
Originally Posted by tolio
hört sich nach ner fehlerhaften abbruchbedingung in einer schleife an.
dafür müsstest du ihn posten oder linken
|
Ja, ich glaube auch, dass ich etwas nicht richtig habe mit einer Schleife.
Kann ich ihn dir privat zukommen lassen?
|
|
|
04/11/2015, 12:37
|
#4
|
elite*gold: 2932
Join Date: Oct 2009
Posts: 6,966
Received Thanks: 1,097
|
können, klar, wer soll dich davon abhalten.
ich persöhnlich würde es besser finden wenn du einfach den relevaten teil hier postet, dann besteht die möglichkeit das in zukunft jemand mit dem selben problem hier eine lösung findet.
|
|
|
04/12/2015, 01:34
|
#5
|
elite*gold: 0
Join Date: Mar 2015
Posts: 776
Received Thanks: 313
|
Ich habe das in einer Console nochmal neu geschrieben, auch, damit man den Sourcecode noch überblicken kann (was bei der GUI nicht der Fall war!).
Das Problem nun:
in der version.cfg steht "420", also Client = 420. Serverversion sagt "423", also Server = 423.
Es funktioniert, allerdings bei 423 (also der Datei PATCH_423.zip) bricht er ab und sagt mir, es sei kein gültiges ZIP-Archiv, was ich auch glaube, da die Datei auf dem Server ~6 MB groß ist, bei mir jedoch nur ~ 122 KB. Hat der WebClient zu früh abgeschlossen?
Source:
€dit: Beim 2. Versuchen ist PATCH_423 ganze 0 KB groß. Wenn ich die Clientversion in der Datei auf 422 setze, lädt er einwandfrei herunter und es funktioniert, bei 421 auch, aber weshalb bei 420 nicht?
€dit²: Scheinbar lädt er bei mehr als zwei Updates, die ausstehen, das dritte nicht komplett runter, mal ist "423" 100 KB, mal 0 oder 577 KB groß.
Hast du eine Idee, tolio?
|
|
|
04/12/2015, 15:29
|
#6
|
elite*gold: 0
Join Date: Apr 2008
Posts: 495
Received Thanks: 817
|
Quote:
Originally Posted by *static_cast
Ich habe das in einer Console nochmal neu geschrieben, auch, damit man den Sourcecode noch überblicken kann (was bei der GUI nicht der Fall war!).
Das Problem nun:
in der version.cfg steht "420", also Client = 420. Serverversion sagt "423", also Server = 423.
Es funktioniert, allerdings bei 423 (also der Datei PATCH_423.zip) bricht er ab und sagt mir, es sei kein gültiges ZIP-Archiv, was ich auch glaube, da die Datei auf dem Server ~6 MB groß ist, bei mir jedoch nur ~ 122 KB. Hat der WebClient zu früh abgeschlossen?
Source:
€dit: Beim 2. Versuchen ist PATCH_423 ganze 0 KB groß. Wenn ich die Clientversion in der Datei auf 422 setze, lädt er einwandfrei herunter und es funktioniert, bei 421 auch, aber weshalb bei 420 nicht?
€dit²: Scheinbar lädt er bei mehr als zwei Updates, die ausstehen, das dritte nicht komplett runter, mal ist "423" 100 KB, mal 0 oder 577 KB groß.
Hast du eine Idee, tolio?
|
Servus,
ich habe deinen SourceCode ausprobiert und es kam kein Fehler, alles hat funktioniert. Selbst der Patch_423.zip wurde geladen und entpackt. Gtestet habe ich es über meinen FTP-Server.
Spontan würde mir einfallen:
- try/catch ggf. wird eine Fehlermeldung geschmissen.
- Überprüfen, ob die Dateinamen richtig sind, ggf. Leerzeichen dazwischen.
- Debuggen. Einfach alle Schritte durchgehen und überprüfen, ob die Werte richtig gesetzt werden.
- ggf. die richtige URL's geben, damit man selber ausprobieren/debuggen kann
Ich würde gerne Verbesserungsvorschläge geben.
- Verwende try/catch
- Verwende bei IDisposable Objekten 
(z.B. WebClient, StreamReader/Writer usw)
- Vermeide und nimm besser
Code:
bool = int.TryParse();
Dies hat zum Vorteil, dass die Exception bereits von der Funktion selbst ausgwertet wird. (  )
- Nach jedem Patch rufst Du die Funktion
Code:
getServerVersion();
erneut auf. Ich bin der Meinung, dass es reichen würde, wenn Du die ServerVersion einmalig am Programmstart abfragst.
Ich habe mir mal die Mühe gemacht einen Updater zu schreiben, der genau diese Aufgabe wie deiner absolvieren soll. Man brauch mindestens das .Net Framework 4.5, ich mit der TPL gearbeitet habe. Was noch nicht vorhanden ist, ist das setzten der aktuellen Version für den Client.
Code:
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Ionic.Zip;
namespace Updater
{
class Program
{
static string _ServerUrl = @"http://url./Updater/Version.txt";
static string _PatchUrl = @"http://url.de/Updater/Patch_";
static string _LocalFolder = Environment.CurrentDirectory;
static string _ClientUrl = string.Format(@"{0}\Version.txt", _LocalFolder);
static void Main(string[] args)
{
Task.Run(() => MainAsync(args)).Wait();
Console.ReadKey();
}
static async Task MainAsync(string[] args)
{
int serverVersion, clientVersion;
string server, client;
try
{
server = await ServerVersion(_ServerUrl);
client = await ClientVersion(_ClientUrl);
Console.WriteLine("Server: {0}", server);
Console.WriteLine("Client: {0}", client);
int.TryParse(server, out serverVersion);
int.TryParse(client, out clientVersion);
if (clientVersion < serverVersion)
{
Console.WriteLine("Update vorhanden!");
while (clientVersion < serverVersion)
{
clientVersion++;
Console.WriteLine("Downloading Patch: {0}", clientVersion);
if (!await GetFilesFromServer(clientVersion.ToString()))
{
Console.WriteLine("Patch Nummer {0} konnte nicht geladen werden.", clientVersion);
}
}
}
else
{
Console.WriteLine("Kein Update vorhanden.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static async Task<string> ServerVersion(string Url)
{
if (string.IsNullOrEmpty(Url))
throw new ArgumentNullException("Url", "Url darf nicht NULL oder leer sein.");
string ret = string.Empty;
using (WebClient wc = new WebClient())
{
//wc.UseDefaultCredentials = true;
//wc.Credentials = new NetworkCredential("", "");
ret = await wc.DownloadStringTaskAsync(Url);
}
return ret;
}
static async Task<string> ClientVersion(string FilePath)
{
if (string.IsNullOrEmpty(FilePath))
throw new ArgumentNullException("FilePath", "FilePath darf nicht NULL oder leer sein.");
string ret = string.Empty;
using (StreamReader sr = new StreamReader(FilePath))
{
ret = await sr.ReadToEndAsync();
}
return ret;
}
static async Task<bool> GetFilesFromServer(string PatchVersion)
{
if (string.IsNullOrEmpty(PatchVersion))
throw new ArgumentNullException("PatchVersion", "Die Patchversion darf nicht NULL oder leer sein.");
bool success = false;
string patchUrl = string.Format(@"{0}{1}.zip", _PatchUrl, PatchVersion);
string localFile = string.Format(@"{0}\Patch_{1}.zip", _LocalFolder, PatchVersion);
using (WebClient wc = new WebClient())
{
wc.DownloadProgressChanged += (s, e) =>
{
//Console.WriteLine(e.ProgressPercentage);
};
wc.DownloadFileCompleted += (sender, args) =>
{
Console.WriteLine("Patch erfolgreich geladen.");
Unzip(localFile);
};
//wc.UseDefaultCredentials = true;
//wc.Credentials = new NetworkCredential("", "");
await wc.DownloadFileTaskAsync(new Uri(patchUrl), localFile);
success = true;
}
return success;
}
static void Unzip(string Filepath)
{
if (string.IsNullOrEmpty(Filepath))
throw new ArgumentNullException("Filepath", "Filepath darf nicht NULL oder leer sein.");
string destination = @"";
try
{
using (ZipFile zip = ZipFile.Read(Filepath))
{
Console.WriteLine("Datei wird entpackt.");
foreach (ZipEntry entry in zip)
{
entry.Extract(destination, ExtractExistingFileAction.OverwriteSilently);
Console.WriteLine("Patching: {0}", entry.FileName);
}
}
File.Delete(Filepath);
Console.WriteLine("{0} wurde gelöscht.", Filepath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
|
|
|
04/12/2015, 16:35
|
#7
|
elite*gold: 0
Join Date: Mar 2015
Posts: 776
Received Thanks: 313
|
Quote:
Originally Posted by schnewin
...
[/code]
|
Hallo! Danke, für deinen Code. Ich habe es bereits debuggt und natürlich wurde auch ein Fehler geworfen, nämlich, dass 423 kein gültiges ZIP-Archiv ist. Ich teste deinen Code mal.
€dit: Zu welchem Namespace gehört dieses Objekt?
€dit²: Habe nun statt dem Objekt lediglich "true" gesetzt, funktioniert auch. Wäre es sinnvoll, wenn alle Updates installiert sind, einfach die Clientversion auf die Serverversion zu setzen?
|
|
|
04/12/2015, 17:16
|
#8
|
elite*gold: 0
Join Date: Apr 2008
Posts: 495
Received Thanks: 817
|
Quote:
Originally Posted by *static_cast
Hallo! Danke, für deinen Code. Ich habe es bereits debuggt und natürlich wurde auch ein Fehler geworfen, nämlich, dass 423 kein gültiges ZIP-Archiv ist. Ich teste deinen Code mal.
€dit: Zu welchem Namespace gehört dieses Objekt?
€dit²: Habe nun statt dem Objekt lediglich "true" gesetzt, funktioniert auch. Wäre es sinnvoll, wenn alle Updates installiert sind, einfach die Clientversion auf die Serverversion zu setzen?
|
Du benutzt doch die  oder?
Die Methode ZipEntry.Extract() erwartet ein Dateipfad und/oder eine das enum ExtractExistingFileAction, welches besagt was passieren soll, falls eine Datei vorhanden ist.
Dann hättest Du das Problem, falls ein Update nicht erfolgreich ist, wird die Serverversion gesetzt.
|
|
|
04/12/2015, 17:35
|
#9
|
elite*gold: 0
Join Date: Mar 2015
Posts: 776
Received Thanks: 313
|
Quote:
Originally Posted by schnewin
Du benutzt doch die  oder?
Die Methode ZipEntry.Extract() erwartet ein Dateipfad und/oder eine das enum ExtractExistingFileAction, welches besagt was passieren soll, falls eine Datei vorhanden ist.
Dann hättest Du das Problem, falls ein Update nicht erfolgreich ist, wird die Serverversion gesetzt.
|
Vorschlag?
|
|
|
04/12/2015, 18:45
|
#10
|
elite*gold: 0
Join Date: Apr 2008
Posts: 495
Received Thanks: 817
|
Quote:
Originally Posted by *static_cast
Vorschlag?
|
Ich würde es so ähnlich machen, wie in meinem Code, nur vorher überprüfen, ob dass entpacken erfolgreich war.
Hier mal meinen Vorschlag als Pseudocode:
Code:
bool success = false;
do
{
success = false;
clientVersion++;
if(GetFilesFromServer(clientVersion.ToString()))
{
if(UnzipFile(FileName))
{
SetClientVersion(clientVersion);
success = true;
}
}
}while(clientVersion < serverVersion && success == true);
|
|
|
04/13/2015, 18:31
|
#11
|
elite*gold: 4
Join Date: Feb 2008
Posts: 3,854
Received Thanks: 1,268
|
Ich persönlich, würde das mit den Archiven wie folgt handhaben: Erstelle jeweils bei einem Patch, oÄ. einfach das Archiv neu und stelle nur das bereit. Wenn ein Client nun eine Verbindung zum Server herstellt, siehst Du nach, welche Version er hat und stellst dann entsprechend das Archiv bereit. Anders herum wäre dann das Archiv unnötig groß und er würde willkürlich alle Dateien herunterladen.
Und je nach Version kannst Du ja festlegen, welche Dateien benötigt werden bzw. bereits wurden und darauf agieren.
|
|
|
All times are GMT +1. The time now is 16:58.
|
|