# Updates?



## cwriter (2. April 2010)

Hallo Welt!

Ich benutzte Dev-C++, schreibe in C.
Ich versuche Updates zu machen, die sich selbst installieren. Bis jetzt öffnet der Browser einfach das Fenster und man muss den Download bestätigen.
Wie ist es möglich, dass das Programm die Datei direkt herunterlädt, installiert und ausführt?

Die Update-Datei ist auf Skydrive gespeichert: http://www.microsoft.com/switzerland/windows/de/windowslive/products/skydrive.aspx

Vielen Dank

cwriter


----------



## Rocky (5. April 2010)

Ich würde es mal mit Sockets versuchen:


```
#include <winsock2.h>
#include <string>
#include <fstream>
#include <conio.h>
#include <iostream>

#pragma comment (lib, "ws2_32.lib")

BOOL CALLBACK MainDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);

int main (int argc, char** argv)
{
	WORD version;
	WSADATA wsadata;
	SOCKET connect_socket;
	long bytes;

	version = MAKEWORD (1, 1);

	STARTUPINFO startupinfo = {sizeof(startupinfo)};
	PROCESS_INFORMATION processinfo;

	if (CreateProcess ("md5_checksum.exe", NULL, 0, 0, FALSE, 0, 0, 0, LPSTARTUPINFOA(&startupinfo), &processinfo))
	{
		WaitForSingleObject (processinfo.hProcess, INFINITE);

		CloseHandle (processinfo.hProcess);
		CloseHandle (processinfo.hThread);
	}

	if ((WSAStartup (version, &wsadata)) != 0)
	{
		printf ("Es wurde nicht die richtige Winsock DLL gefunden...\n");
		getchar();
		return -1;
	}

	if (LOBYTE (wsadata.wVersion) != 1 ||
		HIBYTE (wsadata.wVersion) != 1)
	{
		printf ("Eine falsche Winsock Version wurde gefunden...\n");
		WSACleanup ();
		getchar();
		return -1;
	}

	printf ("Winsock erfolgreich initialisiert...\n");

	struct sockaddr_in addy2;
	addy2.sin_family = AF_INET;
	addy2.sin_port = htons(80);
	addy2.sin_addr.s_addr = inet_addr ("188.40.53.86"); 

	printf ("Verbindung wird hergestellt...\n\n");

	std::string file_array[8] = {"Datei1.exe", "Datei2.dll", ... };

	connect_socket = socket (AF_INET, SOCK_STREAM, 0);

	if (connect_socket == INVALID_SOCKET)
	{
		printf ("Socket konnte nicht erstellt werden... Fehler Code: %d\n", WSAGetLastError());
		WSACleanup ();
		return -1;
	}
	if (connect (connect_socket, (struct sockaddr*)&addy2, sizeof(addy2)) == SOCKET_ERROR)
	{
		printf ("Fehler beim Herstellen der Verbindung... Fehler Code: %d\n", WSAGetLastError());
		closesocket (connect_socket);
		WSACleanup ();
		getchar();
		return -1;
	}

	char getmd5[82];
	sprintf_s (getmd5, 82, "GET /ORDNERNAME/md5.dat HTTP/1.1\r\n"
						   "Host: urlohnehttp.de\r\n"
						   "Connection: close\r\n\r\n");

	bytes = send (connect_socket, getmd5, sizeof (getmd5), 0);

	if (bytes == SOCKET_ERROR)
	{
		printf ("Fehler beim Anfordern der Datei: md5.dat... Fehler Code: %d\n", WSAGetLastError());
		closesocket (connect_socket);
		WSACleanup ();
		getchar();
		return -1;
	}
	else if (bytes == 0)
	{
		printf ("Die Verbindung wurde unterbrochen...\n");
		closesocket (connect_socket);
		WSACleanup ();
		getchar();
		return -1;
	}

	printf ("%i bytes gesendet...\n", bytes);

	bytes = 150000;
	int bytes_read = 0;
	char* receive = new char[150000];

	for (int j = 0; j < 150000; j++)
		receive[j] = NULL;

	while (bytes_read != bytes) 
	{ 
		int rec = recv (connect_socket, receive+bytes_read, bytes-bytes_read, 0);

		// Grad keine Daten zum empfangen da? 
		if (rec == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) 
			Sleep (20);
		// Fehler bzw Verbindung geschlossen? 
		else if (rec == 0) 
			break;
		else if (rec == SOCKET_ERROR)
		{
			printf ("Fehler beim Empfangen der Datei: md5.dat - Fehler Code: %d\n", WSAGetLastError());
			closesocket (connect_socket);
			WSACleanup ();
			delete receive;
			receive = NULL;
			getchar();
			return -1;
		}
		else
			bytes_read += rec;
	}

	printf ("%i bytes empfangen...\n", bytes_read);

	std::fstream file_in ("md5.dat", std::ios::in | std::ios_base::binary);

	if (!file_in.is_open()) // Überprüfen ob die Datei geöffnet werden konnte
	{
		printf ("Die Datei md5.dat konnte nicht geöffnet werden!");
		closesocket (connect_socket);
		WSACleanup ();
		delete receive;
		receive = NULL;
		getchar();
		return 0; // Wenn nicht, Programm beenden
	}

	int count = 0;
	std::string read;
	std::string md5_list[8];
	std::string md5_list_local[8];
	md5_list[0] = receive;

	while (!file_in.eof() && count != 8)
	{
		getline (file_in, read, '\n');
		md5_list_local[count].append (read);
		md5_list_local[count].erase (md5_list_local[count].size() -1, md5_list_local[count].size());
		count++;
	}

	file_in.close();

	int pos;

	if ((pos = md5_list[0].rfind ("\r\n\r\n")) != std::string::npos)
		md5_list[0].erase (0, pos+4);

	for (count = 7; count >= 1; count--)
	{
		if ((pos = md5_list[0].find_last_of ("\n\n")) != std::string::npos)
		{
			md5_list[count].append (md5_list[0].substr (pos-33, 32));
			md5_list[0].erase (pos-33);
		}
	}

	if ((pos = md5_list[0].find_last_of ("\n\n")) != std::string::npos)
		md5_list[0].erase (pos-1);

	delete receive;
	receive = NULL;

	printf ("Download beendet...\n\n");

	closesocket (connect_socket);

	for (int i = 0; i <= 7; i++)
	{
		connect_socket = socket (AF_INET, SOCK_STREAM, 0);

		if (connect_socket == INVALID_SOCKET)
		{
			printf ("Socket konnte nicht erstellt werden... Fehler Code: %d\n", WSAGetLastError());
			WSACleanup ();
			return -1;
		}
		if (connect (connect_socket, (struct sockaddr*)&addy2, sizeof(addy2)) == SOCKET_ERROR)
		{
			printf ("Fehler beim Herstellen der Verbindung... Fehler Code: %d\n", WSAGetLastError());
			closesocket (connect_socket);
			WSACleanup ();
			getchar();
			return -1;
		}

		printf ("Datei: %s - \232berpr\201fe Dateiversion...\n", file_array[i].c_str());

		if (md5_list[i] == md5_list_local[i])
			printf ("Diese Datei ist up to date!\n\n");
		else
		{
			printf ("Neue Dateiversion gefunden, starte Download...\n");

			char* buffer = new char[150000];

			for (int j = 0; j < 150000; j++)
				buffer[j] = NULL;

			char request[96];
			sprintf_s (request, 96, "GET /ORDNERNAME/%s HTTP/1.1\r\n" // 31 + 21
									 "Host: urlohnehttp.de\r\n" // 30
									 "Connection: close\r\n\r\n", file_array[i].c_str()); // 26

			bytes = send (connect_socket, request, sizeof (request), 0);

			if (bytes == SOCKET_ERROR)
			{
				printf ("Fehler beim Anfordern der Datei: %s... Fehler Code: %d\n", file_array[i].c_str(), WSAGetLastError());
				closesocket (connect_socket);
				WSACleanup ();
				delete buffer;
				buffer = NULL;
				getchar();
				return -1;
			}
			else if (bytes == 0)
			{
				printf ("Die Verbindung wurde unterbrochen...\n");
				closesocket (connect_socket);
				WSACleanup ();
				delete buffer;
				buffer = NULL;
				getchar();
				return -1;
			}

			printf ("%i bytes gesendet...\n", bytes);

			bytes = 150000;
			bytes_read = 0;
			std::string out;

			if (i == 7)
			{
				std::fstream file_out (file_array[i].c_str(), std::ios_base::out | std::ios_base::binary);

				while (true)
				{
					int rec = recv (connect_socket, buffer, 1, 0);

					out += buffer;

					int pos;

					if ((pos = out.rfind ("\r\n\r\n")) != std::string::npos)
						break;
				}

				while (true)
				{
					int rec = recv (connect_socket, buffer, sizeof(buffer), 0);

					if (rec == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) 
						Sleep (20);
					else if (rec == 0) 
						break;
					else if (rec == SOCKET_ERROR)
					{
						printf ("Fehler beim Empfangen der Datei: %s - Fehler Code: %d\n",
							file_array[i].c_str(), WSAGetLastError());

						closesocket (connect_socket);
						WSACleanup ();
						delete buffer;
						buffer = NULL;
						getchar();
						return -1;
					}

					file_out.write (buffer, rec);
					bytes_read += rec;
				}

				file_out.close();
			}
			else
			{
				while (bytes_read != bytes) 
				{ 
					int rec = recv (connect_socket, buffer+bytes_read, bytes-bytes_read, 0);

					// Grad keine Daten zum empfangen da? 
					if (rec == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) 
						Sleep (20);
					// Fehler bzw Verbindung geschlossen? 
					else if (rec == 0) 
						break;
					else if (rec == SOCKET_ERROR)
					{
						printf ("Fehler beim Empfangen der Datei: %s - Fehler Code: %d\n",
								file_array[i].c_str(), WSAGetLastError());

						closesocket (connect_socket);
						WSACleanup ();
						delete buffer;
						buffer = NULL;
						getchar();
						return -1;
					}
					else
						bytes_read += rec;
				}
			}

			printf ("%i bytes empfangen...\n", bytes_read);

			if (i < 7)
			{
				std::fstream file_out (file_array[i].c_str(), std::ios_base::out);
				std::string out = buffer;
				int pos;

				if ((pos = out.rfind ("\r\n\r\n")) != std::string::npos)
					out.erase (0, pos+4);

				file_out.write (out.c_str(), out.size());
				file_out.close ();
			}

			printf ("Download beendet...\n\n");

			delete buffer;
			buffer = NULL;
		}
			
		closesocket (connect_socket);
	}

	printf ("Verbindung erfolgreich getrennt...\n\n");
	printf ("Update erfolgreich durchgef\201hrt!");

	printf ("Mlchten Sie das Programm jetzt starten? (j/n): ");

	char input = ' ';

	while ((input != 'j') && (input != 'J') && (input != 'n') && (input != 'N'))
	{
		std::cin.sync();
		std::cin.get(input);
	}

	if (input == 'j' || input == 'J')

	ShellExecute (NULL, "open", "Programm.exe", NULL, NULL, SW_SHOW);

	return 0;
}
```


