BUG: VC-2010 ftell liefert negative Werte wenn eine UTF-8 Datei mit ccs=UNICODE geöffnet wird, die nicht mit fseek funktionieren

In VS-2005 hielt die Unicode und UTF-8 Unterstützung Einzug in die CRT und damit auch in die MFC. Jochen und ich haben dazu gebloggt.

Leider ist die Implementierung nicht fehlerfrei. Wenn man eine UTF-8 Datei mit ccs=UNICODE öffnet dann liefert ftell zum Teil auch negative Werte. Das ftell nicht die exakte Position in der Datei liefert ist dokumentiert, nur sollte es mit dem Wert zumindest möglich sein wieder fseek aufzurufen um an eine alte Dateiposition zurück zu gelangen.
Das ist mit der jetzigen Implementierung nicht möglich.

Ein Sample dazu ist schnell gebaut:

int _tmain()
{
  FILE *file = NULL;
  if (_tfopen_s(&file,_T("Test.txt"),_T("rt") _T(", ccs=UNICODE")))
    return -1;

  TCHAR szBuffer[_MAX_PATH];
  while (_fgetts(szBuffer,_countof(szBuffer),file))
  {
    int iPos = static_cast(ftell(file));
    _tprintf(_T("%d\n"),iPos);
    _ASSERTE(fseek(file,iPos,SEEK_SET)==0);
  }

  fclose(file);
  return 0;
}

Ein entsprechendes Sample kann man hier herunterladen.

Der Fehler betrifft natürlich auch die MFC mit CStdioFile und GetPosition!

Hintergrund:
Ich kam auf den Fehler, weil wir ein Programm benutzen, dass sich bestimmte Dateipositionen merkte um einen Datenimport bei einer bestimmten Bedingung, ab einer definierten Stelle, neu aufnehmen zu können. Bisher hatten wir hier nur pure ASCII Dateien erlaubt, jetzt wollten wir auch UTF-8 Dateien unterstützen.
Sicher man kann auch alles im Speicher zwischenhalten, aber wenn es eine simple Dateiposition ist das Ganze so weitaus Ressourcen schonender.

Soweit ich das übersehen kann, betrifft der Fehler alle VS-Versionen ab VS-2005. Ein entsprechende Bug wurde von mir schon vor längerer Zeit auf Connect geöffnet. Getan hat sich bisher noch nichts:
https://connect.microsoft.com/VisualStudio/feedback/details/591030/ftell-returns-negative-value-for-utf-8-files-opened-with-textmode-and-ccs

So lange wollte eigentlich nicht warten…

Wie gut das manche Anzeigen einfach nicht stimmen:

In einer Teamviewer Session bekam ich beim übertragen der Datei, den Hinweis, dass es ca. 357.020 Jahre dauern wird bis die Datei übertragen ist 😮
Das Ganze obwohl der Fortschrittsbalken zügig voran geschritten ist. Das Ganze hatte wirklich nur 25 Sekunden gedauert und ich musste mich sputen das Bild einzufangen.

Berechnungen über die Dauer von Operationen führen immer wieder zu erstaunlichen Ergebnissen in unserer Branche…

TFS Fehler TF248015…

Ein nettes Hilfsmittel ist die Work-Item Suche mit dem Addin http://visualstudiogallery.msdn.microsoft.com/de-de/3f31bfff-5ecb-4e05-8356-04815851b8e7

Leider funktionierte dies bei mir nicht sofort. Ich bekam die folgende Fehlermeldung:

TF248015: Your work item query could not be completed due to an unexpected error returned by the Microsoft SQL Server Full-text engine. Contact your system administrator to check the Application event log for Team Foundation Server.

Na fein ❗ Also muss ich mich selbst kontaktieren weil irgendwas mit der Volltext Suche nicht klappt.

Nach einigem hin und her irren durch alle möglichen Einstellungen entdeckte ich den Missetäter: Der „SQL Full-text Filter Daemon Launcher“ war nicht gestartet. Dies ist ein Dienst, den man in der Computer-Verwaltung oder dem SQL-Server-Konfigurations-Manager findet.
Aus irgend einem mysteriösen Grund war hier ein falsches Dienstkonto angegeben und der Dienst konnte nicht starten.

Nachdem das korrigiert war habe ich danach noch ein Rebuild des Warehouse veranlasst damit die Indizes sofort zur Verfügung aktuell sind. Das erfolgt über die folgende Web Adresse: http://servername:8080/tfs/TeamFoundation/Administration/v3.0/WarehouseControlService.asmx 
in dem man ProcessWarehouse auswählt. Unter collectionName gibt man seine Team Project Collection an um die es geht. Wer die Namen der Collections vergessen hat, findet sie in der Team Foundation Server Administration Console aufgelistet.

BUG: VS-2005 langsam durch extreme Anzahl von Dateien im WebsiteCache

 Für einige Legacy-Anwednungen habe ich virtuelle Maschinen mit VC6 und VS-2005.

Bei der VS-2005 Maschine hatte ich in er letzten Zeit das Gefühl, dass die Kiste immer langsamer wird. Also ging ich etwas auf die Suche und fand schließlich die Ursache.

