Attaching Console to C# Windows Application with STDOUT Print Statements - c#

I have a C# GUI application that also supports a command line mode for server-side scripting. My application keys off of the number of input arguments, and if > 0, attaches the parent console.
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
[STAThread]
static void Main(string[] args)
{
bool runningFromConsole = args.Length > 0 && AttachConsole(ATTACH_PARENT_PROCESS);
if(runningFromConsole)
// Handle input arguments
else
// Launch GUI
}
I am able to successfully write text to the console with Console.Out.WriteLine("Text");, but the line is not sent to the console as a STDOUT (or STDERR if I use Console.Error.WriteLine("Text")).
When running my application locally, this is not a big deal, but when running on a build server, the application returns do not register. Right now, I am working around the issue by creating a supplimental log file that I type application.log to the console once my application finishes running.
Is there a way for force text printed to the console to be sent as STDOUT/STDERR?

AttachConsole doesn't quite behave the way you expect, what you need to do often is to AllocConsole and change your stdio handles to use that console.
The accepted answer for this question I can verify works in this scenario because I've used it: No console output when using AllocConsole and target architecture x86

Related

How to print console output in ATL COM module?

I have a ATL exe module, which I want to print some output to the console.
This module is called by another C# console application, so it should already has a console.
In ATL:
extern "C" int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR , int nShowCmd)
{
printf("test"); // <- this did nothing
MessageBox(nullptr, L"test", L"caption", MB_OK); // <- this work
//...
}
EXE COM server will be launched by itself and not attached to console of the caller - it may be even already launched by some previous client which may not even be console app.
If you need to send output to caller's console you'd better just return text to caller.
It may be possible to pass caller's console handle to the COM object as method parameter and try to configure default output to use that console, but I'd personally will not even try. I.e. you'd have to figure out how multiple clients can provide multiple console handles to set as default...

Programatically paste text into text box in another application

I want to be able to paste the results from my application to another application. Been Googling and all I can find is the ApplicationCommands.Paste. That will paste it into my application not another application.
Background: My application needs to interact with a very old application. This application is not being developed and DOES NOT have any API calls. Meaning any answers like "Link your application via DLLs" will only be excepted if it also includes a time machine :P So the solution is to simple paste results from my app to the old application.
For workflow reasons the client wants my Application to disappear and automatically paste the results into an open text box in (if it fails then manually pasting the results in).
Hiding the window is simple, but how do I find current active application and then paste it in? Is this even possible? Also note this application is NOT .NET (VB 6 if I am correct).
You can bring up the other app and send a key combination... something like:
[DllImport ("User32.dll")]
static extern int SetForegroundWindow(IntPtr hwnd);
public static void PasteToApplication(string appName)
{
var proc = Process.GetProcessesByName(appName).FirstOrDefault();
if(proc != null)
{
var handle = proc.MainWindowHandle;
SetForegroundWindow(handle);
SendKeys.SendWait("^v");
}
}
This should bring up the other app's window and send a ctrl-v command. With a bit of experimentation, you could find out the exact handle of the control you want to send the paste to, and set focus on it aswell

ShowWindow Function Doesn't Work When Target Application Is Run As Administrator

