SetThreadDesktop not switching form to the other desktop - c#

private async void WrongPassword_Load(object sender, EventArgs e)
{
IntPtr NEWDESKTOP = CreateDesktop("dew", IntPtr.Zero, IntPtr.Zero, 0, (uint) DESKTOP_ACCESS.GENERIC_ALL,IntPtr.Zero);
IntPtr OLDDESKTOP = GetThreadDesktop(GetCurrentThreadId());
SwitchDesktop(NEWDESKTOP);
SetThreadDesktop(NEWDESKTOP);
Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
ShowIcon = false;
Text = "";
TopMost = true;
ControlBox = false;
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
button1.Enabled = false;
MessageCycle();
var i = 60;
Task.Factory.StartNew(() =>
{
SoundPlayer dewd = new SoundPlayer(Resources.WrongPassword);
dewd.PlaySync();
});
PlayMusic();
while (i > 0)
{
CountDownLabel.Text = "Please wait " + i +
" seconds before you can dismiss to prevent \n DDOS, BRUTE FORCE ATTACKS";
i = i - 1;
Task.Delay(1000);
}
SetThreadDesktop(OLDDESKTOP);
CloseDesktop(NEWDESKTOP);
SwitchDesktop(OLDDESKTOP);
CountDownLabel.Text = "We are not responsible if you lose your password and files";
button1.Enabled = true;
}
When I put SetThreadDesktop(NEWDESKTOP), my form does not transfer from my current desktop to NEWDESKTOP, I have also put TrySetApartmentState(ApartmentState.STA) and it still does not work, can someone give me a solution to how to transfer a form from your current desktop to NEWDESKTOP?