In dem Verzeichnis C:\Users\Name\AppData\Local\Microsoft\WebsiteCache fanden sich nicht weniger als 50000 (in Worten Fünfzigtausend Verzeichnisse) unscheinbar brachte jedes Öffnen einer Solution ein weiteres Verzeichnis für jedes Projekt in der Solution.

Ein bekannter Bug, wie ich nach weiterer Recherche herausfand:
https://connect.microsoft.com/VisualStudio/feedback/details/347228/large-numbers-of-websitecache-files-slowing-visual-studio-2005-and-windows-performance?wa=wsignin1.0

Nachdem ich die Verzeichnisse entsorgt hatte, war auch wieder die gewohnte Geschwindigkeit da.

Es bringt so gut wie nichts andere Antennen in WLAN Geräte einzubauen…

Ich habe meinen WLAN-Router in meinem Arbeitszimmer, dass sich an der einen Hausecke befindet.
Im Wohnzimmer habe ich immer noch einigermaßen Empfang. Um auf der Terrasse im Sommer surfen zu können und damit unsere Tochter in Ihrem Zimmer WLAN Empfang hat, habe ich einen Fritz!Repeater (den man nur empfehlen kann).

Um die Grundreichweite meines WLAN-Routers zu vergrößern habe ich mir eine 9dbi WLAN Antenne gekauft und die kleine WLAN Antenne getauscht. Der Erfolg war minimal. Maximal 3-5% Verbesserung. Weil mir das zu wenig vorkam, habe ich den Versuch gleich noch an einem zweiten unterschiedliche WLAN-Router, den ich noch im Haus hatte wiederholt. Der Tausch der Antenne war bei beiden gleich einfach. Die Schwierigkeit war eher die Gehäuse zu öffnen.

Resultat:
Antennentausch lohnt sich nach meiner Meinung nicht, besser das Geld in die Spardose schmeißen für einen guten Single-Malt oder so 😉
Das einzige was ich positiv anmerken kann, ist dass sich die Konstanz des WLANs verbessert hat. Vorher hatte ich ab und zu schon etwas Schwankungen im Netz. Das hat sich wirklich gebessert.

Beta Version von VS-2010 SP1 veröffentlicht

Es wurde ja schon einiges geredet über VS-2010 SP1. Jetzt ist die Beta 1 veröffentlicht worden.
Ich kann leider noch nicht sagen, was sich für VC Nutzer ändert. Der Blog Artikel (s.u.) gibt darüber keine Auskunft.

Mehr Infos hier:
http://blogs.msdn.com/b/jasonz/archive/2010/12/07/announcing-visual-studio-2010-service-pack-1-beta.aspx

Warum es manchmal nicht genügt die Basisklasse aufzurufen und die miesen Konsequenzen…

Wenn man eine Windowsnachricht bearbeitet dann ruft man in den meisten Fällen die Funktion der Elternklasse auf. Was aber, wenn man die Nachricht nicht nur entgegennehmen will, sondern sie „verändert“ an die Basisfunktion weitergeben will. Was dann?
Kein Problem denkt man. Man ändert die Parameter eben und gibt diese neuen Werte an die Basisklasse weiter.

Nehmen wir mal als Beispiel ein Eingabe Control, das sich möglichst intelligent verhalten soll. D.h. in diesem Fall, wenn ein Datum eingegeben wird, dann sollte auch bei der Eingabe auf numerischen Ziffernbock, das Komma in einen Punkt gewandelt werden, oder bei englischem Datumsformat in einen Slash…

Na OK. Man überschreibt als CMyWnd::OnChar. Man prüft ob ein bestimmtes Zeichen ankommt und wenn es mir passt, dann ändere ich den Parameter und gebe diesen dann an die Basis Funktion weiter.

:Eeek: aber was ist das? Der Code hat keine Wirkung? Egal was wir an die Basisfunktion übergeben, es ändert sich nichts. Warum?

Die Antwort liegt in dem für mich etwas eigentümlichen Design der MFC. Alle CWnd Nachrichten Routinen rufen letzten Endes immer genau ein und die selbe Funktion auf: CWnd::Default(); Aber was macht CWnd::Default? Es nimmt die ursprünglichen Parameter, die Windows mal gesendet hat und übergibt die an die Window-Proc des Fensters. D.h. alle tollen Manipulationen an der WM_CHAR Nachricht sind weg in dem Moment in dem CWnd::OnChar aufgerufen wird.

Was also tun, wenn man nun aber wirklich die WM_CHAR Nachricht manipulieren will?
Eigentlich nicht schwer. Man macht das Gleiche, dass eben auch CWnd::Default macht. Man ruft DefWindowProc mit den passenden wParam und lParam Werten auf.

Aber jetzt wird es dumm ❗ Damit umgehen wir alle anderen geerbten Funktionalitäten des Controls. Ich habe keine Ahnung was die Entwickler der MFC in der Anfangszeit dazu getrieben hat immer CWnd::Default aufzurufen? War es Ihnen zu kompliziert wieder aus den Parametern wParam und lParam zusammen zu bauen?