Defekte Canon-Tintenpatronen

Na toll!

Da will man nur mal schnell was mit seinem neuen Drucker, einem Canon Pixma MP510 Multifunktionsgerät, ausdrucken und schon stellt man fest, dass die Magenta-Tintenpatrone nicht mehr erkannt wird. U150 Folgender Tintenbehälter wird nicht erkannt.

Die ist nichtmal ansatzweise gebraucht worden, wird aber einfach so nicht mehr erkannt. Wie ich aus vielen Foren erfahren durfte, liegt das wohl an dem eingebauten Chip, der das Einsetzen von Billig-Patronen verhindern soll. Dagegen habe ich ja prinzipiell gar nichts. Jeder muss sehen, wie er sein Geld verdient. Aber das Canon Chips von offensichtlich so schlechter Qualität verbaut ist wirklich traurig…

Dabei ist der Drucker nichtmal 2 Monate alt. Und die Originalpatronen kosten locker mal 12 Euro das Stück (für die CLI-8M/Y/C) 🙁

Früher fand ich Canon mal richtig gut…

UPDATE (19.07.2010):

Inzwischen gibt es auch vernünftige Nachbau-Patronen inkl. Chip für den Canon MP510! Die funktionieren super und das Druckbild ist genauso gut wie mit den Originalpatronen. Ich habe die hier ausprobiert und verwende sie ab jetzt immer:

5 x Tintenpatrone kompatibel zu CANON PGI-5BK CLI-8BK CLI-8C CLI-8M CLI-8Y – mit Chip
(12 EUR für alle 4 Patronen!).

UPDATE (19.05.2011)
…und hier gibt es noch günstigere Patronen (5,40 EUR), die genauso gut laufen:

1x Satz kompatible Patronen PGI-5/CLI-8 Canon

title-Feld der Frontend Usergroups in TYPO3 verlängern

Bin gerade auf ein kleines Problem bei der Entwicklung meiner TYPO3-Extension gestoßen. Ich wollte ja die Frontend Usergroups als Speicherort für die Abteilungen des Unternehmens nutzen und nun ist mir aufgefallen, dass die maximale Länge der Bezeichnung einer solchen Gruppe 20 Zeichen beträgt. Nicht gerade viel für eine aussagekräftige Abteilungsbezeichnung.

Doch wie gut, dass dieses Problem recht schnell zu lösen ist. Abgeschaut habe ich mir die Lösung bei der Extension Group title length extender. Zunächst muss der entsprechende SQL-Befehl in die ext_tables.sql: CREATE TABLE fe_groups ( title varchar(50) DEFAULT '' NOT NULL )
Das verändert schonmal die Datenbank. Jedoch ändert das nichts an der Einstellung des Formularfeldes im Backend. Dazu sind die folgenden Zeilen in der ext_tables.php notwendig: $TCA['fe_groups']['columns']['title']['config']['size'] = 50; $TCA['fe_groups']['columns']['title']['config']['max'] = 50; $TCA['fe_groups']['ctrl']['default_sortby'] = 'ORDER BY title';
Das habe ich nun also in meine Extension eingebaut und schwupps: es funktioniert…

Windows-Abmeldescripts werden trotz langsamer Verbindung ausgeführt

Wie bereits in einem früheren Beitrag beschrieben, bietet Windows die Möglichkeit, mittels Pings herauszufinden, ob sich der Benutzer über eine “langsame Verbindung” (z.B. per VPN) anmeldet. Die Richtlinien greifen soweit auch bei uns, allerdings werden entgegen der Einstellung die An- und Abmeldescripts der Benutzer trotzdem ausgeführt, wenn eine langsame Verbindung vorliegt. Das scheint bei den Abmeldescripts nicht so richtig zu klappen, denn die Rechner hängen über 10 Minuten beim Ausführen derselben fest.

Die einzige Lösung dieses Problems besteht laut Knowledge Base Eintrag 892496 in der Installation einer neuen %SYSTEMROOT%\system32\gptext.dll, die es jedoch nur direkt vom Microsoft Support gibt. Deswegen verzichte ich jetzt mal darauf, die Datei hier zu posten 😉

Mal wieder Musik

Habe mal wieder ein wenig Zeit gehabt und bei YouTube nach Musik geschaut…

Da gibt’s echt verdammt geniale Sachen, besonders was Gitarrenmusik angeht. Mein erster Tip: Andy Mckee – Drifting. Was der da mit seinen Händen macht, ist der Wahnsinn. Er schlägt ja kaum ne Saite mit der rechten Hand an. Es gibt noch mehr Sachen von ihm und anderen Musikern seines Labels. Sehr nett ist z.B. Antoine Dufour – Scratch. Einfach genial, was die beiden da zusammenspielen…