Comments the [STAThread] and try to activate STA manually:
Also make sure that Don't use anything which will prevent you switching desktop before calling SetThreadDesktop
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace WindowsFormsApp1
{
static class Program
{
[Flags]
internal enum ACCESS_MASK : uint
{
DESKTOP_NONE = 0,
DESKTOP_READOBJECTS = 0x0001,
DESKTOP_CREATEWINDOW = 0x0002,
DESKTOP_CREATEMENU = 0x0004,
DESKTOP_HOOKCONTROL = 0x0008,
DESKTOP_JOURNALRECORD = 0x0010,
DESKTOP_JOURNALPLAYBACK = 0x0020,
DESKTOP_ENUMERATE = 0x0040,
DESKTOP_WRITEOBJECTS = 0x0080,
DESKTOP_SWITCHDESKTOP = 0x0100,
GENERIC_ALL = 0x10000000,
}
[DllImport("user32.dll", EntryPoint = "CreateDesktop", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateDesktop(
[MarshalAs(UnmanagedType.LPWStr)] string desktopName,
[MarshalAs(UnmanagedType.LPWStr)] string device, // must be null.
[MarshalAs(UnmanagedType.LPWStr)] string deviceMode, // must be null,
[MarshalAs(UnmanagedType.U4)] int flags, // use 0
[MarshalAs(UnmanagedType.U4)] ACCESS_MASK accessMask,
IntPtr attributes);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetThreadDesktop(uint dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SetThreadDesktop(IntPtr hDesktop);
[DllImport("user32.dll", SetLastError = true)]
public static extern int SwitchDesktop(IntPtr hDesktop);
[DllImport("user32.dll", SetLastError = true)]
public static extern int CloseDesktop(IntPtr hDesktop);
/// <summary>
/// The main entry point for the application.
/// </summary>
//[STAThread]
static void Main()
{
int ret = 0;
IntPtr NEWDESKTOP = CreateDesktop("dew", null, null, 0, ACCESS_MASK.GENERIC_ALL, IntPtr.Zero);
IntPtr OLDDESKTOP = GetThreadDesktop(GetCurrentThreadId());
ret = SetThreadDesktop(NEWDESKTOP);
ret = SwitchDesktop(NEWDESKTOP);
Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
ret = SwitchDesktop(OLDDESKTOP);
CloseDesktop(NEWDESKTOP);
}
}
}

Related

How to update console window's taskbar progress in Windows Terminal

I have this code that works perfectly in cmd and PowerShell, but does nothing in Windows Terminal.
internal class TaskbarProgress : IDisposable
{
private IntPtr consoleWindowHandle = IntPtr.Zero;
[DllImport("kernel32.dll")]
private static extern IntPtr GetConsoleWindow();
internal TaskbarProgress()
{
consoleWindowHandle = GetConsoleWindow();
if (consoleWindowHandle != IntPtr.Zero)
{
TaskbarProgressCom.SetState(consoleWindowHandle, TaskbarProgressState.Normal);
}
}
internal void SetProgress(ulong currentValue, ulong maximumValue)
{
if (consoleWindowHandle != IntPtr.Zero)
{
TaskbarProgressCom.SetValue(consoleWindowHandle, currentValue, maximumValue);
}
}
public void Dispose()
{
if (consoleWindowHandle != IntPtr.Zero)
{
TaskbarProgressCom.SetState(consoleWindowHandle, TaskbarProgressState.NoProgress);
consoleWindowHandle = IntPtr.Zero;
}
}
}
internal enum TaskbarProgressState
{
NoProgress = 0,
Indeterminate = 0x1,
Normal = 0x2,
Error = 0x4,
Paused = 0x8
}
internal static class TaskbarProgressCom
{
... // Removed for StackOverflow complaint of too much code, but basically the same as https://www.nuget.org/packages/Microsoft-WindowsAPICodePack-Shell
}
I thought maybe the console window is childed, so grab the root window:
[DllImport("user32.dll", ExactSpelling = true)]
private static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);
// ...
IntPtr rootOwnerHandle = GetAncestor(consoleWindowHandle, GetAncestorFlags.RootOwner);
if (rootOwnerHandle != IntPtr.Zero)
{
consoleWindowHandle = rootOwnerHandle;
}
But that didn't change anything. What am I missing?
Extra context: https://github.com/dotnet/BenchmarkDotNet/pull/2158
Thanks to folks on the Windows Terminal repo, I got the answer:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out ConsoleModes lpMode);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetConsoleMode(IntPtr hConsoleHandle, ConsoleModes dwMode);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
[Flags]
private enum ConsoleModes : uint
{
ENABLE_PROCESSED_INPUT = 0x0001,
ENABLE_LINE_INPUT = 0x0002,
ENABLE_ECHO_INPUT = 0x0004,
ENABLE_WINDOW_INPUT = 0x0008,
ENABLE_MOUSE_INPUT = 0x0010,
ENABLE_INSERT_MODE = 0x0020,
ENABLE_QUICK_EDIT_MODE = 0x0040,
ENABLE_EXTENDED_FLAGS = 0x0080,
ENABLE_AUTO_POSITION = 0x0100,
ENABLE_PROCESSED_OUTPUT = 0x0001,
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002,
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004,
DISABLE_NEWLINE_AUTO_RETURN = 0x0008,
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
}
static void Main(string[] args)
{
IntPtr handle = GetStdHandle(STD_OUTPUT_HANDLE);
ConsoleModes previousConsoleMode;
GetConsoleMode(handle, out previousConsoleMode);
SetConsoleMode(handle, ConsoleModes.ENABLE_VIRTUAL_TERMINAL_PROCESSING | ConsoleModes.ENABLE_PROCESSED_OUTPUT);
for (uint i = 0; i < 100; ++i)
{
// Set progress value (0-100).
Console.Write($"\x1b]9;4;1;{i}\x1b\\");
Thread.Sleep(100);
}
// Set state to no progress.
Console.Write($"\x1b]9;4;0;0\x1b\\");
SetConsoleMode(handle, previousConsoleMode);
}
The supported sequences are:
ESC ] 9 ; 4 ; st ; pr ST
Set progress state on Windows taskbar and tab. When `st` is:
0: remove progress.
1: set progress value to pr (number, 0-100).
2: set the taskbar to the "Error" state
3: set the taskbar to the "Indeterminate" state
4: set the taskbar to the "Warning" state
https://github.com/microsoft/terminal/issues/6700

