www.mikrocontroller.net

Forum: PC-Programmierung Visual C++ CRT Linker-Problem?


Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo miteinander...


Ich hatte heute einen wunderbaren Vortrag in der Schule bei dem es um 
ein kleines Projet (Sensor mit MCU auswrten und entsprechendes C++ 
Programm) geht.
Aus mehreren Gründen hatte ich zuhause und im Betrieb meine Umgebung in 
Visual C++ Express 2008 geschrieben. Soweit so gut. Die Anwendung 
funktionierte auch überall (mehrere PC's und Notebooks im Betrieb und 
bei mir zuhause getestet, alle mit Win XP und >= SP2).
Doch wie schon oft, ist ein guter Kollege von mir Murphy heute wieder 
mal im Schulzimmer anwesend gewesen...
Ich konnte zwar die Releas-Datei ausführen, aber die Datei selber lief 
nicht ganz so wie sie es sollte:
-> Automatische Sensor/MCU Suche über RS232 funktionierte nicht, die 
Software wollte einfach nichts finden...
-> 2. Versuch: Statisch den Comport zuweisen und konntinuierlich die 
Messwerte abfragen -> keine Antwort

die Kommunikation mit dem MCU läuft einwandfrei (Terminal und Borland 
CPP)
Hat jemand eine Ahnung, wieso es nicht mit Visual C++ läuft??

hab mich mal zwischendurch selber etwas im www umgesehen, und bin auf 
folgendes Thema gestossen:
- Statisch Linken... CRT
Dort wird aber jeweis beschrieben, dass beim Ausführen der EXE-Dateien 
schon Fehlermeldungen erscheinen, ist bei mir aber nicht so...

Ich weiss echt nicht weiter (Ihr könnt euch ja sicherlich vorstellen, 
wie dann die Präsentation noch verlief...)

Danke für die Infos
MFG
Patrick

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, das geschilderte ist definitiv kein Linkerproblem.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:

> Ich weiss echt nicht weiter (Ihr könnt euch ja sicherlich vorstellen,
> wie dann die Präsentation noch verlief...)

Kann ich.
Was lernen wir daraus?
Mach eine Präsentation nie auf einem Rechner, den du vorher noch nie in 
den Fingern hattest. Spätestens 1 Tag vorher eine Präsentation 
duchspielen. Dabei auch den Rechner runterfahren und neu starten und 
kontrollieren obs dann immer noch geht.

> Danke für die Infos

Welche Infos?
Zu welcher Frage? Du hast zwar viel geschrieben aber keine verwertbare 
Information gegeben.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die Kommunikation mit dem MCU läuft einwandfrei (Terminal und
> Borland CPP)

Woher weißt du das?

> Hat jemand eine Ahnung, wieso es nicht mit Visual C++ läuft??

Hast du dir ins Programm ein paar Testausgaben eingebaut?
Kannst du mit Sicherheit (zb dadurch dass dir eine Messagebox "ok" bzw. 
"nicht ok" gibt) sagen, dass der COM Port geöffnet werden konnte? Wenn 
du Kommandos zur MCU schickst, was schickt sie dann zurück? Kennst du 
den Text (oder die Bytes bei binärer Kommunikation) den die MCU 
zurückschickt? Hast du dir das mal ausgeben lassen?

Stochern im Nebel bringt dich nicht weiter. Du musst Debuggen! Wenn du 
auf dem Zielsystem keinen Debugger hast, dann muss eben das Programm dir 
Debug-Info geben. Mach dir Ausgaben rein. Alles und jedes was dich 
interessiert wird in einer Messagebox (oder auf stdout bei einem 
Command-Line Porgramm) ausgegeben, damit du eben nicht im Nebel 
stocherst, sondern nachvollziehen kannst, was wann warum im Programm 
geschieht.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Welche Infos?
> Zu welcher Frage? Du hast zwar viel geschrieben aber keine verwertbare
> Information gegeben.

Die Frage lautete, ob jemand weiss an was dass das liegen kann?


>> die Kommunikation mit dem MCU läuft einwandfrei (Terminal und
>> Borland CPP)

>Woher weißt du das?

