Verzeichnisstring ins 8.3 Format umwandeln



  • Hallo

    ich würde gerne einen Verzeichnispfad à la...
    C:\Dokumente und Einstellungen\Christoph\Lokale Einstellungen
    ...in...
    C:\Dokume1\Christ1\Lokale~1
    umwandeln lassen.

    Wie macht man das in C++ .NET? Man wird ja irgendwie auf Windows zugreifen müssen, weil man ja nicht weiß ob es "Dokume~1" oder "Dokume~6" heißt.

    Würde mich sehr freuen, wenn jemand einen Weg aufzeigen könnte.

    Gruß Christoph



  • Hmm... das einfachste ist "GetShortPathName"

    In .NET... mhhh... gibt es AFAIK nicht...



  • Danke erstmal!

    ja GetShortPathName hab ich vorher auch schon gegoogelt, aber ich habs nicht zum laufen gebracht.

    ich habe in der MSDN das hier gefunden:

    ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VSADD.v10.en/dncscol/html/csharp09192002.htm

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern int GetShortPathName(
    [MarshalAs(UnmanagedType.LPTStr)]
    string path,
    [MarshalAs(UnmanagedType.LPTStr)]
    StringBuilder shortPath,
    int shortPathLength);

    Gehört zwar zur Kategorie C# aber kann ich damit in C++ .Net was anfangen und wenn ja wie?

    Ich habe keine Ahnung, wie man dll's importiert, geschweige denn wo im Code ich sowas erledigen muss.



  • In C++/CLI kannst Du es einfach *aufrufen*!

    Nur:

    #include <windows.h>
    

    hinzufügen und *aufrufen*!

    Du brauchst *kein* DllImport!



  • Ja das habe ich auch schon mal probiert, aber dann bekomme ich selbst ohne die Funktion zu nutzen, nur durch #include <windows.h> hunderte Fehler. Ein paar verschiedene habe ich mal hier rein kopiert.
    Irgendwie gefällt im die windows.h wohl nicht. Und ich weiß nicht tun muss.

    Fehler 2 error C3699: "*": Diese Referenzierung kann nicht für den Typ "IDataObject" verwendet werden. C:\Programme\Microsoft Visual Studio 8\VC\PlatformSDK\include\objidl.h 7408

    Fehler 51 error C2872: 'IServiceProvider': Mehrdeutiges Symbol c:\programme\microsoft visual studio 8\vc\platformsdk\include\servprov.h 238

    Fehler 17 error C2872: 'IMessageFilter': Mehrdeutiges Symbol C:\Programme\Microsoft Visual Studio 8\VC\PlatformSDK\include\objidl.h 7885

    #include "StdAfx.h"
    #include "Hierarchie.h"
    #include "Verweise.h"
    #include <windows.h>
    
    using namespace System::Xml;
    using namespace Microsoft::Win32;
    using namespace System::Diagnostics;
    using namespace System::ComponentModel;
    
    CHierarchie::CHierarchie(int instancenumber)
    {
    
    ...
    ...
    


  • Mit windows.h muss man immer clr compilieren, nicht clr:safe oder clr:pure.



  • danke

    ja ich hatte es auf clr::safe stehen. Und jetzt habe ich es im Eigenschaftsmanager von VS umgestellt, aber es hat sich leider nichts geändert.

    Wenn ich die "windows.h" in eine "leeres" Form in einem neuen Projekt einfüge, dann beschwert sich VS nicht.
    Sobald ich aber irgendeine meiner selbst gemachten Klassen einbinde #include ".\Statistik.h" , kommen die Fehler von oben. Ich habe die Klasse mal gepostet. die cpp ist gekürzt, weil da eigentlich nichts besonderes drin ist, außer ein paar String-Operationen.
    Ich will das Forum ja nicht so zumüllen, aber bei Bedarf kann ich das natürlich vollständig posten.

    Statistik.h

    #pragma once
    #include ".\Entity.h"
    
    ref class CStatistik
    {
    private:
    	List<CEntity^>^ entities;
    public:
    	CStatistik(void);
    	int pruefevorhanden(String^ string);
    
    public:
    	bool Entity_Name_internal_mapping(String^ str);
    public:
    	bool Add_Entity(String^ tempstr);
    public:
    	bool Entity_Names_extern_mapping(String^ str);
    public:
    	int Klammern_gleiche_Ebene(String^ str,int anfang);
    public:
    	void sortieren(void);
    };
    

    Statisstik.cpp

    #include "StdAfx.h"
    #include "Statistik.h"
    
    CStatistik::CStatistik(void)
    {
    	entities = gcnew List<CEntity^>();
    	String^ str;
    	//String^ tempstr;
    	int i=0,j=0,k=0,/*stelle,*/rest=0;
    	OpenFileDialog^ ofd = gcnew OpenFileDialog;
    	ofd->InitialDirectory = "d:\\sa\\step";
    	ofd->Filter = "All files (*.*)|*.*";
    	ofd->FilterIndex = 2;
    	ofd->RestoreDirectory = true;
    	ofd->ShowDialog();
    	StreamReader^ sr = gcnew StreamReader(ofd->FileName);
    	do{
    		str=sr->ReadLine();
    	}while(!str->Contains("DATA;"));
    	str=sr->ReadLine();
    	while(!str->Contains("ENDSEC;")){
    		j=str->IndexOf('=');
    		if(str[j+1]!='('){
    			Entity_Name_internal_mapping(str);
    		}
    		else
    		{
    			Entity_Names_extern_mapping(str);
    		}
    		str=sr->ReadLine();
    	}
    	sortieren();
    	sortieren();
    	StreamWriter^ sw=gcnew StreamWriter(ofd->FileName+" Statistik.txt");
    	int summe=0;
    	for(i=0;i<entities->Count;i++){
    		sw->Write(Convert::ToString(entities[i]->get_quant()));
    		sw->Write("    ");
    		sw->WriteLine(entities[i]->get_name());
    		summe+=entities[i]->get_quant();
    	}
    	sw->Write("Summe:	");
    	sw->WriteLine(summe);
    	sw->Close();
    }
    
    int CStatistik::pruefevorhanden(String^ string){
    
    }
    
    bool CStatistik::Entity_Name_internal_mapping(String^ str)
    {
    
    }
    
    bool CStatistik::Add_Entity(String^ tempstr)
    {
    
    }
    
    bool CStatistik::Entity_Names_extern_mapping(String^ str)
    {
    
    }
    
    int CStatistik::Klammern_gleiche_Ebene(String^ str,int anfang)
    {
    
    }
    
    void CStatistik::sortieren(void)
    {
    
    }
    


  • using namespace System;
    using namespace System::Runtime::InteropServices;
    
    ref class Foo
    {
    public:
     [DllImport("kernel32.dll", CharSet = CharSet::Auto, SetLastError=true)]
    static int GetShortPathName(
        [MarshalAs(UnmanagedType::LPTStr)]
        String^ lpszLongPath,
        [MarshalAs(UnmanagedType::LPTStr)]
        System::Text::StringBuilder^ lpszShortPath,
        unsigned int cchBuffer);
    
    };
    

    Nächstesmal siehe:
    http://www.pinvoke.net/default.aspx/kernel32/GetShortPathName.html?DelayRedirect=1



  • Also erstmal Danke an alle Helfer!

    Wie ich es aus anderen Foren kenne, ist es normalerweise erwünscht, wenn jemand Feedback und endgültige Problemlösung gibt. Wenn nicht, einfach irgnorieren 😉

    - also auf Anweisung habe ich die <windows.h> eingebunden.
    - Dann ging erstmal nichts mehr 😃
    - Nachdem ich herausbekommen habe, dass sie die windows.h mit den namespaces System:: und System::Windows::Forms "gekabbelt" hat, habe ich die Namespaces herausgenommen und sie an die nötigen Stellen manuell hinzugefügt ( aus String^ wird dann System::String^)
    - wird bestimmt weniger umständlich gehen?!(für Verbesserungen bin ich immer offen)
    ->Dann nach ewigen herumprobieren mit tausend Casts und Konvertierungen kam das erwünschte Ergenis:

    D:\Programme\Dassault Systemes\B16\intel_a\code\bin\
    ->
    D:\PROGRA1\DASSAU1\B16\intel_a\code\bin\

    Ciao und Danke! Christoph

    char *szAnsi;
    szAnsi=static_cast<char*>(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(CatiaPath).ToPointer());
    LPCSTR ansistr = (LPCSTR) szAnsi;
    int len = MultiByteToWideChar(CP_UTF8, 0, ansistr, CatiaPath->Length, NULL, 0);
    LPWSTR unicodestr = (LPWSTR)malloc(len);
    int len2=MultiByteToWideChar(CP_ACP, 0, ansistr, -1, unicodestr, len);
    *(unicodestr+len)=(WCHAR)'\0' ;
    TCHAR szModuleShort[128];
    int result = GetShortPathName(unicodestr, szModuleShort, 2*len);
    

    Ich dachte schon ich wäre fertig, aber jetzt kommt ein Fehler.
    wenn ich die Funktion ein zweites mal benutzen will, dann geht die unicodestr nicht mehr("Nicht definierter Wert").
    wenn ich als Test die unicodestr direkt nach "malloc" wieder "free(unicodestr)" mache, geht es ohne Beanstandung.
    Wenn aber die Zeile...
    int len2=MultiByteToWideChar(CP_UTF8/*CP_ACP*/, 0, ansistr, longpath->Length/-1/, unicodestr, len);
    nach dem "malloc" und noch vor dem "free" ausgeführt wurde, geht das "free(unicodestr)" nicht mehr. Warum?



  • triumvirn schrieb:

    Nachdem ich herausbekommen habe, dass sie die windows.h mit den namespaces System:: und System::Windows::Forms "gekabbelt" hat, habe ich die Namespaces herausgenommen und sie an die nötigen Stellen manuell hinzugefügt ( aus String^ wird dann System::String^)
    - wird bestimmt weniger umständlich gehen?!(für Verbesserungen bin ich immer offen)

    Grundsätzlich ist "windows.h" durchzogen mit extrem viel nervigen Makros etc.

    Ich würde dir raten eine kleine Wrapperklasse zu schreiben wo du die Funktionen die du aus ihr brauchst bereitstellst, die windows.h aber nur in dessen Source includierst. Dann sollten deine Probleme zumindestens nur lokal für diese Klasse gelten und nicht Projektglobal.

    cu André


Anmelden zum Antworten