C# sending input to a window not in focus

Upfront: I am still fairly new to C#. I have done all the research I can up to the point I am at now. This is my first time asking for help online.
I am trying to create a program in C# that sits in the background and receives input from a scanner. From what I have researched so far the scanner acts like a keyboard wedge. This is created as a console application. The program is supposed to compare the part number scanned with the previous part number that was scanned. If the new part number is different than the last then it sends an e-mail saying that the previous part number is completed and out for delivery and that the new part number is starting production. It works except for 2 issues:
I tried using Hooks to intercept input. My resources where:
https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/
While the code I have works for sending input to the console in the background it prints one character per line as well as the issue the other issue I am having...
Either its capturing input to a blank console with one character per line or it's running the rest of my code without the functionality of the hooks.
I have been working on this program for several days and I am at a loss. Any help would be greatly appreciated...
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using System.Windows.Input;
namespace Test1
{
class Program
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
public static LowLevelKeyboardProc _proc = HookCallBack;
public static IntPtr _hookID = IntPtr.Zero;
#region Import DLLs
[DllImport("user32.dll", CharSet = CharSet.Auto,SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc Ipfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr IParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string IpModuleName);
#endregion
#region Key Tracker Delegates/Functions
public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName),0);
}
}
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr IParam);
public static class PreviousDriver
{
public static string previousDriver{get;set;}
}
#endregion
#region Email functionality
public static void CreateMail()
{
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MailItem mailItem = (Outlook.MailItem)app.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
mailItem.Subject="Driver Update";
//mailItem.To = ; email here
mailItem.Body = "Your " + PreviousDriver.previousDriver + "is finished and is out for delivery.\n\n";
mailItem.Display(false);
mailItem.Send();
}
#endregion
public static class CurrentDriverCount
{
public static int currentDriverCount{get;set;}
}
#region Main
public static void Main()
{
//var handle = GetConsoleWindow();
//ShowWindow(handle, SW_HIDE);
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
DriverStart();
}
#endregion
#region DriverStart()
public static void DriverStart()
{
//string PreviousDriver = null;
Console.WriteLine("What is your driver?\n");
string CurrentDriver = Console.ReadLine(); //Scan driver
Console.WriteLine("Your current driver is " + CurrentDriver + "\n");
if(CurrentDriver == PreviousDriver.previousDriver)
{
//When it's the same driver
Console.WriteLine("Your previous driver was " + PreviousDriver.previousDriver + "\n");
CurrentDriverCount.currentDriverCount +=1;
Console.WriteLine("Your driver count is " + CurrentDriverCount.currentDriverCount + ".\n");
DriverStart();
} else {
//When the driver is different
Console.WriteLine("Your " + PreviousDriver.previousDriver + "is finished and is out for delivery.\n\n" +
"Your "+ CurrentDriver + "are starting now!\n");
CreateMail();
PreviousDriver.previousDriver = CurrentDriver;
CurrentDriverCount.currentDriverCount = 0;
CurrentDriverCount.currentDriverCount +=1;
Console.WriteLine("Your driver count is " + CurrentDriverCount.currentDriverCount + ".\n");
DriverStart();
}
}
#endregion
private static IntPtr HookCallBack(int nCode, IntPtr wParam, IntPtr IParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(IParam);
Console.WriteLine((Keys)vkCode);
StreamWriter sw = new StreamWriter(Application.StartupPath,true);
sw.Write((Keys)vkCode);
sw.Close();
}
return CallNextHookEx(_hookID, nCode, wParam, IParam);
}
}
}

Retrieving the parent window Handle C# (trying to maximize outlook)

