I need to eventually set the game screen to the topmost (foreground) window.
But my function does nothing (other user32.dll functions do work however)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using System;
using System.Diagnostics;
public class DatabaseManager : MonoBehaviour
{
//DLL imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
static Process proc = Process.GetProcessesByName("firefox")[0];
IntPtr ptrFF = proc.Handle;
//------------------------------------------------------------------------
void Awake()
{
SetForegroundWindow(ptrFF);
}
//Other code functions like Update etc.
}
Nothing happens, no errors. Is there a way to force a window to the front
Related
I'm trying to pull folder icons for a listview in a winform. I'm using [Drawing.Icon]::ExtractAssociatedIcon for file icons, but it doesn't work on folders.
I found this question here on stack which said to use SHGetStockIconInfo, but I can't wrap my head around how to load this function and use it in Powershell (I have no C programming experience). I managed to pull this from the linked question, but I'm stuck:
Add-Type -NameSpace WinAPI -Name DefaultIcons -MemberDefinition #'
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO {
public uint cbSize;
public IntPtr hIcon;
public int iSysIconIndex;
public int iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szPath;
}
[DllImport("shell32.dll")]
public static extern int SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO psii);
[DllImport("user32.dll")]
public static extern bool DestroyIcon(IntPtr handle);
private const uint SHSIID_FOLDER = 0x3;
private const uint SHGSI_ICON = 0x100;
private const uint SHGSI_LARGEICON = 0x0;
private const uint SHGSI_SMALLICON = 0x1;
'#
This runs without error, but that's as far as I can get and I don't fully understand what's going on.
I know I need to call the function SHGetStockIconInfo with three parameters:
uint to identify what icon I want
uint flag for the size of icon I want
a reference to a SHSTOCKICONINFO structure
The question I got all this from includes a GetStockIcon function definition, but I keep getting errors trying to include it saying The type or namespace name 'Icon' could not be found (are you missing a using directive or an assembly reference?)
With a few adjustments I got the code from that C# question to work under both PowerShell 5.1 and 7.2.6.
$refAsm = if( $PSVersionTable.PSVersion.Major -le 5 ) {'System.Drawing'} else {'System.Drawing.Common'}
Add-Type -ReferencedAssemblies $refAsm -TypeDefinition #'
using System;
using System.Runtime.InteropServices;
using System.Drawing;
public static class DefaultIcons
{
public static Icon GetStockIcon(uint type, uint size)
{
var info = new SHSTOCKICONINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
SHGetStockIconInfo(type, SHGSI_ICON | size, ref info);
var icon = (Icon)Icon.FromHandle(info.hIcon).Clone(); // Get a copy that does not use the original handle
DestroyIcon(info.hIcon); // Clean up native icon to prevent resource leak
return icon;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO
{
public uint cbSize;
public IntPtr hIcon;
public int iSysIconIndex;
public int iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szPath;
}
[DllImport("shell32.dll")]
public static extern int SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO psii);
[DllImport("user32.dll")]
public static extern bool DestroyIcon(IntPtr handle);
public const uint SHSIID_FOLDER = 0x3;
public const uint SHGSI_ICON = 0x100;
public const uint SHGSI_LARGEICON = 0x0;
public const uint SHGSI_SMALLICON = 0x1;
}
'#
Use it like this:
$folderIconLarge = [DefaultIcons]::GetStockIcon( [DefaultIcons]::SHSIID_FOLDER, [DefaultIcons]::SHGSI_LARGEICON )
$folderIconSmall = [DefaultIcons]::GetStockIcon( [DefaultIcons]::SHSIID_FOLDER, [DefaultIcons]::SHGSI_SMALLICON )
I'm trying to get the user32.dll into my unity FREE version. (Not pro)
I simply dropped user32.dll into my Assets/Plugins/ folder and the error it gives me is:
DLLNotFoundException: Assets/Plugins/user32.dll
Here is the code I am using:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
using System;
using System.Diagnostics;
public class DatabaseManager : MonoBehaviour
{
//DLL imports
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
static Process proc = Process.GetProcessesByName("firefox")[0];
IntPtr ptrFF = proc.Handle;
//------------------------------------------------------------------------
void Awake()
{
SetForegroundWindow(ptrFF);
}
//Other code functions like Update etc.
}
I heard somewhere that unmanaged dlls (c++) can only be used in Unity Pro, but I really need this DLL, am I doing something not accurate??? I am not sure if user32.dll actually falls under an unmanaged c++ dll.
Please help.
Change the path from Assets/Plugins/ to Assets/Plugins/x86_64/.
using UnityEngine;
using System.Runtime.InteropServices;
public class DatabaseManager : MonoBehaviour {
[DllImport("user32.dll")] static extern int GetForegroundWindow();
[DllImport("user32.dll", EntryPoint="MoveWindow")]
static extern int MoveWindow (int hwnd, int x, int y,int nWidth,int nHeight,int bRepaint);
void Awake()
{
int handle = GetForegroundWindow();
Debug.Log(handle);
int fWidth = Screen.width;
int fHeight = Screen.height;
// Move the Unity windows.
MoveWindow(handle,0,0,fWidth,fHeight,1);
}
}
I'm in the process of building a little utility using powershell and have spent a good deal of time teaching myself about building windows forms and controls using powershell. In order to keep my deployment to a small footprint I have packaged all of my graphics icons (.ico) and images (.bmp) in a dynamically linked library (*.dll) using a third party utilty (greenfish icon editor pro, which I highly recommend).
The problem that I have now is that I can't load the assembly because the resulting *.dll is missing a manifest. I've searched all over but was unable to find any concise answer on how to access the resource without using the add-type cmdlet to load the *.dll.
I was able to find a way to load icons from a dll in an answer to this post from Kazun. Then utilizing technet I was able to find a corresponding entry point in the dll for a method to extract a bitmap. See my kludged together script below which combines both the IconExtractor and my newly created BitmapExtractor classes.
$code = #"
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace System {
public class IconExtractor { #Credit to Kazun from https://social.technet.microsoft.com/Forums/windows/en-US/16444c7a-ad61-44a7-8c6f-b8d619381a27/using-icons-in-powershell-scripts?forum=winserverpowershell
public static Icon Extract(string file, int number, bool largeIcon) {
IntPtr large;
IntPtr small;
ExtractIconEx(file, number, out large, out small, 1);
try {
return Icon.FromHandle(largeIcon ? large : small);
} catch {
return null;
}
}
[DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);
}
public class BitmapExtractor { #Credit to Chad Estes (chadwestes#gmail.com)
public static Bitmap Extract(string file, string resourceID) {
IntPtr hModule = LoadLibraryEx(file,IntPtr.Zero,0x00000020);
Bitmap bmp = null;
IntPtr hBitmap = IntPtr.Zero;
try {
if (hModule != IntPtr.Zero) {
hBitmap = LoadBitmap(hModule, resourceID);
if (hBitmap != IntPtr.Zero) {
bmp = Bitmap.FromHbitmap(hBitmap);
}
}
} catch {
bmp = null;
} finally {
DeleteObject(hBitmap);
FreeLibrary(hModule);
}
return bmp;
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, uint dwFlags);
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeLibrary(IntPtr hModule);
[DllImport("user32.dll")]
static extern IntPtr LoadBitmap(IntPtr hInstance, string lpBitmapName);
[DllImport("gdi32.dll", EntryPoint="DeleteObject", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool DeleteObject(IntPtr hBitmap);
}
}
"#
Add-Type -TypeDefinition $code -ReferencedAssemblies System.Drawing
$myImage = [System.BitmapExtractor]::Extract("C:\SomePath\Some.dll", "LOGO")
$myIcon = [System.IconExtractor]::Extract("C:\SomePath\Some.dll", 1, $true)
I was thinking of a scenario to detect a key combination [preferably window key + a] using the built in scripting languages like vb script, powershell script, batch script etc.. is there any way to do this ?
I personally love AutoHotKey you create a script and it will detect any key combination. It is fast and easy to use and I have dozens of key combinations that I have scripted and use every day.
If you must use a built-in scripting language, then the easiest is to create the desired script in whatever language that you prefer (for ex. PowerShell). Then create a shortcut that will run your script (for ex. something like powershell.exe -file "c:\myScript.ps1").
Then after testing your shortcut and script, go to the Shortcut's properties, and there is a "Shortcut key" field that you can bind a key combination to.
Using built in languages is a bit more cumbersome, and you have to have a separate script and shortcut for each key combination. Compared to AutoHotKey which you can combine all your key combinations into one file.
To do this via powershell or other built-in tools seems to be quite ambitious.
What you're going to need to learn about are "System Hooks" which are used in the Windows operating system to keep track of things that are going on outside the running program or script.
I found this link on the subject, it's something I'm still trying to learn myself so I can't promise it's a good explanation:
http://www.codeproject.com/Articles/6362/Global-System-Hooks-in-NET
Here is an example of a powershell script to operate a keylogger, it records all keystrokes and sends them to a log file:
http://hinchley.net/2013/11/02/creating-a-key-logger-via-a-global-system-hook-using-powershell/
Add-Type -TypeDefinition #"
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyLogger {
public static class Program {
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const string logFileName = "log.txt";
private static StreamWriter logFile;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
public static void Main() {
logFile = File.AppendText(logFileName);
logFile.AutoFlush = true;
hookId = SetHook(hookProc);
Application.Run();
UnhookWindowsHookEx(hookId);
}
private static IntPtr SetHook(HookProc hookProc) {
IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
int vkCode = Marshal.ReadInt32(lParam);
logFile.WriteLine((Keys)vkCode);
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
"# -ReferencedAssemblies System.Windows.Forms
[KeyLogger.Program]::Main();
Hopefully this points you in the right direction and you're able to get something working out of this!
i want to build an app that work in the background, and will capture all click events
on the minimize button, of all opened forms / windows that actually running. (not only in my current app)
it will be some sort of hook to add minimize handler to all of other windows.
how to setup this kind of hook ? ( please provide some code example in csharp with marsheling )
To better understand the idea : this procedure already exists in program called TrayIt that handle Ctrl+Click on the Minimize button, and send programs to system tray .
EDIT:
i have found that SetWindowsHookEx cannot set a global hook with c# due to limitation in manged code (see the msdn documentation )
but may WinEventProc with EVENT_OBJECT_STATECHANGE should do the work
finely i have found solution for this hook ,
this is not the best solution that i can get but it do the work
i have mixed window_state_change in SetWinEventHook
and component to track Control Key in Gma.UserActivityMonitor
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Windows;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security.Permissions;
using Gma.UserActivityMonitor;
namespace example {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
public const uint WINEVENT_OUTOFCONTEXT = 0;
public const uint EVENT_OBJECT_STATECHANGE = 0x800A;
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
public static bool ControlDown = false;
public static IntPtr hhook;
static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);
private void load(object sender, System.EventArgs e) {
hhook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE, IntPtr.Zero, procDelegate, 0, 0, winapi.WINEVENT_OUTOFCONTEXT);
HookManager.KeyDown += HookManager_KeyDown;
HookManager.KeyUp += HookManager_KeyUp;
}
private void closing(object sender, System.Windows.Forms.FormClosingEventArgs e) {
UnhookWinEvent(hhook);
HookManager.KeyDown -= HookManager_KeyDown;
HookManager.KeyUp -= HookManager_KeyUp;
}
private void HookManager_KeyUp(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.LControlKey) { ControlDown = false; }
}
private void HookManager_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.LControlKey) { ControlDown = true; }
}
static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime) {
if (idObject == -2 && idChild == 2) {
if (ControlDown) {
// HookWindow(hwnd);
.....
}
}
}
}
}
if you like you can setup a simple hook with RegisterHotKey
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);