Change desktop background in C# - c#

I try to change the background using C#.Example:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32
uiParam, String pvParam, UInt32 fWinIni);
private static UInt32 SPI_SETDESKWALLPAPER = 20;
private static UInt32 SPIF_UPDATEINIFILE = 0x1;
And then
SystemParametersInfo(SPI_SETDESKWALLPAPER, 1, #"C:\background.bmp", SPIF_UPDATEINIFILE);
}
But it doesn't work...Help?

pvParam should be a local file. It will not work for urls...
First download the image, then give its local path to SystemParametersInfo method.
var filename = "4.jpg";
new WebClient().DownloadFile("http://www.scottgames.com/4.jpg", filename);
SystemParametersInfo(SPI_SETDESKWALLPAPER, 1, filename, SPIF_UPDATEINIFILE);

Related

Error when trying to get content of a VBA MsgBox in c#

I am trying to intercept VB MsgBoxes from a word template and click them automatically. This code is inserted in a C# Winforms Application, in a class and KillMbox() runs at the click of a button from that form.
I have tried the app in Debug Mode of Visual Studio and the code ran perfectly, intercepting the VBA messagebox.
However, after I have closed the Debug Mode and tried again, I receive An unhandled exception of type 'System.NullReferenceException' occurred in Unknown Module. Object reference not set to an instance of an object.
The error appears at the line GetWindowText(txtHandle, sb, len + 1);.
I have tried the app at a different computer in Debug Mode and it has the same issue, working only for the first time.
In Build version, the app just crashes, receiving App-Name has stopped working.
[DllImport("user32.dll")] static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")] static extern int SendMessage(int hWnd, int wMsg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern int GetWindowTextLength(IntPtr hWnd);
public static void KillMbox()
{
for (int h = 0; h == 0;)
{
Thread.Sleep(1000);
h = FindWindow(null, "Microsoft Word");
if (h != 0)
{
IntPtr hAsIntPtr = new IntPtr(h);
IntPtr txtHandle = FindWindowEx(hAsIntPtr, IntPtr.Zero, "Static", null);
int len = GetWindowTextLength(txtHandle);
StringBuilder sb = new StringBuilder();
GetWindowText(txtHandle, sb, len + 1);
SendMessage(h, 16, 0, 0);
MessageBox.Show(sb.ToString());
}
}
}
Is this a code-related error or a bug? Thank you!

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.

How do I use INTERNET_HANDLE_TYPE_INTERNET to constrain the effects of END_BROWSER_SESSION to the current WebBrowser?

We have a WebBrowser that needs to have login information reset.
There is a solution in this question that suggests using INTERNET_HANDLE_TYPE_INTERNET with INTERNET_OPTION_END_BROWSER_SESSION. However, I'm not sure where INTERNET_HANDLE_TYPE_INTERNET should go.
private const int INTERNET_OPTION_END_BROWSER_SESSION = 42;
private const int INTERNET_HANDLE_TYPE_INTERNET = 1;
[DllImport("wininet.dll", SetLastError = true)]
private static extern bool InternetSetOption(IntPtr hInternet, int dwOption,
IntPtr lpBuffer, int lpdwBufferLength);
I call it right before I navigate:
InternetSetOption(IntPtr.Zero, INTERNET_OPTION_END_BROWSER_SESSION, IntPtr.Zero,
0);
browserCtrl.WebBrowser.Navigate(loginUrl);

Interact with a form using handle C#

I am trying to automate a dynamically appearing dialogue box.
I need to pass text to it,s text field and then press a button over this.
What I have tried so far.
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
IntPtr handle= FindWindowByCaption(System.IntPtr.Zero, "Caption Of File");
I am getting the handle of dialogue box correctly.
List<IntPtr> childWindows= GetChildWindows(handle);//To get the child controls in this dialogue box
Source
But when I try to cast it to control I get null.
foreach (IntPtr i in childWindows)
{
Control c = Control.FromHandle(i);
}
So can any body tell what is wrong.I am supposing that I shall cast handle to control and then interact with control properties(e.g: text).
I've been using code like this sucessfully for years to perform single sign on to an application that prompts the user for their username/pwd/domain. The only caution is you need to know the control structure of the dialog you're targeting, but this is easily accomplished with Spy++ and rarely changes. Of course you will need to modify this code for the control structure of your window.
[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
string lpszClass, string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, string lParam);
[DllImport("User32.Dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
private const uint WM_GETTEXTLENGTH = 0x000E;
private const uint WM_SETTEXT = 0x000C;
private const uint WM_GETTEXT = 0x000D;
private const uint BM_CLICK = 0x00F5;
private const uint WM_CLOSE = 0x0010;
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
var dialog FindWindow("optionalClassNameHere", "Log On"); //Get the handle of the window
var w3 = GetWindow(dialog , (uint)GetWindow_Cmd.GW_CHILD); //I use GetWindow to walk the window controls
var wUid = FindWindowEx(w3, IntPtr.Zero, "Edit", "");
var w4 = GetWindow(wUid, (uint)GetWindow_Cmd.GW_HWNDNEXT);
var wPwd = FindWindowEx(w4 , IntPtr.Zero, "Edit", "");
var wOK = FindWindowEx(w3, IntPtr.Zero, "Button", "OK");
SendMessage(wUid, WM_SETTEXT, 0, _WinDomain + "\\" + Username); //Send username to username edit control
SendMessage(wPwd, WM_SETTEXT, 0, Password); //Send password to password edit control
PostMessage(wOK, BM_CLICK, 0, 0); //Send left click(0x00f5) to OK button
Control.FromHandle can only work for controls in your process that are implemented by Control descendents. I'd guess this window is outside your process.
You need to use Win32 API methods to modify it.

C# Change Desktop Pattern

Im making a simple wallpaper changer. It works when changing the wallpaper but i cant change the pattern of the wallpaper. I tried something like this but it doesnt work :S
SystemParametersInfo(SPI_SETDESKPATTERN, 0, "Center",
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
Can some1 please show me the proper way of setting the wallpaper pattern?
I assume you mean the centred/ streched / tiled setting that would be the second past value int 1-3
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern Int32 SystemParametersInfo(UInt32 action, UInt32 uParam, String vParam, UInt32 winIni);
private static readonly UInt32 SPI_SETDESKWALLPAPER = 0x14;
private static readonly UInt32 SPIF_UPDATEINIFILE = 0x01;
private static readonly UInt32 SPIF_SENDWININICHANGE = 0x02;
private void SetWallpaper(string path)
{
if (File.Exists(path))
{
Image imgInFile = Image.FromFile(path);
try
{
imgInFile.Save(SaveFile, ImageFormat.Bmp);
SystemParametersInfo(SPI_SETDESKWALLPAPER, 3, SaveFile, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
}
catch
{
MessageBox.Show("error in setting the wallpaper");
}
finally
{
imgInFile.Dispose();
}
}
}

Categories