I generally do run the method listed below to maximize iconized windows;
however when it comes to outlook, there are times where it will maximize a Mail (message) that i have open instead of the parent application (outlook) ; its just pulling up anything outlook that it finds and i need the parent, how can i achieve this?
I have tried using WINAPI GetAncestor, I have also tried GetParent .
public static bool EventChecking(string progr)
{
int bb = 0;
if (Process.GetProcessesByName(progr).Length > 0)
{
bb++;
}
if (bb == 0)
{
return false;
}
foreach (Process ddcd in Process.GetProcesses())
{
if (ddcd.ProcessName.Contains(progr))
{
if (ddcd.MainWindowHandle != IntPtr.Zero)
{
pointer = ddcd.MainWindowHandle;
if (IsIconic(pointer))
{
SendMessage(pointer, 0x112, 0xF120, 0);
}
SetForegroundWindow(pointer);
}
};
}
return true;
}
EDIT:
I also recently tried:
if (ddcd.MainWindowTitle.EndsWith("- Outlook"))
and it still pulls up the single email
I have also had trouble working with Outlook via C# but I have had some success with Win32 calls. Below is one way to locate the Outlook Main Window by checking the Caption.
You could also try EnumWindows but it takes more effort to implement due to Callbacks.
using System.Text;
using System.Runtime.InteropServices;
public IntPtr GetOutlookHandle()
{
string windowClass = "rctrl_renwnd32";
uint GW_HWNDNEXT = 2;
IntPtr firstHandle = new IntPtr(0);
IntPtr handle = new IntPtr(0);
// Look for a Window with the right Class
firstHandle = FindWindow(windowClass, null);
// Nothing Found
if (firstHandle.Equals(IntPtr.Zero)) return IntPtr.Zero;
// Remember where we started to avoid an infinite loop
handle = firstHandle;
do
{
// Check the Caption to find the Main Window
if (GetWindowCaption(handle).EndsWith(" - Microsoft Outlook"))
{
return handle;
}
// Get the next Window with the same Class
handle = GetWindow(handle, GW_HWNDNEXT);
} while (handle != firstHandle);
// Didn't find any matches
return IntPtr.Zero;
}
private static string GetWindowCaption(IntPtr windowHandle)
{
// Determine Length of Caption
int length = GetWindowTextLength(windowHandle);
StringBuilder sb = new StringBuilder(length + 1);
// Get Window Caption
GetWindowText(windowHandle, sb, sb.Capacity);
return sb.ToString();
}
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetWindowTextLength(IntPtr hWnd);

C# - Is there any reliable event that exists to be notified when the screen saver become active/inactive

