Is there a way to remove close button from another process with C#? - c#

I tried it with C++ and it seems like one needs to inject code into another process to disable its main window's close button. But I'm curious, since I actually need it for a .NET program, can I gray out its main window's close button with C#?
PS. Again the process that I'm doing it for is not mine. I can find it as such:
Process[] processes = Process.GetProcessesByName("Notepad");
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
//Now how to disable it's close button?
}

I think I got it:
[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);
const uint SC_CLOSE = 0xF060;
const uint MF_BYCOMMAND = 0x00000000;
Process[] processes = Process.GetProcessesByName("Notepad");
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
IntPtr nSysMenu = GetSystemMenu(pFoundWindow, false);
if (nSysMenu != IntPtr.Zero)
{
if (DeleteMenu(nSysMenu, SC_CLOSE, MF_BYCOMMAND))
{
//Done!
}
}
}

Related

Emulation of pressing the space bar

I have a problem, I can't emulate pressing the space bar. I need the CS GO game to emulate pressing the space bar. So that the character in the game jumps.
Here's an example mirroring Simulating Key Press C#:
static class Program
{
const UInt32 WM_KEYDOWN = 0x0100;
const int VK_SPACE = 0x20;
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
[STAThread]
static void Main()
{
while(true)
{
Process [] processes = Process.GetProcessesByName("iexplore");
foreach(Process proc in processes)
PostMessage(proc.MainWindowHandle, WM_KEYDOWN, VK_SPACE, 0);
Thread.Sleep(5000);
}
}
}

Why is the process I am writing the memory to crash?

So I recently stumbled onto a blog that described how to run your WinForms application from another process.
I instantly thought this was something really cool an unique and wanted to test it out myself. While there was no code it explained how to do so and this is what I've done.
class Program
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
Int32 nSize,
out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess,
IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
int processId
);
public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags)
{
return OpenProcess(flags, false, proc.Id);
}
static void Main(string[] args)
{
Process notepad = null;
Process[] processes = Process.GetProcesses();
foreach (var process in processes)
{
if (process.ProcessName.ToLower() == "notepad")
{
notepad = process;
}
}
OpenProcess(notepad, ProcessAccessFlags.All);
byte[] payload = File.ReadAllBytes(#"C:\Users\developer\source\repos\WindowsFormsApp2\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe");
foreach (ProcessThread pt in notepad.Threads)
{
IntPtr openThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
SuspendThread(openThread);
CloseHandle(openThread);
}
WriteProcessMemory(notepad.Handle, notepad.Modules[0].BaseAddress, payload, payload.Length, out IntPtr lpNumberOfBytesWritten);
CreateRemoteThread(notepad.Handle, IntPtr.Zero, 0x0, notepad.Modules[0].BaseAddress, IntPtr.Zero, 0x0, out _);
}
}
It's something very simple that is supposed to suspend the process and all of it's threads.
And then write the bytearray from my other application which is a simple WinForms application witha button that when you click on it, it shows a MessageBox saying Hello World
But as soon as I run the code, notepad crashes and nothing shows up, where did I go wrong?
Check out this Memory problem with application in C# Windows Forms and also this High memory usage of a windows forms method. I'm led to believe you may have a caching issue or are not writing safe code for memory management. I would start by looking at your entry point to the program and debugging the foreach blocks.

PostMessage to Open Outlook Reply Window?

I want to send keys to a background window.
In this case, outlook.
I have this code
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private void button1_Click(object sender, EventArgs e)
{
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x0101;
string processName = "outlook";
Process[] processList = Process.GetProcesses();
foreach (Process P in processList)
{
if (P.ProcessName.Equals(processName))
{
IntPtr edit = P.MainWindowHandle;
PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.LControlKey), IntPtr.Zero);
PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.R), IntPtr.Zero);
PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.R), IntPtr.Zero);
PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.LControlKey), IntPtr.Zero);
}
}
}
What is wrong with this? It is supposed to open a reply window in outlook, but it doesn't.
Also, please don't answer with something outlook specific related as I want to use this method to do it.

Outlook security prompt auto approval

