Marshal.h nicht vorhanden



  • Hallo zusammen,

    ich wollte mir wie hier ein System::String^ in eine normale Charzeichenfolge umwandeln mittels

    msclr::interop::marshal_context c3;
    const char *us3 = c3.marshal_as<const char*>(s);
    

    Nur hab ich jetzt das Problem, das ich

    #include <msclr/marshal.h>
    #include <msclr\marshal_cppstd.h>
    

    nicht einbinden kann, da er beides nicht findet, bzw. ich auch nix auf der Festplatte habe. Ich nutze MV C++ 2008 Express Edition. Wie komme ich am besten an die Dateien, bzw. woran kann es liegen das mir diese fehlen?

    Und wenn ich nur

    msclr::interop::marshal_context
    

    nutze um ein

    const char*
    

    zu erzeugen, brauche ich die marshal_cppstd.h doch nicht, oder? Bei MSDN steht ja nur was von der marshal.h

    Grüße



  • Tio schrieb:

    Hallo zusammen,

    Herzlich Willkommen im Forum 😃

    Tio schrieb:

    Ich nutze MV C++ 2008 Express Edition. Wie komme ich am besten an die Dateien, bzw. woran kann es liegen das mir diese fehlen?

    Auf der Suche nach der Datei bin ich auf folgendes Posting im Forum gestoßen und da gehts genau um diese Datei(en). Anscheinend gibt es diese Datei(en) nicht bei der Express Version von Visual Studio.

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-227314.html

    Desweiteren wird hier hingewiesen das man dann die anderen Möglichkeiten vom diesem Post nehmen sollte: www.c-plusplus.net/forum/viewtopic-var-t-is-158664.html+system::string+in+char&hl=de&ct=clnk&cd=1&gl=de

    Gruß
    Rudi G



  • Danke für deine schnelle Antwort.

    Ja den thread hab ich auch gefunden, nur leider hat er mir nicht wirklich geholfen.
    Und jetzt mal dumm gefragt, kann man die nicht irgendwo runterladen und selber in den Ordner kopieren? Gibt es da keine Möglichkeit ranzukommen, kann das garnicht glauben.

    Ich hab jetzt mal versucht es nach der oberen Methode zu machen und habe folgende Anwendung jetzt:

    const char *first = (LPCSTR) StringConvA(laden);
    const char *second = (LPCSTR) StringConvA(textBox1->Text);
    system( "bla.exe " + first + " " + second );
    

    Wie man sieht will ich eine *.exe starten und 2 Parameter mit übergeben.
    Leider bekomme ich dazu folgende Fehlermeldung:

    error C2679: Binärer Operator '+': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operanden vom Typ 'const char *' akzeptiert (oder keine geeignete Konvertierung möglich)
    1>        kann 'eingebauter C++ Operator+(volatile const System::Object ^, volatile const System::String ^)' sein
    1>        oder "integrierter C++-Operator+(volatile const System::String ^, volatile const System::Object ^)"
    1>        oder "integrierter C++-Operator+(volatile const System::String ^, volatile const System::String ^)"
    1>        bei Anpassung der Argumentliste '(System::String ^, const char *)'
    

    Liegt die Fehlermeldung jetzt an den const chars, oder an dem System-Befehl? Sorry für die Frage, aber ich bin noch etwas neu in der ganzen Problematik.

    Grüße



  • Tio schrieb:

    Liegt die Fehlermeldung jetzt an den const chars, oder an dem System-Befehl? Sorry für die Frage, aber ich bin noch etwas neu in der ganzen Problematik.

    Grüße

    An der Zeile mit dem System-Befehl.

    Den Operator "+" benutzt du ja nur in der Zeile, die Zeiger kann man nicht Addieren.

    Du musst die Zeiger Deferenzieren, das heißt du deutlich machen das du den Wert auf den die Zeiger zeigen addieren möchtest und nicht die Zeiger (bzw. die Adressen).

    Das könntest du machen in dem du vor dem Zeiger ein * setzt:

    const char *first = (LPCSTR) StringConvA(laden);
    const char *second = (LPCSTR) StringConvA(textBox1->Text);
    
    // mit dem * vor den Zeigern sage ich das ich den Wert davon addieren möchte
    system( "bla.exe " + *first + " " + *second );
    

    Tio schrieb:

    Und jetzt mal dumm gefragt, kann man die nicht irgendwo runterladen und selber in den Ordner kopieren? Gibt es da keine Möglichkeit ranzukommen, kann das garnicht glauben.

    Glaub ich kaum und wenn du die Datei bekommen könntest, es könnte dann aber so sein das diese Datei weitere Dateien includiert die nur bei den nicht Express-Version dabei sind.

    Gruß
    Rudi G



  • Abermals danke für die schnelle Antwort,Rudi G. Von alleine wäre ich da wohl jetzt nie drauf gekommen.

    Ich hab noch etwas rumprobiert und jetzt kompieliert es. Es sieht so aus:

    const char *a = (LPCSTR) StringConvA("bla.exe ");
    const char *b = (LPCSTR) StringConvA(laden);
    const char *c = (LPCSTR) StringConvA(" ");
    const char *d = (LPCSTR) StringConvA(textBox1->Text);
    const char *buf = (char*)*a+*b+*c+*d;
    system((char*)*a+*b+*c+*d);
    

    die festen Strings muss ich auch umwandeln, weil sie sonst als System::String^ gehandhabt werden. Leider stimmt der Gesamtstring trotzdem nicht. Das Programm wird nicht ausgeführt, aber ich habs mit der Komandozeile getestet, es funktioniert. Also muss es am Zusammenbau des Gesamstrings liegen. Leider habe ich keine Idee was ich noch ändern könnte.

    So siehst im Debugger aus:
    http://www.bilder-space.de/thumb/08.01p2O7EgNni5WmAva.jpg

    Aber da das Pointer sind, sieht man dort ja nur die Speicherstelle und nicht den Wert, deswegen muss es noch nciht falsch sein, oder? Mich wundert es aber, das buf als char* und der Rest nur als char angezeigt wird.

    Was könnte jetzt noch bei den Strings falsch sein. Kann ich mir die Strings irgendwie im Debugger anschauen?

    Grüße

    edit:
    Im Debugger kommt folgende Fehlermeldung, wenn ich den System-Befehl ausführe:

    Eine nicht behandelte Ausnahme des Typs "System.AccessViolationException" ist in GUI.exe aufgetreten.

    Zusätzliche Informationen: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

    Wenn ich die fertige Exe direkt ausführe als Admin (hab Vista und einige Lese- und Schreibzugriffe in andere Ordner) kommt folgendes:
    Unbehandelte Ausnahme in der Anwendung. (...) Es wurde versucht, im geschützen Speicher zu lesen oder zu schreiben.

    Aber ich hab wie gesagt meine bla.exe schon mit der Kommandozeile getestet, da gings auch in andere Ordner, glaube nicht das es daran liegt.

    edit2:
    wenn ich meine bla.exe mittels Batchdatei starte klappt auch alles wunderbar. Wenn ich jetzt allerdings die Batch in meiner GUI starte mittels:

    system("start.bat");
    

    bekomme ich eine FEhlermeldung mit "Unbehandelter Ausnahme" und "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."
    Bei Details steht folgendes:

    Informationen über das Aufrufen von JIT-Debuggen
    anstelle dieses Dialogfelds finden Sie am Ende dieser Meldung.

    ************** Ausnahmetext **************
    System.AccessViolationException: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.
    bei system(SByte* )
    bei GUI.Form1.button4_Click(Object sender, EventArgs e) in (der Zeile mit dem System-Befehl).
    bei System.Windows.Forms.Control.OnClick(EventArgs e)
    bei System.Windows.Forms.Button.OnClick(EventArgs e)
    bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    bei System.Windows.Forms.Control.WndProc(Message& m)
    bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
    bei System.Windows.Forms.Button.WndProc(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    ************** Geladene Assemblys **************
    mscorlib
    Assembly-Version: 2.0.0.0.
    Win32-Version: 2.0.50727.3053 (netfxsp.050727-3000).
    CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll.
    ----------------------------------------
    GUI
    Assembly-Version: 1.0.3295.3658.
    Win32-Version: .
    CodeBase: xxx
    ----------------------------------------
    msvcm90d
    Assembly-Version: 9.0.30729.1.
    Win32-Version: 9.00.30729.1.
    CodeBase: file:///C:/Windows/WinSxS/x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.1_none_bb1f6aa1308c35eb/msvcm90d.dll.
    ----------------------------------------
    System
    Assembly-Version: 2.0.0.0.
    Win32-Version: 2.0.50727.3053 (netfxsp.050727-3000).
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll.
    ----------------------------------------
    System.Windows.Forms
    Assembly-Version: 2.0.0.0.
    Win32-Version: 2.0.50727.3053 (netfxsp.050727-3000).
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll.
    ----------------------------------------
    System.Drawing
    Assembly-Version: 2.0.0.0.
    Win32-Version: 2.0.50727.3053 (netfxsp.050727-3000).
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll.
    ----------------------------------------
    mscorlib.resources
    Assembly-Version: 2.0.0.0.
    Win32-Version: 2.0.50727.3053 (netfxsp.050727-3000).
    CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll.
    ----------------------------------------
    System.Windows.Forms.resources
    Assembly-Version: 2.0.0.0.
    Win32-Version: 2.0.50727.3053 (netfxsp.050727-3000).
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms.resources/2.0.0.0_de_b77a5c561934e089/System.Windows.Forms.resources.dll.
    ----------------------------------------

    ************** JIT-Debuggen **************
    Um das JIT-Debuggen (Just-In-Time) zu aktivieren, muss in der
    Konfigurationsdatei der Anwendung oder des Computers
    (machine.config) der jitDebugging-Wert im Abschnitt system.windows.forms festgelegt werden.
    Die Anwendung muss mit aktiviertem Debuggen kompiliert werden.

    Zum Beispiel:

    <configuration>
    <system.windows.forms jitDebugging="true" />
    </configuration>

    Wenn das JIT-Debuggen aktiviert ist, werden alle nicht behandelten
    Ausnahmen an den JIT-Debugger gesendet, der auf dem
    Computer registriert ist, und nicht in diesem Dialogfeld behandelt.

    Ich bin für jeden Hinweis dankbar 🙂

    Grüße



  • 1. Es ist nicht gut, wenn Du C++/CLI und "normales" C mischt... also verwende lieber "Process::Start" anstelle von "system"
    2. Der String, der von StringConvA zurückgegeben wird ist nur in dieser einen Zeile gültig!!! Wenn Du den String anschliessend noch verwenden willst, so verwende einen std::string oder _strdup



  • Tio schrieb:

    const char *a = (LPCSTR) StringConvA("bla.exe ");
    const char *b = (LPCSTR) StringConvA(laden);
    const char *c = (LPCSTR) StringConvA(" ");
    const char *d = (LPCSTR) StringConvA(textBox1->Text);
    const char *buf = (char*)*a+*b+*c+*d;
    system((char*)*a+*b+*c+*d);
    

    Kann das sein das die Variable laden vom Typ System::String^ ist?

    Wenn ja verwende den Befehl Process::Start den Jochen Kalmbach dir im letzten Post genannt hat. Bei dem Befehl solltest du dann auch System::String^ direkt benutzen und den müsstest du addieren können.

    Desweiteren hat meine Lösung das du ein * als Deferenzierungsoperator vor dem Zeiger setzten musst nicht ganz richtig.

    Ich habe erst heute die möglichkeit gehabt das mal zu testen, bei dem Dereferenzieren wir der Wert der Adresse angezeigt auf die der Zeiger zeigt und der Zeiger zeigt nun mal immer auf das erste Element.

    Deswegen hast du nur ein Buchstabe in den Variablen.

    Tio schrieb:

    die festen Strings muss ich auch umwandeln, weil sie sonst als System::String^ gehandhabt werden. Leider stimmt der Gesamtstring trotzdem nicht.

    siehe oben, sorry habe hier was falsches behauptet.

    Gruß
    Rudi G



  • const char *buf = (char*)*a+*b+*c+*d;
    

    Man kann unmanaged Strings nicht "addieren"! Verwende String. Oder, wenn Du es unbeding mittels unmanaged Code machen willst, setze Dich mit strcpy, strcat auseinander.



  • Jochen Kalmbach schrieb:

    1. Es ist nicht gut, wenn Du C++/CLI und "normales" C mischt... also verwende lieber "Process::Start" anstelle von "system"

    Das ist wirklich perfekt, jetzt siehst so bei mir aus und klappt super:

    Process::Start("bla.exe",laden+" "+(textBox1->Text));
    

    Und dmait fällt auch die ganze Stringumwandlung weg. Ich hatte nur gegoogelt wie man eine exe startet und bin nur auf den System-Befehl und irgendwie per shell gestoßen. Der System-Befehl sah aber einfacher aus, ich hab garnicht gemerkt das das ein C-Befehl ist.

    Rudi G schrieb:

    Kann das sein das die Variable laden vom Typ System::String^ ist?

    Ja, ich baue mir eine GUI mit C++/CLI und .NET. ODer anders gesagt, ich hab beim Projekttyp auf Windows Forms Anwendung geklickt 😃 Sorry falls das oben nicht richtig rüber kam.

    Ein Glück das das mit den Stringumwandlung jetzt wegfällt, das kann ja richtig kompliziert werden. Trotzdem danke euch beiden für die Hilfe.

    Eine Frage hätte ich noch. Gibt es eine Möglichkeit die Zeit zu messen, wie lange es dauert bis die bla.exe abgearbeitet ist. Es würde mir schon helfen wenn ich ein paar Klassennamen weiß, wo ich mich bei MSDN umschauen kann.

    Nochmal vielen Danke Euch beiden für die Hilfe.

    Grüße

    edit:

    Process^ myProcess = gcnew Process;
    try
    {
    myProcess->StartInfo->FileName="bla.exe";
    myProcess->StartInfo->CreateNoWindow=true;
    myProcess->StartInfo->Arguments = laden+" "+(textBox1->Text);
    //start Zeitmessung
    myProcess->Start();
    myProcess->WaitForExit();
    //ende Zeitmessung
    //Messagebox mit Zeit
    }
    catch ( Win32Exception^ e ) 
    {
    Console::WriteLine( "{0}", e->Message );	
    }
    

    Ich habe es jetzt so umgebogen um die Zeitmessung einbauen zu können. Ich werd das jetzt probieren, aber über Vorschläge oder Klassen, die man sich dafür anschauen sollte wäre ich dankbar. Hab bei sowas immer das Problem das ich nicht weiß, welche Klassen ich mir bei MSDN anschauen muss, und auch nicht weiß wie ich das am besten rausfinde 🙄



  • System::Diagnostics::Stopwatch



  • Jochen Kalmbach schrieb:

    System::Diagnostics::Stopwatch

    vielen Dank. Ich hab alles mit "time" abgesucht, aber auf "watch" bin ich nicht gekommen. Gibt es eine andere Möglichkeit einem unbekannte Klassen zu finden, außer die Namen zu raten?

    Process^ myProcess = gcnew Process;
    Stopwatch^ sw = gcnew Stopwatch;
    try
    {
    myProcess->StartInfo->FileName = "bla.exe";
    						 myProcess->StartInfo->CreateNoWindow = true;
    						 myProcess->StartInfo->Arguments = laden+" "+(textBox1->Text);
    //start Zeitmessung
    sw->StartNew();
    if (myProcess->Start())
    							myProcess->WaitForExit();
    //ende Zeitmessung
    sw->Stop();
    System::Int64 a = sw->ElapsedMilliseconds;
    textBox1->Text = a;
    
    label2->Text = a.ToString();
    System::TimeSpan dt = myProcess->StartTime - myProcess->ExitTime
    }
    catch ( Win32Exception^ e ) 
    {
    Console::WriteLine( "{0}", e->Message );	
    }
    

    So siehts jetzt bei mir aus, falls es wen interessiert ^^
    Ich bekomme aber eine Zeit von 0ms 😞 Bla.exe hat nicht allzuviel zu tun, aber ein bisschen was berechnet wird da schon. Blockiert das WaitForExit() evtl. die Zeitmessung? Und dt liefert mir auch komische Werte, ich hab zB

    Ticks	-4620000	__int64
    TotalMilliseconds	-462.00000000000000	double
    

    Woran liegt es das die Zeitmessung mit beiden Methoden nicht funktioniert?

    Grüße



  • Hat keiner eine Idee?



  • process^ myProcess = gcnew Process;
    Stopwatch^ sw = gcnew Stopwatch;
    try
    {
    myProcess->StartInfo->FileName = "bla.exe";
    myProcess->StartInfo->CreateNoWindow = true;
    myProcess->StartInfo->Arguments = laden+" "+(textBox1->Text);
    //start Zeitmessung
    sw->Start();
    if (myProcess->Start())
                                myProcess->WaitForExit();
    //ende Zeitmessung
    sw->Stop();
    System::Int64 a = sw->ElapsedMilliseconds;
    textBox1->Text = a;
    
    label2->Text = a.ToString();
    System::TimeSpan dt = myProcess->ExitTime - myProcess->StartTime;
    }
    catch ( Win32Exception^ e )
    {
    Console::WriteLine( "{0}", e->Message );   
    }
    

    geändert, funktioniert jetzt, falls es jmd. interessiert ^^


Anmelden zum Antworten