Output to command-line if started from command line - command-line

I'm writing an application that can be started either as a standard WinForms app or in unattended mode from the command-line. The application was built using the VS 2k5 standard WinForms template.
When the application is executed from the command-line, I want it to output information that can be captured by the script executing the application. When I do this directly from Console.WriteLine(), the output does not appear, although it can be captured by piping to a file.
On the other hand, I can force the application to pop up a second console by doing a P/Invoke on AllocConsole() from kernel32. This is not what I want, though. I want the output to appear in the same window the application was called from.
This is the salient code that allows me to pop up a console from the command line:
<STAThread()> Public Shared Sub Main()
If My.Application.CommandLineArgs.Count = 0 Then
Dim frm As New ISECMMParamUtilForm()
frm.ShowDialog()
Else
Try
ConsoleControl.AllocConsole()
Dim exMan As New UnattendedExecutionManager(ConvertArgs())
IsInConsoleMode = True
OutputMessage("Application started.")
If Not exMan.SetSettings() Then
OutputMessage("Execution failed.")
End If
Catch ex As Exception
Console.WriteLine(ex.ToString())
Finally
ConsoleControl.FreeConsole()
End Try
End If
End Sub
Public Shared Sub OutputMessage(ByVal msg As String, Optional ByVal isError As Boolean = False)
Trace.WriteLine(msg)
If IsInConsoleMode Then
Console.WriteLine(msg)
End If
If isError Then
EventLog.WriteEntry("ISE CMM Param Util", msg, EventLogEntryType.Error)
Else
EventLog.WriteEntry("ISE CMM Param Util", msg, EventLogEntryType.Information)
End If
End Sub

Raymond Chen recently posted (a month after the question was posted here on SO) a short article about this:
How do I write a program that can be run either as a console or a GUI application?
You can't, but you can try to fake it.
Each PE application contains a field
in its header that specifies which
subsystem it was designed to run
under. You can say
IMAGE_SUBSYSTEM_WINDOWS_GUI to mark
yourself as a Windows GUI application,
or you can say
IMAGE_SUBSYSTEM_WINDOWS_CUI to say
that you are a console application. If
you are GUI application, then the
program will run without a console.
The subsystem determines how the
kernel prepares the execution
environment for the program. If the
program is marked as running in the
console subsystem, then the kernel
will connect the program's console to
the console of its parent, creating a
new console if the parent doesn't have
a console. (This is an incomplete
description, but the details aren't
relevant to the discussion.) On the
other hand, if the program is marked
as running as a GUI application, then
the kernel will run the program
without any console at all.
In that article he points to another by Junfeng Zhang that discusses how a couple of programs (Visual Studio and ildasm) implement this behavior:
How to make an application as both GUI and Console application?
In VisualStudio case, there are actually two binaries: devenv.com and devenv.exe. Devenv.com is a Console app. Devenv.exe is a GUI app. When you type devenv, because of the Win32 probing rule, devenv.com is executed. If there is no input, devenv.com launches devenv.exe, and exits itself. If there are inputs, devenv.com handles them as normal Console app.
In ildasm case, there is only one binary: ildasm.exe. It is first compiled as a GUI application. Later editbin.exe is used to mark it as console subsystem. In its main method it determines if it needs to be run as console mode or GUI mode. If need to run as GUI mode, it relaunches itself as a GUI app.
In the comments to Raymond Chen's article, laonianren has this to add to Junfeng Zhang's brief description of how Visual Studio works:
devenv.com is a general purpose console-mode stub application. When it runs it creates three pipes to redirect the console's stdin, stdout and stderr. It then finds its own name (usually devenv.com), replaces the ".com" with ".exe" and launches the new app (i.e. devenv.exe) using the read end of the stdin pipe and the write ends of the stdout and stderr pipes as the standard handles. Then it just sits and waits for devenv.exe to exit and copies data between the console and the pipes.
Thus even though devenv.exe is a gui app it can read and write the "parent" console using its standard handles.
And you could use devenv.com yourself for myapp.exe by renaming it to myapp.com. But you can't in practise because it belongs to MS.

Update 1:
As said in Michael Burr answer, Raymond Chen recently posted a short article about this. I am happy to see that my guess was not totally wrong.
Update 0:
Disclaimer: This "answer" is mostly speculation. I post it only because enough time has passed to establish that not many people have the answer to what look like a fundamental question.
I think that the "decision" if the application is gui or console is made at compile time and not at runtime. So if you compile your application as gui application, even if you don't display the gui, its still a gui application and doesn't have console. If you choose to compile it as console application then at minimum you will have a console windows flashing before moving to gui "mode". And I don't know if it is possible in managed code.
The problem is fundamental, I think, Because a console application has to take "control" of the calling console application. And it has to do so before the code of the child application is running.

