Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInternal'

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Blackholyman
Posts: 1293
Joined: 29 Sep 2013, 22:57
Location: Denmark
Contact:

Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInternal'

02 Sep 2019, 02:00

Hi,

I'm trying to move a top level window to another virtual desktop without switching virtual desktop (not to easy it seems)

examples:
(VirtualDesktop.ps1)
(VirtualDesktop is C# wrapper for IVirtualDesktopManager on Windows 10.)

after finding those two examples above i continued searching the interwebz and what i found is 'MoveWindowToDesktop' only works on windows owned by the current process (IVirtualDesktopManager::MoveWindowToDesktop method)
and what i'm trying to do is move a window of another process (in the script below it is a GUI window the script owns but did also try with a notepad window)

So online i found that others had luck doing that using the undocumented method 'MoveViewToDesktop' from 'IVirtualDesktopManagerInternal' (Requesting API calls for Windows 10's virtual desktops) (IVirtualDesktopManagerInternal instance not returned) (You can move a window not owned by the executing process, but it requires the use of additional, undocumented COM objects.)
so i tried piecing something together both from what was already on the forum (How to call a Win32 API with UUID [IVirtualDesktopManager]) and from what i was able to google

Currently I've taken a step back and am trying to use the 'view' returned from the method 'GetViewForHwnd' from 'IApplicationViewCollection' (Win10Desktops.h)
using 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInternal' (Updated interfaces in Windows 10 build 17134, 17661, and 17666)

so when i run the code below i end op getting an ErrorLevel of '0xC0000005' (normally means 'Access Violation') from the 'CanViewMoveDesktops' call

Code: Select all

#SingleInstance, force

; create a new virtual desktop with ctrl + win + d

Gui, new, +hwndhwnd
Gui, add, text,, let us try and move this window to another virtual desktop
Gui, add, button, w100, Ok
Gui, show
return

Cancel:
ExitApp
return

buttonok:
; IVirtualDesktopManager interface
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager
IVirtualDesktopManager          := ComObjCreate("{AA509086-5CA9-4C25-8F95-589D3C07B48A}", "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}")
IsWindowOnCurrentVirtualDesktop := vtable(IVirtualDesktopManager, 3)
GetWindowDesktopId              := vtable(IVirtualDesktopManager, 4)
MoveWindowToDesktop             := vtable(IVirtualDesktopManager, 5)

; internal interface IVirtualDesktopManagerInternal14328
; https://sourceforge.net/p/virtual-desktop-grid-switcher/src/ci/d85ff70ced929d161bd45d10a47ebb0c0f2a1f68/tree/VirtualDesktop-master/source/VirtualDesktop/Interop/IVirtualDesktopManagerInternal.cs#l71
IServiceProvider               := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{6D5140C1-7436-11CE-8034-00AA006009FA}")
IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{F31574D6-B682-4CDC-BD56-1827860ABEC6}")
GetCount                       := vtable(IVirtualDesktopManagerInternal, 3)
MoveViewToDesktop                := vtable(IVirtualDesktopManagerInternal, 4)
CanViewMoveDesktops            := vtable(IVirtualDesktopManagerInternal, 5)
GetCurrentDesktop              := vtable(IVirtualDesktopManagerInternal, 6)
GetDesktops                    := vtable(IVirtualDesktopManagerInternal, 7)
GetAdjacentDesktop             := vtable(IVirtualDesktopManagerInternal, 8)
SwitchDesktop                  := vtable(IVirtualDesktopManagerInternal, 9)
CreateDesktopW                 := vtable(IVirtualDesktopManagerInternal, 10)
RemoveDesktop                  := vtable(IVirtualDesktopManagerInternal, 11)
FindDesktop                    := vtable(IVirtualDesktopManagerInternal, 12)

ImmersiveShell := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{00000000-0000-0000-C000-000000000046}")
;~ try 
    ;~ ppDesktopManager := ComObjQuery(ImmersiveShell, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{f31574d6-b682-4cdc-bd56-1827860abec6}")
;~ if (!ppDesktopManager)
    ;~ ppDesktopManager := ComObjQuery(ImmersiveShell, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{AF8DA486-95BB-4460-B3B7-6E7A6B2962B5}")

; HKEY_CLASSES_ROOT\Interface\{2C08ADF0-A386-4B35-9250-0FE183476FCC}
if !(IApplicationViewCollection 				:= ComObjQuery(ImmersiveShell,"{2C08ADF0-A386-4B35-9250-0FE183476FCC}","{2C08ADF0-A386-4B35-9250-0FE183476FCC}" ) )
{
    MsgBox IApplicationViewCollection interface not supported.
    ExitApp	
}
GetViews								:= vtable(IApplicationViewCollection, 3) ; (out IObjectArray array);
GetViewsByZOrder						:= vtable(IApplicationViewCollection, 4) ; (out IObjectArray array);
GetViewsByAppUserModelId				:= vtable(IApplicationViewCollection, 5) ; (string id, out IObjectArray array);
GetViewForHwnd							:= vtable(IApplicationViewCollection, 6) ; (IntPtr hwnd, out IApplicationView view);
GetViewForApplication					:= vtable(IApplicationViewCollection, 7) ; (object application, out IApplicationView view);
GetViewForAppUserModelId				:= vtable(IApplicationViewCollection, 8) ; (string id, out IApplicationView view);
GetViewInFocus							:= vtable(IApplicationViewCollection, 9) ; (out IntPtr view);
;Unknown1                                := NumGet(NumGet(IApplicationViewCollection+0)+10*A_PtrSize) ; (out IntPtr view);
;outreshCollection                       := NumGet(NumGet(IApplicationViewCollection+0)+11*A_PtrSize) ; ();
;RegisterForApplicationViewChanges       := NumGet(NumGet(IApplicationViewCollection+0)+12*A_PtrSize) ; (object listener, out int cookie);
;//int RegisterForApplicationViewPositionChanges(object listener, out int cookie); //Removed in 17661
;UnregisterForApplicationViewChanges     := NumGet(NumGet(IApplicationViewCollection+0)+13*A_PtrSize) ; (int cookie);

; IApplicationViewCollection::GetViews method
IObjectArray := 0
DllCall(GetViews, "UPtr", IApplicationViewCollection, "UPtrP", IObjectArray, "UInt")

; IObjectArray::GetCount method
; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getcount
ViewCount := 0
DllCall( vtable(IObjectArray, 3), "UPtr", IObjectArray, "UIntP", ViewCount, "UInt")

VirtualDesktopCount := 0
DllCall(GetCount, "UPtr", IVirtualDesktopManagerInternal, "UIntP", VirtualDesktopCount, "UInt")

msgbox % "Number of views = " ViewCount "`nNumber of VDs = " VirtualDesktopCount "`n`nLet's contuine with the moving action of windows id: " hwnd

; IApplicationViewCollection::GetViewForHwnd method
pView := 0
GetViewForHwnd_return_value := DllCall(GetViewForHwnd, "UPtr", IApplicationViewCollection, "Ptr", hwnd, "Ptr*", pView, "UInt")
dllcall_errorlevel := errorlevel
if GetViewForHwnd_return_value
	msgbox % "GetViewForHwnd did not work - return value = " ok
if dllcall_errorlevel
	msgbox % "GetViewForHwnd errorlevel = " errorlevel

pfCanViewMoveDesktops := 0
CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "Ptr*", pView, "Uint", pfCanViewMoveDesktops, "UInt") ; return value BOOL
dllcall_errorlevel := errorlevel
if CanViewMoveDesktops_return_value
	msgbox % "CanViewMoveDesktops did not work - return value = " ok
if dllcall_errorlevel
	msgbox % "CanViewMoveDesktops errorlevel = " errorlevel

msgbox % "pfCanViewMoveDesktops = " pfCanViewMoveDesktops
	

ExitApp
return

; Errors
; Errorlevel 				:= -2 ; The return type or one of the specified arg types is invalid.
; RPC_X_NULL_REF_POINTER 	:= -2147023116
; E_NOTIMPL 				:= -2147467263 	; Not implemented 0x80004001
; 0xC0000005 means "access violation"


vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
i'm having a hard time moving on from here as i don't even know if im handling/using the 'view' returned from the 'GetViewForHwnd' call correctly as i don't know how to test the returned 'view' so i'm a bit lost

hopefully someone will have a bit of insight they can share on this
Also check out:
Courses on AutoHotkey

My Autohotkey Blog
:dance:
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInter

02 Sep 2019, 04:06

You try to call a method, so you have to pass the this parameter, i.e, "ptr", IVirtualDesktopManagerInternal, also from your link I see

Code: Select all

virtual HRESULT STDMETHODCALLTYPE CanViewMoveDesktops(
		IApplicationView *pView,
		int *pfCanViewMoveDesktops) = 0;
which tells means that "ptr*", pView should be just ptr, pView and "Uint", pfCanViewMoveDesktops should be "int*", pfCanViewMoveDesktops, so try,

Code: Select all

CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "ptr", IVirtualDesktopManagerInternal, "Ptr", pView, "int*", pfCanViewMoveDesktops, "UInt")
Likely you get the access violation from the method trying to use an IApplicationView** as the this parameter.

Cheers.
just me
Posts: 9467
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInter

02 Sep 2019, 04:22

Moin,

on Win 10 1903 I had to change the ID of the IApplicationViewCollection interface to {1841C6D7-4F9D-42C0-AF41-8747538F10E5}.

After that I still got the error 0xC0000005 until I changed

Code: Select all

CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "Ptr*", pView, "Uint", pfCanViewMoveDesktops, "UInt") ; return value BOOL
to

Code: Select all

CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "UPtr", pView, "Uint", pfCanViewMoveDesktops, "UInt") ; return value BOOL
After that I get the error 0x06E4 (The requested operation is not supported).