----------



## cwriter (5. April 2010)

Danke, dass du geantwortet hast. Aber ist das alles in C geschrieben? 

Und noch eine Bitte: Es wäre für mich als Dummy angenehm, wenn ich das ganze mit Kommentaren zur Funktion hätte.

Danke!

cwriter


----------



## Matthias Reitinger (5. April 2010)

Rocky hat gesagt.:


> Ich würde es mal mit Sockets versuchen:


Umständlicher geht es nicht mehr, oder? ;-] Lieber fertige und getestete Komponenten verwenden, anstatt das Rad neu zu erfinden:

```
#include <urlmon.h>
// …

// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    L"http://example.com/Update.exe", // URL zur Datei
    L"Update.exe", // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK) {
  // Verifizieren, Ausführen, etc.
} else {
  // Fehler beim Download
}
```

Grüße,
Matthias


----------



## Rocky (5. April 2010)

Also ich habe deinen Code bei mir mal eben probiert und es gibt nur fehler:

```
1>------ Erstellen gestartet: Projekt: download, Konfiguration: Debug Win32 ------
1>Kompilieren...
1>main.cpp
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(10) : error C2664: 'URLDownloadToFileA': Konvertierung des Parameters 2 von 'const wchar_t [55]' in 'LPCSTR' nicht möglich
1>        Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(11) : error C2059: Syntaxfehler: 'if'
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(11) : error C2143: Syntaxfehler: Es fehlt ';' vor '{'
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(11) : error C2447: '{': Funktionsheader fehlt - Parameterliste im alten Stil?
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(13) : error C2059: Syntaxfehler: 'else'
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(13) : error C2143: Syntaxfehler: Es fehlt ';' vor '{'
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(13) : error C2447: '{': Funktionsheader fehlt - Parameterliste im alten Stil?
1>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\\Eigene Dateien\Visual Studio 2008\Projects\download\download\Debug\BuildLog.htm" gespeichert.
1>download - 7 Fehler, 0 Warnung(en)
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
```

Habe den Code folgendermaßen Verändert:

```
#include <urlmon.h>
// …
 
// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    L"http://home.arcor.de/Terra23/DeckButler/DeckButler.zip", // URL zur Datei
    L"DeckButler.zip", // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK) {
  // Verifizieren, Ausführen, etc.
} else {
  // Fehler beim Download
}
```


