|
Your statement is also somewhat nonsensical in that when my sample app quits it destroys the console you wouldn't see it (see WM_DESTROY).
So I can only assume you mean your app you are running wont display until it exits????
So are you wanting live output keeping the app alive ???
You will have to spawn the thread before the call at the moment the program is
CreateProcess
Process output
That is the app must complete it's setup to deal with normal DOS like command files.
If it doesn't complete then the app will still be on the screen so why do you want it redirected to the console?????
In vino veritas
modified 19-Feb-18 12:30pm.
|
|
|
|
|
Okay so this spawns the thread before it executes the command passed in.
It should spit the console even if the command doesn't terminate, which I still find strange.
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <tchar.h>
FILE* OutStream;
FILE* InStream;
FILE* ErrStream;
struct execData {
TCHAR* CmdLine;
TCHAR* CmdRunDir;
PROCESS_INFORMATION process_info;
STARTUPINFO startup_info;
};
struct execData data = { 0 };
LRESULT CALLBACK GUIDemoHandler (HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_CREATE:
AllocConsole();
freopen_s(&InStream, "CONIN$", "r", stdin);
freopen_s(&OutStream, "CONOUT$", "w", stdout);
freopen_s(&ErrStream, "CONOUT$", "w", stderr);
break;
case WM_DESTROY:
if (data.process_info.hProcess) TerminateProcess(data.process_info.hProcess, 0);
FreeConsole();
PostQuitMessage(0);
break;
default: return DefWindowProc(Wnd, Msg, wParam, lParam);
};
return 0;
}
DWORD WINAPI ExecThreadFunction(LPVOID lpParam)
{
int Success;
struct execData* data = (struct execData*)lpParam;
Success = CreateProcess(
nullptr,
data->CmdLine,
nullptr,
nullptr,
TRUE,
0,
nullptr,
data->CmdRunDir,
&data->startup_info,
&data->process_info
);
if (!Success) {
CloseHandle(data->process_info.hProcess);
CloseHandle(data->process_info.hThread);
return -4;
}
else {
CloseHandle(data->process_info.hThread);
}
WaitForSingleObject(data->process_info.hProcess, INFINITE);
CloseHandle(data->process_info.hProcess);
data->process_info.hProcess = 0;
return (0);
}
int SystemCapture(
TCHAR* CmdLine,
TCHAR* CmdRunDir)
{
SECURITY_ATTRIBUTES security_attributes;
data.CmdLine = CmdLine;
data.CmdRunDir = CmdRunDir;
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = nullptr;
data.startup_info.cb = sizeof(STARTUPINFO);
data.startup_info.hStdInput = 0;
data.startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
data.startup_info.hStdError = 0;
data.startup_info.dwFlags |= STARTF_USESTDHANDLES;
CreateThread(NULL, 0, ExecThreadFunction, (LPVOID)&data, 0, NULL);
return 0;
}
const TCHAR* ClassName = _T("GUI_CONSOLE_APP");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG Msg;
HWND Wnd;
WNDCLASSEX WndClass = { 0 };
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.style = CS_OWNDC;
WndClass.lpfnWndProc = &GUIDemoHandler;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = GetModuleHandle(NULL);
WndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(0, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = ClassName;
RegisterClassEx(&WndClass);
Wnd = CreateWindowEx(0, ClassName, _T("GUI Console Demo Program"),
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
50, 50, 500, 400,
0, 0, 0, NULL);
_tprintf(_T("This will go to the console\r\n"));
std::cout << "Second line to console\r\n" << std::endl;
int rc;
TCHAR szCmdDir[256] = _T(".");
std::cout << "\r\nExecute console app:" << std::endl;
TCHAR szCmdLine1[256] = _T("ConsoleApp.exe");
rc = SystemCapture(
szCmdLine1,
szCmdDir
);
while (GetMessage(&Msg, 0, 0, 0)){
TranslateMessage(&Msg);
DispatchMessage(&Msg);
};
return (0);
}
I made a strange console app that just spins the cursor to test it worked which was called ConsoleApp.exe hence my name above
static const char Spin[4] = { '|', '/', '-', '\\' };
int main()
{
int i = 0;
while (1) {
printf("Deadloop %c\r", Spin[i]);
for (long j = 0; j < 10000000; j++) {};
i++;
i %= 4;
}
return 0;
}
In vino veritas
modified 19-Feb-18 13:37pm.
|
|
|
|
|
I am checking it using test app with WriteFile function and it works. But I will check it using target app tomorrow because it needs some hardware to work.
Thanks
|
|
|
|
|
This code is working.
Now I will try to analyze outputs and build GUI.
I am not sure if can I use the code in C# WPF application. If not I will try to build GUI using Win API starting from your examples. Thank you.
|
|
|
|
|
It's a simple background worker thread it will work without issue in a C# WPF application.
How to: Use a Background Worker[^]
Inside the worker thread you want a standard command execute
static void runCommand() {
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c yourfile.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) {
Console.WriteLine(outLine.Data);
}
In vino veritas
modified 20-Feb-18 2:21am.
|
|
|
|
|
I do simple test and problem is the same as before. Only when console app quits OutputHandler is executed and then I can read every line by line that app prints during running. Furthermore, it seems that StandardInput is not redirected because click on the button does not quit the app. App quits when 'e' key is pressed in the console window.
public partial class MainWindow : Window
{
Process process = new Process();
public MainWindow()
{
InitializeComponent();
runCommand();
}
private void button_Click(object sender, RoutedEventArgs e)
{
textBox.Text += "test\r\n";
process.StandardInput.Write('e');
}
void runCommand()
{
process.StartInfo.FileName = "c:\\ConsoleApp.exe";
process.StartInfo.Arguments = ".";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine);
}
}
|
|
|
|
|
Yes because you didn't put it in a worker thread
You need runCommand() to be in a worker thread .. it has to execute in the background so you can keep the WPF framework running in the foreground.
Look back at the windows code I had to do the same thing the CreateProcess(...) is inside a function which is spawned into it's own thread via CreateThread.
Unfortunately I don't use C# enough to know the code for making a worker thread off the top of my head.
I actually don't have the WPF framework installed on my VisualStudio at the moment to work it out.
Basically however we can describe it
1.) everything in runCommand() needs to go inside the worker thread start function .. when the thread starts it runs the app
2.) When the app finishes or your WPF app finishes you need to close the worker thread (LOOK at WM_DESTROY on the windows code)
So basically this worker thread will be chugging along in the background running the app but your program comes back to you to continue on to run the WPF framework.
So you job is to work out how to make a WPF worker thread and incorporate the code
In vino veritas
|
|
|
|
|
If you want a total guess looking at the MSDN reference and your code but ignoring the exit problem
using System.Threading;
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
runCommand();
}).Start();
|
|
|
|
|
Running runCommand() from new Thread didn't help. I can read all outputs after console app quits.
It is harder to build GUI using WinAPI than using WPF but WinAPI code works.
|
|
|
|
|
|
OK, I know what you mean
For me, it is easier to use WPF because I am embedded system engineer.
I am from embedded world and I do not know Windows internals.
That is why I am asking a lot of (stupid) questions. After reading several articles I supposed that redirect output and develop GUI app should be easier
Now I know that my strange console app does not use standard printf function
|
|
|
|
|
The obvious question is can you not simply replace the program communicating with a proper windows code or is it a private format they won't disclose. Just saying it would be faster, cleaner and less code than what you are doing now
In vino veritas
|
|
|
|
|
Yes, it is a private closed format.
Another way to communicate with the console app is passing command line arguments:
MyApp.exe -Iinput.txt -Ooutput.txt
where in the input.txt file in each line is a key command (e - exits the program, other keys do some actions):
l
f
m
c
o
e
in the output.txt file, the program saves its output. Even something like this works:
MyApp.exe -OCON - prints output to console twice.
But problem is the same. If I monitor the output file, the content appears after app quits (e command in input file)
|
|
|
|
|
This smells to me of buffering. I'm guessing your app doesn't call flush() or equivalent on its output file, so the output is buffered until the explicit or implicit close() call at termination.
If you can make your app output lots of data, you will probably see it appear in chunks, which will be whatever buffer size is used.
The reason it works on the console is that console drivers do not buffer.
I have no idea if you can suppress buffering in your redirection, but if you could, my 2c says that would solve your problem.
Good luck!
Peter
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
Yes standard console output is always buffered.
You can actually easily remove it
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
The problem is it will slow the console program down like a dog as each character invokes a full call.
I sometimes do it when I have a embedded target with UART debugger like on the Raspberry Pi.
In vino veritas
|
|
|
|
|
my code is:
#include<stdio.h>
#include<conio.h>
struct point
{
int x,y;
void getdis()
{
printf("%d",x+y);
}
};
int main()
{
struct point p;
int a=5,b=10;
p.getdis(a,b);
getch();
return 0;
}
problem is:8 2 F:\software\Dev-Cpp\bin\point.c [Error] expected ':', ',', ';', '}' or '__attribute__' before '{' token
I cannot understand what to write before the getdis function to avoid this error
suman chandra modak
|
|
|
|
|
void getdis()
...
p.getdis(a,b);
These two do not match. Hint: they should.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
methods are a C++ feature you can only mimic in C , suing function pointers and the like. For instance
#include<stdio.h>
struct point
{
int x,y;
void (*pfun)(struct point *pp);
};
void getdis(struct point *pp)
{
printf("%d\n", (pp->x + pp->y));
}
int main()
{
struct point p;
p.x = 5; p.y = 10;
p.pfun = getdis;
p.pfun(&p);
getchar();
return 0;
}
|
|
|
|
|
i am trying to write a code to solve Laplace equation using Successive
Over relaxation(SOR)on a NXN matrix
boundary condition is X^2-y^2
i dont know how to set this boundary condition on the Mesh created by me
here is the code
import numpy as np
from pylab import *
import sys
import copy
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
L =[[]for i in range(2)]
N=int(input("Enter a number N for N x N grid: "))
h=1/N
def clear_list1():
L[1].clear()
L[0].clear()
iterat=0
error=0.75
clear_list1()
xx=np.arange(0,N,h)
yy=np.arange(0,N,h)
x,y = np.meshgrid(xx,yy)
phi= copy.deepcopy((x**2-y**2))
phi[1:-1,1:-1]=0
phi_new = copy.deepcopy(phi)
resid=np.zeros((N,N))
while True:
if iterat<21:
for w in np.linspace(1,2,11):
for i in range(1,N-1):
for j in range(1,N-1):
phi1=(phi[i+1,j]+phi[i-1,j]+phi[i,j+1]+phi[i,j-1])/4
phi[i,j]=w*phi1+(1-w)*phi1
Sumresidual=0
for i in range(1,N-1):
for j in range(1,N-1):
resid[i,j]= -4*phi[i,j]+phi[i+1,j]+phi[i-1,j]+phi[i,j+1]+phi[i,j-1]
Sumresidual=Sumresidual+(resid[i,j])**2
else:
break
iterat=iterat+1
p=np.sqrt(Sumresidual)
L[0].append(p)
L[1].append(w)
ax = plt.axes()
ax.xaxis.set_major_locator(ticker.MaxNLocator(5))
plt.plot(L[0],L[1])
plt.yscale('log')
plt.xlabel('w')
plt.ylabel('|| residual ||')
plt.title('effect of w on residual')
plt.show()
|
|
|
|
|
And what does your code have to do with the C / C++ / MFC Forum?
|
|
|
|
|
hi
I was getting storage overlays in my local variable when I noticed that the SP register was 0X4652E25F0 and my BP registers was 0X4C652E2A60 does that mean that my stack size is 144 bytes
I have a table in the function itself that is 256 bytes to translate ASCII to EBCDIC
beginthread stack size is 0
|
|
|
|
|
Quote: In addition, the stack_size argument can be 0, in which case the operating system uses the same value as the stack that's specified for the main thread.
Don't try to guess what the situation may be just by looking at registers. In most code BP is set as a base register from an offset of SP, but that does not imply any particular stack size.
|
|
|
|
|
I guess it could be set /F compiler option thanks
|
|
|
|
|
ForNow wrote: I guess it could be ... ... anything. Guessing is not generally a good strategy for fixing problems. You need to be sure what the problem is first. Maybe if you show the code where the problem occurs, and a few more details, we could make some useful suggestions.
|
|
|
|
|
if stepped thru the code in Assembler after the function prologue by subtracting BP - SP = stack size right ?
I added code to a source file in Hercules cpu.c thing is its a makefile build which very confusing I was wondering if there isn't -F or /F flag for the stack size I guess it would default to some number my local variables and parameters would make the stack a little over 300 bytes, which is not too big
I am trying to figure to determine where in the makefile is the compile for CPU.C
Thanks
|
|
|
|
|