I'm looking for an event that would happen when the screen saver become active or inactive. I want to be notified. I do not want to use any timer.
I do not want to poll for it. I don't want to use: SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0 );
I tried that without success, I never receive the SC_SCREENSAVE...
// ************************************************************************
public MainWindow()
{
InitializeComponent();
}
// ************************************************************************
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
if (mainWindowSrc != null)
{
mainWindowSrc.AddHook(WndProc);
}
//HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//source.AddHook(WndProc);
}
// ************************************************************************
private const Int32 WM_SYSCOMMAND = 0x112;
private const int SC_SCREENSAVE = 0xF140;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND)
{
Debug.Print("SysCommand : " + wParam);
if (wParam.ToInt32() == SC_SCREENSAVE)
{
Debug.Print(DateTime.Now.ToString());
}
}
return IntPtr.Zero;
}
Anybody has any other idea or does know what is wrong with my code ???
if (wParam.ToInt32() == SC_SCREENSAVE)
That's not correct. It is an odd quirk in the WM_SYSCOMMAND message, surely dating to a long gone era where they had to squeeze a GUI operating system in 640 kilobytes. The low 4 bits in the command value are used for internal purposes. You'll have to mask them out before you compare. Fix:
if ((wParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
You'd probably had figured this out yourself by using the proper Debug statement formatting :)
Debug.Print("SysCommand : 0x{0:X}", wParam);
Hans answer seems to not work for me on Windows 7 when it is activated normally by the timer (at least when your account is part of a domain and a policy make screen saver parameters as readonly).
Using SystemParametersInfo with SPI_GETSCREENSAVERRUNNING work fine but it require a timer (polling) which is to my point of view: horrible poorly designed code... but up to now, it is the only way I found that works all the time... :-(
I left my code as reference. It include many of my tests.
There is a lot more but just remove what you don't need.
You could consult the HotKey excellent class there (I couldn't found my initial source but this one is exactly the same): https://github.com/shellscape/Lumen/blob/master/Application/HotkeyHandler.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using HQ.Util.General;
using HQ.Util.Unmanaged;
using HQ.Wpf.Util;
using Microsoft.Win32;
using SpreadsheetGear;
namespace MonitorMe
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
private HotKeyHandeler _hotKeyHandler = null;
private Timer _timerToMonitorScreenSaver = null;
// ************************************************************************
public MainWindow()
{
InitializeComponent();
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
Monitor.Instance.Add(SessionSwitchReason.SessionLogon);
_timerToMonitorScreenSaver = new Timer(TimerCallbackMonitorScreenSaver, this, 3000, 3000);
}
private void TimerCallbackMonitorScreenSaver(object state)
{
int active = 1;
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref active, 0);
if (active == 1)
{
Debug.Print("Timer detected Screen Saver activated on: " + DateTime.Now.ToString());
}
}
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpFileName);
// Signatures for unmanaged calls
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(
int uAction, int uParam, ref int lpvParam,
int flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SystemParametersInfo(
int uAction, int uParam, ref bool lpvParam,
int flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int PostMessage(IntPtr hWnd,
int wMsg, int wParam, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr OpenDesktop(
string hDesktop, int Flags, bool Inherit,
uint DesiredAccess);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseDesktop(
IntPtr hDesktop);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool EnumDesktopWindows(
IntPtr hDesktop, EnumDesktopWindowsProc callback,
IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool IsWindowVisible(
IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetForegroundWindow();
// Callbacks
private delegate bool EnumDesktopWindowsProc(
IntPtr hDesktop, IntPtr lParam);
// Constants
private const int SPI_GETSCREENSAVERACTIVE = 16;
private const int SPI_SETSCREENSAVERACTIVE = 17;
private const int SPI_GETSCREENSAVERTIMEOUT = 14;
private const int SPI_SETSCREENSAVERTIMEOUT = 15;
private const int SPI_GETSCREENSAVERRUNNING = 114;
private const int SPIF_SENDWININICHANGE = 2;
private const uint DESKTOP_WRITEOBJECTS = 0x0080;
private const uint DESKTOP_READOBJECTS = 0x0001;
private const int WM_CLOSE = 16;
[DllImport("User32.dll")]
public static extern int SendMessage
(IntPtr hWnd,
uint Msg,
uint wParam,
uint lParam);
public enum SpecialHandles
{
HWND_DESKTOP = 0x0,
HWND_BROADCAST = 0xFFFF
}
// Registers a hot key with Windows.
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
// Unregisters the hot key with Windows.
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private IntPtr _hHook;
// ************************************************************************
void _hotKeyHandler_HotKeyPressed(object sender, HotKeyEventArgs e)
{
ActivateScreenSaver();
}
// ************************************************************************
private IntPtr MessageHookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code == WM_SYSCOMMAND)
{
Debug.Print("SysCommand : " + wParam);
if ((wParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
{
Debug.Print("MessageHookProc" + DateTime.Now.ToString());
}
}
return CallNextHookEx(_hHook, code, wParam, lParam);
}
// ************************************************************************
private const Int32 WM_SYSCOMMAND = 0x0112;
private const int SC_SCREENSAVE = 0xF140;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND)
{
Debug.Print("SysCommand : " + wParam);
if ((wParam.ToInt32() & 0xfff0) == SC_SCREENSAVE)
{
// Works fine in almost all cases. I already did some code in the past which activate the screen saver
// but I never receive any WM_SYSCOMMAND for that code, I do not have source code for it anymore).
Debug.Print("WndProc" + DateTime.Now.ToString());
}
}
return IntPtr.Zero;
}
// ************************************************************************
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
Monitor.Instance.Add(e.Reason);
}
// ************************************************************************
private void CmdExportToExcel_Click(object sender, RoutedEventArgs e)
{
ExportToExcel();
}
// ************************************************************************
private void ExportToExcel()
{
IWorkbook wb = Factory.GetWorkbook();
IWorksheet workSheet = wb.Worksheets[0];
int col = 1;
for (int dayIndex = -30; dayIndex <= 0; dayIndex++)
{
DateTime day = DateTime.Today + new TimeSpan(dayIndex, 0, 0, 0);
Debug.Print(day.ToString("yyyy-MM-dd"));
workSheet.Cells[0, col].Value = day.DayOfWeek.ToString();
workSheet.Cells[1, col].Value = day;
DayMonitor dayMonitor = Monitor.Instance.DayMonitors.FirstOrDefault(dm => dm.Day == day);
if (dayMonitor != null)
{
workSheet.Cells[2, col].Value = "Last - First";
workSheet.Cells[2, col + 1].Value = dayMonitor.TotalHours;
workSheet.Cells[3, col].Value = "Has estimated time (7h00 or 18h00)";
workSheet.Cells[3, col + 1].Value = dayMonitor.HasSomeEstimatedHours;
int row = 5;
foreach (var state in dayMonitor.SessionLockStateChanges)
{
workSheet.Cells[row, col].Value = state.SessionSwitchReason.ToString();
workSheet.Cells[row, col + 1].Value = state.DateTime;
row++;
}
}
workSheet.Cells[1, col].ColumnWidth = 18;
workSheet.Cells[1, col + 1].ColumnWidth = 18;
col += 2;
}
if (wb != null)
{
if (FileAssociation.IsFileAssociationExistsForExtensionWithDot(".xlsx"))
{
string path = TempFolderAutoClean.GetTempFileName("xlsx", "Export ");
wb.SaveAs(path, FileFormat.OpenXMLWorkbook);
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.FileName = path;
p.Start();
}
else
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.InitialDirectory = Environment.CurrentDirectory;
saveFileDialog.Filter = "Excel file (*.xlsx)|*.xlsx";
saveFileDialog.DefaultExt = ".xlsx";
if (saveFileDialog.ShowDialog(Application.Current.MainWindow) == true)
{
string path = saveFileDialog.FileName;
wb.SaveAs(path, FileFormat.OpenXMLWorkbook);
}
}
}
}
// ************************************************************************
private void PrintOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
ExportToExcel();
}
// ************************************************************************
private void ExitOnExecuted(object sender, ExecutedRoutedEventArgs e)
{
this.Close();
}
// ************************************************************************
private void PrintOnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.ContinueRouting = false;
}
// ************************************************************************
private void ExitOnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.ContinueRouting = false;
}
// ************************************************************************
private void CmdLaunchScreenSaver_Click(object sender, RoutedEventArgs e)
{
ActivateScreenSaver();
}
// ************************************************************************
private void ActivateScreenSaver()
{
// Next won't work in a secured Screen Saver by Account Policy (ex: by a domain policy)
//int nullVar = 0;
//SystemParametersInfo(SPI_SETSCREENSAVERACTIVE, 1, ref nullVar, SPIF_SENDWININICHANGE);
// This works fine all the time... and also send appropriate message to every top level window
SendMessage(new IntPtr((int)SpecialHandles.HWND_BROADCAST), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
}
// ************************************************************************
private void MainWindow_OnInitialized(object sender, EventArgs e)
{
int error;
IntPtr hMod = LoadLibrary("user32.dll"); // Hans Passant info in stackOverflow
_hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, MessageHookProc, IntPtr.Zero, (uint)Thread.CurrentThread.ManagedThreadId);
error = Marshal.GetLastWin32Error(); // Error 87
_hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, MessageHookProc, hMod, (uint)Thread.CurrentThread.ManagedThreadId);
error = Marshal.GetLastWin32Error(); // Error 87
_hHook = SetWindowsHookEx(HookType.WH_GETMESSAGE, MessageHookProc, hMod, 0);
error = Marshal.GetLastWin32Error(); // Work fine, got a hook, but never receive the WM_SYSCOMMAND:SC_SCREENSAVE
}
// ************************************************************************
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
}
// ************************************************************************
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Method 1
//IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
//HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
//if (mainWindowSrc != null)
//{
// mainWindowSrc.AddHook(WndProc);
//}
// Method 2
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
_hotKeyHandler = new HotKeyHandeler(this);
_hotKeyHandler.HotKeyPressed += _hotKeyHandler_HotKeyPressed;
// _hotKeyHandler.RegisterHotKey(0, Key.NumPad0);
this.Visibility = Visibility.Hidden;
}
// ************************************************************************
}
}