ganz einfach:
auf der MCU Ebene mussten wir so Standarttockens vom Lehrer verwenden 
('{' senden und '}' zurückbekommen oder '?' senden und Systeminfos 
zurückkriegen)
Dies lief mit mehreren Terminals wunderbar.

PC Seitig habe ich die ersten Versuche auf Borland gemacht: * senden und 
Messwerte erhalten...

Das Problem war jetzt volgendes: die Suche läuft so ab: @ senden und 
Systemname als Antwort überprüfen. * senden Messwert empfangen
Nur lief das Programm nur beim Schul-PC bei der suche von ComPort 1 bis 
50 durch und fing wieder vorne an. Ohne beim Com10 den MCU zu finden.
wenn ich Com10 als Standart eingestellt habe, sendete er ein * empfieng 
dann aber nichts. => keine Verbindung.

OK, das ob der Comport überhaupt geöffnet werden konnte habe ich nicht 
überprüft, und das werde ich erst in 3 Wochen wieder nachschauen können.

Das Interessante daran war, dass das Programm auf einem CAD PC, auf 
einem normalen PC (ca 3jährig) und einem älteren Notebook einwandfrei 
lieft.
Alle hatten XP und >= SP2 aber nur auf den PC's war VC++ Express 
installiert.

Ist es möglich, dass der Comport nicht geöffnet werden konnte, selbst 
wenn das identische Programm verwendet wurde?

Was ist, wenn die Schul-PC's nicht sauber aufgesetzt wurden? kein 
aktuelles Framework? kann das einen Einfluss haben, auf nur gewisse 
Teile des Programms?

MFG
Patrick

Auf den Schul-PC's ist Borland 2007, VC++ 2006, XP Pro, SP2 und noch 
andere Software drauf, da die PC's vorallem für GAL, C und C++ verwendet 
werden, in dem Schulzimmer...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist es möglich, dass du immer noch nicht begriffen hast, dass man 
Fehlerursachen nur in den seltensten Fällen richtig erraten kann.

Schau deinem Programm auf die Finger!
Wenn du einen Debugger hast, dann lass das Programm im Debugger laufen 
und sieh nach was schief geht, indem du Returnwerte ansiehst, Variablen 
verfolgst und generell den Programmfluss im Debugger verfolgst.
Wenn du keinen Debugger hast, dann bau Ausgaben ins Programm ein, die 
die gleiche Aufgabe erfüllen.

Alles andere ist Stochern im Nebel und Ratespielchen spielen. Es ist 
müssig darüber zu spekulieren was warum nicht funktioniert. Spekulieren 
machen die Banker und Wahrsager. Wir sind Techniker. Wir sehen uns die 
harten Fakten an und entscheiden dann. Dazu benötigt man aber Mittel und 
Wege um sich die Fakten zu besorgen.
Methoden dazu (im konkreten Fall)
* Debugger
* Ausgaben ins Programm einbauen

In jedem Programm, welches länger als 10 Zeilen ist, gibt es tausende 
Möglichkeiten, was schief gehen kann! Vor allen Dingen dann, wenn 
Systemcalls oder Systemresourcen im Spiel sind.

> OK, das ob der Comport überhaupt geöffnet werden konnte habe ich
> nicht überprüft,

Das ist schon mal der erste Fehler.
Man überprüft IMMER, ob die Allokierung eines Gerätes gut gegangen ist.

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sind das immer noch die Routinen aus dem anderen Thread?
Beitrag "comtools Baudrate höher als 57600?"

