How to print console output in ATL COM module? - c#

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...

Related

Attaching Console to C# Windows Application with STDOUT Print Statements

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

Custom Powershell Host Invoke external program without console window

I'm writing an embedded powershell host in C# (windows application), and if there is an external program called in the pipeline the console window flashes as it's executed. Ping and netstat are examples of this as shown in the following code snippet
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("Get-Content test.txt; ls; ping www.google.com");
PowerShellInstance.Invoke();
# ...more code here to print output etc
}
Once the ping command is reached in the pipeline a console window will popup execute the command and return results. I would like to do this without the console window showing. I've searched and found examples of how to deal with this by starting a process for external commands and redirecting output.
I can do that of course, but then how would I test if a command in the pipeline is a call to an external program?
I would really like to be able to handle this generically if possible; meaning that I don't want to test for specific programs (e.g. ping, netstat, net) if I don't have to. The native powershell.exe does this so it's somehow possible.
It turns out that this is expected behavior of invoking console commands. In Windows 7 and above conhost.exe is responsible for handling calls to console programs. In this case, ping and netstat trigger an instance of conhost to be created, it handles the request, returns the results, and then remains open. conhost.exe starting up is what is causing the console flash I'm seeing. The fact that it remains open is why I was only seeing the console window flash once. Once conhost is connected to the calling process all subsequent console commands are handled by that same instance.
I'm marking this as an answer because a new question should be created to address conhost specifically.
Source. Windows Internals Part 1

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.

Windows Mobile 5 - How to kill other application?

currently I’m creating 2 applications (app A and B) for Windows Mobile 5.0 and using Compact Framework 2.0. App A is the main application and B is the sub application.
Below is the flow:
Start app A.
App A will start app B.
App B will do some process.
App B will kill app A.
App B will patch/upgrade app A. (ala update manager)
App B will restart app A.
App B will exit.
Now I’m stuck in killing app A. I did tried using OpenNETCF ProcessEntry Kill() function. When calling Kill(), it made the device crash.
I did tried using the SendMessage(hWnd, WM_CLOSE, 0, 0) funct where WM_CLOSE will have the ProcessEntry.ProcessID value and I didn’t assigned any value to hWnd variable. But it didn’t terminate app A. Did I assign the wrong value?
I also did tried using
Process.GetProcessById(processEntry.ProcessID).CloseMainWindow()
, but failed as GetProcessById only accepts int32 value. Note that processEntry.ProcessID value is larger than int32 value and GetProcessByName() is not supported in Compact Framework.
Could you help me in killing app A through app B?
Thanks.
You may try native code, using the TerminateProcess function:
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
success = TerminateProcess(processHandle, 0);
The above code is from a Task Manager at Code Project.
However if you are writing the code for both the applications, it will be better if you designed a communication mechanism between the two applications. In this way you will send a message from app B to app A and app A will kill itself.
Stormenet, I hardcoded the application's name. Then I generate an object to get all the available process using OpenNETCF.ToolHelp.ProcessEntry[ ] = ProcessEntry.GetProcesses();
then in a foreach loop, if the ProcessEntry object eg: processEntry.ExeFile matches with the "applicationName", i shall use processEntry.Kill().
I think you can get the OpenNETCF.ToolHelp dll from the OpenNETCF site.
Note that if the application you are trying to kill is holding open ports or other system resources then it might hang on exiting. Ensure everything is effectively disposed when the form closes.
This can be acheived by putting stuff in the:
public void Dispose(bool disposing)
{
}
block of code in the designer of your main form, or if you've chosen a less Windows Form centric architecture then just run your dispose calls following Application.Run(new YourForm()) and it will execute after the application has closed.
If you're feeling really lazy then just setup some destructors (otherwise known as finalizers ~) but be careful about navigating through relationships between managed objects at "destruct" time if you do this as there is no guarantee as to which order objects will be destroyed.
ctacke, I think app A crashes due to some of the running threads are not closed properly or still running at the background as app A will run multiple threads during app B executing the Kill( ) function.
If I use the SendMessage(hWnd, WM_CLOSE, 0, 0) function, it will not crash the device (which is a good thing)... it only closes the form. (app A contains multiple forms eg: frmLogin and frmMainMenu). hmmm maybe I need to point hWnd to the right form...
Now I'm taking a different route.
After downloading the patch and put it in a temp folder, I'll do a soft reset using OpenNETCF.WindowsCE.PowerManagement.SoftReset().
App B will be launched upon startup, then it will scan the temp folder and replace app A with the new version.