How can I load a program icon in C#

I have a path of some program (for example explorer), how can I get program icon, convert it to png/jpeg and then display in PictureBox?
I have something like this:
string filePath = "C:\\myfile.exe";
Icon TheIcon = IconFromFilePath(filePath);
if (TheIcon != null) {
// But then I don't know what to do...
}
public Icon IconFromFilePath(string filePath){
Icon programicon = null;
try {
programicon = Icon.ExtractAssociatedIcon(filePath);
}
catch { }
return programicon;
}
I found something similar here. Here is the icon. How I can create 32-bit icon?
The code is surprisingly simple if you know where to look. Start with the Icon class, since that's fundamentally what you're after here.
If you browse its methods, you'll come across a very interesting looking ExtractAssociatedIcon. That accepts a single string parameter that specifies the path to a file containing an icon, such as an executable file.
So that gives you an Icon object, now you just need to display it in a PictureBox. You don't have to convert it to a PNG or JPEG, a bitmap works fine. And there's a built-in member function for that: ToBitmap.
Assigning the new bitmap to the PictureBox.Image property is all you need to do to display it.
This question might be old but here's my answer.
Here's a full code snippet I used in extracting full 256 x 256 icons from any exe file.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
namespace IconUtils
{
internal static class ExtractIcon
{
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam);
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private readonly static IntPtr RT_ICON = (IntPtr)3;
private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14;
public static Icon ExtractIconFromExecutable(string path)
{
IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
var tmpData = new List<byte[]>();
ENUMRESNAMEPROC callback = (h, t, name, l) =>
{
var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name);
// Calculate the size of an entire .icon file.
int count = BitConverter.ToUInt16(dir, 4); // GRPICONDIR.idCount
int len = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
len += BitConverter.ToInt32(dir, 6 + 14 * i + 8); // GRPICONDIRENTRY.dwBytesInRes
using (var dst = new BinaryWriter(new MemoryStream(len)))
{
// Copy GRPICONDIR to ICONDIR.
dst.Write(dir, 0, 6);
int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
{
// Load the picture.
ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID
var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);
// Copy GRPICONDIRENTRY to ICONDIRENTRY.
dst.Seek(6 + 16 * i, 0);
dst.Write(dir, 6 + 14 * i, 8); // First 8bytes are identical.
dst.Write(pic.Length); // ICONDIRENTRY.dwBytesInRes
dst.Write(picOffset); // ICONDIRENTRY.dwImageOffset
// Copy a picture.
dst.Seek(picOffset, 0);
dst.Write(pic, 0, pic.Length);
picOffset += pic.Length;
}
tmpData.Add(((MemoryStream)dst.BaseStream).ToArray());
}
return true;
};
EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
byte[][] iconData = tmpData.ToArray();
using (var ms = new MemoryStream(iconData[0]))
{
return new Icon(ms);
}
}
private static byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
{
// Load the binary data from the specified resource.
IntPtr hResInfo = FindResource(hModule, name, type);
IntPtr hResData = LoadResource(hModule, hResInfo);
IntPtr pResData = LockResource(hResData);
uint size = SizeofResource(hModule, hResInfo);
byte[] buf = new byte[size];
Marshal.Copy(pResData, buf, 0, buf.Length);
return buf;
}
}
}
Usage:
Icon ExeIcon = IconUtils.ExtractIcon.ExtractIconFromExecutable(#"C:\Windows\explorer.exe");
Source: https://www.codeproject.com/Articles/26824/Extract-icons-from-EXE-or-DLL-files

Categories

Resources