I am writing a program that shows/hides the window of some target application. I was testing it out earlier and noticed something strange. If I run the target application as Administrator (right-click->Properties, "Compatability" tab, "Run this program as administrator") it doesn't work.
To demonstrate I wrote a simple GUI app called "TargetApplication" and then I wrote the following code to test showing/hiding this application:
class Program
{
static void Main(string[] args)
{
IntPtr windowPtr = FindWindow(null, "TargetApplication");
ShowWindow(windowPtr, 0); // 0 = Hide
Console.WriteLine("The window is now hidden. Press Enter to restore");
Console.ReadLine();
ShowWindow(windowPtr, 9); // 9 = Restore
Console.WriteLine("The window is now restored. Press Enter to exit.");
Console.ReadLine();
}
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
If I start the windowed application without Administrator rights it doesn't work.
Would anyone mind testing this for me? I have uploaded the .exe's for both applications here:
TestShowWindow Download
All you have to do is download them and run TestApplication.exe then run TestShowWindow.exe. You will find that by changing TestApplication.exe to run as Administrator causes ShowWindow to no longer work.
Of course if you don't trust downloading my stuff you can always compile my code and test it on any target application in Windows that you are able to change compatability mode of.
P.S. I am not sure if it makes a difference but I am running Windows 8 Pro. 64-bit.
This is by design. It is the lesser known twin of UAC, called UIPI or User Interface Privilege Isolation. An un-elevated program cannot commandeer an elevated one. Given the capabilities of UI Automation, this is an obvious counter-measure to stop programs from hijacking the capabilities of an elevated process. A security violation called a shatter attack.
Workarounds are to provide a manifest with uiAccess = true for a program stored in c:\windows or c:\program files and provided with a certificate. And for the target program to call ChangeWindowMessageFilter to allow certain messages to be sent. In your case that ought to be WM_SHOWWINDOW.
If you don't mind the window acting like you minimized it to the taskbar; You can, generally, show and hide windows from elevated processes by posting WM_SYSCOMMAND with a wParam of SC_RESTORE or SC_MINIMIZE.

How to run a .NET console application in the background

I have a console application written in C# that is scheduled to run every 15 minutes or so using the built-in Windows Task Scheduler.
Every time it runs, the black console box pops up for the duration of its execution and then closes. I am not writing anything to the console. Is there a way to make this run in the background?
Project > Properties> Application tab > change Output type to "Windows application".
No more console window.
Easy!
It seems hard to believe, but it works as a charm. I have used this for some setup projects, when you want to perform custom tasks with no signs of it.
Create the project as a Windows application project (this is the hard part).
Never make calls to any form. Just keep on in exactly as in your console application
class Program
{
static void Main(string[] args)
{
// Just don't call Application.Run(new frmMain(args));
// ... your code
}
}
This is because windows application projects are no really different than console, except because of the first form and references.
It is totally hidden execution. Try it!
You can use the Windows API to minimize the console box. Otherwise you can make it a Windows EXE file that does not actually load a form and call System.Windows.Forms.Application.Run().
Code to minimize the console:
[DllImport( "user32.dll" )]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public const int SW_SHOWMINIMIZED = 2;
IntPtr winHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
ShowWindow(winHandle, SW_SHOWMINIMIZED);
What about implementing the app into a windows service? You can set the interval to 15 mins and run the operation in the timer_tick.
If you already have a Windows Console app created you can simply change the Output type of your app to Windows Application.
Under your project:
Go to Properties > Application
Select "Windows Application" as the Output type.
This would be the least impact and you can keep your Windows Task Scheduler running the same task.
If it doesn't write anything to the console you could make it a service.
http://msdn.microsoft.com/en-us/library/9k985bc9%28VS.80%29.aspx
It will only show up if it's scheduled to run as the same user that's currently logged in. Create another user on the machine with a ridiculously long password, set it to be an Administrator (only if needed) and schedule the task to run as that user.
This is easy. Set the task to run under an account that is not your login account.

Using a debug mode for a program that runs on a remote desktop

I have a short program that is used exclusively with a remote desktop connection that's been set to only run that program and not allow any other access into the remote machine. Previously, the program just exited and let the connection terminate, but it was very slow, so I wrote the following code to terminate the remote session when the program is done running.
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSLogoffSession(IntPtr hServer, int SessionId, bool bWait);
private IntPtr WTS_CURRENT_SERVER_HANDLE;
private const int WTS_CURRENT_SESSION = -1;
...
private void HardTerminalExit()
{
WTSLogoffSession(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, false);
}
This works fine when this program is in its production environment, used by the people who are remoting in using a specific RDP connection file. The connection exits after the program is run. However, when testing and debugging this program, my computer restarts after every run.
I'm looking for a good way to distinguish between these cases. Should I set up some kind of debug script that remotes in and runs the program remotely? Or is there some way to programmatically detect whether the program is running in debug mode and just disable the exit procedure in that case?
You can use the pragma directives:
private void HardTerminalExit()
{
#if DEBUG
// Soft Exit
#else
// Hard Exit
#end if
}
I believe it's better practice to use the newer ConditionalAttribute, but I don't think you can negate that, so you'd need to set an environment variable for "RELEASE" yourself:
[Conditional ( "RELEASE" )]
private void HardTerminalExit()
{
// Hard Exit, only called when "RELEASE" is defined.
}
This will tell the compiler to only call this method when the "RELEASE" environment variable is declared somewhere - this can declared in during compilation (Conditional compilation symbols on the Build property pane) or as part of the operating system shell, see ConditionalAttribute for more inforamation on this.

Categories

Resources