VARIANT Variable mit String füllen



  • Hi,

    ich bin ein absoluter Newbee und würde gerne folgenden Code für meine Anwendung benutzten: 🙄

    VARIANT vFilename;
    vFilename.vt = VT_BSTR;
    vFilename.bstrVal = SysAllocString(L"C:\\Dokument.doc");
    

    Wie kann ich "vFilename.bstrVar" mit einer Variablen, z. B. "CString Datei", füllen? 😕

    Danke!

    Gruß, Elayas



  • Hast Du schon zur der Frage ein Antwort?



  • Zusrt mal VariantInit aufrufen... dann sollte es doch passen, oder wo ist die Frage?



  • CString Datei = _T("C:\\Dokument.doc");
    
    VARIANT vFilename;
    VarInit(&vFilename);
    vFilename.vt = VT_BSTR;
    vFilename.bstrVal = SysAllocString(CStringW(Datei));
    

    Bzw. falls immer UNICODE verwendet wird kann man statt SysAllocString(CStringW(Datei)) auch einfach SysAllocString(Datei) schreiben.



  • Danke für die Antwort. Meine Frage, wenn ich ein variant Array aufbauen möchte und diese dann mit BSTR füllen möchte. Wie würde das gehen?
    Also:
    z.B
    VARIANT vsa;
    vsa.vt = VT_BSTR | VT_ARRAY;
    Es soll ein zwei dimensionaler Array aufgebaut werden, der dann gefüllt werden soll.

    z.B:

    vsa[1][1].bstrVal = "test";


  • Mod

    CString kann doch AllocSysString.

    Und wenn es um einen Array geht wirst Du mit SaferArrayCreate und SafeArrayAccessData arbeiten müssen.

    Willst Du wirklich einen VT_BSTR Array bauen?
    In den meisten Fällen in der Automation benötigt man einen Array von Variants die einen BSTR enthalten...



  • so http://www.c-plusplus.net/forum/317641
    Nur halt mit zwei Dimensionen.
    Also ein Array von SAFEARRAYBOUND und nDim = 2 bei SafeArrayCreate mitgeben.

    Wie das Layout von dem was SafeArrayAccessData zurückgibt dann ist bitte ggf. selbst ergoogeln.



  • Martin Richter schrieb:

    CString kann doch AllocSysString.

    Oops 🙂
    Ich mach einfach viel zu wenig mit MFC.

    Willst Du wirklich einen VT_BSTR Array bauen?
    In den meisten Fällen in der Automation benötigt man einen Array von Variants die einen BSTR enthalten...

    Ah! Guter Hinweis!
    Dann sollte ich das in dem anderen Thread wohl auch noch anmerken.



  • Hallo,

    danke für die schnelle Antwort. Ich möchte ein Variant aufbauen, in dem mehrere Strings enthalten sind. Wie eben ein Array.


  • Mod

    Ähhhh Rembrand? Was hat CString mit MFC zu tun?

    IMHO seit VS-2005 gehört CString zu ATL und ist ein freies Template, dass auch ohne jedes Framework benutzt werden kann.


  • Mod

    gast1 schrieb:

    danke für die schnelle Antwort. Ich möchte ein Variant aufbauen, in dem mehrere Strings enthalten sind. Wie eben ein Array.

    Dann erzeuge einen Array von BSTRs mit SafeArrayCreate...
    Dennoch erlaube ich mir mal die Frage: An wen willst Du das übergeben?
    Ich habe Definitiv noch keine COM-Schnittstelle gesehen die einen VARIANT mit einem VT_BSTR|VT_ARRAY übernimmt.
    Von VB-Script aus könnte man so was nicht mal erzeugen.



  • Laut diesem hier nutzt CString die MFC90.dll, nur CAtlString geht ohne MFC:

    CString, CStringA und CStringW werden in atlstr.h definiert und Exportieren von MFC90.dll. CStringT wird in cstringt.h definiert. Der folgende Satz von Zeichenfolgenklassen kann verwendet werden, ohne eine MFC-Bibliothek zu verknüpfen, mit oder ohne CRT-Unterstützung: CAtlString, CAtlStringA und CAtlStringW.

    http://msdn.microsoft.com/de-de/library/ms174288%28v=vs.110%29.aspx



  • Martin Richter schrieb:

    Ähhhh Rembrand?

    Versteh ich nicht 😕

    Was hat CString mit MFC zu tun?

    IMHO seit VS-2005 gehört CString zu ATL und ist ein freies Template, dass auch ohne jedes Framework benutzt werden kann.

    Jaaaaaaaaa 🙂
    Ich kenns von der MFC her, von daher ist das in meinem Hirn einfach mit MFC verknüpft. Ich mach aber auch kaum was mit ATL.
    Also richtiger...

    Oops 🙂
    Ich mach einfach viel zu wenig mit ATL oder MFC.



  • Hallo noch mal,

    &http://www.c-plusplus.net/forum/317641;
    Wie bekomme ich V_Array kennt mein Compiler nicht? Gibt es den keine einfachere Variante?

    VARIANT destArray;
    destArray.vt = VT_ARRAY | VT_BSTR;
    SAFEARRAYBOUND rgb [] = { 1, 0 };
    destArray.parray = SafeArrayCreate(VT_VARIANT, 2, rgb);
    

    und jetzt die einzelne Elemente ein Wert zuweisen

    destArray[1][1].bstrVal =  SysAllocString(L"1") ;
    


  • Nein, so einfach geht es nicht.
    Meinst du ich schreib den ganzen Code zum Spass oder was?

    Dass du statt V_ARRAY(&var) einfach var.parray schreibst ist OK - mehr macht das Makro auch nicht.
    Der Rest ist Quark.



  • Hallo,

    Du kannst auch einfach einen CComVariant erzeugen
    und einen CComBstr

    Diese beiden verkapseln den ganzen Vorgang recht praktisch;

    CComVariant covar;

    CComBstr bstr(_T"Hello World");

    covar += bstr;

    Grüße
    Karsten



  • Hallo,

    danke für die Antworten. Ich habe die Seite

    http://www.c-plusplus.net/forum/p2331676#2331676
    

    Angeguckt. Aber wie bekomme ich, wenn ich ein String Array habe dessen Werte in VARIANT diese ist mir leider nicht klar geworden.



  • Aber wie bekomme ich, wenn ich ein String Array habe dessen Werte in VARIANT diese ist mir leider nicht klar geworden.

    Das steht in dem Beitrag.
    Wenn du C++ kannst, dann lies was da steht.
    Wenn du nicht C++ kannst, tjoah, wie willst du dann verstehen wie man etwas mit C++ macht?

    Ansonsten: du darfst gerne gezielt Fragen stellen. Aber einfach nur so "ich versteh das nicht" und ich fange dann an jede Zeile zu erklären ... naja sagen wir so: falls das dein Plan war, kannst du lange warten.



  • Hallo Gast,

    ein Variantarray kannst Du so auslesen, zum Verständnis, ein
    Variant ist eine Union die eigentlich ein DWORD unter verschiedenen
    Datentypen ablichtet, das kann auch ein Zeiger auf Text oder sonnst was
    sein :

    Beispiel einer varianten initialisierung:
    VARIANT var;
    var.vt_type = VT_INT;
    var.val = 4711

    CComVariant covar(var); //der ComVariant initalisiert sich nun selbst als int
    das geht Dito für Text und auch mit CStringList.

    Pseudocode! bezüglich variantlist

    HRESULT tracevarlst(VARIANT varSelectionList)
    {
       HRESULT hRes = S_FALSE;
    
       if(varSelectionList.vt != (VT_ARRAY | VT_VARIANT) || varSelectionList.parray == NULL)
       {
    	 return hRes;
       }
    
       CComVariant covarDescriptor;
       register SAFEARRAY * psaSelectionList = varSelectionList.parray;
       register long  Vstart = psaSelectionList->rgsabound->lLbound;
       register long  Vcnt   = psaSelectionList->rgsabound->cElements;
    
       for(register long i=Vstart; i < Vstart+Vcnt; i++)
       {
    		hRes = SafeArrayGetElement(psaSelectionList, &i, &covarDescriptor);
    		if(FAILED(hRes))
    		 break;
    
    		if(covarDescriptor.vt != VT_BSTR)
    		{
    		  hRes = covarDescriptor.ChangeType(VT_BSTR);
    
    		  if(FAILED(hRes))
    		    break;
    		}
    
    		TRACE(_T("[%s],"),CString(covarDescriptor.bstrVal));
       }
    
       return hRes;
    }
    

    Hier Prinzip zum befüllen.. (ungetestet als Hinweis)

    CComVariant *andersrum(void)
    {
       TCHAR test[11][]={"1","1","1","1","1","1","1","1","1","1","1"};
       HRESULT hRes = S_FALSE;
    
       static CComVariant    covarDescriptor;//zum testen hier mal
    
       register long  start    = 0;
       register long  cnt      = 0;
    
       //Create Save Array to store results in a VARlist
       SAFEARRAYBOUND  size    = {cnt,start};//start is here null
       register SAFEARRAY      *psaResult = SafeArrayCreate(VT_VARIANT, 1, &size);
       if(psaResult == NULL)
         return hRes;
    
       for(register long n=start;n<10; n++)
       {
         size.cElements++;
    	 hRes = SafeArrayRedim(psaResult,&size);
         if(FAILED(hRes))
           break;
    
    	 covarDescriptor = CString(&test[n][0]);
    	 hRes = SafeArrayPutElement(psaResult, &n, &covarDescriptor);
    	 if(FAILED(hRes))
    	  break;			
       }
    
       if(hRes == S_OK )
       {
        VariantInit(pvarRecordValues);
    	(*pvarRecordValues).parray = psaResult;
        (*pvarRecordValues).vt = VT_ARRAY | VT_VARIANT;
       }else SafeArrayDestroy(psaResult);
    
       return &covarDescriptor;
    }
    


  • Achromat schrieb:

    ...
       for(register long i=Vstart; i < Vstart+Vcnt; i++)
       {
    		hRes = SafeArrayGetElement(psaSelectionList, &i, &covarDescriptor);
    		if(FAILED(hRes))
    		 break;
    
    		if(covarDescriptor.vt != VT_BSTR)
    		{
    		  hRes = covarDescriptor.ChangeType(VT_BSTR);
    
    		  if(FAILED(hRes))
    		    break;
    		}
    
    		TRACE(_T("[%s],"),CString(covarDescriptor.bstrVal));
       }
    ...
    

    Das leakt.
    Der 3. Parameter von SafeArrayGetElement ist "out". D.h. es wird das was da vorher dort steht blind überschrieben - OHNE Cleanup. D.h. das was vorher dort steht darf keinen Cleanup erfordern.
    VT_BSTR erfordert aber Cleanup.

    => du leakst (Vcnt - 1) BSTR s.

    Fix:
    covarDescriptor.Clear(); vor dem SafeArrayGetElement() machen.

    ps:

    Achromat schrieb:

    register long ...
    

    *facepalm*


Log in to reply