I'm writing a function that will allow users to import their e-mails from outlook in to corporate storage. But I've encounter a problem with security promt, and since we still have clients with office 2003 we can't disable it.
I'm trying to autoclick it with this code:
[DllImport("User32.dll")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, int msg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_LBUTTONUP = 0x0202;
private void button1_Click(object sender, EventArgs e)
{
int hwnd = 0;
IntPtr hwndChild = IntPtr.Zero;
while (true)
{
hwnd = FindWindow(null, "Microsoft Outlook");
if (hwnd != 0)
{
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "Button", "Yes");
if (hwndChild != IntPtr.Zero)
{
SendMessage((int)hwndChild, WM_LBUTTONDOWN, 0, IntPtr.Zero);
SendMessage((int)hwndChild, WM_LBUTTONUP, 0, IntPtr.Zero);
}
else
{
//...
}
}
else
{
//...
}
hwnd = 0;
}
}
But when I'm trying to use that code I've encounter unexpected problem. Security promt will only disappear only when I'm actually performing mouse click no matter where even on some empty screen space. What is wrong with it?
Try out MAPILab's Advanced Security for Outlook. Should also work for Outlook 2003. This will let you give a permanent access for your application - a pop-up window will show only the first time you access Outlook items:
http://www.mapilab.com/outlook/security/
Advanced Security will have to be installed on each machine you run your app. It's free for noncommercial and commercial use.
You should try using SendKeys and send Y for Yes.

How do I know how much time I should wait for PrintDialog after sending Commands to Print(to press "Ctrl+P" button)?

I am writing a Console application using C#, in which I am firing Print jobs through code. My issue is I do not know how much time I should wait for Print Dialog after sending commands to Print. For the time being I am using Thread sleep of 1000 milliseconds.
//Sending Commands to Print(to press "Ctrl+P" button).
SendKeys.SendWait("^(p)");
Thread.Sleep(1000);
//Sending Commands to Print(to press "Enter" Button).
SendKeys.SendWait("{ENTER}");
Can anybody help me to fix this issue please. Any help will be appreciated.
Thanks in advance
Update:
Here is my whole code:
//Launch the file from the location specified in.
White.Core.Application application =White.Core.Application.Launch(#path);
Console.WriteLine("launch is done");
Thread.Sleep(_delayOfPrint);
//Sending Commands to Print(to press "Ctrl+P" button).
SendKeys.SendWait("^(p)");
Thread.Sleep(1000);
//Sending Commands to Print(to press "Enter" Button).
SendKeys.SendWait("{ENTER}");
//Get the current time as the document fired for print job.
_printedTime = DateTime.Now;
Thread.Sleep(1500);
//Closing the window.
SendKeys.SendWait("%{F4}");
I would have a maximum wait of a few seconds, but during that time I would periodically use the Win32 function FindWindowEx to see if the print dialog actually came up, and if so proceed. You can get a process' main window with code like this:
Process[] processes = Process.GetProcessesByName(appName);
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
}
You can then pass the found main window handle to FindWindowEx to peruse the child windows to check for the print dialog. FindWindowEx has PInvoke signatures like this:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
Edit 2: Since the OP seems to be demanding I give a perfectly working function, I wrote a general one that does the trick and tested it. Here it is, working general code to wait for any child window. Call as WaitForChildWindow("myApp", "Print", 5000) for this case:
/// <summary>
/// Wait for a child window of an application to appear
/// </summary>
/// <param name="appName">Application name to check (will check all instances)</param>
/// <param name="childWindowName">Name of child window to look for (titlebar)</param>
/// <param name="timeout">Maximum time, in milliseconds, to wait</param>
/// <returns>True if the window was found; false if it wasn't.</returns>
public static bool WaitForChildWindow(string appName, string childWindowName, int timeout)
{
int sleepTime = timeout;
while (sleepTime > 0)
{
Process[] processes = Process.GetProcessesByName(appName);
foreach (Process p in processes)
{
IntPtr pMainWindow = p.MainWindowHandle;
IntPtr pFoundWindow = FindWindowEx(pMainWindow, IntPtr.Zero, null, childWindowName);
if (pFoundWindow != IntPtr.Zero)
return true;
}
Thread.Sleep(100);
sleepTime -= 100;
}
// Timed out!
return false;
}
Edit 3: Here's another way of doing it for merely owned windows that don't have a child relationship:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hwnd, IntPtr processId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumThreadWindows(uint dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);
public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);
static bool EnumThreadCallback(IntPtr hWnd, IntPtr lParam)
{
StringBuilder text = new StringBuilder(500);
GetWindowText(hWnd, text, 500);
if (text.ToString() == "Print")
return false;
return true;
}
public static bool FindThreadPrintWindow(uint threadId)
{
return !EnumThreadWindows(threadId, EnumThreadCallback, IntPtr.Zero);
}
public static bool WaitForOwnedPrintWindow(string appName, int timeout)
{
int sleepTime = timeout;
while (sleepTime > 0)
{
Process[] processes = Process.GetProcessesByName(appName);
foreach (Process p in processes)
{
IntPtr pMainWindow = p.MainWindowHandle;
uint threadId = GetWindowThreadProcessId(pMainWindow, IntPtr.Zero);
if (FindThreadPrintWindow(threadId))
return true;
}
Thread.Sleep(100);
sleepTime -= 100;
}
// Timed out!
return false;
}

Categories