I agree with Helgef in respect of pfCanViewMoveDesktops. :wave:
User avatar
Blackholyman
Posts: 1293
Joined: 29 Sep 2013, 22:57
Location: Denmark
Contact:

Re: Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInter

02 Sep 2019, 04:52

Thank you both for helping me with this

Code: Select all

#SingleInstance, force

; create a new virtual desktop with ctrl + win + d

Gui, new, +hwndhwnd
Gui, add, text,, let us try and move this window to another virtual desktop
Gui, add, button, w100, Ok
Gui, show
return

Cancel:
ExitApp
return

buttonok:
; IVirtualDesktopManager interface
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager
IVirtualDesktopManager          := ComObjCreate("{AA509086-5CA9-4C25-8F95-589D3C07B48A}", "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}")
IsWindowOnCurrentVirtualDesktop := vtable(IVirtualDesktopManager, 3)
GetWindowDesktopId              := vtable(IVirtualDesktopManager, 4)
MoveWindowToDesktop             := vtable(IVirtualDesktopManager, 5)

; internal interface IVirtualDesktopManagerInternal14328
; https://sourceforge.net/p/virtual-desktop-grid-switcher/src/ci/d85ff70ced929d161bd45d10a47ebb0c0f2a1f68/tree/VirtualDesktop-master/source/VirtualDesktop/Interop/IVirtualDesktopManagerInternal.cs#l71
IServiceProvider               := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{6D5140C1-7436-11CE-8034-00AA006009FA}")
IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{F31574D6-B682-4CDC-BD56-1827860ABEC6}")
GetCount                       := vtable(IVirtualDesktopManagerInternal, 3)
MoveViewToDesktop                := vtable(IVirtualDesktopManagerInternal, 4)
CanViewMoveDesktops            := vtable(IVirtualDesktopManagerInternal, 5)
GetCurrentDesktop              := vtable(IVirtualDesktopManagerInternal, 6)
GetDesktops                    := vtable(IVirtualDesktopManagerInternal, 7)
GetAdjacentDesktop             := vtable(IVirtualDesktopManagerInternal, 8)
SwitchDesktop                  := vtable(IVirtualDesktopManagerInternal, 9)
CreateDesktopW                 := vtable(IVirtualDesktopManagerInternal, 10)
RemoveDesktop                  := vtable(IVirtualDesktopManagerInternal, 11)
FindDesktop                    := vtable(IVirtualDesktopManagerInternal, 12)

