Seite 1 von 2
Probleme mit Qt4 unter Windows
Verfasst: 6. August 2006 16:54
von mrbm74
Hi,
ich versuche nun schon seit Tagen erfolglos eine einfache Anwendung mit Qt4 unter Windows zum laufen zu bekommen. Die Anwendung, die ich schreiben möchte, soll auf einen selbst geschriebenen Kerneltreiber zugreifen und eine einfache Gui für die Kommunikation mit dem Treiber haben. Als Konsolenanwendung existiert das Programm bereits, das ich mit der Express Edition von MS erstellt habe. Dieses Programm funktioniert auch tadellos.
Ich habe mir zuerst von MS die aktuelle Visual Express+SDK besorgt und installiert. Anschließend die Qt4-Sourcen und den zugehörigen Patch besorgt und Qt4 kompiliert. Dann die Anwendung geschrieben und kompiliert. Läuft auf dem Entwicklungsrechner wunderbar. NUR wenn ich die Anwendung auf einen anderen Rechner kopiere, dann lässt die sich nicht starten. Ich habe schon alle möglichen Libs rüberkopiert und auch eine Manifest-Datei erstellt, wie im Forum beschrieben, aber gar nix hat geholfen.
Nun habe ich Qt4 nochmals mit "-static" übersetzt. Jetzt bekomme ich aber beim Linken immer eine ganze Menge an Fehlern über unaufgelöste Symbole.
Dann habe ich noch die ganze Sache mit dem vorkompilierten Qt4 und MingW probiert. Kompilieren kein Problem. Die Anwendung startet auch sogar auf einem anderen Rechner, NUR funktioniert das CreateFile nicht! Das ist aber notwendig, um mit dem Treiber, Filename "\\\\.\\PLC0", Kontakt aufzunehmen. Der zurück gelieferte Fehlercode ist 2 (FILE NOT FOUND). Das Device exisitiert aber definitiv. Die Konsolenversion (mit der Express Edition erstellt und dem MS-Compiler übersetzt) funktioniert auch einwandfrei.
Ich habe auch versucht mit Hilfe von QtDir eine einfache Anwendung zu schreiben, die mir alle Device-Node anzeigt:
int main(int argc, char *argv[])
{
QDir dir("\\\\.\\");
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
dir.setSorting(QDir::Size | QDir::Reversed);
QFileInfoList list = dir.entryInfoList();
printf(" Bytes Filename\n");
for (int i = 0; i < list.size(); ++i) {
QFileInfo fileInfo = list.at(i);
printf("%10li %s\n", fileInfo.size(), qPrintable(fileInfo.fileName()));
}
return 0;
}
Dummerweise hängt sich dieses Programm aber auf und lässt sich nicht einmal mehr beenden. Nur mehr ein Neustart von Windows hilft hier.
Ich bin nun schon echt am verzweifeln. Kann mir bitte jemand helfen?
MfG, Martin
Verfasst: 6. August 2006 23:22
von Nassian
Ich habe mal versucht "manuell" auf \\\\.\\ zuzugreifen, den Pfad gibt es gar nicht. Vielleicht liegt es daran, dass das Programm ihn nicht findet? Oder gibt es diesen Pfad nur in Verbindung mit deinem Treiber?
Verfasst: 7. August 2006 07:23
von mbreitinger
Zeig mal den Code der Konsolenversion. Verwendest Du dort direkt die Windows-API? ES könnte daran liegen, daß Qt das Dateisystem verallgemeinert um portierbar zu sein und damit mit Deinem Versuch kollidiert.
Verfasst: 7. August 2006 20:39
von mrbm74
@Nassian: Der Pfad "\\\\.\\" ist in Wirklichkeit der Pfad "\\.\", da ja ein "\\" zu "\" wird. Auf diesen Pfad kann man mit den Dateifunktionen der Windows-API (z.B. CreateFile) zu greifen. Der Pfad ist rein virtuell und man kann darauf z.B. mit dem Programm devicetree.exe (ein Tools des WindowsDDK) zugreifen und sich eine Liste aller DeviceNodes anzeigen lassen, die die Treiber angelegt haben.
Gut dass Qt nicht darauf zugreifen kann sehe ich aufgrund der Plattformunabhängigkeit vielleicht noch ein, obwohl ich es für sinnvoll halten würde, wenn Qt den Zugriff unter Windows auf "\\.\" gleich behandeln würde wie unter Linux auf "/dev". Dann hätte man sinngemäß jeweils Zugriff auf die DeviceNodes. Was mir aber weniger gefällt, ist daß ein Qt-Programm sich komplett aufhängt und sich meist sogar nicht einmal mehr beenden lässt wenn man versucht auf "\\.\" zuzugreifen. Das ist wohl mehr ein Bug, als ein fehlendes Feature.
Aber das ist nicht wirklich mein Problem, da ich über die Windows-API auf die DeviceNodes zugreifen kann, wenn nur MingW den Code richtig übersetzen würde. Wie schon im letzten Beitrag geschrieben funktioniert CreateFile beim Zugriff auf "\\.\PLC0" nicht wenn mit MingW kompiliert. Wenn mit dem Compiler von MS übersetzt geht's. Entweder ist das ein Bug in MingW, oder das mit QMake erzeugte Makefile ist fehlerhaft. Das stört mich sehr, da ich gerne MingW einsetzen würde.
Wenn nun alle Stricke reißen und ich das DevStudio einsetzen muß, dann habe ich aber wieder das Problem mit den DLLs. Bei dynamisch gelinktem Qt4 schaffe ich es nicht alle DLLs so auf einem anderen Rechner zu installieren, daß sich das Programm dort starten läßt. Bei statisch gelinktem Qt4 meckert der Linker vom DevStudio über viele unresolved Symbols, obwohl ich ja QtCore und QtGui hinzulinke.
Hier ein Ausschnitt des Codes der Consolenanwendung:
CDriver PLCDriver("\\\\.\\PLC0");
bool InitCard()
{
unsigned char ucValue = 0;
cout << "Connecting to PCI-Card... ";
if (PLCDriver.Open() != 0) {
cout << endl << "ERROR: Could not connect to the PCI-Card!" << endl;
return FALSE;
}
cout << "OK" << endl;
return TRUE;
}
In der Klasse CDriver ist die Funktion Open() so definiert:
DWORD CDriver::Open()
{
DWORD dwErrorCode = 0;
// handle already opened?
if (m_hDevice == NULL) {
// open handle to device
m_hDevice = CreateFile(
m_deviceName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// error checking
if (m_hDevice == INVALID_HANDLE_VALUE) {
dwErrorCode = GetLastError();
cout << endl << "Error: CDriver::Open() = " << dwErrorCode << endl;
cout << "Konnte Device " << m_deviceName << " nicht öffnen!" << endl;
return dwErrorCode;
}
}
return dwErrorCode;
}
Obiger Code ist praktisch 1:1 auch in der Qt-Version enthalten.
Was ich nun bräuchte ist ein funktionierender Lösungsweg, sei es mit MingW oder mit dem DevStudio.
Meine Frage wäre:
1) Bei dynamischem Linken von Qt: Welche Dateien sind alle notwendig (und wo müssen die platziert werden) wenn ich ein Qt-Programm auf einen anderen Rechner kopiere. Ich habe alle Hinweise und Anleitungen aus dem Netz ohne Erfolg ausprobiert. Im Forum gibt es einen Thread der zwar genau dieses Problem beschreibt und vermittelt, daß man eine Datei mit der Endung Manifest erstellen muß. Aber a) wohin muß diese Manifest-Datei und b) welchen Inhalt muß diese Datei GENAU haben. Ich habe verschiedene Varianten ohne Erfolg ausprobiert.
2) Bei statischen Linken: Was ist alles notwendig, um mit dem DevStudio (oder MingW??) ein Programm erfolgreich zu kompilieren?
Danke für alle Tipps!
MfG, Martin
Verfasst: 7. August 2006 21:03
von mrbm74
Also was das blockieren des Programms anbelangt wenn man über QDir auf "\\.\" zugreifen möchte, so könnte es sich tatsächlich um einen Compiler-Bug handeln:
http://kernelmustard.com/2006/06/
Hier wird zwar auf den Compiler von MS verwiesen, aber es könnte ja der Zufall so wollen, dass MingW genau das gleiche Problem hat. Qt4 verwendet nämlich für das Öffnen eines Files _wsopen_s (hab im Source rumgestöbert) und genau diese Funktion kann ein Kernel-Locking Problem verursachen. Das würde erklären warum sich das Programm auch nicht mehr beenden läßt (nicht einmal mehr durch den Taskmanager).
Verfasst: 7. August 2006 22:19
von mrbm74
Noch eine Ergänzung:
Folgende Fehlermeldung erhalte ich wenn ich mit dem "Depency Walker" (enthalten im SDK) das Programm auf einem anderen Rechner öffne:
Error: The Side-by-Side configuration information in "c:\temp\qtplctest\QTPLCTEST.EXE" contains errors. Diese Anwendung konnte nicht gestartet werden, weil die Anwenungskonfiguration nicht korrekt ist. Zur Problembehebung sollten Sie die Anwendung neu installieren (14001).
Nun habe ich es geschafft das Programm mit den statisch gelinkten Qt-Libs im DevStudio zu linken. Ich mußte folgende zusätzliche Libs hinzulinken:
shell32.lib gdi32.lib advapi32.lib winspool.lib imm32.lib winmm.lib comdlg32.lib wsock32.lib
Einige Warnings "lokally defines symbol" blieben allerdings übrig.
Bei der Ausführung dieser fetten Datei (4MB!) erhielt ich allerdings leider genau die gleiche Meldung "Fehler beim Programmaufruf!". Der Depency Walker gibt ebenfalls wieder obige Fehlermeldung aus.
Was zum Geier muß ich denn noch Alles machen, damit das Programm endlich auf anderen Rechnern startet??
Verfasst: 8. August 2006 11:37
von uhu01
Hy!
Beim letzten mal mussten ich nur die entsprechenden QT Libs, die verwendeten QT Plugins und eine Library vom Visual Studio in der Debug Version auf den anderen Rechner kopieren (war noch Debug Exe). Diese dll's hab ich in das Installationsverzeichniss meines Programms kopiert, dann hat eigentlich alles funktioniert.
Wenn du release kompilierst sollten eigentlich alle Librarys die VS von sich aus benötigt auf dem Rechner sein.
Schreib mal was du für einen Fehler beim starten mit der dynamisch gelinkten QT bekommst.
mfg
uhu01
Verfasst: 8. August 2006 18:16
von mrbm74
Die Fehlermeldung ist leider nichtssagend: "Fehler beim Programmaufruf!"
Welche Libs hast denn alle kopiert? Vielleicht habe ist eine dabei, die ich vergessen habe.
Danke, MfG
Verfasst: 8. August 2006 22:12
von FlorianBecker
Benutzt du visual studio 2005?
Verfasst: 8. August 2006 22:21
von mrbm74
Ja, Visual C++ 2005 Express Edition
Verfasst: 8. August 2006 22:41
von Christian81
FlorianBecker hat geschrieben:Benutzt du visual studio 2005?
Bei dieser Problembeschreibung doch eigentlich kar
Ich tippe auf fehlende Manifests, nicht installiertes .Net2.0 framework und/oder das nichtinstalliertes .Net2.0 package (da gibts doch so ein Redist, oder?) für die Leute die nicht den kompletten framework installieren wollen.
Hatten wir aber schon öfter und ist auch zig mal bei google zu finden, deshalb habe ich bis jetzt nocht nichts gesagt.
Verfasst: 8. August 2006 22:54
von mrbm74
Also mit dem Google hab ich schon stundenlang gesucht, aber nix dazu gefunden.
Das mit dem .NET Framework könnte ein guter Tipp sein. Werd ich mir gleich mal anschaun.
Hab aber dazu noch folgende Fragen:
1) Muß ich das Framework auf jedem Rechner installieren auf dem das Programm laufen soll?
2) Wozu dienen diese Manifests Dateien?
Danke für die Antworten.
MfG, Martin
Verfasst: 8. August 2006 23:01
von FlorianBecker
Ich wette knallhart auf fehlende redist.exe
Die Runtimes werden mit Visual Studio 2005 als Com Objecte geladen und die müssen entweder über die manifestdatei gesteuert werden oder für den dafür passenden Platz installiert sein.
Installier mal die redist.exe auf dem anderen Rechner und sag, ob es dann klappt. Die redist.exe gibt es nur in der Vollversion und befindet sich sonst wo in der Installation, weiß ich halt ned auswendig.
Damit ist das Problem 100%ig mal gelöst. Wenn ich mich irren sollte, gabs wohl schon wieder mal ein Update

Verfasst: 8. August 2006 23:03
von FlorianBecker
Ich würde dir empfehlen Qt aus den Sourcen mit dem Paramter MT anstelle von MD zu bauen, dann werden die Runtimes mit einkompiliert.
Dazu gibt es eine Anleitung auf qtnode.net im Wiki.
Verfasst: 8. August 2006 23:05
von FlorianBecker
Ist schon Wahnsinn, da denkt man das nach all den Jahren die Kinderkrankheiten mal weg sein sollten, aber nein, es kommen andere noch viel schlimmere... Mal sehen, wie lange es dieses Mal dauert, bis SP1 für Vista da ist.