[Gelöst]Anwendung in neues Verzeichnis verschieben



  • Hallo,
    ich möchte dass sich meine Anwendung nach dem Starten in ein neues Verzeichnis verschiebt, dass sie sich selber erstellt. CreateDirectory() kenn ich und funktioniert auch, aber SetCurrentDirectory() verschiebt mir meine Anwendung irgendwie nicht. Hier ist mal mein C/C++ Code...

    #include "stdafx.h"
    #include <windows.h> 
    #include <fstream>
    
    int main()	{
       ofstream datei;
       string filename = "text.txt";
    
       if( !SetCurrentDirectory(L"C:\\testordner") )
       {
    	  /*Fehlerbehandlung*/ return -1;
       }
    
       datei.open(filename.c_str(),ios_base::out);
       datei.close();
    
       getchar();
       return 0;
    }
    

    Die datei "text.txt" wird zwar in "C:\testordner" erstellt aber die Anwendung befindet sich nicht in diesem Verzeichnis sondern in ihrem ursprünglichem. Habe ich SetCurrentDirectory()
    falsch verstanden oder habe ich einen anderen Fehler?
    Kennt jemand vieleicht eine andere möglichkeit, die dieser dann auch (per link) erklären kann?

    PS: Der Compiler zeigt mir keine Fehler an und "C:\testordner" existiert bei mir.

    thx im voraus 🙂



  • SetCurrentDirectory() setzt nur das "Arbeitsverzeichnis".
    Öffnest du eine Datei so:

    datei.open("bla.txt",ios_base::out);
    

    statt so:

    datei.open("c:\\blupp\\bla.txt",ios_base::out);
    

    ...dann legt Windows die bla.txt im Arbeitsverzeichnis an, auf die .exe hat SetCurrentDirectory() keinerlei Auswirkungen.

    "Datei öffnen" / "Datei speichern" Dialoge zeigen auch gerne beim Öffnen direkt erstmal das Arbeitsverzeichnis an.

    SetCurrentDirectory() erzeugt keine Ordner und verschiebt auch keine Ordner.
    Es wird vermutlich sogar meckern, wenn man nicht existierende Ordner angibt.

    D.h. mit CreateDirectory() bist du da schon näher an der Lösung.
    msdn: CopyFile() / MoveFile() / SHFileOperation() könnten nützlich sein 😉

    Edit: Virenscanner könnten sowas anmeckern. In der Regel verschiebt sich eine .exe eher selten selber 😉



  • Erstmal danke für deine schnelle antwort!!!
    Zweitens: Es geht mir nicht darum die datei "test.txt" in ein besonderes verzeichnis zu bekommen sondern meine exe soll in einem neuen verzeichnis landen.
    Das war wohl aber mein Fehler da ich unnötigerer weise darauf eingegangen bin.
    drittens: ich habe es mit SHFileOperation() und allen anderen möglichen funktionen, denk aber dass SHFileOperation() am ehesten zum Erfolg führt, probiert hat aber noch immer nicht funktioniert. 😞 Kann es sein das mein AntiVir (Avira) das blockiert ohne mir es zu sagen??Hier ist mal die funktion die ich geschrieben habe um meine exe zu verschieben:

    int verschieben(PCZZTSTR neuerPfad)
    {
    	TCHAR Buffer[MAX_PATH];
    	DWORD dwRet;
    
    	dwRet = GetCurrentDirectory(MAX_PATH,Buffer);
    	if(dwRet == 0 || dwRet > MAX_PATH)
    	{
    		/*Fehlerbehandlung*/ return -1;
    	}
    
    	SHFILEOPSTRUCTW shellstruct;
    	shellstruct.wFunc = FO_MOVE;
    	shellstruct.pFrom = Buffer;
    	shellstruct.pTo = neuerPfad;
    
    	SHFileOperation(&shellstruct);
    
    	return 0;
    }
    

    diese funktion wird dann natürlich noch in der main() aufgerufen.
    Hat jemand ne idee was falsch sein kann???



  • Wenn mich nicht alles täuscht, wird Deine exe-Datei vom OS während der Laufzeit schreibgeschützt. Das würde bedeuten, Du könntest sie zwar irgendwohin kopieren, aber nicht an dem Ort, von dem Du sie gestartet hast, löschen, dementsprechend auch nicht verschieben.



  • Für pFrom und pTo gilt:

    msdn schrieb:

    Note This string must be double-null terminated.

    Bei Strukturen würde ich sicherheitshalber auch vorher alles auf 0 setzen:

    ZeroMemory(&shellstruct,sizeof(SHFILEOPSTRUCT));
    

    ...sonst könnten schonmal nicht-gesetzte Member einer Struktur Probleme machen 😉

    ...und da du SHFILESTRUCTW benutzt:

    msdn schrieb:

    SHFILEOPSTRUCTW and SHFILEOPTSTRUCTA should never be used directly; the appropriate structure is redefined as SHFILEOPSTRUCT by the precompiler depending on whether the application is compiled for ANSI or Unicode.

    😉

    Eine laufende .exe kann man glaube ich schon verschieben/umbenennen (aber nicht löschen), aber das Verzeichnis in dem die .exe läuft nicht.


  • Mod

    Es kann ebenso sein, dass Du kene Rechte hast, auf das Zielverzeichnis oder das Quellverzeichnis, wenn es um C:\Program Files o.ä. geht.
    Dannn müsste Dein Programm elevated laufen.



  • Also ich habe jetzt die msdn aufmerksam durchgelesen habe hier die verbesserte form meiner verschieben-funktion...

    int verschieben(PCZZTSTR neuerPfad)//Hier setze ich "C:\\testordner ein"
    {
    	TCHAR Buffer[MAX_PATH];
    	DWORD dwRet;
    
    	dwRet = GetCurrentDirectory(MAX_PATH,Buffer);
    	if(dwRet == 0 || dwRet > MAX_PATH)
    	{
    		/*Fehlerbehandlung*/ return -1;
    	}
    
    	SHFILEOPSTRUCT shellstruct;
    	ZeroMemory(&shellstruct,sizeof(SHFILEOPSTRUCT));
    
            //So steht das in der msdn mit diesem '\\*\0'(double-null terminated)
    
    	PCZZTSTR dblZeroTerminated = L"\\*\0";    
    	neuerPfad =+ dblZeroTerminated;            
    
    	shellstruct.wFunc = FO_MOVE;
    	shellstruct.pFrom = Buffer;
    	shellstruct.pTo = neuerPfad;
    
    	SHFileOperation(&shellstruct);
    
    	return 0;
    }
    

    jetzt kommt mittendrin eine Fehlermeldung, dass der Ordner '\*' nicht existiert wenn ich dann allerdings auf den Button 'ordner erstellen' drücke, passiert wieder nichts.
    msdn für SHFILEOPSTRUCT
    http://msdn.microsoft.com/en-us/library/windows/desktop/bb759795(v=vs.85).aspx



  • Hier passiert nicht, was Du denkst:

    floorball schrieb:

    [...]
    
    	PCZZTSTR dblZeroTerminated = L"\\*\0";    
    	neuerPfad =+ dblZeroTerminated;            
    
            [...]
    

    Vielleicht fehlen Dir ein paar C-Grundlagen - Kenntnisse?



  • void test()
    {
    	TCHAR aktuellerPfad[MAX_PATH];
    	TCHAR neuerPfad[MAX_PATH];
    
    	// Pfad der .exe holen:
    	GetModuleFileName(NULL,aktuellerPfad,MAX_PATH);
    	// aktuellerPfad enthält jetzt 'c:\\bla\\blupp\\meine.exe'
    
    	// Dateiname abschneiden:
    	PathRemoveFileSpec(aktuellerPfad);
    	// aktuellerPfad enthält jetzt 'c:\\bla\\blupp'
    
    	// Neuen Pfad setzen:
    	lstrcpy(neuerPfad,"c:\\bla\\foo");
    
    	// Jeweils das zweite \0 dranhängen:
    	PathDoubleNull(aktuellerPfad);
    	PathDoubleNull(neuerPfad);
    
    	SHFILEOPSTRUCT sop; 
    	ZeroMemory(&sop,sizeof(SHFILEOPSTRUCT)); 
    
    	sop.wFunc=FO_MOVE;
    	sop.pFrom=aktuellerPfad;
    	sop.pTo=neuerPfad;
    
    	int returnVal=SHFileOperation(&sop);
    	if (returnVal!=0)
    	{
    		OutputDebugString(TEXT("Verdammt, SHFileOperation() ist fehlgeschlagen ;( \r\n"));
    		DebugBreak();
    	}
    	else
    	{
    		OutputDebugString(TEXT("Alles wunderbar ;D \r\n"));
    		DebugBreak();
    	}
    }
    
    // Position:  0  1  2  3  4   5
    // Vorhanden: A  B  C  D  \0      <= das ist unser str="ABCD"
    // Gewünscht: A  B  C  D  \0 \0   <= so muss es für SHFILEOPSTRUCT() aussehen
    // lstrlen("ABCD") = 4 = len
    // ...es müsste also noch str[len+1] auf '\0' gesetzt werden:
    void PathDoubleNull(TCHAR *str)
    {
       int len=lstrlen(str);
    
       str[len+1]='\0';
    }
    

    ungetestet 😉



  • @geeky:
    bin auch gerade fertig geworden 🙂 ist auch getestet.

    #include <windows.h>
    #include <cstdio>
    
    void moveTo(const char *alterOrdner, const char *neuerOrdner, const char *datei)
    {
    	char aO[MAX_PATH];
    	char nO[MAX_PATH];
    
    	//Quellordner um "\Dateiname" erweitern und in aO (alter Ort) speichern
    	lstrcpy(aO, alterOrdner);
    	if(aO[lstrlen(aO) - 1] != '\\')
    		lstrcat(aO, "\\");
    	lstrcat(aO, datei);
    
    	//Zielordner um "\Dateiname" erweitern und in nO (neuer Ort) speichern
    	lstrcpy(nO, neuerOrdner);
    	if(nO[lstrlen(nO) - 1] != '\\')
    		lstrcat(nO, "\\");
    	lstrcat(nO, datei);
    
    	//zweites Nullbyte gemäß SHFILEOPSTRUCT - Spezifikation anhängen
    	aO[lstrlen(aO) + 1] = 0;
    	nO[lstrlen(nO) + 1] = 0;
    
    	//SHFILEOPSTRUCT anlegen und vorbereiten
    	SHFILEOPSTRUCT sfo;
    
    	sfo.hwnd = 0;
    	sfo.wFunc = FO_MOVE;
    	sfo.pFrom = aO;
    	sfo.pTo = nO;
    	sfo.fFlags = FOF_SILENT;
    
    	SHFileOperation(&sfo);  //verschieben
    }
    
    int main(int argc, char **argv)
    {
    	char currDir[MAX_PATH];
    	char newDir[MAX_PATH];
    	char datei[MAX_PATH];
    
    	GetCurrentDirectory(MAX_PATH, currDir);  //aktuelles Verzeichnis
    
    	//Testverzeichnis im aktuellen Verzeichnis anlegen
    	lstrcpy(newDir, currDir);
    	lstrcat(newDir, "\\testDir");
    	CreateDirectory(newDir, 0); 
    
    	//Name der exe-Datei holen
    	GetModuleFileName(0, datei, MAX_PATH);
    
    	//Pfadnamen entfernen
    	char *datName = datei + lstrlen(datei);
    	while(datName > datei && *(datName - 1) != '\\')
    		--datName;
    
    	//Verschiebefunktion aufrufen
    	moveTo(currDir, newDir, datName);
    }
    


  • Das was ich oben geschrieben habe ist natürlich kompletter Schwachsinn!!!!! Ohne nachzudenken aus der msdn abgeschrieben...
    (Derartigen schwachsinn schreibe ich sonst nur in Lateinschulaufgaben ;))

    konnte euren code leider noch nicht testen werds aber bald machen.

    @Belli: sehr wahrscheinlich das mir noch irgendwo Grundlagen fehlen, da wir in der Schule nur Java (auf einem Niveau das bekommt jeder Schimpanse hin) programmieren und so meine C/C++ Kenntnisse aus dem Internet und mehr oder weniger guten Büchern basieren. zusätzlich programmiere ich C/C++ noch nicht sehr lange.



  • Shlussfazit:
    die methode von geeky funktioniert fantastisch, aber dazu ein paar anmerkungen:
    1.PathDoubleNull() muss vor der anderen funktion deklariert werden.
    2.PathRemoveFileSpec() benötigt "#include <Shlwapi.h>"
    3.PathRemoveFileSpec() benötigt "pragma comment (lib,"Shlwapi.lib)"
    4. Man kann PathRmoveFileSpec() weglassen und der Ordner der .exe wird nicht mitverschoben.

    @geeky & Belli vielen Dank für eure Hilfe


Anmelden zum Antworten