----------



## Cromon (5. April 2010)

Hast du den Code einfach so in eine Datei kopiert?


----------



## Rocky (5. April 2010)

Cromon hat gesagt.:


> Hast du den Code einfach so in eine Datei kopiert?



Ich habe ihn folgender massen in meine "main.cpp" eingegeben:


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>

// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    L"http://home.arcor.de/Terra23/DeckButler/DeckButler.zip", // URL zur Datei
    L"DeckButler.zip", // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK) {
  system("explorer /*Pfad*/ C:\\\Dokumente und Einstallungen\\\...");
} else {
  cout << "Fehler beim Download" << endl
}
```


----------



## sheel (5. April 2010)

Was Cromon damit sagen will: Da fehlt ein main...


----------



## Rocky (5. April 2010)

Stimmt ohne main nixx los^^

ich schreibe noch nicht soo lange c/c++ drum is mir das noch alles neu


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>

int main()
{
// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    L"http://example.com/Update.exe", // URL zur Datei
    L"Update.exe", // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK) {
  system("explorer /*Pfad*/ C:\\\Dokumente und Einstallungen\\\...");
} else {
  cout << "Fehler beim Download" << endl
}
}
```


----------



## Maik (5. April 2010)

*Da* sucht sich einer einen Wolf :suspekt:



Rocky hat gesagt.:


> ```
> explorer /*Pfad*/ C:\\\Dokumente und Einstallungen
> ```


mfg Maik


----------



## Rocky (5. April 2010)

Hatte ich auch gerade gesehen^^

Wie müsste der code denn richtig sein ich blick da gerade nichtmehr durch


----------



## Cromon (5. April 2010)

Welche Stelle, welcher Fehler, welches Ziel?


----------



## Matthias Reitinger (5. April 2010)

Hallo,

sorry, ich hab mich auf die Schnelle bei den Parametertypen verlesen. Meine Variante funktioniert nur, wenn man mit Unicode-Unterstützung kompiliert. Mit dem TEXT-Makro kann man dieses Manko ausbügeln:


```
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://example.com/Update.exe"), // URL zur Datei
    TEXT("Update.exe"), // Lokaler Name der Datei
    0,
    NULL);
```

Grüße,
Matthias


----------



## Rocky (5. April 2010)

Code

```
#include <iostream>
#include <windows.h>
#include <urlmon.h>

int main()
{
// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    L"http://example.com/Update.exe", // URL zur Datei
    L"Update.exe", // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  system("explorer /*Pfad*/ C:\\\Dokumente und Einstellungen\\\"");
}
else
{
  cout << "Fehler beim Download" << endl;
}
}
```

Fehler

```
1>------ Erstellen gestartet: Projekt: download, Konfiguration: Debug Win32 ------
1>Kompilieren...
1>main.cpp
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(13) : error C2664: 'URLDownloadToFileA': Konvertierung des Parameters 2 von 'const wchar_t [30]' in 'LPCSTR' nicht möglich
1>        Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(16) : warning C4129: 'D': Nicht erkannte Folge von Escapesequenz
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(20) : error C2065: 'cout': nichtdeklarierter Bezeichner
1>c:\dokumente und einstellungen\\eigene dateien\visual studio 2008\projects\download\download\main.cpp(20) : error C2065: 'endl': nichtdeklarierter Bezeichner
1>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\\Eigene Dateien\Visual Studio 2008\Projects\download\download\Debug\BuildLog.htm" gespeichert.
1>download - 3 Fehler, 1 Warnung(en)
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
```


----------



## sheel (5. April 2010)

Zeile 16: \\ reicht jeweils, statt \\\
Cout-Problem: Namespace noch einbinden

Und das mit dem TEXT wurde ja schon gesagt


----------



## Rocky (5. April 2010)

Jetzt is es nur noch 1 Problem:


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>
using namespace std;

int main()
{
// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://arcor.com/Terra23/DeckButler/DeckButler.zip"), // URL zur Datei
    TEXT("DeckButler.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  system("explorer C:\\Dokumente und Einstellungen\\");
}
else
{
  cout << "Fehler beim Download" << endl;
}
}
```


```
1>------ Erstellen gestartet: Projekt: download, Konfiguration: Debug Win32 ------
1>Kompilieren...
1>main.cpp
1>Verknüpfen...
1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_URLDownloadToFileA@20" in Funktion "_main".
1>C:\Dokumente und Einstellungen\?\Eigene Dateien\Visual Studio 2008\Projects\download\Debug\download.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
1>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\?\Eigene Dateien\Visual Studio 2008\Projects\download\download\Debug\BuildLog.htm" gespeichert.
1>download - 2 Fehler, 0 Warnung(en)
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
```


----------



## Cromon (5. April 2010)

Gemäss MSDN steht die FUnktion in folgender Bibliothek:
Import library	: Urlmon.lib


----------



## Rocky (5. April 2010)

Könnte mir jemnad bitte mal den richtigen code posten ich bin nämlich mit meinem "Latein" am Ende


----------



## Cromon (5. April 2010)

Du musst einfach diese Bibliothek importieren. Entweder über die Projekteinstellungen oder (falls vom Compiler unterstütz, da ich nicht ischer bin, ob es ein Teil des Standards ist) über #pragma comment(lib, "URLMon.lib")


----------



## Rocky (6. April 2010)

Ne scheint nicht zu gehen

gibt es vllt ne andere einfache lösung für nen download


----------



## Cromon (6. April 2010)

Der Code funktioniert einwandfrei, ich habe es gerade eben selbst getestet. Was klappt denn bei dir nicht?


----------



## sheel (6. April 2010)

Einfacher als das wird es wohl nicht mehr gehn.
Am Code ist auch überhaupt nichts mehr zu auszusetzen, du musst nur noch die Bibliothek dazuschreiben.

Was "geht nicht" bei der pragma-Methode? VS unterstützt das schon, wie lautet die Fehlermeldung?


----------



## Rocky (6. April 2010)

kompilieren lässt es sich nun..
Kann  man auch mehrere Dateien auf einmal so downloaden

Kann man evtl noch machen,dass die gedownloadeten daten dann in einen Ordner entzippt werden und danach die .zip ordner gelöscht werden?

Hier mal der momentane Code:


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>
using namespace std;

#pragma comment(lib,"URLMon.lib")

int main()
{
// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://example.de/download.zip"), // URL zur Datei
	TEXT("C:\\Programme\\download.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  cout << "Download erfolgreich" << endl;
  system("PAUSE");
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}
```


----------



## Rocky (6. April 2010)

kompilieren lässt es sich nun..
Kann  man auch mehrere Dateien auf einmal so downloaden

