WinMove to move an admin window? Topic is solved
WinMove to move an admin window?
I have several hotkeys that trigger WinMove to move and/or resize the active window. They understandably never work on processes run as administrator. Say, for example, diskmgmt.msc is the target window. I get an access denied message when I try to move it. I think I understand WHY this is but I'm hoping there might me a way to fix it? Specifically,
1. Is there a way to detect that the window owner is admin and that the access denied is about to occur. I know I can use Try/Catch, but is there some attribute about a window of an admin process that I could check for programmatically to tell me to use the alternate approach?
2. Is there in fact an alternate approach to move such an admin window? Do I have to relaunch the script elevated as admin? Could I launch a helper script that could move it? I'm not sure where to start on this.
Any help or pointers would be much appreciated. Many thanks!
1. Is there a way to detect that the window owner is admin and that the access denied is about to occur. I know I can use Try/Catch, but is there some attribute about a window of an admin process that I could check for programmatically to tell me to use the alternate approach?
2. Is there in fact an alternate approach to move such an admin window? Do I have to relaunch the script elevated as admin? Could I launch a helper script that could move it? I'm not sure where to start on this.
Any help or pointers would be much appreciated. Many thanks!
Re: WinMove to move an admin window? Topic is solved
I tried (updated),
Code: Select all
IsElevated(pid) {
local result := false, proc
local hToken := 0
static TOKEN_QUERY := 0x0008
static PROCESS_QUERY_INFORMATION := 0x0400
try {
if ! proc := OpenProcess(PROCESS_QUERY_INFORMATION, false, pid) {
static ERROR_ACCESS_DENIED := 0x5
if !a_isadmin && a_lasterror == ERROR_ACCESS_DENIED
return true ; probably :=)
else throw OSError(,, 'OpenProcess')
}
if OpenProcessToken( proc, TOKEN_QUERY, &hToken ) {
static sizeof_elevation := 4
static TokenElevation := 20
local cbSize := 4
local Elevation := 0
if GetTokenInformation( hToken, TokenElevation, &Elevation, sizeof_elevation, &cbSize )
result := Elevation
else
throw OSError(,, 'GetTokenInformation')
}
else
throw OSError(,, 'OpenProcessToken')
} finally {
if hToken
CloseHandle hToken
if proc
CloseHandle proc
}
return result
; Windows lib:
/*
HANDLE OpenProcess(
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwProcessId
);
*/
OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId)
=> dllcall('Kernel32.dll\OpenProcess', 'uint', dwDesiredAccess, 'int', bInheritHandle, 'uint', dwProcessId, 'ptr')
/*
BOOL OpenProcessToken(
[in] HANDLE ProcessHandle,
[in] DWORD DesiredAccess,
[out] PHANDLE TokenHandle
);
*/
OpenProcessToken(ProcessHandle, DesiredAccess, &TokenHandle)
=> dllcall('Advapi32.dll\OpenProcessToken', 'ptr', ProcessHandle, 'uint', DesiredAccess, 'ptr*', &TokenHandle, 'int')
/*
BOOL GetTokenInformation(
[in] HANDLE TokenHandle,
[in] TOKEN_INFORMATION_CLASS TokenInformationClass,
[out, optional] LPVOID TokenInformation,
[in] DWORD TokenInformationLength,
[out] PDWORD ReturnLength
);
*/
GetTokenInformation(
TokenHandle,
TokenInformationClass,
&TokenInformation,
TokenInformationLength,
&ReturnLength
)
=> dllcall('Advapi32.dll\GetTokenInformation',
'ptr', TokenHandle,
'ptr', TokenInformationClass,
'uint*', &TokenInformation,
'uint', TokenInformationLength,
'uint*', &ReturnLength
)
/*
BOOL CloseHandle(
[in] HANDLE hObject
);
*/
CloseHandle(hObject)
=> dllcall('Kernel32.dll\CloseHandle', 'ptr', hObject, 'int')
; from: https://stackoverflow.com/questions/8046097/how-to-check-if-a-process-has-the-administrative-rights
}
Code: Select all
; run as admin for hotkeys to work
full_command_line := DllCall("GetCommandLine", "str")
if not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)"))
{
try
{
if A_IsCompiled
Run '*RunAs "' A_ScriptFullPath '" /restart'
else
Run '*RunAs "' A_AhkPath '" /restart "' A_ScriptFullPath '"'
}
ExitApp
}
z::tooltip IsElevated(wingetpid(winexist('a')))
x::exitapp
If that works, I'd do that. I have no idea though.Do I have to relaunch the script elevated as admin?
Cheers.
Last edited by Helgef on 24 May 2022, 05:48, edited 2 times in total.
Re: WinMove to move an admin window?
This is great!!! Thanks so much. I'm testing it now. I'm trying to see if I have to be elevated to call any of it... or if I can see if something is elevated before elevating my own script? I am not as good as I should be with the windows DLLs. I'll keep monkeying with it, but this helps immensely. If I refine the question more I'll post an update. In the meantime, I'm marking it solved. Thanks again @Helgef!
Re: WinMove to move an admin window?
It seems you get an access denied error from OpenProcess if you are not elevated and the target process is. I updated the code above to handle it.
But, there might be situations when this error is thrown for other reasons.
Cheers.
But, there might be situations when this error is thrown for other reasons.
Cheers.
Last edited by Helgef on 24 May 2022, 05:43, edited 1 time in total.
Re: WinMove to move an admin window?
A safer alternative to running the script as administrator is to run with UI access, but since you don't have the v2 installer yet, you would have to create the UIA executable manually. That can be done by copying a v2 executable and passing its path to EnableUIAccess() from the v1 installer (using AutoHotkey v1 to execute it, of course).
Re: WinMove to move an admin window?
Interesting. Thanks, @lexikos! So, if I'm thinking of just the WinMove action to move an admin-launched window... and assuming I don't want to be interrupted by the UAC elevation prompt (or whatever it's called) just to reposition the window... are you saying I would make a companion script that took command-line parameters of PID,x,y,w,h and run it whenever I needed to move/resize an admin-launched window (i.e. when I've caught the access denied error or foretold its occurrence using Helgef's code)? I'm trying to see how the "run with UI access" context menu thing then fits into all that. Am I somehow triggering that when I call the special purpose mover script with a command line switch, or do I have to right click on something?
Sorry if I'm being overly dense here... I think I'm just missing it. So bottom line is I have a script with many unrelated hotkeys (including WinMove to predefined regions) running without elevation. When that main script sees the "WinMove hotkey" has triggered relative to moving an admin window (Helgef's code), then I need to call a companion script (which I'm trying to flesh out now), but with UI access (Lexikos' link, which I don't completely understand how to trigger the elevation (a) in this way, (b) from another script, (c) without further user prompting). Is that right? Many thanks!
Sorry if I'm being overly dense here... I think I'm just missing it. So bottom line is I have a script with many unrelated hotkeys (including WinMove to predefined regions) running without elevation. When that main script sees the "WinMove hotkey" has triggered relative to moving an admin window (Helgef's code), then I need to call a companion script (which I'm trying to flesh out now), but with UI access (Lexikos' link, which I don't completely understand how to trigger the elevation (a) in this way, (b) from another script, (c) without further user prompting). Is that right? Many thanks!
Re: WinMove to move an admin window?
The context menu item just causes the shell to execute something like "C:\Program Files\AutoHotkey\AutoHotkeyU64_UIA.exe" "%1" %*, where %1 is the selected file and %* is usually empty. You don't need to use the context menu for this any more than for any of the other context menu items.
In its current unreleased form, the v2 installer automatically and unconditionally creates the UIA files. After installation, it is possible to set (via a simple checkbox) v1 and/or v2 scripts to run with UI access by default. The installer and related scripts are nearly at a point where I am ready to share them for more testing.
I don't use the context menu, and wouldn't be bothered with switching to UIA at the last minute; I just run my main hotkey and gesture scripts with AutoHotkeyU32_UIA.exe via Run in a startup script.Scripts which need to run other scripts with UI access can simply Run the appropriate UIA.exe file with the normal command line parameters.
Source: Using the Program | AutoHotkey
In its current unreleased form, the v2 installer automatically and unconditionally creates the UIA files. After installation, it is possible to set (via a simple checkbox) v1 and/or v2 scripts to run with UI access by default. The installer and related scripts are nearly at a point where I am ready to share them for more testing.
-
- Posts: 59
- Joined: 01 Mar 2022, 17:07
- Contact:
Re: WinMove to move an admin window?
@Helgef That is great. Thank you so much!