ImmersiveShell := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{00000000-0000-0000-C000-000000000046}")
;~ try 
    ;~ ppDesktopManager := ComObjQuery(ImmersiveShell, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{f31574d6-b682-4cdc-bd56-1827860abec6}")
;~ if (!ppDesktopManager)
    ;~ ppDesktopManager := ComObjQuery(ImmersiveShell, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{AF8DA486-95BB-4460-B3B7-6E7A6B2962B5}")

; HKEY_CLASSES_ROOT\Interface\{2C08ADF0-A386-4B35-9250-0FE183476FCC}
; on Win 10 1903 I had to change the ID of the IApplicationViewCollection interface to {1841C6D7-4F9D-42C0-AF41-8747538F10E5}
if !(IApplicationViewCollection 				:= ComObjQuery(ImmersiveShell,"{2C08ADF0-A386-4B35-9250-0FE183476FCC}","{2C08ADF0-A386-4B35-9250-0FE183476FCC}" ) )
{
    MsgBox IApplicationViewCollection interface not supported.
    ExitApp	
}
GetViews								:= vtable(IApplicationViewCollection, 3) ; (out IObjectArray array);
GetViewsByZOrder						:= vtable(IApplicationViewCollection, 4) ; (out IObjectArray array);
GetViewsByAppUserModelId				:= vtable(IApplicationViewCollection, 5) ; (string id, out IObjectArray array);
GetViewForHwnd							:= vtable(IApplicationViewCollection, 6) ; (IntPtr hwnd, out IApplicationView view);
GetViewForApplication					:= vtable(IApplicationViewCollection, 7) ; (object application, out IApplicationView view);
GetViewForAppUserModelId				:= vtable(IApplicationViewCollection, 8) ; (string id, out IApplicationView view);
GetViewInFocus							:= vtable(IApplicationViewCollection, 9) ; (out IntPtr view);
;Unknown1                                := NumGet(NumGet(IApplicationViewCollection+0)+10*A_PtrSize) ; (out IntPtr view);
;outreshCollection                       := NumGet(NumGet(IApplicationViewCollection+0)+11*A_PtrSize) ; ();
;RegisterForApplicationViewChanges       := NumGet(NumGet(IApplicationViewCollection+0)+12*A_PtrSize) ; (object listener, out int cookie);
;//int RegisterForApplicationViewPositionChanges(object listener, out int cookie); //Removed in 17661
;UnregisterForApplicationViewChanges     := NumGet(NumGet(IApplicationViewCollection+0)+13*A_PtrSize) ; (int cookie);

; IApplicationViewCollection::GetViews method
IObjectArray := 0
DllCall(GetViews, "UPtr", IApplicationViewCollection, "UPtrP", IObjectArray, "UInt")

; IObjectArray::GetCount method
; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getcount
ViewCount := 0
DllCall( vtable(IObjectArray, 3), "UPtr", IObjectArray, "UIntP", ViewCount, "UInt")

VirtualDesktopCount := 0
DllCall(GetCount, "UPtr", IVirtualDesktopManagerInternal, "UIntP", VirtualDesktopCount, "UInt")

msgbox % "Number of views = " ViewCount "`nNumber of VDs = " VirtualDesktopCount "`n`nLet's contuine with the moving action of windows id: " hwnd

; IApplicationViewCollection::GetViewForHwnd method
pView := 0
GetViewForHwnd_return_value := DllCall(GetViewForHwnd, "UPtr", IApplicationViewCollection, "Ptr", hwnd, "Ptr*", pView, "UInt")
dllcall_errorlevel := errorlevel
if GetViewForHwnd_return_value
	msgbox % "GetViewForHwnd did not work - return value = " ok
if dllcall_errorlevel
	msgbox % "GetViewForHwnd errorlevel = " errorlevel

pfCanViewMoveDesktops := 0
; CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "Ptr*", pView, "Uint", pfCanViewMoveDesktops, "UInt") ; return value BOOL
CanViewMoveDesktops_return_value := DllCall(CanViewMoveDesktops, "ptr", IVirtualDesktopManagerInternal, "Ptr", pView, "int*", pfCanViewMoveDesktops, "UInt")
dllcall_errorlevel := errorlevel
if CanViewMoveDesktops_return_value
	msgbox % "CanViewMoveDesktops did not work - return value = " ok
if dllcall_errorlevel
	msgbox % "CanViewMoveDesktops errorlevel = " errorlevel

msgbox % "pfCanViewMoveDesktops = " pfCanViewMoveDesktops
	

ExitApp
return

; Errors
; Errorlevel 				:= -2 ; The return type or one of the specified arg types is invalid.
; RPC_X_NULL_REF_POINTER 	:= -2147023116
; E_NOTIMPL 				:= -2147467263 	; Not implemented 0x80004001
; 0xC0000005 means "access violation"


vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
that now sets pfCanViewMoveDesktops to 1 = true

i'll now try and use this new info to see if i can move the view to another desktop :) i'll post here again if i make it work or to ask more...
Also check out:
Courses on AutoHotkey

My Autohotkey Blog
:dance:
just me
Posts: 9467
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInter

02 Sep 2019, 05:03

...that now sets pfCanViewMoveDesktops to 1 = true
Same here when using ID {1841C6D7-4F9D-42C0-AF41-8747538F10E5}.
User avatar
Blackholyman
Posts: 1293
Joined: 29 Sep 2013, 22:57
Location: Denmark
Contact:

Re: Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInter

05 Sep 2019, 07:24

I did continue chipping away at this... and have made a version that works on my windows 10 build 1607

This is able to send a view/window of it's own process (AHK GUI) or of another process (tested with Notepad) to another virtual desktop

Code: Select all

#Persistent
#SingleInstance, force
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SetBatchLines -1
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Gui, new, +hwndhwnd
Gui, add, text,, let us try and move this window to another virtual desktop
Gui, add, button, w100, Ok
Gui, show,, Virtual Desktop test window
OnMessage(DllCall("RegisterWindowMessage", Str, "TaskbarCreated"), "WM_TASKBARCREATED")
return

Cancel:
ExitApp
return

f6::
hwnd := WinExist("ahk_class Notepad") ; Change the variable 'Hwnd' to use the id of a open notepad window
return

WM_TASKBARCREATED()
{
    Reload
}

buttonok:
; IVirtualDesktopManager interface
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager
IVirtualDesktopManager          := ComObjCreate("{AA509086-5CA9-4C25-8F95-589D3C07B48A}", "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}")
IsWindowOnCurrentVirtualDesktop := vtable(IVirtualDesktopManager, 3)
GetWindowDesktopId              := vtable(IVirtualDesktopManager, 4)
MoveWindowToDesktop             := vtable(IVirtualDesktopManager, 5)

; internal interface IVirtualDesktopManagerInternal14328
; https://sourceforge.net/p/virtual-desktop-grid-switcher/src/ci/d85ff70ced929d161bd45d10a47ebb0c0f2a1f68/tree/VirtualDesktop-master/source/VirtualDesktop/Interop/IVirtualDesktopManagerInternal.cs#l71
IServiceProvider               := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{6D5140C1-7436-11CE-8034-00AA006009FA}")
IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{F31574D6-B682-4CDC-BD56-1827860ABEC6}")
GetCount                       := vtable(IVirtualDesktopManagerInternal, 3) ; int GetCount();
MoveViewToDesktop              := vtable(IVirtualDesktopManagerInternal, 4) ; void MoveViewToDesktop(object pView, IVirtualDesktop desktop);
CanViewMoveDesktops            := vtable(IVirtualDesktopManagerInternal, 5) ; bool CanViewMoveDesktops(object pView);
GetCurrentDesktop              := vtable(IVirtualDesktopManagerInternal, 6) ; IVirtualDesktop GetCurrentDesktop();
GetDesktops                    := vtable(IVirtualDesktopManagerInternal, 7) ; IObjectArray GetDesktops();
GetAdjacentDesktop             := vtable(IVirtualDesktopManagerInternal, 8) ; IVirtualDesktop GetAdjacentDesktop(IVirtualDesktop pDesktopReference, AdjacentDesktop uDirection);
SwitchDesktop                  := vtable(IVirtualDesktopManagerInternal, 9) ; void SwitchDesktop(IVirtualDesktop desktop);
CreateDesktopW                 := vtable(IVirtualDesktopManagerInternal, 10) ; IVirtualDesktop CreateDesktopW();
RemoveDesktop                  := vtable(IVirtualDesktopManagerInternal, 11) ; void RemoveDesktop(IVirtualDesktop pRemove, IVirtualDesktop pFallbackDesktop);
FindDesktop                    := vtable(IVirtualDesktopManagerInternal, 12) ; IVirtualDesktop FindDesktop(ref Guid desktopId);

;class AdjacentDesktop(ENUM):
;    LeftDirection = 3
;    RightDirection = 4

ImmersiveShell := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{00000000-0000-0000-C000-000000000046}") 

; HKEY_CLASSES_ROOT\Interface\{2C08ADF0-A386-4B35-9250-0FE183476FCC}
; on Win 10 1903 I had to change the ID of the IApplicationViewCollection interface to {1841C6D7-4F9D-42C0-AF41-8747538F10E5}
;    (IApplicationViewCollection 				:= ComObjQuery(ImmersiveShell,"{1841C6D7-4F9D-42C0-AF41-8747538F10E5","{1841C6D7-4F9D-42C0-AF41-8747538F10E5" ) ) ; 1809-1903

if !(IApplicationViewCollection 				:= ComObjQuery(ImmersiveShell,"{2C08ADF0-A386-4B35-9250-0FE183476FCC}","{2C08ADF0-A386-4B35-9250-0FE183476FCC}" ) ) ; 1607-1809
{
    MsgBox IApplicationViewCollection interface not supported.
    ExitApp	
}
GetViews								:= vtable(IApplicationViewCollection, 3) ; (out IObjectArray array);
GetViewsByZOrder						:= vtable(IApplicationViewCollection, 4) ; (out IObjectArray array);
GetViewsByAppUserModelId				:= vtable(IApplicationViewCollection, 5) ; (string id, out IObjectArray array);
GetViewForHwnd							:= vtable(IApplicationViewCollection, 6) ; (IntPtr hwnd, out IApplicationView view);
GetViewForApplication					:= vtable(IApplicationViewCollection, 7) ; (object application, out IApplicationView view);
GetViewForAppUserModelId				:= vtable(IApplicationViewCollection, 8) ; (string id, out IApplicationView view);
GetViewInFocus							:= vtable(IApplicationViewCollection, 9) ; (out IntPtr view);
Unknown1                                := vtable(IApplicationViewCollection, 10) ; (out IntPtr view);
outreshCollection                       := vtable(IApplicationViewCollection, 11) ; ();
RegisterForApplicationViewChanges       := vtable(IApplicationViewCollection, 12) ; (object listener, out int cookie);
;//int RegisterForApplicationViewPositionChanges(object listener, out int cookie); //Removed in 17661
UnregisterForApplicationViewChanges     := vtable(IApplicationViewCollection, 13) ; (int cookie);

; IApplicationViewCollection::GetViews method
IObjectArray := 0
DllCall(GetViews, "UPtr", IApplicationViewCollection, "UPtrP", IObjectArray, "UInt")

; IObjectArray::GetCount method
; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getcount
ViewCount := 0
DllCall( vtable(IObjectArray, 3), "UPtr", IObjectArray, "UIntP", ViewCount, "UInt")

VirtualDesktopCount := 0
DllCall(GetCount, "UPtr", IVirtualDesktopManagerInternal, "UIntP", VirtualDesktopCount, "UInt")

msgbox % "Number of views = " ViewCount "`nNumber of VDs = " VirtualDesktopCount "`n`nLet's contuine with the moving action of windows id: " hwnd


; IVirtualDesktopManagerInternal::GetDesktops method
IObjectArray := 0
DllCall(GetDesktops, "UPtr", IVirtualDesktopManagerInternal, "UPtrP", IObjectArray, "UInt")

; IObjectArray::GetCount method
; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getcount
Count := 0
DllCall( vtable(IObjectArray, 3), "UPtr", IObjectArray, "UIntP", Count, "UInt")

if (count <= 1) ; only one virtual desktop
{
    msgbox,0x4, Virtual Desktops, Only one Virtual Desktop detected!`n`nDo you wish to create one more?
    IfMsgBox, No
    {
        return
    }
    else ; create more virtual desktops
    {
        ; IVirtualDesktop CreateDesktopW();
        new_IVirtualDesktop := 0
        DllCall(CreateDesktopW, "UPtr", IVirtualDesktopManagerInternal, "Ptr*", new_IVirtualDesktop, "UInt")
        if (new_IVirtualDesktop) ; new desktop created
            goto buttonok
    }
}
; Convert GUID string into a GUID struct
pGUID := GUID_FromStr("{FF72FFDD-BE7E-43FC-9C03-AD81681E88E4}", IID_IVirtualDesktop) ; IID_IVirtualDesktop

; IVirtualDesktop GetCurrentDesktop();
CurrentIVirtualDesktop := 0
GetCurrentDesktop_return_value := DllCall(GetCurrentDesktop, "UPtr", IVirtualDesktopManagerInternal, "UPtrP", CurrentIVirtualDesktop, "UInt")

; IVirtualDesktop::GetID method
DllCall( vtable(CurrentIVirtualDesktop, 4), "UPtr", CurrentIVirtualDesktop, "UPtr", &IID_IVirtualDesktop, "UInt")

strGUID := GUID_ToStr(IID_IVirtualDesktop) ; DllCall("Ole32.dll\StringFromGUID2", "UPtr", &IID_IVirtualDesktop, "UPtr", &strGUID, "Int", 38 + 1)

CurrentDesktop := {"id":strGUID, "desktop": CurrentIVirtualDesktop}

IVirtualDesktops := {} ; Object to hold info about the Virtual Desktops

IVirtualDesktop := 0
Loop % (Count) ; store virtual desktop id's in an Autohotkey object
{
    ; https://github.com/nullpo-head/Windows-10-Virtual-Desktop-Switching-Shortcut/blob/master/VirtualDesktopSwitcher/VirtualDesktopSwitcher/VirtualDesktops.h
    pGUID := GUID_FromStr("{FF72FFDD-BE7E-43FC-9C03-AD81681E88E4}", IID_IVirtualDesktop) ; IID_IVirtualDesktop

    ; IObjectArray::GetAt method
    ; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getat
    DllCall( vtable(IObjectArray, 4), "UPtr", IObjectArray, "UInt", A_Index-1, "UPtr", &IID_IVirtualDesktop, "UPtrP", IVirtualDesktop, "UInt")

    ; IVirtualDesktop::GetID method
    DllCall( vtable(IVirtualDesktop, 4), "UPtr", IVirtualDesktop, "UPtr", &IID_IVirtualDesktop, "UInt")
    
    strGUID := GUID_ToStr(IID_IVirtualDesktop) ; DllCall("Ole32.dll\StringFromGUID2", "UPtr", &IID_IVirtualDesktop, "UPtr", &strGUID, "Int", 38 + 1)

    IVirtualDesktops[A_index] := {"id":strGUID, "IVirtualDesktop": IVirtualDesktop}
}


; IApplicationViewCollection::GetViewForHwnd method
pView := 0
DllCall(GetViewForHwnd, "UPtr", IApplicationViewCollection, "Ptr", hwnd, "Ptr*", pView, "UInt")


pfCanViewMoveDesktops := 0
DllCall(CanViewMoveDesktops, "ptr", IVirtualDesktopManagerInternal, "Ptr", pView, "int*", pfCanViewMoveDesktops, "UInt") ; return value BOOL

if (pfCanViewMoveDesktops)
{
    for key,oDesktop in IVirtualDesktops
    {
        if (oDesktop.id != CurrentDesktop.id)
        {
            msgbox,, Move to another virtual desktop, % "Moving window with id: " hwnd "`n`nMoving it to:`t" oDesktop.id "`nFrom current:`t`t" CurrentDesktop.id
            
            ; void MoveViewToDesktop(object pView, IVirtualDesktop desktop);
            DllCall(MoveViewToDesktop, "ptr", IVirtualDesktopManagerInternal, "Ptr", pView, "UPtr", oDesktop.IVirtualDesktop, "UInt")
            break
        }
    }
}
else
    msgbox % "The window:" hwnd " can not move Virtual Desktop!"

msgbox % "Now it's time to check if the window was moved to another Virtual Desktop!`n`nWhen this msgbox is closed the script will exit. (any GUI is destroyed)"

ExitApp
return

; Errors
; Errorlevel 				:= -2 ; The return type or one of the specified arg types is invalid.
; RPC_X_NULL_REF_POINTER 	:= -2147023116
; E_NOTIMPL 				:= -2147467263 	; Not implemented 0x80004001
; 0xC0000005 means "access violation"


vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}

