Невозможно выполнить команду echo в QProcess
Я хочу запустить команду SCPI на моем устройстве с помощью утилиты netcat под Ubuntu 10.04 LTS с Qt. Мой код выглядит так:
env = "echo TRIG | nc 192.168.1.100 23 -q1";
process1.execute(env);
process1.waitForFinished(1000);
Эта команда не возвращает никаких данных, а просто запускает сбор данных. При использовании терминала с той же командой "echo TRIG | nc 192.168.1.100 23 -q1" все работает нормально. С Qt не работает. Вывод отладки: "TRIG | nc 10.0.3.250 23 -q1" ... так что без "echo". Мое устройство не получает команду TRIG.
Подскажите, пожалуйста, что я делаю не так? Большое спасибо.
2 ответа
Вы не можете использовать команду pipe (|) с QProcess таким образом.
Есть несколько способов решить эту проблему:
Вы можете вызвать первую команду и получить ее вывод перед обработкой в Qt или с другим вызовом QProcess.
Или создайте скрипт, который вы вызываете из QProcess, и получите вывод.
Наконец, предполагая, что вы используете linux / OSX, вы можете вызвать QProcess с помощью /bin/bash и передать ему команду. Например: -
env = "/bin/bash \"echo TRIG | nc 192.168.1.100 23 -q1\"";
process1.execute(env);
Вы, вероятно, можете найти эквивалент /bin/bash для Windows, возможно, cmd.exe
Приведенный ниже код демонстрирует довольно полную асинхронную реализацию этой функции. Он демонстрирует, как это можно сделать без запуска внешних процессов, и как использовать лямбда-выражения C++11 в Qt 5. Для Qt 4 слоты из main()
нужно будет жить по-своему QObject
класс.
#include <QtWidgets>
#include <QtNetwork>
class SocketSignaler : public QObject
{
Q_OBJECT
Q_SLOT void stateChanged(QAbstractSocket::SocketState state) {
if (state == QAbstractSocket::UnconnectedState) emit unconnected();
else emit busy();
emit hasState(this->state());
}
public:
explicit SocketSignaler(QAbstractSocket * socket) : QObject(socket) {
connect(socket, &QAbstractSocket::stateChanged, this, &SocketSignaler::stateChanged);
connect(&(const QObject&)QObject(), &QObject::destroyed, this, // defer signal emission
[=]{ emit stateChanged(socket->state()); }, Qt::QueuedConnection);
}
Q_SIGNAL void busy();
Q_SIGNAL void unconnected();
Q_SIGNAL void hasState(const QString &);
QString state() const {
switch (static_cast<QAbstractSocket*>(parent())->state()) {
case QAbstractSocket::UnconnectedState: return "Disconnected";
case QAbstractSocket::HostLookupState: return "Looking up host";
case QAbstractSocket::ConnectingState: return "Connecting";
case QAbstractSocket::ConnectedState: return "Connected";
case QAbstractSocket::ClosingState: return "Closing";
default: return {};
}
}
};
class Ui : public QWidget {
Q_OBJECT
Q_PROPERTY(bool busy WRITE setBusy)
QVBoxLayout m_layout{this};
QFormLayout m_form;
QLineEdit m_target{"192.168.1.100"};
QLineEdit m_message{"TRIG"};
QLabel m_state;
QDialogButtonBox m_box;
QPushButton * const m_send = m_box.addButton("Send", QDialogButtonBox::AcceptRole);
QPushButton * const m_cancel = m_box.addButton(QDialogButtonBox::Cancel);
QMessageBox m_msgBox{this};
public:
Ui() {
m_form.addRow("Target Host", &m_target);
m_form.addRow("Command", &m_message);
m_layout.addLayout(&m_form);
m_layout.addWidget(&m_state);
m_layout.addWidget(&m_box);
m_msgBox.setIcon(QMessageBox::Critical);
connect(m_send, &QPushButton::clicked, this, &Ui::send);
connect(m_cancel, &QPushButton::clicked, this, &Ui::cancel);
}
void setState(const QString & text) { m_state.setText(text); }
QString target() const { return m_target.text(); }
QString message() const { return m_message.text(); }
void showError(const QString & text) {
m_msgBox.setText(text);
m_msgBox.show();
}
void setBusy(bool busy) {
m_send->setEnabled(!busy);
m_cancel->setEnabled(busy);
}
Q_SIGNAL void send();
Q_SIGNAL void cancel();
};
int main(int argc, char *argv[])
{
const int targetPort = 23;
QApplication app{argc, argv};
Ui ui;
ui.show();
QTcpSocket socket;
SocketSignaler socketSig{&socket};
QObject::connect(&socketSig, &SocketSignaler::hasState, &ui, &Ui::setState);
QStateMachine machine;
QState sReady{&machine};
QState sBusy{&machine};
sReady.assignProperty(&ui, "busy", false);
sBusy.assignProperty(&ui, "busy", true);
sReady.addTransition(&socketSig, &SocketSignaler::busy, &sBusy);
sBusy.addTransition(&socketSig, &SocketSignaler::unconnected, &sReady);
QObject::connect(&ui, &Ui::send, [&](){
socket.connectToHost(ui.target(), targetPort);
});
QObject::connect(&ui, &Ui::cancel, [&](){ socket.abort(); });
QObject::connect(&socket,
static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>
(&QAbstractSocket::error), [&]()
{
ui.showError(socket.errorString());
});
QObject::connect(&socket, &QAbstractSocket::connected, [&](){
auto msg = ui.message().toLatin1();
msg.append('\n');
if (socket.write(msg) >= msg.size()) socket.close();
});
QObject::connect(&socket, &QAbstractSocket::bytesWritten, [&](){
if (!socket.bytesToWrite()) socket.close();
});
machine.setInitialState(&sReady);
machine.start();
return app.exec();
}
#include "main.moc"