Falls ja, sieh dir mal den zitierten Teil der Funktion ComOpen an, dazu 
hComFile, bIsOpen und MAX_COM_PORTS...
int ComOpen(unsigned Nr,int Baud,int Parity,int Stopbits,int Databits) {
    ...
    if (Nr >= MAX_COM_PORTS) return 0;
    if (bIsOpen[Nr]) return 0;

    cName[7] = '1' + Nr;

    hFile = CreateFile(cName, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE) {
        hFile = 0;
        return 0;
    }

    ...

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem muss für Schnittstellennummern > 9 eine andere Syntax für deren 
Namen verwendet werden:

  COM1 .. COM9

aber

  \\.\COM10 .. \\.\COM256

In einer C-String-Konstanten ist \ das Escapezeichen und muss also \\ 
geschrieben werden:
   hFile = CreateFile("\\\\.\\COM13", GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Ist es möglich, dass du immer noch nicht begriffen hast, dass man
> Fehlerursachen nur in den seltensten Fällen richtig erraten kann.
Dem stimme ich dir zu, nur bin ich ratlos, da das identische programm 
auf mehreren Rechnern mit unterschiedlichen OS und Benutzeraccounts 
funktioniert hat, und dann plötzlich nicht mehr.

>> OK, das ob der Comport überhaupt geöffnet werden konnte habe ich
>> nicht überprüft,
>
> Das ist schon mal der erste Fehler.
> Man überprüft IMMER, ob die Allokierung eines Gerätes gut gegangen ist.
hätte ich lieben gerne in der Schule gemacht, nur ist dor Visual C++ 
2006 und Borland 2007 installiert. Da ich mein Projekt aber in Visual 
C++ 2007 erstellt hatte und dafon eine Release-Version benutzte, konnte 
ich auch mit noch so guten Absichten am Programm selber nichts ändern. 
Leider konnte ich auch nicht Visual C++ 2007 installieren (fehlende 
Adminrechte auf dem Laufwerk C und auf dem Persönlichen auch nicht.)
Die Debuggerei so wie du sie beschreibst mit Labels hatte ich, da wie 
üblich das ganze Programm nicht von Anfang an so lief, wie ich es wollte 
(Probleme mit Substrings, und Timern... => zu schnelles Abfragen)

Arc Net schrieb:
> Sind das immer noch die Routinen aus dem anderen Thread?
> Beitrag "comtools Baudrate höher als 57600?"
>
> Falls ja, sieh dir mal den zitierten Teil der Funktion ComOpen an, dazu
> hComFile, bIsOpen und MAX_COM_PORTS...
Ja, es sind die gleichen Klassen aber ein anderes Projekt. Mal abgesehen 
davon, dass ich MAX_COM_PORTS so definiert habe
#define   MAX_COM_PORTS  50
und nicht die Defines der COM1 bis COM4 verwende, und den Sensor (RTC 
DS1307) so suche
  private: System::Void timerSearch_Tick_1(System::Object^  sender, System::EventArgs^  e) {       
       static unsigned int comport;                // Zählvariable für Comports
       static int loops = 0;                    // Suchdurchläufe
       static int search = 0;                    // Toggeln Anfrage, Antwort
       if( (timerSearch->Tag == "0") && (loops < searchLoops) && (buttonSearch->Tag == "1") ){  
                                    // Wenn RTC nicht schon gefunden
         labelDS1307info->Text = "search";            // Anzeige
         labelComInf->Visible = false;
         if(search == 0){
          if( ComOpen(comport,baud,P_NONE,S_1BIT,D_8BIT) ){  // Test ob Comport nicht verwendet
            ComWrite(comport,'@');              // Anfrage für Systemname 
            search = 1;                    // Antwort abwarten
          }
          else{                        // Comport schon belegt, nächster
            comport ++;  
            if(comport == 50){                 // max bis Com50
              comport = 0;
              loops ++;                  // Begrenzte Suchdurchläufe
            }
          }
        }
        else{                          // Abfrage
          if( ComGetReadCount(comport) != 0 ){        // Wenn eine Antwort vorhanden
            int i,q,ok;
            char id[]={"rtc_ds1307"};            // Systemname zum Abgleich
            char response[50];                // Zwischenvariable für RX-String
            i = ComRead(comport,response,14);        // max 14 Zeichen auslesen
            for(q = 0; q < 10; q++){            // Systemname vergleichen
              if(response[q] = id[q]) ok = 1;        // Charakter stimmt
              else ok = 0;                // Charakter stimmt nicht
            }
            if(ok){                      // Wenn alle Charakteren stimmen
              timerSearch->Tag = System::Convert::ToString(comport+1);
                                    // Comport an Membervariable übergeben
            }
            else{
              ComClose(comport);
            }
          }
          else{                        // keine Antwort
            ComClose(comport);                // ComPort schliessen
            comport ++;                    // nächster Comport 
            if(comport == 50){                // max 50
              comport = 0;
              loops ++;                  // Begrenzte Suchdurchläufe
            }
            search = 0;                    // Anfrage senden
          }
        }
        if( loops >= searchLoops){                // Keine RTC gefunden
          labelDS1307info->Text = "No DS1307 found\nCheck the connection";
          labelComInf->Visible = true;
          labelComInf->Text = "Unterstützte Comports:\n1 bis 50";
          buttonSearch->Visible = true;            // Suchbutton freigeben
          loops = 0;                      // Variblen zurücksetzen
          comport = 0;
          buttonSearch->Tag = "0";
        }
       }
       labelCom->Text = "ComPort: " + System::Convert::ToString(comport + 1);
                                    // Angezeigter ComPort-Wert
     }
hätte das doch nie und nimmer auf 4 anderen Rechnern laufen dürfen, wenn 
der FT232 einen höheren Comport als 9 installiert hätte (Dumme Eigenheit 
der FT232 ist, dass JEDER Chip sich eine neue Schnittstelle installiert: 
50 Geräte mit USB RS232 Wandler entsprechen 50 "vorgemerkten" Comports, 
die man manuel zurücksetzen kann/muss)


@  Rufus t. Firefly
Bei der ComTool-Klasse ist dies schon vordefiniert (die ersten Zeilen 
der ComOpen Funktion):
static const int  iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
static const int  iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
TCHAR        cName[]=Z("\\\\.\\COM1");
HANDLE        hFile;
COMMTIMEOUTS    sTo;
DCB          sDcb;

  if(Nr>=MAX_COM_PORTS)return 0;
  if(bIsOpen[Nr])return 0;

  cName[7]='1'+Nr;

     hFile= CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:
> @  Rufus t. Firefly
> Bei der ComTool-Klasse ist dies schon vordefiniert (die ersten Zeilen
> der ComOpen Funktion):
>
> static const int
> iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
> static const int
> iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
> TCHAR        cName[]=Z("\\\\.\\COM1");
> HANDLE        hFile;
> COMMTIMEOUTS    sTo;
> DCB          sDcb;
> 
>   if(Nr>=MAX_COM_PORTS)return 0;
>   if(bIsOpen[Nr])return 0;
> 
>   cName[7]='1'+Nr;
> 
>      hFile=
> CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
> 

Die Zeile
cName[7]= '1' + Nr; 
generiert so allerdings immer noch nicht die richtigen Strings...

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 private: System::Void timerSearch_Tick_1(System::Object^  sender, System::EventArgs^  e) {       

Das ist kein C++ und erst recht kein C, sondern "Managed C++", eine 
MS-Perversion, um das .Net-geraffel mit einer C++-artigen Sprache 
programmieren zu können.

Mit einem Borland-Compiler kann man das nicht übersetzen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:
> Karl heinz Buchegger schrieb:
>> Ist es möglich, dass du immer noch nicht begriffen hast, dass man
>> Fehlerursachen nur in den seltensten Fällen richtig erraten kann.
> Dem stimme ich dir zu, nur bin ich ratlos, da das identische programm
> auf mehreren Rechnern mit unterschiedlichen OS und Benutzeraccounts
> funktioniert hat, und dann plötzlich nicht mehr.

Vergiss das gleich wieder.
Interessiert nicht wirklich.
Es gibt einen Rechner auf dem es nicht funktioniert und dem muss man 
nachgehen. Irgendetwas im Programm stimmt nicht und bei einigen (vielen) 
fällt das nicht auf.

Suche die Schuld erst mal nicht bei den unterschiedlichen OS Versionen 
oder Accounts, das ist praktisch immer eine Sackgasse (*), sondern suche 
die Schuld in deinem Programm und wie es auf diese Unterschiede nicht 
richtig reagiert.

(*) vor allen Dingen deshalb, weil du ohnehin nichts dagegen tun kannst. 
Dein Programm muss sich an das OS anpassen, nicht umgekehrt.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arc Net schrieb:
> Die Zeile
>
> cName[7]= '1' + Nr;
> 
> generiert so allerdings immer noch nicht die richtigen Strings...

wie müsste diese den aussehen?? Es war die Rede von den beiden \\, wenn 
ich mich nicht täusche


Rufus t. Firefly schrieb:
> Mit einem Borland-Compiler kann man das nicht übersetzen.
Das sagte ich auch nie, ich sagte lediglich, dass Borland installiert 
ist, aber das Programm mit Visual C++ erstellt und damit auch eine 
Releasdatei erstellt wurde.


Ich werde mich über die Ferien wohl noch ein wenig mit dem Problem 
beschäftigen, vielleicht finde ich den Fehler...
ein Ansatz ist das Problem, das Arc Net beschreibt.

Danke für die Beiträge...
MFG
Patrick

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:
> Arc Net schrieb:
>> Die Zeile
>>
>> cName[7]= '1' + Nr;
>> 
>> generiert so allerdings immer noch nicht die richtigen Strings...
>
> wie müsste diese den aussehen?? Es war die Rede von den beiden \\, wenn
> ich mich nicht täusche

Na, indem man sich zb mit sprintf den String aus den konstanten Teilen 
und der Zahl zusammensetzt.
Bestimmt hast du auch eine String-Klasse zur Verfügung, mit der man da 
arbeiten kann.

Alles ist gut, ausser von einem fixen Format auszugehen und ein 
einzelnes Zeichen direkt im ASCII Code da reinzupfriemeln.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs noch nicht gerallt:

hast du die auf einem Rechner erstellete .exe-Datei auf einem Anderen 
ausgeführt und dann gings nicht?

Oder hast du das Quell-Code-Projekt auf jedem Rechner in der 
Entwicklungsumgebung geöffnet und von dort aus probiert es zu starten?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke, er ist in das klassische Problem aller Windows Entwickler 
geraten. Auf einem Rechner ein EXE gebaut um festzustellen, dass es auf 
einem anderen nicht richtig läuft.
Kennt jeder der Windows-Software verkauft. Bei 100 Kunden hast du immer 
ein paar dabei, bei denen es einfach nicht so will, wie vorgesehen. Ist 
der Kunde gutmütig, kann man das eventuell aussortieren. Ist er nicht 
gutmütig, dann hat es keinen Sinn: Geld zurück und hoffen, dass ein 
anderer Kunde das gleiche Problem hat, mitspielt und bereit ist ein paar 
mit MessageBoxen gespickte Programmversionen durchzutesten.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, hab den Fehler gefunden:
Es ist genau das, was Arc Net beschrieben hat: die ComPorts ab 9 lassen 
sich nicht öffnen...
(hab mal die Ports manuell geändert und siehe da, es läuft nicht... das 
label sagt auch, dass sie nicht zu öffnen sind)

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry, aber ich kappiers einfach nicht. hab gerade nen riesen 
blackout...
TCHAR        cName[]=Z("\\\\.\\COM1");
cName[7]='1'+Nr;

der String sieht doch so aus: \\\\.\\COM1 oder?? an der 8ten Stelle ist 
aber nicht die Zahl sondern das C oder werden die 3 ersten \ ignoriert??

ausserdem wie handhabe ich jetzt das ganze mit createfile, da bei COMs 
über 9 irgendwie nicht gleich zu öffnen sind?

das einzige was ich im moment sehe ist, dass es irgenwie so gehen 
sollte:
String cName = "\\\\.\\COM"+System::Convert::ToString(Nr);
hFile= CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
aber dann hab ich das Problem dass cName kein LPCWSTR ist.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:
> sorry, aber ich kappiers einfach nicht. hab gerade nen riesen
> blackout...
>
>
> TCHAR        cName[]=Z("\\\\.\\COM1");
> cName[7]='1'+Nr;
> 
>
> der String sieht doch so aus: \\\\.\\COM1 oder?? an der 8ten Stelle ist
> aber nicht die Zahl sondern das C oder werden die 3 ersten \ ignoriert??
[/c]

Der String steht im Speicher als '\\.\COM1' und das C steht an der 5. 
Stelle.

Ich frage mich, aus welchen hirnverbrannten Gründen man sich bei Windows 
und anderen unbedingt für den Rückstrich als Pfadtrenner entscheiden 
musste.

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:
> sorry, aber ich kappiers einfach nicht. hab gerade nen riesen
> blackout...
>
>
> TCHAR        cName[]=Z("\\\\.\\COM1");
> cName[7]='1'+Nr;
> 
>
> der String sieht doch so aus: \\\\.\\COM1 oder?? an der 8ten Stelle ist
> aber nicht die Zahl sondern das C oder werden die 3 ersten \ ignoriert??

\ ist in einem C-String ein Escape-Zeichen (\n, \t, \" oder eben \\ für 
einen \ der im String auftauchen soll)

> ausserdem wie handhabe ich jetzt das ganze mit createfile, da bei COMs
> über 9 irgendwie nicht gleich zu öffnen sind?

\\.\COM12345 geht immer


> das einzige was ich im moment sehe ist, dass es irgenwie so gehen
> sollte:
>
> String cName = "\\\\.\\COM"+System::Convert::ToString(Nr);
> hFile=
> CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
> 
> aber dann hab ich das Problem dass cName kein LPCWSTR ist.

char cName[40];
sprintf(cName, "\\\\.\\COM%d", Nr)
bzw. sprintf(cName, "\\\\.\\COM%u", Nr) wenn Nr unsigned ist
http://msdn.microsoft.com/en-us/library/56e442dc(V...


Sven P. schrieb:
> Ich frage mich, aus welchen hirnverbrannten Gründen man sich bei Windows
> und anderen unbedingt für den Rückstrich als Pfadtrenner entscheiden
> musste.

Warum nutzt man auf anderen Systemen ein Trennzeichen, das durchaus 
sinnvoller Bestandteil eines Names sein kann?
Wobei auch das bei Windows nicht geht, da es dort die Trennung von / und 
\ eigentlich noch nie gab (ausser bei UNC-Pfaden)...
http://blogs.msdn.com/larryosterman/archive/2005/0...
Und aus
http://msdn.microsoft.com/en-us/library/aa365247(V...
"Note  File I/O functions in the Windows API convert "/" to "\" as part 
of converting the name to an NT-style name, except when using the "\\?\" 
prefix as detailed in the following sections."

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arc Net schrieb:
> char cName[40];
> sprintf(cName, "\\\\.\\COM%d", Nr)
> bzw. sprintf(cName, "\\\\.\\COM%u", Nr) wenn Nr unsigned ist

Nach einer Warnung habe ich sprintf_s verwendet, aber wie schon vorher 
erwähnt, hab ich jetzt das Problem, dass ich den char nicht in LPCWSTR 
convertieren kann.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arc Net schrieb:
> Warum nutzt man auf anderen Systemen ein Trennzeichen, das durchaus
> sinnvoller Bestandteil eines Names sein kann?
So wie man |\?*<":>+[]/ bis Win95 verboten hat?

sprintf_s kannste dir schenken, der Sicherheitsgewinn tendiert dabei 
gegen Null.

Für das WSTR-Gedöhns vermutlich sowas: MultiByteToWideChar
Einfacher gehts, wenn du vor die Stringkonstante ein L setzt und dann 
mit dem breitzeichenverträglichen sprintf arbeitest.

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:
> Arc Net schrieb:
>> Warum nutzt man auf anderen Systemen ein Trennzeichen, das durchaus
>> sinnvoller Bestandteil eines Names sein kann?
> So wie man |\?*<":>+[]/ bis Win95 verboten hat?
>
> sprintf_s kannste dir schenken, der Sicherheitsgewinn tendiert dabei
> gegen Null.

sprintf_s ist eigentlich ganz sinnvoll, da die max. Anzahl der Zeichen 
übergeben werden muss und zum anderen garantiert wird, dass der 
generierte String null-terminiert ist.

>
> Für das WSTR-Gedöhns vermutlich sowas: MultiByteToWideChar
> Einfacher gehts, wenn du vor die Stringkonstante ein L setzt und dann
> mit dem breitzeichenverträglichen sprintf arbeitest.

oder CreateFileA statt CreateFile

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arc Net schrieb:
> Sven P. schrieb:
>> sprintf_s kannste dir schenken, der Sicherheitsgewinn tendiert dabei
>> gegen Null.
>
> sprintf_s ist eigentlich ganz sinnvoll, da die max. Anzahl der Zeichen
> übergeben werden muss und zum anderen garantiert wird, dass der
> generierte String null-terminiert ist.
[ ] ich kenne snprintf

Ist sogar ISO-C.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, hab jetzt ein wenig herumgespielt und das Resultat ist zwar, dass 
der Compiler keine Fehlermeldung mehr bringt, wegen 
Convertierungsproblemen, aber jetzt lässt sich kein Comport mehr öffnen, 
weder die über 9 noch 1 bis 9.

neu sehen die erstel Zeilen der ComOpen-Funktion so aus:
int ComOpen(unsigned Nr,int Baud,int Parity,int Stopbits,int Databits)
{
static const int  iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
static const int  iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
//TCHAR        cName[]=Z("\\\\.\\COM1");
char           cName[40];
HANDLE         hFile;
COMMTIMEOUTS   sTo;
DCB            sDcb;

  if(Nr>=MAX_COM_PORTS)return 0;
  if(bIsOpen[Nr])return 0;

//  cName[7]='1'+Nr;
  sprintf_s(cName, "\\\\.\\COM%u", Nr);

  hFile= CreateFile( (LPCWSTR)cName ,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
machts einen Unterschied, wenn ich den char via (LCPWSTR)-cast (so in 
etwa oder?) umwandle, anstelle die "MultiByteToWideChar" Version nutze?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, der Cast geht in die Hose, da ein Breitzeichen größer als ein char 
ist, und der Aufruf von sprintf_s ist falsch, denn es fehlt ein 
Argument.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh, mist, da hab ich ja vergessen die max Bytes zu übergeben und das 
andere Problem wäre eigentlich auch logisch.

nur wiso hat der Compiler nicht gemeckert??

ausserdem hab ich vergessen, dass die Zählvariable von 0 anfängt und als 
ComPort übergeben wird.

so siehts momentan bei mir aus. Hat jemand noch Verbesserungsvorschläge?
int ComOpen(unsigned Nr,int Baud,int Parity,int Stopbits,int Databits)
{
static const int  iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
static const int  iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
char        cName[40];
HANDLE        hFile;
COMMTIMEOUTS    sTo;
DCB          sDcb;


  if(Nr>=MAX_COM_PORTS)return 0;
  if(bIsOpen[Nr])return 0;


  sprintf_s(cName,40,"\\\\.\\COM%u",Nr+1);
  hFile= CreateFileA( (LPCSTR)cName ,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

und nochmals danke für die gute Unterstützung, selbst bei einem so 
schönen verschneiten Wochenende (und schön kalt -12° bei mir in der 
Schweiz)
MFG
Patrick

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:
> Arc Net schrieb:
>> Sven P. schrieb:
>>> sprintf_s kannste dir schenken, der Sicherheitsgewinn tendiert dabei
>>> gegen Null.
>>
>> sprintf_s ist eigentlich ganz sinnvoll, da die max. Anzahl der Zeichen
>> übergeben werden muss und zum anderen garantiert wird, dass der
>> generierte String null-terminiert ist.
> [ ] ich kenne snprintf
>
> Ist sogar ISO-C.

ich dachte ihr wollt c++ schreiben?
was soll da der ganze scheiß, von wegen char* sprintf sprintf_s 
snprintf?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich will mit Sicherheit kein C++ schreiben.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad Tepesch schrieb:
> ich dachte ihr wollt c++ schreiben?
> was soll da der ganze scheiß, von wegen char* sprintf sprintf_s
> snprintf?

was sind das denn für dich für Befehle?? also printf gibst ja sogar bei 
c als standart Output-String-Funktion.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für C++ sind die 'Befehle' dann eher cout und cin. Is nur blöd, dass man 
damit ziemlich schnell wieder an der Wand steht und auf die blöden 
'C-Befehle' zurückgreifen muss, da die aktuelle Standardbibliothek von 
C++ recht akademisch ist :-}

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Is nur blöd, dass man damit ziemlich schnell wieder an der Wand steht
> und auf die blöden 'C-Befehle' zurückgreifen muss, da die aktuelle
> Standardbibliothek von C++ recht akademisch ist :-}

Naja, für die Teile, die ich in C++ als "akademisch" bezeichnen würde, 
gibt es in C gar nichts.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.