/* Function: Guid_FromStr
 *     Converts a GUID string into a GUID struct
 * Syntax:
 *     pGuid := Guid_FromStr( sGuid, ByRef VarOrAddress )
 * Parameter(s):
 *     pGuid              [retval] - address of the GUID struct
 *     sGuid                  [in] - string representation of the GUID
 *     VarOrAddress   [ByRef, out] - GUID, memory address or variable
 */
Guid_FromStr(sGuid, ByRef VarOrAddress)
{
	if IsByRef(VarOrAddress) && (VarSetCapacity(VarOrAddress) < 16)
		VarSetCapacity(VarOrAddress, 16) ; adjust capacity
	pGuid := IsByRef(VarOrAddress) ? &VarOrAddress : VarOrAddress
	if ( DllCall("ole32\CLSIDFromString", "WStr", sGuid, "Ptr", pGuid) < 0 )
		throw Exception("Invalid GUID", -1, sGuid)
	return pGuid ; return address of GUID struct
}
/* Function: Guid_ToStr
 *     Converts a GUID into a string of printable characters
 * Syntax:
 *     sGuid := Guid_ToStr( ByRef VarOrAddress )
 * Parameter(s):
 *     sGuid              [retval] - GUID string
 *     VarOrAddress    [ByRef, in] - GUID, memory address or variable
 */
Guid_ToStr(ByRef VarOrAddress)
{
	pGuid := IsByRef(VarOrAddress) ? &VarOrAddress : VarOrAddress
	VarSetCapacity(sGuid, 78) ; (38 + 1) * 2
	if !DllCall("ole32\StringFromGUID2", "Ptr", pGuid, "Ptr", &sGuid, "Int", 39)
		throw Exception("Invalid GUID", -1, Format("<at {1:p}>", pGuid))
	return StrGet(&sGuid, "UTF-16")
}
Hopefully others will be able to use it :)

Thanks for your help on this...
Also check out:
Courses on AutoHotkey

My Autohotkey Blog
:dance:
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Getting '0xC0000005' = 'Access Violation' when trying to use 'CanViewMoveDesktops' from 'IVirtualDesktopManagerInter

07 Sep 2019, 09:17

Cool, it works both with the gui and notepad on Microsoft Windows 10 Pro Version 10.0.17134 Build 17134.

Thanks for sharing :thumbup:.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 254 guests