Send windows message to a Windows Service

Is there any tool to send (mimic) a windows message like 'WM_ENDSESSION' to a windows service?
OR
How can I send a windows message to a process using C#?
(I know only C#)
EDIT: Purpose: Basically I have to debug a windows service for fixing a bug that occurs only on system shut down.
Services should be controlled using ServiceController class
Represents a Windows service and allows you to connect to a running or stopped service, manipulate it, or get information about it.
You can use it to start, stop and communicate with services using this class.
Generally, services don't have windows (let alone message pumps) to receive a windows message.
If the bug really does only happen on shutdown (as opposed to just stopping the service), it may be the case that something depends on a resource that is going away, which is not being handled gracefully (in which case, the bug fix might be to set up the service dependencies correctly). Have you tried using the remote debugging tools to attach to the process prior to shutdown?
It's worth investigating if you can get the problem to occur without shutting down, perhaps when just stopping the service with the Service Control Manager (no need to do this programmatically, as this is a debugging scenario), in which case, you can breakpoint OnStop() in your service (I'm assuming C#) and watch what happens.
Check out the answers to How to simulate windows shutdown while debugging?
Services have an 'event' called OnShutdown they can subscribe to, so it could be the problem is in that code. If the code is .net you could subclass it so you can call the protected OnShutdown method to debug. But the problem could also be as suggested by others that the service is expecting resources to be available which aren't because they've already been closed.
Also, if the service was written in .net 2.0 note that the Stop() command isn't called automatically on a service when the workstation is being shut down! This is very surprising and was fixed in .net 3.5, but if you're using .net 2.0 you need to call Stop() yourself within OnShutdown().
If you have the hwnd of a window you can send it messages. The only limitation is that you can't send messages that contain pointers like setting window text.
Simply call PostMessage() with the value of the hwnd and the message you want to send.
To find the hwnd you can use spy++.
I'm not sure how you connect all this to windows services since windows services don't have windows.
I would recommend Importing and defining the following:
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool PostMessage(IntPtr handleWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
const int WM_ENDSESSION = 0x0016,
WM_TRUE = 0x1,
WM_FALSE = 0x0;
Then send through 0x1 or 0x0 representing true or false as the wParam message.
So in your code you will use:
PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0);
Where HandleToSendTo is the Window Handle of the window you would like to send the message to.
Edit
To get the windows handle if you don't know it, I'm assuming that you will know it's title or name. If so you can use this:
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern int FindWindowEx(int hwndParent, int hwndEnfant, int lpClasse, string lpTitre);
Which more information about can be found in this question.
Or maybe
I don't know if this is a similar handle, I doubt it, but someone could let me know if it is, but you can get a Process handle, which means you could get the process using Process.GetProcessesByName("MyAppName");, althought don't rely on this as I don't think that it will get the handle that you are after. Just a suggestion.
I don't think there is a tool to send arbitrary messages because each message can have arbitrary LPARAM and WPARAM values.
But the most useful tool surrounding windows messages is spy++. Spy++ is included with Visual Studio and it helps you see what messages are sent, window hierarchy, and more.
You can send messages via C# with the SendMessage Win32 API. You can get the window handle it asks for by using a Win32 API like FindWindow or FindWindowEx.
Edit (to match question's edit): Services are stopped by windows automatically on shutdown. So to fix your bug it sounds like you need to modify the code of the service itself to properly shut down.
Edit2: Or if you want to stop the service you should use the Win32 API ControlService passing in SERVICE_CONTROL_STOP 0x00000001.
I don't know if this is a similar handle, I doubt it, but someone could let me know if it is, but you can get a Process handle, which means you could get the process using Process.GetProcessesByName("MyAppName");, althought don't rely on this as I don't think that it will get the handle that you are after. Just a suggestion.
Actually this method will work...you just need to access the 'MainWindowHandle' property of the process object. For Instance...
Process myProcess;
Int handle;
myProcess = Process.GetProcessesByName("MyAppName");
handle = myProcess.MainWindowHandle;

Categories

Resources