If you want to check if your app is started from the command line in .NET, you can use Console.GetCursorPosition().
The reason that this works is that when you start it from the command line, the cursor moves away from the initial point ((0, 0)) because you typed something in the terminal (the name of the app).
You can do this with an equality check (code in C#):
class Program
{
public static void Main
{
if (Console.GetCursorPosition() == (0, 0))
{
//something GUI
}
else
{
//something not GUI
}
}
}
Note: You must set the output type to Console Application as other output types will make Console.GetCursorPosition() throw an exception.

Related

Boost Asio tcp::iostream construction raise an Access Violation Exception on every second use

I am trying to use the implementation of std::iostream provided by boost::asio on top of boost::asio::ip::tcp::socket. My code replicate almost line to line the example that is published in Boost Asio's documentation:
#include <iostream>
#include <stdexcept>
#include <boost/asio.hpp>
int main()
{
using boost::asio::ip::tcp;
try
{
boost::asio::io_service io_service;
tcp::endpoint endpoint(tcp::v4(), 8000);
tcp::acceptor acceptor(io_service, endpoint);
for (;;)
{
tcp::iostream stream; // <-- The exception is triggered on this line, on the second loop iteration.
boost::system::error_code error_code;
acceptor.accept(*stream.rdbuf(), error_code);
std::cout << stream.rdbuf() << std::flush;
}
}
catch (std::exception& exception)
{
std::cerr << exception.what() << std::endl;
}
return 0;
}
The only difference is the use I make of the resulting tcp::iostream: I forward everything I receive to the standard output.
When I compile this code with VisualStudio2019/toolset v142 and Boost from the NuGet boost-vc142, I get an Access Violation Exception only in the second iteration in the for loop, in the function
template <typename Service>
Service& service_registry::use_service(io_context& owner)
{
execution_context::service::key key;
init_key<Service>(key, 0);
factory_type factory = &service_registry::create<Service, io_context>;
return *static_cast<Service*>(do_use_service(key, factory, &owner));
} // <-- The debugger show the exception was raised on this line
in asio/detail/impl/service_registry.hpp. So the first iteration everything goes as planned, the connection is accepted, the data shows up on the standard output, and as soon as the stream is instanciated on the stack for the second time, the exception pops.
I don't have a high confidence in the accuracy of this location of the exception reported by the debugger. For some reason, the stack seams to be messed up and show only one frame.
If the declaration of stream is moved out of the loop, no exception is raised any more but then I need to stream.close() at the end of the loop, or nothing shows up on the standard output except the data from the first client's connection.
Basically, as soon as I try to instanciate more than one boost::asio::tcp::iostream (not necessarily at the same time), the exception is raised.
I tried the exact same code under linux (Arch linux, latest version of g++, same version of Boost) and everything works perfectly.
I could work around this issue by not using iostreams, but my idea is to feed the data received on the tcp socket to a parser which only accept implementations of std::iostream, hence I would still need to wrap asio's tcp socket in an homebrewed (and mediocre) implementation of std::iostream.
Does anybody have an idea on what's wrong with this setup, if I missed a crucial #define somewhere or anything?
Update:
Subsequent investigation show that the only situation where the access violation happens is when the executable is run from within Visual Studio (typ. from the menu Debug -> Start Debugging).
The build process seems to have no effect (calling directly cl.exe, using MSBuild, using devenv.exe).
Moreover, if the executable is run from a command prompt, and only then the debugger is attached, no access violation happens.
At this point, the issue is most likely not linked to the code itself.
Okay, it was exceedingly painful to test this on windows.
Of course I first tried on Linux (clang/gcc) and MingW 8.1 on windows.
Then I bit the bullet and jumped the hoops to get MSVC in command line with boost packages¹.
I cheated by manually copying the .lib/.dll for boost_{system,date_time,regex} into the working directory so the command line stayed "wieldy":
C:\work>C:\Users\sghee\Downloads\nuget.exe install boost_system-vc142
C:\work>C:\Users\sghee\Downloads\nuget.exe install boost_date_time-vc142
C:\work>C:\Users\sghee\Downloads\nuget.exe install boost_regex-vc142
(Be sure to get some coffee during those)
C:\work\> cl /EHsc test.cpp /I .\boost.1.72.0.0\lib\native\include /link
Now I can run test.exe
C:\work\> test.exe
And it listens fine, accepts connections (sequentially, not simultaneously). If you connect a second client while the first is still connected, it will be queued and be accepted only after the first disconnects. That's fine, because it's what you expect with the synchronous accept and loop.
I used Ncat.exe (from Nmap) to connect:
C:\Program Files (x86)\Nmap>.\ncat.exe localhost 8000
Quirk: The buffering was fine with the MSVC cl.exe build (linewise) as opposed to MingW behaviour, even though MingW also uses ws2_32.dll. #trivia
I know this doesn't "help", but maybe you can compare notes and see what is different with your system.
Video Of Test
¹ (that's a tough job without VS and also I - obviously - ran out of space, because 50GiB for a VM can't be enough right)

Connecting FluidEnter/FluidExit at run-time

I am toying with the FluidEnter/FluidExit. So in a simple form, here is what I am trying to do:
I created in Main an empty population of agent called Terminal. For now, in Terminal, there is only a fluidEnter connected to a fluidExit (very simple)
enter image description here
Now, on startup, I want to fill this population and set up the proper connections (the terminals are ordered).
So, on startup, I call a function init(), whose body start with Terminal t = add_terminals(); (I have only one terminal for now, just toying with things)
In Main, obviously, I also have a fluidEnter and a fluidExit. I would like to connect the fluidExit of Main to the fluidEnter of the terminal t, and the fluidExit of the terminal t to the fluidEnter of Main, so code (still in init()) looks like
fluidExit.set_fluidEnter(t.fluidEnter);
t.fluidExit.set_fluidEnter(fluidEnter);
I get an exception so obviously, I am doing something wrong. Any idea?
I think the set_fluidEnter function is deprecated or just non-functional.
Instead, you should do:
fluidExit.connect(t.fluidEnter);
So just replace set_fluidEnter with connect... nothing else.
That should do the trick
I was going down the same path as you a couple of months ago. Yes... .connect() works great. It even works as a gate. If it is disconnected, then fluid stops at the exit. Once connected, fluid starts to flow again. It is very slick.

application creating muant handles and never frees them

My c++ application is creating mutant handles. I couldn't find where the handle is being created, so I used Windbg and with !htrace. It doesnt give the exact function name. All my symbol files are loaded and the application is built in debug mode.
!htrace shows open handles but the exact function where the handle is been opened,it doesnt show.
The trace looks like this
Handle = 0x00000d34 - OPEN
Thread ID = 0x00003670, Process ID = 0x00004748
0x77a0473c: ntdll!ZwCreateMutant+0x0000000c
0x75d7a0cd: KERNELBASE!CreateMutexExW+0x0000005e
0x75d7bb94: KERNELBASE!CreateMutexExA+0x0000002f
0x75d7bb5c: KERNELBASE!CreateMutexA+0x0000001d
Is there any alternative way to debug this issue?

Stop VFP from showing dialog boxes when errors occur

I am trying to call an existing VFP 6 application using Jacob which is a COM bridge for Java.
val vfp = new Application(new ActiveXComponent("VisualFoxPro.Application").getProperty("Application").toDispatch())
vfp.setVisible(false)
try {
vfp.doCmd("do my.exe with myconfig.txt")
} catch {
case t: Throwable => t.printStackTrace
} finally {
vfp.doCmd("close data")
vfp.doCmd("clear all")
vfp.doCmd("clear")
vfp.quit
vfp.safeRelease
}
When there are no error conditions this code executes well and generates the expected .dbfs. The problem is that when an error occurs (.dbf not found, file in use by another user, etc) a GUI window pops up and stops execution of the program until I use the mouse to cancel it. I want this program to run on a server with no user interaction so this won't work.
How can I gracefully handle the errors preferably without making a change to the VFP 6 program?
Since you have the source code for VFP6, I would suggest looking into
SYS(2335,0)
Sys 2335 is used to identify if the program is running in an "unattended" mode, any such popup dialog boxes will throw an error and prevent an actual "hit" ok/cancel/whatever button to continue. This includes popup window prompting user to pick a table.
I'm not positive of when it was made available as I had limited use of it. Like you, when dealing with a COM server under IIS and obviously nobody there to respond.
Start JVM in headless mode, catch HeadlessException or something. Or, write a Java program that will execute your GUI program using Runtime, and restart in a case of parsed errors in console.

perl: Launch process with system(), then check if its running under a specific display number

I have a locked down "kiosk" terminal server.
This terminal server has a perl script as its .Xsession, and launches a Tk interface. When that Tk interface is done, the perl script launches "process2" and lets the user interact with "process2" (which is a graphical application).
If a user tampers with "process2", and make it crash, the user might be able to access the underlying desktop, therefore I would want to check if "process2" is running, and if "process2" is not running on $display, I would want to just execute logout (which would logout the display the perl script is currently running as).
Since the system is running 10 instances of "process2" to 10 different users simultanuosly, I cant just check if "process2" is running on the system with "ps" or someting like that. I need to check if "process2" is running under that specific display $display.
Note that all 10 users log on as the same username in all sessions, so I cannot check all processes run by a specific user, that would return all 10 instances too.
Like:
system("process2 &");
while(1) {
sleep(1);
if (is_it_running("process2", $display) == false) {
system("logout &");
}
}
Its the function "is_it_running" that I need to get to know how it should look.
$display can either contain the raw display number, like this: ":1.0", or it can contain the display number parsed out, like this: "1".
If you use fork and exec instead of system("...&"), you can store the Process IDs of your child processes and more directly check their status. See also perlipc.
Why not just run process2 in the foreground? Then your perl script won't get control back until it's done executing, at which point it can exit:
system("process2");
system("logout");
Of course, if that's the entire script, maybe a bash script would make more sense.
I solved it after many attempts.
Did a piped open
$pidofcall = open(HANDLE, "process2|");
Then I did whatever I did need to do, and I made the server send a signal to me if it loses connection with process2. If I did need to bang out, I simply did a "goto killprocess;" Then I simply had:
killprocess:
kill(9,$pidofcall);
close(HANDLE);
$mw->destroy;
system("logout");