Probleme mit Qt4 unter Windows
Probleme mit Qt4 unter Windows
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
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
-
mbreitinger
- Beiträge: 15
- Registriert: 16. November 2005 11:00
- Wohnort: Blaubeuren
- Kontaktdaten:
@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
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
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).
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).
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??
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??
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
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
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Bei dieser Problembeschreibung doch eigentlich karFlorianBecker hat geschrieben:Benutzt du visual studio 2005?
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.
MfG Christian
'Funktioniert nicht' ist keine Fehlerbeschreibung
'Funktioniert nicht' ist keine Fehlerbeschreibung
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
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
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
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
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
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten:
-
FlorianBecker
- Beiträge: 1213
- Registriert: 2. Dezember 2004 10:54
- Kontaktdaten: