diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui index d0e0ed5afe968698a714797f09cdfd01e6c6f763..370dd882ddc63e8832aec084a05468de0c481a9b 100644 --- a/src/plugins/debugger/commonoptionspage.ui +++ b/src/plugins/debugger/commonoptionspage.ui @@ -85,14 +85,24 @@ </property> </widget> </item> - <item row="6" column="0"> + <item row="6" column="0" colspan="2"> + <widget class="QCheckBox" name="checkBoxRegisterForPostMortem"> + <property name="toolTip"> + <string>Register Qt Creator for debugging crashed applications.</string> + </property> + <property name="text"> + <string>Use Creator for post-mortem debugging</string> + </property> + </widget> + </item> + <item row="7" column="0"> <widget class="QLabel" name="labelMaximalStackDepth"> <property name="text"> <string>Maximal stack depth:</string> </property> </widget> </item> - <item row="6" column="1"> + <item row="7" column="1"> <widget class="QSpinBox" name="spinBoxMaximalStackDepth"> <property name="layoutDirection"> <enum>Qt::LeftToRight</enum> diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 7e1b1690ef285846b7657021ed22d5a325d559fd..c93cd385fc7ed2f56458653fb46d15ca993ca61e 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -90,6 +90,13 @@ false { HEADERS += $$PWD/modeltest.h DEFINES += USE_MODEL_TEST=1 } +win32 { +include(../../shared/registryaccess/registryaccess.pri) +HEADERS += registerpostmortemaction.h +SOURCES += registerpostmortemaction.cpp +LIBS *= -lole32 \ + -lshell32 +} include(cdb/cdb.pri) include(gdb/gdb.pri) include(script/script.pri) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index e8758c84cff00f7ed87e524c674bf737a916c63e..feeb7b4445aac8c4b02e09fc68cad8e97d55227d 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -28,6 +28,9 @@ **************************************************************************/ #include "debuggeractions.h" +#ifdef Q_OS_WIN +#include "registerpostmortemaction.h" +#endif #include <utils/savedaction.h> #include <utils/qtcassert.h> @@ -403,6 +406,15 @@ DebuggerSettings *DebuggerSettings::instance() item->setDefaultValue(false); instance->insertItem(EnableReverseDebugging, item); +#ifdef Q_OS_WIN + item = new RegisterPostMortemAction(instance); + item->setSettingsKey(debugModeGroup, QLatin1String("RegisterForPostMortem")); + item->setText(tr("Register For Post-Mortem Debugging")); + item->setCheckable(true); + item->setDefaultValue(false); + instance->insertItem(RegisterForPostMortem, item); +#endif + item = new SavedAction(instance); item->setSettingsKey(debugModeGroup, QLatin1String("AllPluginBreakpoints")); item->setDefaultValue(true); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 368ff1b7b085290f0e4d362386f365484d536c85..66f762cade384699b7f10e29739629be3ec3c7f9 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -100,6 +100,8 @@ enum DebuggerActionCode UseAddressInBreakpointsView, UseAddressInStackView, + RegisterForPostMortem, + // Gdb GdbLocation, GdbEnvironment, diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index af233e1259def39d64f4de0692de932ac2f89fd0..05ff7a6e14aae028a08389ea5b4c5cbee1306942 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -389,6 +389,13 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent) m_group.insert(theDebuggerAction(UsePreciseBreakpoints), 0); m_group.insert(theDebuggerAction(BreakOnThrow), 0); m_group.insert(theDebuggerAction(BreakOnCatch), 0); +#ifdef Q_OS_WIN + Utils::SavedAction *registerAction = theDebuggerAction(RegisterForPostMortem); + m_group.insert(registerAction, + m_ui.checkBoxRegisterForPostMortem); + connect(registerAction, SIGNAL(toggled(bool)), + m_ui.checkBoxRegisterForPostMortem, SLOT(setChecked(bool))); +#endif if (m_searchKeywords.isEmpty()) { QTextStream(&m_searchKeywords) << ' ' @@ -399,10 +406,15 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent) << ' ' << m_ui.checkBoxUseToolTipsInMainEditor->text() << ' ' << m_ui.checkBoxSkipKnownFrames->text() << ' ' << m_ui.checkBoxEnableReverseDebugging->text() +#ifdef Q_OS_WIN + << ' ' << m_ui.checkBoxRegisterForPostMortem->text() +#endif << ' ' << m_ui.labelMaximalStackDepth->text(); m_searchKeywords.remove(QLatin1Char('&')); } - +#ifndef Q_OS_WIN + m_ui.checkBoxRegisterForPostMortem->setVisible(false); +#endif return w; } diff --git a/src/plugins/debugger/registerpostmortemaction.cpp b/src/plugins/debugger/registerpostmortemaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..611c885752174ace794a4456e4cd86794bd16d97 --- /dev/null +++ b/src/plugins/debugger/registerpostmortemaction.cpp @@ -0,0 +1,89 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "registerpostmortemaction.h" + +#include "registryaccess.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QString> + +#include <Windows.h> +#include <Objbase.h> +#include <Shellapi.h> + +using namespace RegistryAccess; + +namespace Debugger { +namespace Internal { + +void RegisterPostMortemAction::registerNow(const QVariant &value) +{ + const bool boolValue = value.toBool(); + const QString debuggerExe = QCoreApplication::applicationDirPath() + QLatin1Char('/') + + debuggerApplicationFileC + QLatin1String(".exe"); + const std::wstring debuggerWString = QDir::toNativeSeparators(debuggerExe).toStdWString(); + + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + SHELLEXECUTEINFO shExecInfo; + shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); + shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + shExecInfo.hwnd = NULL; + shExecInfo.lpVerb = L"runas"; + shExecInfo.lpFile = debuggerWString.data(); + shExecInfo.lpParameters = boolValue ? L"-register" : L"-unregister"; + shExecInfo.lpDirectory = NULL; + shExecInfo.nShow = SW_SHOWNORMAL; + shExecInfo.hProcess = NULL; + if (ShellExecuteEx(&shExecInfo) && shExecInfo.hProcess) + WaitForSingleObject(shExecInfo.hProcess, INFINITE); + CoUninitialize(); + readSettings(); +} + +RegisterPostMortemAction::RegisterPostMortemAction(QObject *parent) : Utils::SavedAction(parent) +{ + connect(this, SIGNAL(valueChanged(QVariant)), SLOT(registerNow(QVariant))); +} + +void RegisterPostMortemAction::readSettings(const QSettings *) +{ + bool registered = false; + HKEY handle = 0; + QString errorMessage; + if (openRegistryKey(HKEY_LOCAL_MACHINE, debuggerRegistryKeyC, false, &handle, &errorMessage)) + registered = isRegistered(handle, debuggerCall(), &errorMessage); + if (handle) + RegCloseKey(handle); + setValue(registered, false); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/registerpostmortemaction.h b/src/plugins/debugger/registerpostmortemaction.h new file mode 100644 index 0000000000000000000000000000000000000000..e8aef9e75729f208012ba17020d2e0560da836d3 --- /dev/null +++ b/src/plugins/debugger/registerpostmortemaction.h @@ -0,0 +1,53 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef REGISTERPOSTMORTEMACTION_H +#define REGISTERPOSTMORTEMACTION_H + +#include "utils/savedaction.h" + +namespace Debugger { +namespace Internal { + +class RegisterPostMortemAction : public Utils::SavedAction +{ + Q_OBJECT + +private: + Q_SLOT void registerNow(const QVariant &value); +public: + RegisterPostMortemAction(QObject *parent = 0); + void readSettings(const QSettings *settings = 0); + Q_SLOT virtual void writeSettings(QSettings *) {} +}; + +} // namespace Internal +} // namespace Debugger + +#endif // REGISTERPOSTMORTEMACTION_H