In den Kommentaren zu Andy McKee bin ich dann auf Eric Roche gestoßen, der ebenfalls verdammt gut ist (das “Intro” ist ein wenig lang, aber danach geht’s ab). Hier zeigt er ein bisschen, wie er das so macht.

Dann gibt’s noch ein Video mit dem Titel “Impossible Guitar”. Dort spielt Dominic Frasca auf einer 10-saitigen Gitarre. Auch sehr interessant, wenngleich es nicht so ins Ohr geht, wie Andy McKees Song.

Eine Seite mit den Videos zu den 100 besten Gitarrensolos (laut guitar.com) gibt es bei CityRag (na gut, es sind nur knapp über 20 Videos, aber dafür die ersten 20 Plätze komplett).

Und diese kleine Band kommt bald nach Vechta (ins Gulfhaus): Ten Years After – I’m Going Home (live Woodstock ’69). Rocken auch ganz gut. Aber sind halt schon älter 😉

Dann zum Abschluss noch was für die Gänsehaut: Christina Aguilera mit Hurt. Regelmäßig erschaudere ich bei den hohen Stellen… unglaublich die Stimme!

Und mein Bruder hat auch mal mit ein paar Kumpels ein Video bei YouTube eingestellt. Sehr witzig 🙂 (er ist der “Sänger”!): Sailwork – As We Speak

TYPO3 Extension: Frontend Benutzer einer bestimmten Gruppe ermitteln

Wer sich ein bisschen in die Datenbankstruktur von TYPO3 eingearbeitet hat, merkt sehr schnell, wie seltsam die Zuordnung von Benutzern (Frontend sowie Backend) zu ihren Benutzergruppen gelöst ist. Anstatt über eine “vernünftige” M-zu-N-Tabelle, werden die Benutzergruppen den Benutzern über das Feld usergroup in fe_users bzw. be_users zugewiesen. Dieses Feld ist aber nicht ohne Weiteres editierbar (z.B. mit phpMyAdmin) da es nicht als text oder varchar, sondern als tinyblob definiert ist. Dennoch stehen die Benutzergruppen einfach als kommaseparierte Liste da drin (also z.B. “1,5,10”).

Wie kann man nun aber alle Benutzer einer bestimmten Benutzergruppe auslesen? Der SQL-Befehl ist zwar nicht unbedingt schwierig zu verstehen, aber nicht gerade sehr performant. Er beinhaltet nämlich einen Regulären Ausdruck, der auf das Feld usergroup angewendet wird und wie folgt aussieht:
SELECT * FROM `fe_users` WHERE usergroup REGEXP ( '(^|,)groupID($|,)' )

Dabei ist in Zeile 4 natürlich groupID durch die ID der entsprechenden Gruppe zu ersetzen.

Im TYPO3-Forum wird noch die Möglichkeit genannt, die Funktion find_in_set zu verwenden, die es (in meiner Installation) jedoch nicht gab…

Gruppenrichtlinien: Erkennung von langsamen Netzwerken schlägt fehl

Ich habe ein Problem mit unseren VPN-Clients: Die Erkennung von “langsamen Netzwerken” bei der Verarbeitung von Gruppenrichtlinien schlägt fehl. Dadurch nimmt Windows immer an, es stehe eine schnelle Verbindung zur Verfügung und führt alle Scripts aus, egal wie lange es dauert. Und es kann verdammt lange dauern (10 Minuten und länger).

Vorweg einige Links, die mir bei der Bearbeitung des Problems geholfen haben:

In meiner userenv.log brach die Erkennung der langsamen Netzwerke mit folgendem Fehler ab: PingComputer: Second send failed with 11010 Einen längeren Auszug aus der userenv.log gibt es in der Microsoft Knowledge Base. Die ersten Pings, die ICMP-Pakete mit einer Größe von 0 Byte verwenden, gehen recht normal (für eine UMTS-Verbindung) mit max. 200ms Antwortzeit durch. Die zweiten mit 2 KB Größe erzeugen ein Timeout. Warum ist klar: Unsere Firewall blockt alle “verdächtigen” ICMP-Pakete. Und eine Größe von 2 KB ist anscheinend verdächtig 😉 (dank dieses Artikels auf neohapsis bin ich überhaupt erst drauf gekommen, dass es an der Firewall liegen könnte).

Jetzt muss ich also nur noch die Firewall-Einstellung finden, die die großen ICMP-Pakete durchlässt, und der Erkennung langsamer Netzwerke steht nichts mehr im Weg. Dann werden auch die VPN-Benutzer mit einer vernünftigen Geschwindigkeit an- und abgemeldet.

Windows Updates können nicht installiert werden

Ich hatte auf einem PC das Problem, dass einige Windows Updates (darunter auch der Internet Explorer 7) nicht installiert werden konnten. Laut %SYSTEMROOT%/WindowsUpdate.log brach die Installation immer ab:
Handler Install completed with 0x8007f00d Handler Install was cancelled Handler : Install completed: result type = 0x2, installer error = False, error = 0x8007f00d, disabled until reboot = No, reboot required = No Handler FATAL: UH: 0x80242008: HandleSingleUpdate failed

Nach mehreren verschiendenen Ansätzen habe ich einfach mal alle Lösungsvorschläge von Google vereint und folgendes gemacht:

  1. net stop wuauserv (Windows Update Dienst beenden)
  2. %SYSTEMROOT%\SoftwareDistribution komplett gelöscht
  3. %SYSTEMROOT%\System32\SoftwareDistribution komplett gelöscht
  4. %SYSTEMROOT%\System32\spupdsvc.exe gelöscht (Hinweis aus Google Groups)
  5. %SYSTEMROOT%\WindowsUpdate.log gelöscht (nur interessant, um ein “sauberes” Log zur Fehlersuche zu haben)
  6. Windows Update Komponenten neu registriert: regsvr32 wuapi.dll regsvr32 wuaueng.dll regsvr32 wuaueng1.dll regsvr32 wucltui.dll regsvr32 wups.dll regsvr32 wuweb.dll regsvr32 jscript.dll regsvr32 winhttp.dll regsvr32 Softpub.dll regsvr32 Wintrust.dll regsvr32 Initpki.dll regsvr32 Dssenh.dll regsvr32 Rsaenh.dll regsvr32 Gpkcsp.dll regsvr32 Sccbase.dll regsvr32 Slbcsp.dll regsvr32 Cryptdlg.dll
  7. Windows neu gestartet
  8. Sofort nach der Anmeldung den Windows Update Service kontaktiert: wuauclt /resetauthorization /detectnow

Was auch immer letztlich den Ausschlag gegeben hat: Jetzt laufen die Updates! 😀

UPDATE 09.02.2008: Das Tool WinUpdRestore.exe von mshelper.de erledigt die obigen Aufgaben automatisch. Allerdings enthält es lediglich eine Batch-Datei (siehe WinTotal-Forum), die ich der Einfachheit halber (die Seite ist seit Längerem down) mal hochgeladen habe. Einfach als .BAT oder .CMD abspeichern und ausführen: WinUpdRestore.txt

TYPO3-Extension mittels Flexforms konfigurieren

Zunächste hatte ich vor, meine Extension mittels TypoScript konfigurierbar zu machen, aber mittlerweile bin ich auf die komfortableren Flexforms umgestiegen. Diese bieten dem Benutzer im Backend eine Konfigurationsmöglichkeit, die z.B. so aussehen kann:

Beispiel einer Flexform im TYPO3-Backend

Das sieht doch ein wenig benutzerfreundlicher aus, als einige TypoScript-Zeilen im Template. Außerdem kann ich damit jedes Plugin direkt beim Einfügen konfigurieren und muss nicht noch zusätzlich das Template der gesamten Seite (oder evtl. ein Untertemplate) ändern.

Wie das Ganze funktioniert steht im TYPO3Wiki. Man muss nur darauf achten, dass die Übersertzungstexte heutzutage nicht mehr aus der locallang_db.php geholt werden, sondern aus der locallang_db.xml. Man kann allerdings einfach die Endungen in den Beispielen ändern und es funktioniert.

Ich habe mich recht eng an die beschriebene Vorgehensweise gehalten. Nur dass ich die ausgelesenen Werte aus der Flexform im Array $this->conf unter Index flexform abgelegt habe. So sind diese sofort im gesamten Plugin nutzbar, da das Konfigurations-Array global zur Verfügung steht.

TYPO3-Extension: Erste Programmierschritte

Kommen wir zum nächsten Teil meiner kleinen Reihe zur Extension-Entwicklung. Heute habe ich mich mal mit dem Entwurf der Klassenstruktur und den ersten Programmierschritten auseinandergesetzt.

UML-Entwurf

Vor Beginn der Programmierung habe ich ein UML-Klassendiagramm angefertigt, dass den grundlegenden Aufbau der Klassenstruktur zeigt. Zunächst habe ich nur grob die Klassen modelliert und einige wichtige Methoden definiert, da ich die Integration meiner Klassen in die TYPO3-Extension erstmal testen wollte. Zur Modellierung habe ich ArgoUML verwendet, das die Möglichkeit bietet, PHP5-Quellcode aus dem Modell generieren zu lassen. Daher stehen einige ArgoUML-spezifische Informationen und Kommentare im Quellcode, was aber nicht weiter schlimm sein dürfte. Nur die erste Zeile jeder generierten Datei error_reporting(E_ALL); musste ich entfernen, da die Seite sonst aufgrund der zahlreichen “index not defined“-Fehler aus TYPO3 abstürzt.

