I am using Powershell to call the group policy update API from userenv.dll (see here and here). This works fine:
$sig =@'
[DllImport("userenv.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RefreshPolicy([MarshalAs(UnmanagedType.Bool)] bool bMachine);
'@
$mytype = add-type -memberdefinition $sig -Name "Win32RefreshGP" -Namespace Win32Functions -PassThru
$mytype::RefreshPolicy($false) # Refresh the user policy
When I import this type though as follows:
$sigEx =@'
public enum RefreshPolicyOption:uint
{
RP_FORCE = 1,
RP_SYNC = 2
}
[DllImport("userenv.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RefreshPolicyEx([MarshalAs(UnmanagedType.Bool)] bool bMachine, RefreshPolicyOption dwOptions = 0);
'@
$mytypeEx = add-type -memberdefinition $sigEx -Name "Win32RefreshGP" -Namespace Win32Functions -PassThru
$mytypeEx::RefreshPolicyEx($false) # Refresh the user policy
The following is raised calling $mytypeEx::RefreshPolicyEx($false)
Method invocation failed because [System.Object[]] does not contain a method named 'RefreshPolicyEx'.
At line:1 char:1
+ $mytypeEx::RefreshPolicyEx($false) # Refresh the user policy
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
This seems to be because of the attempt to use the enum in the type defintion. Any ideas?
I have tried using single/double quotes. I'd epxect the type definition to work as it works in C#.
The issue is fairly simple, when you use -PassThru
, Add-Type
will output a type instance for every type defined in your C# inline code, in this case $mytypeEx
will have 2 types, thus the error you're getting:
PS /> $mytypeEx
Namespace: Win32Functions
Access Modifiers Name
------ --------- ----
public class Win32RefreshGP : object
public enum Win32RefreshGP.RefreshPolicyOption : uint
PS /> $mytypeEx.Count
2
Solution is as simple as indexing the Win32RefreshGP
type and then call its static member:
PS /> $mytypeEx[0]::RefreshPolicyEx($false)
Or you can remove -PassThru
and then call the static member from the type itself:
PS /> [Win32Functions.Win32RefreshGP]::RefreshPolicyEx($false)