I have a Console Application app, I would like to minimize (not hide permanently) the Console when i run the app, is it possible?
also, I am using a timer to run the task every 10 minutes, is it possible to minimize the console every time the app runs?
thanks!
The following code should do the trick. Uses Win32 methods to minimize the console window. I am using Console.ReadLine() to prevent the window closing immediately.
internal class Program
{
[DllImport("User32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow([In] IntPtr hWnd, [In] int nCmdShow);
private static void Main(string[] args)
{
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
ShowWindow(handle, 6);
Console.ReadLine();
}
}
Related
I have created a library to inject DLL files into processes using a variety of methods. I am testing it out with a GUI using Windows Forms.
All the methods work as intended except when using QueueUserAPC. When I attempt to use this method, the process that I am injecting a DLL into crashes.
I created a basic console application to test this method outside of a Windows Form and it worked as intended without the process crashing. Furthermore, my error checking tells me that the DLL is injecting without any errors when using the QueueUserAPC method from a Windows Form, however, the process still crashes.
I have a feeling that the reason the process is crashing when using a Windows Form isn't to do with the code of the QueueUserAPC method and more about the permissions of a Windows Form. However, I could be wrong so I will include the code for the method below.
pinvoke
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessPrivileges dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, MemoryAllocation flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern void VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, MemoryAllocation dwFreeType);
public enum MemoryAllocation
{
Commit = 0x1000,
Reserve = 0x2000,
Release = 0x8000,
AllAccess = Commit | Reserve
}
public enum MemoryProtection
{
PageReadWrite = 0x04,
PageExecuteReadWrite = 0x40
}
public enum ThreadAccess
{
SuspendResume = 0x02,
GetContext = 0x08,
SetContext = 0x010,
AllAccess = SuspendResume | GetContext | SetContext
}
QueueUserAPC Method
public static class MQueueUserAPC
{
public static bool Inject(string dllPath, string processName)
{
// Get the pointer to load library
var loadLibraryPointer = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (loadLibraryPointer == IntPtr.Zero)
{
return false;
}
// Get the handle of the specified process
var processId = Process.GetProcessesByName(processName)[0].Id;
var processHandle = OpenProcess(ProcessPrivileges.AllAccess, false, processId);
if (processHandle == IntPtr.Zero)
{
return false;
}
// Allocate memory for the dll name
var dllNameSize = dllPath.Length + 1;
var dllMemoryPointer = VirtualAllocEx(processHandle, IntPtr.Zero, (uint) dllNameSize, MemoryAllocation.AllAccess, MemoryProtection.PageReadWrite);
if (dllMemoryPointer == IntPtr.Zero)
{
return false;
}
// Write the dll name into memory
var dllBytes = Encoding.Default.GetBytes(dllPath);
if (!WriteProcessMemory(processHandle, dllMemoryPointer, dllBytes, (uint) dllNameSize, 0))
{
return false;
}
// Call QueueUserAPC on each thread
foreach (var thread in Process.GetProcessesByName(processName)[0].Threads.Cast<ProcessThread>())
{
var threadId = thread.Id;
// Get the threads handle
var threadHandle = OpenThread(ThreadAccess.SetContext, false, (uint) threadId);
// Add a user-mode APC to the APC queue of the thread
QueueUserAPC(loadLibraryPointer, threadHandle, dllMemoryPointer);
// Close the handle to the thread
CloseHandle(threadHandle);
}
// Close the previously opened handle
CloseHandle(processHandle);
// Free the previously allocated memory
VirtualFreeEx(processHandle, dllMemoryPointer, dllNameSize, MemoryAllocation.Release);
return true;
}
}
How I am using it in my Windows Form / Console Application
var injector = new Injector();
if(Injector.QueueUserAPC(dllPath, processName))
{
MessageBox.Show("No error was raised");
}
I guess what I am asking is do Windows Forms have fewer permissions than Console Applications and if so, how could I configure my Windows Form so that I don't run into the problem of the process crashing when trying the use QueueUserAPC.
If you would like to test the library I have it on Github with instructions on how to use it.
process is crashing because you call VirtualFreeEx for memory, where you store name of dll (dllMemoryPointer). when LoadLibrary begin use this memory it can be already not valid. APC - this is asynchronous procedure call, so you can not know ,at point where you call VirtualFreeEx, are LoadLibrary already executed or in process, or even not begin.
about the permissions - of course no. if you have no permissions - you simply fail open process or threads in process. as result nothing will happens. that you got crash in target process, visa versa confirmed that you have permissions.
also need understand that not all threads in process will be in alertable state, after you inject APC to it. so possible, despite that APC will be successfully queued - it will be never called. inject it to all threads in process, hoping that at least one of them will be in alertable state wrong way. at first may be not, at second - some working threads can be not design for call LoadLibrary at all - say thread can have no activation context, not connect to csrss, may be some else. all this also can produce crash or undefined effects. and finally this is simply not efficient.
the injection via QueueUserAPC useful in case you create process itself (in suspended state) and inject apc to the initial process thread before resume it. this will be work (how minimum until) because new thread in process begin execute in user mode always from LdrInitializeThunk (where he initialize process and/or call load dlls code) and before jump to real entry point always (in all existing windows versions) call ZwTestAlert. exactly at this point your APC call will be executed. but strictly speaking this is also not 100% correct way, because we use LoadLibrary[W/A] as APC entry point. but what will be if APC exceuted too early, when kernel32.dll yet not mapped to process or yet not initialized ? obviously that crash. in clear windows must not be this situation (apc will be called after process fully initialized, all static dll loaded, just before call exe entry point). but possible that some drivers will inject self code to process via APC call (say on mapping kernel32.dll event ) and force APC executing at this point. as result only 100% reliable way here use ZwQueueApcThread to shellcode, which will be call only ntdll api, load dll via LdrLoadDll and dll itself have static import only from ntdll.dll
I have an application that behaves as a windows forms and as a console application depending if I pass parameters or not. If I pass parameters it behaves as a console application.
In this last case, as a console application, I attach to the console using:
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
So at the beginning of the app, I call it as below:
AttachConsole(-1);
Later what I do is simply read the string parameter or parameters passed as a parameter in command line, and I return encrypted these strings. After It I wait for user key press using:
Console.ReadKey(true);
After user press any key I want to close the console window.
My problem is that when user press a key, the application does not continue, it still keeps waiting for a key because this key pressed is catched by the another attached console. So in order the application continues user needs to press key twice. On first key press, command prompt is printed again (this comes from the attached console).
How can I solve this?
UPDATE:
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.Run(new MyForm());
}
else
{
// case args.Length > 0
Console.WriteLine("Start my formless app...");
new FormLessApp().Start(args);
}
}
ReadKey is performed within FormLessApp:
public class FormLessApp
{
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int input);
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
public FormLessApp()
{
IntPtr ptr = GetForegroundWindow();
int u;
GetWindowThreadProcessId(ptr, out u);
Process process = Process.GetProcessById(u);
if (process.ProcessName == "cmd")
{
AttachConsole(process.Id);
Console.WriteLine("attached to console");
}
}
public void Start(string[] args)
{
// Do some things with args
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
}
To Reproduce:
Open a windows command prompt (cmd) and from there execute it as:
MyApp.exe param1 param2 .....
I am trying to close chrome from my application.
I am using the following method:
public class CloseChrome
{
static int WM_CLOSE = 0x0010;
static int WM_QUIT = 0x0012;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
static public void closeCrome()
{
var process = Process.GetProcesses();
foreach (var item in process)
{
if (item.ProcessName.Contains("chrome"))
{
//item.Kill();
int ret = SendMessage(item.Handle, WM_CLOSE, 0, 0);
Console.WriteLine("Chrome Reply: " + a);
}
}
}
}
Using the kill method kills the chrome process, but when I send the WM_CLOSE message nothing happens even though the return value is 0 from sendMessage. Am I doing something wrong is chrome just ignoring my request?
Process.Handle will be the HANDLE of the process, not the HWND of the main window. In fact a process can own many windows, so the concept of a main window doesn't really apply.
What you need to do is call the (csharp equivalent of) EnumWindows and then call GetWindowProcessThreadId to test each HWND to see if it belongs to your target process.
The more usual alternative is to examine a target window with Spy++ to see if the class name is pretty unique, and if it is, you can use FindWindow.
My program, finds any subwindows, the case if an 3-part app shows an Error box, then i want to close it.. and it works fine, when the server not is locked.
Code:
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool PostMessage(IntPtr hwnd, uint msg, IntPtr WParam, IntPtr lParam);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool BringWindowToTop(IntPtr hwnd);
public static bool FocusWindowAndSendEnter(IntPtr hWnd)
{
try
{ // hWnd = pointer to subwindow, like messagebox.
uint WM_KEYDOWN = 0x0100;
//Set focus
var res1 = BringWindowToTop(hWnd);
//Send enter_Key
var res2 = PostMessage(hWnd, WM_KEYDOWN, (IntPtr)Keys.Enter, IntPtr.Zero);
return (res1 == res2 == true);
}
catch (Exception ex)
{
Logger.LogException(MethodInfo.GetCurrentMethod().Name, ex);
}
return false;
}
Can this be done if the server is locked, but running?
When a computer is locked, you are very limited in what you can do - for security purposes. I doubt there is a way around this unless you either stop the computer being locked, or stop the message box from showing up in the first place.
You're attempting to solve a problem in the wrong methods.
Find out what you can about that error message box and do what you can to prevent that happening. Don't expect to have much you can do when the PC is locked.
I am using the below code to exit a process programatically.
since i am new to this concept. I want to know how to use this below code.
Logic : I will have the process name to be terminated, i shud assign that to
this function.
Say if want to terminate a notepad, how to pass parameter [Process Name]
to this function ?
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0xF060;
public void CloseWindow(IntPtr hWindow)
{
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
Use the Process.CloseMainWindow instead of manually sending the message. This will send the message to the main window of the process:
using System.Diagnostics;
// ...
foreach (var process in Process.GetProcessesByName("notepad.exe"))
process.CloseMainWindow();
Alternatively, you can use MainWindowHandle to get the handle of the main window of a Process and send a message to it:
foreach (var process in Process.GetProcessesByName("notepad.exe"))
CloseWindow(process.MainWindowHandle); // CloseWindow is defined by OP.
If you want to kill the process immediately instead of closing the main window, this is not a good approach. You should use the Process.Kill method instead.
Although I agree with Mehrdad's answer but if you really want to re-invent the wheel, then this is how to do it (This is without any error checking etc. Please add that yourself).
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
static bool CloseWindow(IntPtr hWnd)
{
SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
return true;
}
static void Main()
{
IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad");
bool ret = CloseWindow(hWnd);
}
BTW, Here is a good place to view Managed declarations of native API's