Nach ein wenig Rumtesten bin ich zum Entschluss gekommen, meine Extension wie folgt abzubilden. Das Diagramm dürfte selbsterklärend sein, bis auf die Tatsache, dass ich überall, wo Arrays als Variablen übergeben werden, int eintragen musste, da ArgoUML sonst einen neuen Datentypen java_lang_Array erzeugt, den ich jedesmal händisch im Quellcode entfernen musste.

Erstes Klassendiagramm der TYPO3-Extension sm_employeelist

Einbinden der eigenen Klassen in die Plugin-Klasse

Die Plugin-Klasse tx_smemployeelist_pi1 kümmert sich um die Beschaffung der Datensätze aus der Datenbank und das Umwandeln in Arrays, die meine “eigenen” Klassen verarbeiten können. Somit bleiben diese später unabhängig von TYPO3 nutzbar. Vereinfacht gesagt werden alle Objekte unter Übergabe eines einzigen Arrays erzeugt, das die benötigten Daten für alle Attribute enthält. Damit verlagere ich die Verantwortung für die richtige “Zusammenstellung” dieser Arrays in die Plugin-Klasse (Methode CreateEmployeeFromDBRecord() erstellt z.B. solch ein Array für ein Employee-Objekt aus einem Datenbankeintrag).

Die benötigten Klassen müssen zunächst einmal in pi1/class.tx_smemployeelist_pi1.php inkludiert werden. Dazu habe ich eine Konstante definiert, die den absoluten Pfad der Extension enthält und dann jede benötigte Datei inkludiert.

/** * The absolute path of the extension's directory. */ define('EMPLIST_ABSPATH', t3lib_extMgm::extPath('sm_employeelist')); /** * A single employee. */ require_once(EMPLIST_ABSPATH . 'classes/class.Employee.php');

Als Nächstes habe ich dann Methoden definiert, die meine Objekte erzeugen, wie z.B. die folgende, die aus einem Eintrag aus fe_users ein Employee-Objekt erstellt. Nun kann ich bequem mit meinen eigenen Objekten arbeiten.
/** * Creates an Employee object from a fe_users DB-record. * * @param array $r The fe_user DB record. * @return Employee An Employee object. */ private function CreateEmployeeFromDBRecord($r) { // fields from fe_users that can be used without transformation $fields = array( 'id' => 'uid', 'title' => 'title', 'address' => 'address', 'zip' => 'zip', 'city' => 'city', 'country' => 'country', 'birthday' => 'birthday', 'image' => 'image', 'sex' => 'tx_smemployeelist_sex', 'hobbies' => 'tx_smemployeelist_hobbies', 'signature' => 'tx_smemployeelist_abbr', 'company' => 'company', 'firstentry' => 'tx_smemployeelist_firstentry', 'telephone' => 'telephone', 'fax' => 'fax', 'email' => 'email', 'website' => 'www', 'description' => 'tx_smemployeelist_description', 'username' => 'username', 'ipaddress' => 'tx_smemployeelist_ipaddress', 'lastwinlogon' => 'tx_smemployeelist_lastwinlogon', 'settings' => 'tx_smemployeelist_settings' ); $e = array(); foreach ($fields as $k=>$v) { $e[$k] = $v; } // fields that need to be transformed $name = explode(',', $r['name']); $e['lastname'] = $name[0]; $e['firstname'] = $name[1]; // get departments and positions $e['departments'] = array(); $depts = explode(',', $r['usergroup']); foreach ($depts as $d) { $e['departments'][] = $this->departments[$d]; } $e['positions'] = array(); $pos = explode(',', $r['tx_smemployeelist_positions']); foreach ($pos as $p) { $e['positions'][] = $this->positions[$p]; } return new Employee($e); }

Nun kann ich wie folgt einen Mitarbeiter erstellen und seinen Namen ausgeben lassen (in Klasse tx_smemployeelist_pi1).

$res = $this->pi_exec_query('fe_users', 0, ''); $r = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res); try { $emp = $this->CreateEmployeeFromDBRecord($r); $content= $emp->GetFullName(); } catch (Exception $e) { $content = $e->getMessage(); }

Das war’s auch schon wieder. Je nachdem, wie ich nun vorankomme, werde ich dann mal weitere interessante Details der Extension-Entwicklung veröffentlichen…