Search code examples
.netpowershellpinvoke

Invoke Runtime.InteropServices.DllImportAttribute


Editor's note: This question is ultimately about how to call a Windows API function such as SetForegroundWindow from PowerShell, using the .NET P/Invoke feature.

$dll=[Runtime.InteropServices.DllImportAttribute]::new("user32.dll")
$dll.EntryPoint='SetForegroundWindow'
$dll.CharSet=1
$dll.ExactSpelling=$true
$dll.SetLastError=$false
$dll.PreserveSig=$true
$dll.CallingConvention=1
$dll.BestFitMapping=$false
$dll.ThrowOnUnmappableChar=$false
$dll.Invoke(
    #...
    #...    
)

How to finish this code? I don't understand parameters in ".Invoke". As i understand, one of them is for my EntryPoint(HWND)?


Solution

  • The System.Runtime.InteropServices.DllImportAttribute attribute:

    • is normally used declaratively...

    • ... to decorate a .NET method that has a signature matching the unmanaged function being invoked.

    Defining .NET methods this way allows you to call unmanaged (native) functions, i.e. functions from DLLs that weren't written for .NET, such as Windows API functions, via a .NET feature called P/Invoke (Platform Invocation Services).

    You cannot directly do this in PowerShell code, but you can use the Add-Type cmdlet with the -MemberDefinition parameter to compile C# code on demand; -MemberDefinition automatically imports the System.Runtime.InteropServices namespace and automatically wraps the method definition(s) passed to it in class named for the -Name argument, in the namespace named for the -Namespace argument.

    Add-Type -Namespace Util -Name WinApi -MemberDefinition @'
      [DllImport("user32.dll", SetLastError=true)]
      public static extern bool SetForegroundWindow(IntPtr hWnd);
    '@
    
    $hwnd = ... # determine the handle of the target window.
    
    # Now call the unmanaged function.
    [Util.WinApi]::SetForegroundWindow($hwnd)
    
    • Note the declarative use of the DllImportAttribute (in which case the Attribute suffix is optional) and that only the source DLL name is required to construct the instance; supplying values to the various properties (such as SetLastError above) is optional.

    • The method being decorated - the one you'll be able to call from PowerShell code - must be declared as public static extern, and the rest of the method signature must match the return type and the set of parameters, including their types, of the unmanaged DLL function being invoked.

      • By default, the unmanaged function is assumed to have the same name as the method, although you may name the method differently and specify the name of the function to invoke explicitly with the EntryPoint property of DllImportAttribute.
    • Website pinvoke.net is a helpful resource for finding predefined definitions for Windows API functions, such as for the SetForegroundWindow function at hand.