I am trying to maximize my skype window from powershell.
I use the following script...
$sig = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32
$hwnd = #(Get-Process lync)[0].MainWindowHandle
# Restore window
[Win32.NativeMethods]::ShowWindowAsync($hwnd, 4)
I also tried
$hwnd = #(Get-Process -id 2560)[0].MainWindowHandle
Info
Major Minor Build Revision
----- ----- ----- --------
5 1 14409 1012
But when I run the command it doesn't maximize, just returns true. Can I maximize a Skype window from poershell?
You were close in your question statement, but you are using the wrong constant.
$SW_MAXIMIZE = 3
$sig = #'
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
'#
Add-Type -MemberDefinition $sig -Name Functions -Namespace Win32
$hWnd = (Get-Process -Name lync).MainWindowHandle
[Win32.Functions]::ShowWindow($hWnd, $SW_MAXIMIZE)
Related
I am trying to send a Windows notification through Lua, I found a few methods to do it, but in Python, I couldn't find anything for Lua. Is there any method I can do this? And if it is, could someone tell me how? Thanks!
I tried searching for answers, but I couldn't find anything about it.
Lua does not have such standard function, you need to use some external library.
For example, you can use FFI library to invoke Win32API functions directly.
The following script uses LuaJIT FFI:
local ffi = require'ffi'
local shell32 = ffi.load'shell32'
ffi.cdef[[
typedef int BOOL;
typedef unsigned int DWORD;
typedef unsigned int UINT;
typedef intptr_t HANDLE;
typedef intptr_t HWND;
typedef intptr_t HICON;
typedef intptr_t HINSTANCE;
typedef struct {int Data[4];} GUID;
typedef struct {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
char szTip[128];
DWORD dwState;
DWORD dwStateMask;
char szInfo[256];
union {
UINT uTimeout;
UINT uVersion;
};
char szInfoTitle[64];
DWORD dwInfoFlags;
GUID guidItem;
HICON hBalloonIcon;
} NOTIFYICONDATAA;
BOOL Shell_NotifyIconA(
int dwMessage,
NOTIFYICONDATAA * lpData
);
HICON LoadIconA(
HINSTANCE hInstance,
intptr_t IconCode
);
BOOL DestroyIcon(
HICON hIcon
);
HWND GetConsoleWindow();
]]
-- icon codes:
-- 32512 Your application's icon
-- 32513 Error ("X" inside red circle)
-- 32514 Question ("?" inside blue circle)
-- 32515 Warning ("!" inside yellow triangle)
-- 32516 Information ("i" inside blue circle)
-- 32518 Security Shield
local tray_icon_code = 32516 -- Information
local balloon_icon_code = 32518 -- Shield
-- create tray icon
local tray_icon_handle = ffi.C.LoadIconA(0, tray_icon_code)
local balloon_icon_handle = ffi.C.LoadIconA(0, balloon_icon_code)
local notify_icon_data = ffi.new"NOTIFYICONDATAA"
notify_icon_data.cbSize = ffi.sizeof(notify_icon_data)
notify_icon_data.hWnd = ffi.C.GetConsoleWindow() -- HWND of your application window
notify_icon_data.uFlags = 1 + 2 -- NIF_MESSAGE | NIF_ICON
notify_icon_data.hIcon = tray_icon_handle
notify_icon_data.uVersion = 4
notify_icon_data.hBalloonIcon = balloon_icon_handle
shell32.Shell_NotifyIconA(0, notify_icon_data) -- NIM_ADD
shell32.Shell_NotifyIconA(4, notify_icon_data) -- NIM_SETVERSION
print("Tray icon added. Press Enter to continue..."); io.read()
-- show notifications
local function copy_string(dest_array_ptr, str)
ffi.copy(dest_array_ptr, (str or ""):sub(1, ffi.sizeof(dest_array_ptr) - 1))
end
local function show_notification(text, title)
notify_icon_data.uFlags = 1 + 2 + 16 -- NIF_MESSAGE | NIF_ICON | NIF_INFO
notify_icon_data.dwInfoFlags = 4 + 32 -- NIIF_USER | NIIF_LARGE_ICON
copy_string(notify_icon_data.szInfoTitle, title)
copy_string(notify_icon_data.szInfo, text)
shell32.Shell_NotifyIconA(1, notify_icon_data) -- NIM_MODIFY
end
show_notification("some text", "some title")
print("Notification displayed. Press Enter to continue..."); io.read()
show_notification("first line\nsecond line", "another title")
print("Another notification displayed. Press Enter to continue..."); io.read()
-- notification requests generated by show_notification() are queued,
-- each notification is kept on the screen for several seconds before next one is displayed
-- to immediately remove the notification - remove the tray icon
-- remove tray icon
shell32.Shell_NotifyIconA(2, notify_icon_data) -- NIM_DELETE
ffi.C.DestroyIcon(balloon_icon_handle)
ffi.C.DestroyIcon(tray_icon_handle)
print("Tray icon removed. Press Enter to exit..."); io.read()
I have some Windows 10 LTSC/IoT digital signs starting the ShareX screen capture application on boot like so:
"C:\Program Files\ShareX\ShareX.exe" -silent -startautocapture
After the Autocapture fires the Destination config is set to post the image to a URL but when network outages occur the ShareX UI spawns at a higher z-index than the Four Winds digital sign software display and remains there until manually closed or minimized.
I have been over the ShareX docs but this behavior isn't mentioned and the Custom Uploader options only include specifying an error message to display. Anyone have ideas on suppression or minimizing the UI? Possibly a PowerShell trick for shifting the focus?
Per #zett42 comment I started out with this answer. Unfortunately neither ShareX nor ShareX 8.14 is apparently the correct ConsoleWindowClass.
[int]$handle = [WPIA.ConsoleUtils]::FindWindow('ConsoleWindowClass','ShareX 8.14')
In the end this answer got it working using
$handle = $fw::FindWindow([IntPtr]::Zero, 'ShareX 8.14' )
Since this has a version number in the name I will need to sort out an enumeration strategy to iterate over the open windows and do substring matching but for now this succeeds.
I am very new to PowerShell so this may be ungracefully done.
$sig = #'
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(IntPtr sClassName, String sAppName);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MINIMIZE = 0xF020;
'#
$fw = Add-Type -Namespace WPIA -Name ConsoleUtils -MemberDefinition $sig -PassThru
$wname='ShareX 14.1' # any existing window name
[int] $handle = $fw::FindWindow([IntPtr]::Zero, $wname ) # returns the Window Handle
if ($handle -gt 0)
{
[void][WPIA.ConsoleUtils]::SendMessage($handle, [WPIA.ConsoleUtils]::WM_SYSCOMMAND, [WPIA.ConsoleUtils]::SC_MINIMIZE, 0)
}
Is it possible to get process id based on it's child Window Handle in powershell?
For example, this script looking for Window Handle with titile "Warning":
$sig = #"
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(IntPtr sClassName, String sAppName);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
"#
$fw = Add-Type -Namespace Win32 -Name Funcs -MemberDefinition $sig -PassThru
$wname='Warning'
$find_window = $fw::FindWindow([IntPtr]::Zero, $wname )
Write-Host $find_window
How it is shown in Task Manager:
Program.exe
|
\Warning
Now i need to determine - what PID have this warning window. I know it is possible to implement in C# (which i don't use at all), but this should be done on powershell only.
You are looking for GetWindowThreadProcessId. According to this answer, you can call that from PowerShell with this p/invoke:
[DllImport("User32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
You supply a window handle in the first argument. The process and thread IDs are returned in the second argument and return value, respectively.
I have a cmd line exe provided for me which I cannot change at and I need to write a script around, but it has a Pause in built to it and I cannot see any way to skip this pause so the rest of my script can continue.
I have tried all sorts of things, including
#echo | call program.exe
program.exe < nul
cmd /c echo y &echo.| program.exe
Jay's answer here
Variations and combinations of those
Checked the program /? to see if there's a skip pause toggle, but there is not
Appreciate any advice
You can send data to a process using interop. It's called hooking the process, and there are a few resources on it. I like this answer.
This is a little code that allows you to send message to a
backgrounded application. To send the "A" char for example, simply
call sendKeystroke(Keys.A), and don't forget to use namespace
System.windows.forms to be able to use the Keys object.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace keybound
{
class WindowHook
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public static void sendKeystroke(ushort k)
{
const uint WM_KEYDOWN = 0x100;
const uint WM_SYSCOMMAND = 0x018;
const uint SC_CLOSE = 0x053;
IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");
IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, ((IntPtr)k), (IntPtr)0);
//IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
}
}
}
You'll probably have an easier time than they did getting the application instead of searching for the process because you can start it from your application:
Process proc = new Process();
proc.StartInfo.FileName = executablePath;
proc.Start();
proc.WaitForInputIdle();
Then proc.Id will be the PID.
As an alternative, I just ran into a VB type of example that seems even simpler using the Shell function, but I haven't used it before. You'll need to add a pause in your application to wait for the prompt, but this seems cleaner to read than Interop:
Dim ProcID As Integer
' Start the Calculator application, and store the process id.
ProcID = Shell("CALC.EXE", AppWinStyle.NormalFocus)
' Activate the Calculator application.
AppActivate(ProcID)
' Send the keystrokes to the Calculator application.
My.Computer.Keyboard.SendKeys("22", True)
My.Computer.Keyboard.SendKeys("*", True)
My.Computer.Keyboard.SendKeys("44", True)
My.Computer.Keyboard.SendKeys("=", True)
' The result is 22 * 44 = 968.
If you wind up with a System.ArgumentException, it's probably because the Shell function didn't get a process ID. This is because it needs full trust. The application would work if run as administrator. I don't think you'd find an easy way around this if you can't do that since it's a security issue to have applications run each other, but I could be wrong.
I've been trying to write a program in C++ that will monitor running processes in the background and terminate a certain one if it's detected to be running. I have written a program that will do so, however the only way I can think of to do this is to use an infinite WHILE loop that keeps checking for the program. This, as you can imagine, constantly uses CPU power and resources to be constantly looping. In task manager, you can see that most processes that are running are always using 0% of the CPU. My question is: How can I write or modify this program to run in the background, utilizing 0% of the CPU until it detects the process it's supposed to terminate?
My entire program is below. In this example, I have used "Notepad.exe" in WinMain as the process the program should be terminating.
#include <Windows.h>
#include <iostream>
#include <tlhelp32.h>
#include <string>
#define TA_FAILED 0
#define TA_SUCCESS_CLEAN 1
#define TA_SUCCESS_KILL 2
DWORD WINAPI TerminateApp(DWORD dwPID, DWORD dwTimeout);
DWORD WINAPI Terminate16App(DWORD dwPID, DWORD dwThread, WORD w16Task, DWORD dwTimeout);
typedef struct {
DWORD dwID;
DWORD dwThread;
} TERMINFO;
BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;
DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout ) {
HANDLE hProc ;
DWORD dwRet ;
// If we can't open the process with PROCESS_TERMINATE rights,
// then we give up immediately.
hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
dwPID);
if(hProc == NULL) {
return TA_FAILED ;
}
// TerminateAppEnum() posts WM_CLOSE to all windows whose PID
// matches your process's.
EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;
// Wait on the handle. If it signals, great. If it times out,
// then you kill it.
if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
else
dwRet = TA_SUCCESS_CLEAN ;
CloseHandle(hProc) ;
return dwRet ;
}
BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) {
DWORD dwID ;
GetWindowThreadProcessId(hwnd, &dwID) ;
if(dwID == (DWORD)lParam) {
PostMessage(hwnd, WM_CLOSE, 0, 0) ;
}
return TRUE ;
}
DWORD FindProcessId(const std::string& processName);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
std::string process1 = "Notepad.exe";
while (1) {
TerminateApp(FindProcessId(process1),0);
}
return 0;
}
DWORD FindProcessId(const std::string& processName) {
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE) {
return 0;
}
Process32First(processesSnapshot, &processInfo);
if (!processName.compare(processInfo.szExeFile)) {
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
while (Process32Next(processesSnapshot, &processInfo)) {
if (!processName.compare(processInfo.szExeFile)) {
CloseHandle(processesSnapshot);
return processInfo.th32ProcessID;
}
}
CloseHandle(processesSnapshot);
return 0;
}
You can use WMI and event notification to find when processes are created and destroyed. __InstanceCreationEvent is what you need to look for.
Creation of a resource: __InstanceCreationEvent
Suppose you are interested in receiving a notification if Notepad is run on a certain computer. When Notepad runs, a corresponding process is created. Processes can be managed by using WMI and are represented by the Win32_Process class. When Notepad starts running, a corresponding instance of the Win32_Process class becomes available through WMI. If you have registered your interest in this event (by issuing the appropriate event notification query), the availability of this instance results in the creation of an instance of the __InstanceCreationEvent class.