Continuing from this question
With each system call, the function constructs a set of parameters and sends them off to another program that is just console-based. Is there a way I can make it so that no console window pops up for each call?
I've done a search but the ones that aren't a linker issue just aren't working for me. For instance, I tried the _execl call and System::Diagnostics::Process^ myProcess = gcnew System::Diagnostics::Process; but they aren't working.
The _execl will bring a console window up, scroll a bunch of stuff (from the program I called I guess), then close the my app and not even do what it was supposed to do.
The System::Diagnostics::Process^ myProcess = gcnew System::Diagnostics::Process; doesn't seem to execute what I want either because the output folder that should contain files, contains nothing.
So I'm open for ideas.
The CreateProcess API gives you the control you need. For example:
#include <windows.h>
using namespace System;
int main(array<System::String ^> ^args)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR cmdLine[MAX_PATH] = L"myOtherApp.exe -with -some -args";
::ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
::CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
Console::ReadLine();
return 0;
}
With the CreateProcess flags set to 0 as above, the secondary app does not open its own console window, and writes its output to the parent's window. To silence the secondary app entirely, look at other CreateProcess flags, e.g. CREATE_NO_WINDOW.
Related
I have began learning C++ for Arduino and have run into some troubles.
I have some functions reading/writing to SPIFFS files.
Since the code for opening configuration files is common I would want to have a separate function to handle it.
I have come up with following function declaration
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File *file);
The function accepts pointer to char array for the file path, and pointer to opened file.
I then tried to make following function definition
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File *file)
{
if (SPIFFS.exists(path))
{
file = &SPIFFS.open(path, "r+");
return !file ? Failed : Opened;
}
else
{
file = &SPIFFS.open(path, "w+");
return !file ? Failed : Created;
}
}
That did not work as compiler complained with error error: taking address of temporary [-fpermissive]
As I understand this means that the file object will be disposed once DeviceOpenConfigFile function returns?
So my question is whether its possible to implement a function in a way where I can get File object reference and release it later?
SPIFFS.open apparently returns File, by value. The returned value will be a temporary variable available on that line. So taking the address of that one doesn't make any sense, for the same reason as int func (void); ... &func() doesn't make any sense. It has nothing to do with the surrounding DeviceOpenConfigFile function.
It doesn't make sense to assign a new address to pointer passed by parameter, for the same reason as void func (int x) { x = 0; } doesn't make sense - you change a local variable only, nothing on the caller side gets changed and nothing gets returned to the caller.
It would seem that the solution you are looking for is this:
ConfigFileOpenStatus DeviceOpenConfigFile(const char *path, File* file)
{
...
*file = SPIFFS.open(path, "r+");
where file is allocated on the caller-side.
I have an Arduino Uno V3. The sketch I'm working on has a couple of global vars in which a file within a directory is stored which I want to playback on the Adafruit Music Maker shield. All is fine, as long as I just want to play the file which is referenced in the vars on instantiation, but when I call my function where I need to modify these char arrays, my program or the Arduino hangs or crashes.
These are my variables:
// mp3 player variables
boolean plrStartPlaying = false; // Is set to true in case an nfc tag is present with information on tracks to play
char plrCurrentFile[13] = "track001.mp3"; // which track is the player playing?
char plrCurrentFolder[9] = "system00"; // from which directory is the player playing?
char filename[23] = "/system00/track001.mp3"; // path and filename of the track to play
byte firstTrackToPlay = 1; // the track number as received from the tag
char curTrackCharNumber[4] = "001";
And this is my function I call to modify them:
// stores the file to play in the global var filename - it is created from the gloal vars plrCurrentFolder and plrCurrentFile
boolean createFileNameToPlay(byte trackNo) {
// fill global var curTrackCharNumber with provided trackNo - we need it next to create the global var plrCurrentFile
sprintf(curTrackCharNumber, "%03d", trackNo);
// create the name of the track to play from the curTrack
strcpy(plrCurrentFile[0], '\0');
strcat(plrCurrentFile, "track");
strcat(plrCurrentFile, curTrackCharNumber);
//strcat(plrCurrentFile, sprintf(plrCurrentFile, "%03d", trackNo));
strcat(plrCurrentFile, ".mp3");
// create the filename of the track to play, including path, so we can feed it to the music player
strcpy(filename[0], '\0');
strcat(filename, "/");
strcat(filename, plrCurrentFolder);
strcat(filename, "/");
strcat(filename, plrCurrentFile);
if (SD.exists(filename)) {
return (true);
} else {
return (false);
}
}
As said it does not work - I checked by commenting out all strcat() and strcpy() calls in the function and then my program works just fine. But if the code is active, it actually causes my Arduino to hang or the program to crash. Whatever the cause, the effect is that my program won't advance once this function is called and after a certain time, the Arduino resets.
Can someone explain to me why this happens?
You try to use strcpy() to copy a character to a character, not a character pointer to a character pointer — and the problem occurs (at least) twice:
strcpy(plrCurrentFile[0], '\0');
…
strcpy(filename[0], '\0');
That should be generating compiler errors; both arguments should be char *, but neither is a char *. Write either:
plrCurrentFile[0] = '\0';
…
filename[0] = '\0';
or:
strcpy(plrCurrentFile, "");
…
strcpy(filename, "");
Why are you not heeding compiler warnings? If you're not getting at least warnings, why not? Find the options necessary to create such warnings and preferably make them into errors. For example, with GCC, consider:
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes …
That's my base set of options; I don't run code that doesn't compile cleanly with those options. I sometimes add more.
I'm working on porting a Qt 5.5, QWebView project to Qt 5.6 (beta), QWebEngine. I've gone through the porting guide here. My code looks like this:
.h file defines _view like so:
QWebEngineView* _view;
and the .cpp constructor (class inherits from QWidget) has:
QVBoxLayout* vbox = new QVBoxLayout(this);
_view = new QWebEngineView(this);
connect(_view, SIGNAL(loadFinished(bool)), this, SLOT(loadPageFinished(bool)));
QString webDir = getReportBasePath() + no_tr("/index.html#") + startingPage;
// QWebEnginePage *page = _view->page(); // <-- CRASH!!
_view->load( QUrl("file:///" + webDir ) ); // <-- CRASH!!
_view->show();
vbox->addWidget(_view);
Upon doing either the page() or load() method, the whole thing crashes with:
Unhandled exception at 0x67019C66 (Qt5Cored.dll) in qxs.exe: 0xC0000005:
Access violation reading location 0x00000000.
I've verified that the _view pointer is not null.
If you look at the documentation, they have an example here that's almost identical to my code above. I've also tried replacing load() call to be identical to theirs:
view->load(QUrl("http://qt-project.org/"));
and it still crashes. Any ideas what could be causing these crashes?
Do I need to create a QWebEnginePage first and setPage() on the QWebEngineView? (I'm assuming not...) Could it have something to do with the Qt binaries (pre-built for Windows 32-bit MSVC 2013) that I'm using?
Relevant part of stack trace:
Qt5WebEngineWidgetsd.dll!QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile * _profile) Line 95 C++
Qt5WebEngineWidgetsd.dll!QWebEnginePage::QWebEnginePage(QObject * parent) Line 393 C++
Qt5WebEngineWidgetsd.dll!QWebEngineView::page() Line 145 C++
Qt5WebEngineWidgetsd.dll!QWebEngineView::load(const QUrl & url) Line 157 C++
qxs.exe!ReportWidget::ReportWidget(QcaMain * qm, QWidget * parent, QString startingPage) Line 321 C++
It crashes here:
QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
: adapter(new WebContentsAdapter)
, history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this)))
, profile(_profile ? _profile : QWebEngineProfile::defaultProfile())
, settings(new QWebEngineSettings(profile->settings()))
, view(0)
, isLoading(false)
, scriptCollection(new QWebEngineScriptCollectionPrivate(browserContextAdapter()->userScriptController(), adapter.data()))
, m_backgroundColor(Qt::white)
, fullscreenMode(false)
{
memset(actions, 0, sizeof(actions));
}
I thought maybe that had something to do with _profile being NULL, so I attempted to first set a QWebEngineProfile like so:
QWebEnginePage* page = new QWebEnginePage( QWebEngineProfile::defaultProfile(), _view );
_view->setPage( page );
Then it instead crashes in qwebengineprofile.cpp here:
static QWebEngineProfile* profile = new QWebEngineProfile(
new QWebEngineProfilePrivate(BrowserContextAdapter::defaultContext()),
BrowserContextAdapter::globalQObjectRoot());
with stack trace:
Qt5Cored.dll!convert_to_wchar_t_elided(wchar_t * d, unsigned int space, const char * s) Line 256 C++
Qt5Cored.dll!qt_message_fatal(QtMsgType __formal, const QMessageLogContext & context, const QString & message) Line 1593 C++
Qt5Cored.dll!QMessageLogger::fatal(const char * msg, ...) Line 784 C++
Qt5WebEngineCored.dll!`anonymous namespace'::subProcessPath(void) C++
Qt5WebEngineCored.dll!WebEngineLibraryInfo::getPath(int) C++
Qt5WebEngineCored.dll!WebEngineContext::WebEngineContext(void) C++
Qt5WebEngineCored.dll!WebEngineContext::current(void) C++
Qt5WebEngineCored.dll!QtWebEngineCore::BrowserContextAdapter::defaultContext(void) C++
> Qt5WebEngineWidgetsd.dll!QWebEngineProfile::defaultProfile() Line 516 C++
Problem solved. I was missing some key files required by QWebEngine, otherwise it'll crash. These files must be in the same directory as the executable. They are put there by the windeployqt.exe tool, so that's the best way to ensure your Qt application has everything it needs to run without crashing.
qtwebengine_resources.pak
qtwebengine_resources_100p
qtwebengine_resources_200p.pak.pak
QtWebEngineProcess.exe
icudtl.dat
The reason this got me was our development group was formerly using Qt 4.8, and uses an in-house method to copy the required Qt dlls and whatnot into the target directory. When upgrading to Qt 5.x and adding QWebEngine, we didn't realize the files above were required.
You can set Windows environment variable called QTWEBENGINEPROCESS_PATH
Example:
QTWEBENGINEPROCESS_PATH C:\Qt\Qt5.6.0\5.6\msvc2013_64\bin\QtWebEngineProcess.exe
With this solution, no need to copy resources files into your projects output folders
I'm modifying the Qt 5 Terminal example and use a QTextEdit window as a terminal console. I've encountered several problems.
Qt does a strange interpretation of carriage return ('\r') in incoming strings. Ocassionally, efter 3-7 sends, it interprets ('\r') as new line ('\n'), most annoying. When I finally found out I choose to filter out all '\r' from the incoming data.
Is this behaviour due to some setting?
Getting the cursor interaction to work properly is a bit problematic. I want the console to have autoscroll selectable via a checkbox. I also want it to be possible to select text whenever the console is running, without losing the selection when new data is coming.
Here is my current prinout function, that is a slot connected to a signal emitted as soon as any data has arrived:
void MainWindow::printSerialString(QString& toPrint)
{
static int cursPos=0;
//Set the cursorpos to the position from last printout
QTextCursor c = ui->textEdit_console->textCursor();
c.setPosition(cursPos);
ui->textEdit_console->setTextCursor( c );
ui->textEdit_console->insertPlainText(toPrint);
qDebug()<<"Cursor: " << ui->textEdit_console->textCursor().position();
//Save the old cursorposition, so the user doesn't change it
cursPos= ui->textEdit_console->textCursor().position();
toPrint.clear();
}
I had the problem that if the user clicked around in the console, the cursor would change position and the following incoming data would end up in the wrong place. Issues:
If a section is marked by the user, the marking would get lost when new data is coming.
When "forcing" the pointer like this, it gets a rather ugly autoscroll behaviour that isn't possible to disable.
If the cursor is changed by another part of the program between to printouts, I also have to record that somehow.
The append function which sound like a more logical solution, works fine for appending a whole complete string but displays an erratic behaviour when printing just parts of an incoming string, putting characters and new lines everywhere.
I haven't found a single setting regarding this but there should be one? Setting QTextEdit to "readOnly" doesn't disable the cursor interaction.
3.An idea is to have two cursors in the console. One invisible that is used for printouts and that is not possible at all to manipulate for the user, and one visible which enables the user to select text. But how to do that beats me :) Any related example, FAQ or guide are very appreciated.
I've done a QTextEdit based terminal for SWI-Prolog, pqConsole, with some features, like ANSI coloring sequences (subset) decoding, command history management, multiple insertion points, completion, hinting...
It runs a nonblocking user interface while serving a modal REPL (Read/Eval/Print/Loop), the most common interface for interpreted languages, like Prolog is.
The code it's complicated by the threading issues (on user request, it's possible to have multiple consoles, or multiple threads interacting on the main), but the core it's rather simple. I just keep track of the insertion point(s), and allow the cursor moving around, disabling editing when in output area.
pqConsole it's a shared object (I like such kind of code reuse), but for deployment, a stand-alone program swipl-win is more handy.
Here some selected snippets, the status variables used to control output are promptPosition and fixedPosition.
/** display different cursor where editing available
*/
void ConsoleEdit::onCursorPositionChanged() {
QTextCursor c = textCursor();
set_cursor_tip(c);
if (fixedPosition > c.position()) {
viewport()->setCursor(Qt::OpenHandCursor);
set_editable(false);
clickable_message_line(c, true);
} else {
set_editable(true);
viewport()->setCursor(Qt::IBeamCursor);
}
if (pmatched.size()) {
pmatched.format_both(c);
pmatched = ParenMatching::range();
}
ParenMatching pm(c);
if (pm)
(pmatched = pm.positions).format_both(c, pmatched.bold());
}
/** strict control on keyboard events required
*/
void ConsoleEdit::keyPressEvent(QKeyEvent *event) {
using namespace Qt;
...
bool accept = true, ret = false, down = true, editable = (cp >= fixedPosition);
QString cmd;
switch (k) {
case Key_Space:
if (!on_completion && ctrl && editable) {
compinit2(c);
return;
}
accept = editable;
break;
case Key_Tab:
if (ctrl) {
event->ignore(); // otherwise tab control get lost !
return;
}
if (!on_completion && !ctrl && editable) {
compinit(c);
return;
}
break;
case Key_Backtab:
// otherwise tab control get lost !
event->ignore();
return;
case Key_Home:
if (!ctrl && cp > fixedPosition) {
c.setPosition(fixedPosition, (event->modifiers() & SHIFT) ? c.KeepAnchor : c.MoveAnchor);
setTextCursor(c);
return;
}
case Key_End:
case Key_Left:
case Key_Right:
case Key_PageUp:
case Key_PageDown:
break;
}
you can see that most complexity goes in keyboard management...
/** \brief send text to output
*
* Decode ANSI terminal sequences, to output coloured text.
* Colours encoding are (approx) derived from swipl console.
*/
void ConsoleEdit::user_output(QString text) {
#if defined(Q_OS_WIN)
text.replace("\r\n", "\n");
#endif
QTextCursor c = textCursor();
if (status == wait_input)
c.setPosition(promptPosition);
else {
promptPosition = c.position(); // save for later
c.movePosition(QTextCursor::End);
}
auto instext = [&](QString text) {
c.insertText(text, output_text_fmt);
// Jan requested extension: put messages *above* the prompt location
if (status == wait_input) {
int ltext = text.length();
promptPosition += ltext;
fixedPosition += ltext;
ensureCursorVisible();
}
};
// filter and apply (some) ANSI sequence
int pos = text.indexOf('\x1B');
if (pos >= 0) {
int left = 0;
...
instext(text.mid(pos));
}
else
instext(text);
linkto_message_source();
}
I think you should not use a static variable (like that appearing in your code), but rely instead on QTextCursor interface and some status variable, like I do.
Generally, using a QTextEdit for a feature-rich terminal widget seems to be a bad idea. You'll need to properly handle escape sequences such as cursor movements and color mode settings, somehow stick the edit to the top-left corner of current terminal "page", etc. A better solution could be to inherit QScrollArea and implement all the needed painting–selection-scrolling features yourself.
As a temporary workaround for some of your problems I can suggest using ui->textEdit_console->append(toPrint) instead of insertPlainText(toPrint).
To automatically scroll the edit you can move the cursor to the end with QTextEdit::moveCursor() and call QTextEdit::ensureCursorVisible().
I want to use the Irrnet network library in an Irrlicht game.
The source code uses Linux sockets and I'm trying to port it for Windows replacing it with code that uses Windows' Winsock2.
The library compiles successfully but when I try to run the Quake example it crashes. I located the line at which the program stops but i can't figure out how to solve the problem.
The program stops at the second call of the function getNextItem
class NetworkType {
public :
NetworkType();
~NetworkType();
template<class T>
void getNextItem(irr::core::vector3d<T>& data);
private:
typedef std::queue<std::string> Container;
Container items;
};
template<class T>
void NetworkType::getNextItem(irr::core::vector3d<T>& data) {
T X, Y, Z;
std::istringstream item(items.front());
// the program does not get here the second time it calls this function
items.pop();
item >> X;
item >> Y;
item >> Z;
data = irr::core::vector3d<T>(X, Y, Z);
}
and exactly at this line
std::istringstream item(items.front());
Can anyone tell me why does the program stop the second time it gets to this line ?
here is the link for the complete source code
I assume by "stops" you mean "crashes" in some fashion? Likely causes for a crash on the line in question are:
The NetworkType instance that is invoking the getNextItem() method is garbage (the this pointer is garbage or null). This could happen due to bad pointer math elsewhere, a premature delete or destruction of the instance, et cetera. This would manifest as a fault when the program attempted to access the items member.
The items container is empty. In these cases the return value of front() is undefined (since it is a reference) and the constructor for istringstream may be crashing. front() itself may be raising a debug/runtime check error as well depending on your compiler and its configuration.
Actually you might have a runtime error on this one if the dequeue is empty: MSDN deque
So just check the deque isn't empty before you try to pop a value from it.
if(items.size()>0)
{
//do things
}
else
{
//error deque empty
}
[edit] confounded std and (I guess) MSDN ( OP doesn't say) lib.