Kann man evtl noch machen,dass die gedownloadeten daten dann in einen Ordner entzippt werden und danach die .zip ordner gelöscht werden?

Hier mal der momentane Code:


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>
using namespace std;

#pragma comment(lib,"URLMon.lib")

int main()
{
// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://example.de/download.zip"), // URL zur Datei
	TEXT("C:\\Programme\\download.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  cout << "Download erfolgreich" << endl;
  system("PAUSE");
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}
```


----------



## Cromon (6. April 2010)

Ich weiss nicht, ob es vielleicht bereits eine asynchrone Methode von URL Moniker gibt, aber so wie ichs in der Referenz gesehen habe nicht, daher könntest du zum Downloaded wohl mehrere Threads verwenden. Einzige Möglichkeit für eine Nichtfunktionieren dessen wäre, wenn die COM-Objekte nicht auf Multithreading ausgelegt sind.

Entzippen kannst du das auch. Eine Möglichkeit wäre die Routinen zu verwenden, die du in zlib bei den contributes findest (minizip) oder wenn du davon ausgehst, dass der Endbenutzer Winrar installiert hat, wo kannst du auch einen Aufruf an Winrar starten.


----------



## Rocky (6. April 2010)

Wie müsste ich es dem programm beibringen,dass er mehrere nimmt habe es schon mit hintereinanderschreiben geht nicht,weils keine 7 argumente akzeptiert.

Hätte jemand evtl nen code zum entzippen?


----------



## Cromon (6. April 2010)

Eben, eine Möglichkeit wäre es, dass du pro Datei, die du downloaden möchtest einen eigenen Thread startest. Da müsstest du dann halt einfach auch schauen, dass sich nichts überschneidet und plötzlich mehrere Threads auf die gleiche Datei zugreiffen.

Zum Entzippen steht ja schon oben, wie du es machen könntest.


----------



## ComFreek (6. April 2010)

Ich habe gerade den Code in den Dev-C++ eingefügt. Er meldet, dass er die <i>urlmon.h</i> nicht finden kann. Kann mir jemand helfen?


----------



## Cromon (6. April 2010)

UrlMon ist Teil des Windows SDK, vermutlich hast du den Ordner deines SDKs nicht eingefügt (dann solltest du auch die windows.h nicht includieren können).


----------



## ComFreek (6. April 2010)

Also mit Dev-C++ habe ich bereits einige Windows-Applikationen erstellt. Bei <i>Windows.h</i> hat der keine Probleme.

*EDIT:* Habe es jetzt mit dem Borland C++ Builder versucht. Da musste ich noch die LIB-Datei linken und es hat funktioniert. Ein paar Sekunden später hat mein Viren-Scanner Alarm geschlagen. Ich musste den Scanner temporär ausschalten und noch dazu (habe Vista) musste ich das Programm mit Admin-Rechten ausführen.


----------



## Cromon (6. April 2010)

Das ist spannend. Windows.h und Urlmon.h liegen im gleichen Ordner  (Zu finden unter Programme\Microsoft SDKs\Windows\VERSION\include\UrlMon.h)


----------



## Rocky (6. April 2010)

Wie kann man mehrere Threads machen? Gibts irgenewo ein bsp. Wie man unzippen kann


----------



## ComFreek (6. April 2010)

@Cromon: Ich habe nicht so einen Ordner unter Programme. (Lies mal meinen vorherigen Beitrag, ich habe das Problem teilweise gelöst...)


----------



## Cromon (6. April 2010)

Es scheint so als hättest du das Windows SDK nicht installiert, sondern nur einfach ein paar wichtige Header, die Dev-C++ verwendet (würde dir grundsätzlich von diesem IDE abraten, so wie ich gehört habe wird er nicht mehr weiterentwickelt). Das mit dem Scanner kann durchaus sein, da ja versucht wird eine Verbindung zum Internet herzustellen. Je nach Sicherheitseinstellungen kann das als problematische Aktion angesehen werden.

@Rocky:
http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx

Da ist eigentlich alles nötige erklärt. Warte aber vielleicht noch ob jemand eine Methode kennt, dass Windows bereits asynchrone Downloads anbietet, was dann wohl bisschen einfacher wäre.


----------



## Matthias Reitinger (6. April 2010)

Hallo,

wieso müssen die Downloads denn unbedingt nebenläufig ausgeführt werden? Ein sequentieller Download ist einfacher zu realisieren und macht weniger Probleme.

Grüße,
Matthias


----------



## Rocky (6. April 2010)

Also ich möc&te,dass file1 und dann file2 (.zip) heruntergeladen werden und in ein im quelltext festgelegtes verzeichnis entzippt werden und dann die .zip gelœscht werden...

Könnte mir da jemand evtl was posten (code) kommentieren,dass ich verstehe wie sowas geht


----------



## Cromon (6. April 2010)

Ja, wie du Dateien runterlädst weisst du ja jetzt schon, das ist kein Problem. Bezüglich des Entpackens musst du wie gesagt mal überlegen, was du willst. Alles selbständig machen oder ein optional vorhandenes Programm verwenden (Winrar)?


----------



## ComFreek (6. April 2010)

Mit Windows selbst kann man auch ZIP-Ordner entpacken. Vielleicht gibt es ein Programm irgendwo im Windows-Ordner?


----------



## Rocky (6. April 2010)

Cromon hat gesagt.:


> Ja, wie du Dateien runterlädst weisst du ja jetzt schon, das ist kein Problem. Bezüglich des Entpackens musst du wie gesagt mal überlegen, was du willst. Alles selbständig machen oder ein optional vorhandenes Programm verwenden (Winrar)?



Also ich möchte dass es im programm mit drin ist also folgendermassen:

zipFile1 download
zipFile2 download
zipFile1 unzip
zipFile2 unzip
zipFile1 delete
zipFile2 delete

das mit dem download und dem löschen habe ich nun gelöst also bräuchte ich Hilfe beim "unzip" code sieht folgendermassen aus:


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>
using namespace std;

#pragma comment(lib,"URLMon.lib")

void db()
{
	// Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/DeckButler.zip"), // URL zur Datei
	TEXT("C:\\Programme\\DeckButler.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  cout << "DeckButler.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}

void dat()
{
// Datei herunterladen
HRESULT result2 = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/Programmdateien.zip"), // URL zur Datei
	TEXT("C:\\Programme\\Programmdateien.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result2 == S_OK)
{
  cout << "Programmdateien.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}

void remove()
{
	remove("C:\\Programme\\DeckButler.zip");
	remove("C:\\Programme\\Programmdateien.zip");
	cout << "Dateien geloescht" << endl;
	system("PAUSE");
}

int main()
{
db();
dat();
//remove();
}
```

komischerweise springt mein Virenscanner beim Kompilieren immer an und sagt es wäre eine "HEUR/MALWARE".

was ist da los
ich begreifs nicht


----------



## Cromon (6. April 2010)

Ja, aus heuristischer Sicht ist ein Download einer Datei ja auch anschlagwürdig!

Wenn du es im Programm drin haben willst wirst du nicht um eine Library wie zLib rumkommen. Da hats ein Contrib drin (minizip), das so viel ich weiss unzippen kann.


----------



## Rocky (6. April 2010)

Also ich habs jetzt geschafft,dass die Dateien gedownloaded und entpackt werden soweit ich es möchte...

Nun soll er die Datei die zum download führt (Down.exe) nach dem ausführen gelöscht werden und die Dateien die heruntergeladen werden in folgendes verzeichnis gemoved werden: "C:\Programme\DeckButler"..

Angehängt findet ihr die 3 Dateien 
Main.cpp
Unzip.cpp
Unzip.h

und das kompilierte Programm "Down.exe"


----------



## Cromon (6. April 2010)

Pushen ist nicht erlaubt, Rocky! Wie soll ein Programm sich selbst löschen? Da es gerade verwendet wird kann es ja nicht sich selbst löschen.


----------



## Rocky (6. April 2010)

Ich dachte evtl es erstellt eine bat datei die das programm nach dem schliessen schliest und sich dann löscht wenn das möglich wäre....

Wie würde das mit dem unzip in ein bestimmtes verzeichnis gehen?

Ein Verzeichnis zu erstellen schaffe ich schonmal jetzt sollten die Dateien nur noch in den ordner gemoved werden wie geht das?
Wäre gut,wenn auch ohne pfadangabe zur quelldatei!!

Aktualisierter Code im Anhang


----------



## Cromon (7. April 2010)

Cromon hat gesagt.:


> Pushen ist nicht erlaubt, Rocky!



Bitte halte dich daran!

Schau dir doch mal die Kommentare in der unzip.h an. Vielleicht findet sich ja da eine Beschreibung wie du den Ausgabepfad angeben kannst.


----------



## Markus Kolletzky (7. April 2010)

Lieber Rocky,

ich habe jetzt mehrfach Beiträge von dir löschen müssen die das Ziel hatten, dein Thema zu pushen.
Dies ist bei uns unerwünscht. Daher bitte ich dich hiermit, etwas Geduld walten zu lassen und
keine weiteren "Push-Beiträge" zu schreiben.

Danke und Gruß,
Markus


----------



## Rocky (7. April 2010)

Ich weiss nun,dass es mit "ZIP_filename" geht jedoch weiss ich jetzt nicht wie und. Wo ich es einfügen soll..
Könnte mir kemand ein beispiel an meiner "main.cpp",sofern das dorthinein gehört


----------



## Cromon (7. April 2010)

Was ist ZIP_filename? Das finde ich nirgends in der unzip.h. Wir liefern dir nicht den Code einfach so frei Haus, wir wollen dich dazu animieren selber zu überlegen und dann zum Ergebnis zu kommen, alles andere bringt dir im Endeffekt nichts


----------



## Rocky (7. April 2010)

Folgendes kann ich finden:


```
ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn);
ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len);
ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h);
// UnzipItem - given an index to an item, unzips it. You can unzip to:
// to a pipe:             UnzipItemHandle(hz,i, hpipe_write);
// to a file (by handle): UnzipItemHandle(hz,i, hfile);
// to a file (by name):   UnzipItem(hz,i, ze.name);
// to a memory block:     UnzipItem(hz,i, buf,buflen);
// In the final case, if the buffer isn't large enough to hold it all,
// then the return code indicates that more is yet to come. If it was
// large enough, and you want to know precisely how big, GetZipItem.
// Note: zip files are normally stored with relative pathnames. If you
// unzip with ZIP_FILENAME a relative pathname then the item gets created
// relative to the current directory - it first ensures that all necessary
// subdirectories have been created. Also, the item may itself be a directory.
// If you unzip a directory with ZIP_FILENAME, then the directory gets created.
// If you unzip it to a handle or a memory block, then nothing gets created
// and it emits 0 bytes.
ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir);
// if unzipping to a filename, and it's a relative filename, then it will be relative to here.
// (defaults to current-directory).
```

Ich gehe jetzt mal davon aus,dass man "// to a file (by name):   UnzipItem(hz,i, ze.name);" benutzen muss. Ich weiss allerdings nicht,wie ich es richtig mache.


----------



## Cromon (7. April 2010)

Du kannst im letzten Parameter den Ausgabenamen angeben. Du hast also deinen Basispfad, z.B. C: und fügst dann den internen Pfad der Datei an (den du ja in ze.name hast) und extrahierst dann dahin.


----------



## Rocky (7. April 2010)

Also wenn ich meine funktion void unzip1 nehme dann so:


```
void unzip1()
{
  //
  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { GetZipItem(hz,i,&ze);
    UnzipItem(hz,i,ze.name);
  }
```

void unzip1()
{
  //
  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { GetZipItem(hz,i,&ze);
    UnzipItem(hz,i,C:\\Programme\\Test);   <----------- "ze.name" durch pfad ersetzt
  }


----------



## Cromon (7. April 2010)

Also mal ein paar technische Sachen:
Nie mehr als ein Statement pro Zeile!
Nach geschweiften Klammern macht man immer eine neue Zeile für neuen Code

Und beim unteren fehlt der interne Pfad. Du müsstest C:\\Programme\\Test mit dem internen Pfad der Datei verbinden und dann als Parameter an UntzipItem übergeben.


----------



## Rocky (7. April 2010)

Das verstehe ich jetzt nicht ganz wie mit Parametern?

void unzip1()
{
  //
  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { 
    GetZipItem(hz,i,&ze);
    UnzipItem(hz,i,"C\\Programme\\Test\\Datei.txt);
  }

Also fûr jedes file das da drin ist eine neue
"UnzipItem(hz,i,"C:\\Programme\\Test\\Datei.endung");
machen oder?

Und woher kenne ich den internen pfad der datei aus dem zip file?


----------



## Cromon (7. April 2010)

Der Name der Datei ist in ze.name drin.


----------



## Rocky (7. April 2010)

Ja das weiss ich nur wie kann ich dem jetzt nen pfad zuweisen


----------



## Cromon (7. April 2010)

*sigh* Du musst dem nicht den Pfad zuweisen. Du musst Pfad und Dateiname (ze.name) verknüpfen und dann an UnzipFile übergeben. Zum Verknüfen kannst du std::string verwenden.


----------



## Rocky (7. April 2010)

Das verstehe ich nich könntest dus mir evtl mal schreiben,dass ichs verstehe weil ich verstehe davon gerade nixx


----------



## Cromon (7. April 2010)

std::string szBasePath = "C:\\Programme\\";
szBasePath += ze.name;

Damit hast du die beiden zusammengefügt.


----------



## Rocky (7. April 2010)

Habe es nun eingebaut aber er entpackt die Daten trotzdem noch ins Verzeichnis vom Programm (DeckButler downlaod.exe)
Ich möchte , dass die Dateien in folgenden Ordner entzippt werden: "C:\Dokumente und Einstellungen\BENUTZER\Eigene Dateien\DeckButler

wie kann man den "BENUTZER"-Ordner auswählen,da dieser bei allen anders heisst


```
#include <iostream>
#include <windows.h>
#include <urlmon.h>
#include <string>
#include <direct.h>
#include "unzip.h"
using namespace std;
 
#pragma comment(lib,"URLMon.lib")

void deckbutler()
{
    // Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/DeckButler.zip"), // URL zur Datei
    TEXT("C:\\Programme\\DeckButler.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  cout << "DeckButler.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}

void programmdateien()
{
// Datei herunterladen
HRESULT result2 = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/Programmdateien.zip"), // URL zur Datei
    TEXT("C:\\Programme\\Programmdateien.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result2 == S_OK)
{
  cout << "Programmdateien.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}

void remove()
{
    remove("C:\\Programme\\DeckButler.zip");
    remove("C:\\Programme\\Programmdateien.zip");
    cout << "Dateien geloescht" << endl;
    system("PAUSE");
	cout << endl;
}

void unzip1()
{

  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
	std::string szBasePath = "C:\\Programme\\Test\\";
    szBasePath += ze.name;
	GetZipItem(hz,i,&ze);
	UnzipItem(hz,i,ze.name);
  }
  CloseZip(hz);
}

void unzip2()
{
  //
  HZIP hz = OpenZip("C:\\Programme\\Programmdateien.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { GetZipItem(hz,i,&ze);
    UnzipItem(hz,i,ze.name);
  }
  CloseZip(hz);
}

void start()
{
	cout << "Programm starten? (j/n): ";
	char input = ' ';
	while ((input != 'j') && (input != 'J') && (input != 'n') && (input != 'N'))
	{
		cin.sync();
		cin.get(input);
	}
	if (input == 'j' || input == 'J')
	ShellExecute(NULL,"open","DeckButler.exe",NULL,NULL,SW_SHOWNORMAL);
}	

void login()
{
	string passwort;

	cout << "Passwort:";
	cin >> passwort;

	if(passwort=="DB")
	{
		deckbutler();
		programmdateien();
		unzip1();
		unzip2();
		remove();
		start();
	}
	else
	{
		cout << "Login failed" << endl;
		system("PAUSE");
	}
}

int main()
{
	login();
}
```

Hier könnt ihr euch mal die Programmdateien herunterladen:
http://www.file-upload.net/download-2416625/DeckButler-download.zip.html


----------



## Cromon (7. April 2010)

Dass es immernoch an den gleichen Ort extrahiert wird ist logisch, du verwendest ja immernoch ze.name als Parameter für UnzipItem.

Für den Benutzernamen.
http://msdn.microsoft.com/en-us/library/ms724432(VS.85).aspx


----------



## Rocky (7. April 2010)

Wie muss man den denn ändern

Ich habe es jetzt mal folgendermassen gemacht allerdings funktioniert es nicht


```
void unzip1()
{

  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
        std::string szBasePath = "C:\\Programme\\Test\\";
        szBasePath += ze.name;
	GetZipItem(hz,i,&ze);
	UnzipItem(hz,i,ze.name);
  }
  CloseZip(hz);
}
```


----------



## Cromon (7. April 2010)

Überleg doch mal: Der dritte Parameter von UnzipItem ist der Name der Ausgabedatei. Welche Variable beinhaltet den korrekten Ausgabepfad? Die musst du an UnzipItem übergeben.


----------



## Rocky (7. April 2010)

UnzipItem(hz,i,ze.name);

hz = Eingabe Ort
i = PFAD WOHIN    <-------------  das müsste der ausgabepfad sein oder
ze.name = Name der Ausgabedatei

ALSO:


```
void unzip1()
{
 
  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
        std::string szBasePath = "C:\\Programme\\Test\\";
        szBasePath = i;
    GetZipItem(hz,i,&ze);
    UnzipItem(hz,i,ze.name);
  }
  CloseZip(hz);
}
```


----------



## Cromon (7. April 2010)

Ok, jetzt bin sogar ich mit meiner Geduld am Ende, da kannst du dich wirklich "von" schreiben, das braucht einiges...


```
std::string szBasePath = "C:\";
szBasePath += ze.name;
UnzipItem(hz, i, szBasePath.c_str());
```


----------



## Rocky (7. April 2010)

na klar jetzt fällts mir auch wieder ein....

Könntest dus mir noch so machen,dass es auf 

C:\Dokumente und Einstellungen\BENUTZERNAME\

geht

bisher habe ich nur normal konsole ohne winapi gemacht deshalb verstehe ich davon nicht allzu viel


----------



## Cromon (7. April 2010)

Nein, das kannst du jetzt selber, du hast alle Funktionen und alles wurde bereits gezeigt, wie es funktioniert.


----------



## Rocky (7. April 2010)

ok..

es gibt nur noch ein prob und zwar hier:


```
void unzip1()
{
  HZIP hz = OpenZip("C:\\Programme\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
	std::string szBasePath = "C:\\Programme\\DeckButler\\";
    szBasePath += ze.name;
	GetZipItem(hz,i,&ze);
	UnzipItem(hz, i, szBasePath.c_str());
	//UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}

void unzip2()
{
  HZIP hz = OpenZip("C:\\Programme\\Programmdateien.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { 
	std::string szBasePath = "C:\\Programme\\DeckButler\\";
    szBasePath += ze.name;
	GetZipItem(hz,i,&ze);
	UnzipItem(hz, i, szBasePath.c_str());
	//UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}
```

Beide sollen ja ins gleiche Verzeichnis extrahiert werden jedoch extrahiert das programm nur die "Programmdateien" und den "DeckButler" nicht das verstehe ich nicht so ganz es hat doch davor so gut geklappt


----------



## Cromon (7. April 2010)

Entweder du rufst unzip1 nicht auf, DeckButler.zip existiert nicht oder die Dateien können da nicht erstellt werden.


----------



## Rocky (7. April 2010)

Das finde ich sehr komisch weil die Datei heruntergeladen wird und die "Programmdateien" in den Ordner entpackt werden...

Ich habe mal die "remove" funktion ausgeschaltet aber es wird trotzdem nicht dorthin gemacht...

Ganz verstehe ich es nicht hier mal der code:

http://www.file-upload.net/download-2417042/DeckButler-download.zip.html


----------



## Cromon (7. April 2010)

Du musst GetZipItem natürlich vor dem Zuweisen an den Pfad aufrufe, sonst hast du ja nicht den rechten Namen drin.


----------



## Rocky (7. April 2010)

Aso ja klar 

also anstatt


```
void unzippd()
{
  HZIP hz = OpenZip("C:\\Programme\\Programmdateien.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { 
    std::string szBasePath = "C:\\Programme\\DeckButler\\";
    szBasePath += ze.name;
    GetZipItem(hz,i,&ze);
     UnzipItem(hz, i, szBasePath.c_str());
     //UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}
```

folgendes:


```
void unzippd()
{
  HZIP hz = OpenZip("C:\\Programme\\Programmdateien.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  { 
    GetZipItem(hz,i,&ze);
    std::string szBasePath = "C:\\Programme\\DeckButler\\";
    szBasePath += ze.name;
    UnzipItem(hz, i, szBasePath.c_str());
    //UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}
```


----------



## Cromon (7. April 2010)

Genau, sonst extrahiert er nämlich zuerst keine Datei, dann die erste, dann die zweite, ... dann die n-1te und dann ist er fertig, die letzte wird nicht extrahiert.


----------



## Rocky (7. April 2010)

Habe nun versucht den User mithilfe von "%USERPROFILE%" zu bestimmen aber es scheint nicht zu klappen

hier mal der Code ich hoffe mal,dass ihr mir helfen könnt


```
#include <iostream>
#include <cstdlib.>
#include <windows.h>
#include <urlmon.h>
#include <string>
#include <direct.h>
#include "unzip.h" //zum entpacken nötig
 
using namespace std;
 
#pragma comment(lib,"URLMon.lib")
 
void deckbutler()
{
    // Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/DeckButler.zip"), // URL zur Datei
    TEXT("C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\DeckButler.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK)
{
  cout << "DeckButler.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}
 
void programmdateien()
{
// Datei herunterladen
HRESULT result2 = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/Programmdateien.zip"), // URL zur Datei
    TEXT("C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\Programmdateien.zip"), // Lokaler Name der Datei
    0,
    NULL);
if (result2 == S_OK)
{
  cout << "Programmdateien.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}
}
 
void start()
{
    cout << "Programm starten? (j/n): ";
    char input = ' ';
    while ((input != 'j') && (input != 'J') && (input != 'n') && (input != 'N'))
    {
        cin.sync();
        cin.get(input);
    }
    if (input == 'j' || input == 'J')
    {
    ShellExecute(NULL,"open","DeckButler.exe",NULL,NULL,SW_SHOWNORMAL);
    }
    else
    {
    }
}   
 
void remove()
{
    remove("C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\DeckButler.zip");
    remove("C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\Programmdateien.zip");
    cout << "Dateien geloescht" << endl;
    system("PAUSE");
    cout << endl;
}
 
void unzipdb()
{
  HZIP hz = OpenZip("C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
    GetZipItem(hz,i,&ze);
    //std::string szBasePath = "C:\\Programme\\DeckButler\\";
    std::string szBasePath = "C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\";
    szBasePath += ze.name;
    UnzipItem(hz, i, szBasePath.c_str());
    //UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}
 
void unzippd()
{
  HZIP hz = OpenZip("C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\Programmdateien.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
    GetZipItem(hz,i,&ze);
    //std::string szBasePath = "C:\\Programme\\DeckButler\\";
    std::string szBasePath = "C:\\Dokumente und Einstellungen\\%USERPROFILE%\\Eigene Dateien\\DeckButler\\";
    szBasePath += ze.name;
    UnzipItem(hz, i, szBasePath.c_str());
    //UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}

void menu()
{
	int menu;
	cout << "<1> Daten downloaden" << endl;
	cout << "<2> PM an Entwickler" << endl;
	cout << "Was moechten Sie tun:";
	cin >> menu;
	system("cls");
	if(menu==1)
	{
		deckbutler();
        programmdateien();
        unzipdb();
        unzippd();
        remove();
        start();
	}
	else if(menu==2)
	{
		ShellExecute(NULL,"open","http://etcg.de/forum/pms.php?action=newpm&userid=58167&subject=DeckButler download&message=Probleme,Anregungen,Bugs zum DeckButler download:",NULL,NULL,SW_SHOWNORMAL);
	}
}
 
void login()
{
    /*string passwort;
 
    cout << "Passwort:";
    cin >> passwort;
 
    if(passwort=="db")
    {*/
		menu();	
    /*}
    else
    {
        cout << "Login failed" << endl;
        system("PAUSE");
    }*/
}
 
int main()
{
    login();
}
```


----------



## Cromon (8. April 2010)

Wie ich bereits sagte: Für den aktuellen mit dem Prozess verknüpften Usernamen kannst du GetUserName verwenden.


----------



## Rocky (8. April 2010)

Also der Syntax dafür ist:

```
BOOL WINAPI GetUserName(
  __out    LPTSTR lpBuffer,
  __inout  LPDWORD lpnSize
);
```

den einfach in den code setzen und dann %USERNAME% oder wie genau

Ich habe bisher noch nicht wirklich viel mit WinAPI gearbeitet,deswegen weiss ich das nicht soo genau


----------



## ComFreek (8. April 2010)

Es war mal bereits ein Thema darüber im Forum. Guck mal hier: http://www.tutorials.de/forum/c-c/356696-getusername-c.html#post1851057


----------



## cwriter (8. April 2010)

Hallo

Ist es eigentlich auch möglich, den Status des Downloads anzuzeigen? Z.B.: "10% heruntergeladen..."
Zur Übersicht nochmals der Anfangscode:


```
HRESULT result = URLDownloadToFile(
    NULL,
    L"http://example.com/Update.exe", // URL zur Datei
    L"Update.exe", // Lokaler Name der Datei
    0,
    NULL);
if (result == S_OK) {
  // Verifizieren, Ausführen, etc.
} else {
  // Fehler beim Download
}
```

Gruss

cwriter


----------



## Cromon (8. April 2010)

Ja, kann man. Der vierte Parameter von URLDownloadToFile ist ein Zeiger auf eine Implementation von IBindStatusCallback. Da kannst du OnProgress implementieren.


----------



## cwriter (8. April 2010)

Danke für die schnelle Antwort. Was bedeuten diese Begriffe? Was tun diese Funktionen?

Danke

cwriter


----------



## Cromon (8. April 2010)

Wenn du in C arbeitest dürfte das schwer werden. IBindStatusCallback ist eine Klasse von der du erben musst und deren virtuelle Methoden du implementieren musst. Ob Windows da auch eine C-konforme Methode angeboten hat weiss ich nicht.

/Edit:
Habe nachgesehen, es wird eine C-konforme Methode verwendet mit structs und einer konstruierten VMT, wie du damit umgehst kann ich dir nicht sagen, da ich C++ verwende.


----------



## Rocky (8. April 2010)

Habe das Programm nun mal soweit wie es wirklich gut geht:


```
#include <iostream>
#include <cstdlib.>
#include <windows.h>
#include <urlmon.h>
#include <string>
#include <direct.h>
#include "unzip.h" //zum entpacken nötig
 
using namespace std;
 
#pragma comment(lib,"URLMon.lib")
 
void deckbutler()
{
    // Datei herunterladen
HRESULT result = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/DeckButler.zip"), // URL zur Datei
    TEXT("DeckButler.zip"), // Lokaler Name der Datei
    0,
    NULL);
/*if (result == S_OK)
{
  cout << "DeckButler.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}*/
}
 
void programmdateien()
{
// Datei herunterladen
HRESULT result2 = URLDownloadToFile(
    NULL,
    TEXT("http://home.arcor.de/Terra23/DeckButler/Programmdateien.zip"), // URL zur Datei
    TEXT("Programmdateien.zip"), // Lokaler Name der Datei
    0,
    NULL);
/*if (result2 == S_OK)
{
  cout << "Programmdateien.zip erfolgreich heruntergeladen" << endl;
  system("PAUSE");
  cout << endl;
}
else
{
  cout << "Fehler beim Download" << endl;
  system("PAUSE");
}*/
}
 
void start()
{
    cout << "Programm starten? (j/n): ";
    char input = ' ';
    while ((input != 'j') && (input != 'J') && (input != 'n') && (input != 'N'))
    {
        cin.sync();
        cin.get(input);
    }
    if (input == 'j' || input == 'J')
    {
    ShellExecute(NULL,"open","DeckButler\\DeckButler.exe",NULL,NULL,SW_SHOWNORMAL);
    }
    else
    {
    }
}   
 
void remove()
{
	remove("DeckButler.zip");
    remove("Programmdateien.zip");
    /*cout << "Dateien geloescht" << endl;
    system("PAUSE");
    cout << endl;*/
}
 
void unzipdb()
{
  HZIP hz = OpenZip("DeckButler.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
    GetZipItem(hz,i,&ze);
    string szBasePath = "DeckButler\\";
    szBasePath += ze.name;
    UnzipItem(hz, i, szBasePath.c_str());
    //UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}
 
void unzippd()
{
  HZIP hz = OpenZip("Programmdateien.zip",0);
  ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
  for (int i=0; i<numitems; i++)
  {
    GetZipItem(hz,i,&ze);
    string szBasePath = "DeckButler\\";
    szBasePath += ze.name;
    UnzipItem(hz, i, szBasePath.c_str());
    //UnzipItem(hz, i, ze.name);
  }
  CloseZip(hz);
}
 
int main()
{
	deckbutler();
	programmdateien();
	unzipdb();
	unzippd();
	remove();
	start();
}
```

Kann man irgendwie sagen , falls der ordner "DeckButler" existiert soll er ihn löschen und dann downloaden,unzippen....

wie geht des


----------



## Cromon (8. April 2010)

Du kannst zum Beispiel schauen, ob du eine Datei erstellen kannst mit CreateFile da wo du willst. Wenn ein ungültiger HANDLE zurückkommt und GetLastError ERROR_PATH_NOT_FOUND (= 0x03) liefert, dann existiert der Ordner nicht.


----------



## Rocky (9. April 2010)

Ich habe es jetzt nochmal modifiziert und bei mir läuft auch alles sehr gut nut bei einem freund nicht da gibt es nur folgenden Fehler:


```
diese anwendung konnte nicht gestartet werden, da die side-by-side-konfiguration ungültig ist. weitere informationen finden sie im anwendungsprotokol
```

woran kann das liegen

programmdateien im anhang


----------



## sheel (9. April 2010)

Die Meldung ist mir als XP-Nutzer zwar unbekannt, aber nur mal geraten:
Hast du beim Kompilieren nicht auf Release umgestellt?

edit: Ist laut Google doch ein Problem vom Betriebssystem, ab Vista
Hab auf die Schnelle keine garantierte Lösung gefunden


----------



## Cromon (9. April 2010)

In den Projekteinstellungen musst du unter C/C++ bei Codegenerierung sicherstelltn, dass kein -DLL verwendet wird (/MT oder /MTd). Damit wird die Runtime in die Exe einkompiliert und es wird nicht die Runtime als DLL von der Zielplattform bereits erwartet. Wer die Runtime nicht hat als DLL (Konkret: VC Redist nicht installiert) bekommt einen Side-by-Side Fehler.


----------



## cwriter (11. April 2010)

Hallo

Ich habe ein gröberes Problem mit URLDownloadToFile: Ich schreibe normalerweise mit Dev-C++ . Nur für den Download habe ich Microsoft VB++ heruntergeladen. Das damit erstellte Programm funktioniert gut, die Dateien werden korrekt heruntergeladen. Doch bei ausführen heisst es: "Dieses Programm ist nicht mit der ausgeführten Windows Version kompatibel[...]"

Ich habe ein 64bit Win 7 Home Premium. Die Fehlermeldung ist darum ärgerlich, weil der manuelle Download funktioniert und ich dann die Datei auch ausführen kann.
Nur die automatische Version versagt.

Kennt jemand eine Lösung für das Problem oder hat jemand eine gute Alternative für URLDownloadToFile?

Vielen Dank


cwriter


----------



## Cromon (11. April 2010)

Dass es nicht ausgeführt werden kann hat ja nichts mit URLDownloadToFile zu tun. Das liegt wohl eher am Filesystem.


----------



## cwriter (11. April 2010)

@Cromon:

Vielleicht habe ich es ja nicht so genau geschrieben: Manuell funktioniert es. Nur über das VB++ Programm funktioniert es nicht. 
Filesystem?

Gruss 

cwriter


----------



## Cromon (11. April 2010)

Du meinst VC++? Ja, beim manuellen Ausführen wird wohl etwas mehr getan für die Kompabilität zwischen 32Bit und 64Bit. Wie startest du denn das Programm "automatisch"?


----------



## cwriter (11. April 2010)

@Cromon

Oh, da habe ich mich wohl falsch ausgedrückt: 

Ein Programm funktioniert -> Upload auf Skydrive ->Download in Browser ->Ausführen  funktioniert

Update.exe ausführen ->Automatischer Download (Programm macht download) -> system("") funktioniert nicht / Ausführen der Heruntergeladenen Datei mit Doppelklick funktioniert nicht.

Ist jetzt klarer? (Sorry ich bin manchmal etwas schlecht im erklären.)

Gruss

cwriter


----------

