Passing ref type to methods using invocation within Powershell

Whisperer

Member
In the code below [my5.stuff]::EnumDisplayDevices($null,1,[ref]$test,0)
does not work because the $null is cast as ""

The following line does return true but $test is not populated with the expected details.
Presumably this is because [my5.DISPLAY_DEVICE]$test is not a reference
$obj.gettype().getmethod("EnumDisplayDevices").invoke($obj,@($null,[uint32]0,[my5.DISPLAY_DEVICE]$test,[uint32]0))

How can I pass a reference type to the invoked method so that $test is populated with the details for Display Device 0?

I have tried all sorts of different ways can cannot get $test set as needed.

(Watch out for line wrapping in the code)

Thanks

####Code####

[email protected]"
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace My5
{
// Remove the next flags line and the flags will be returned as integers
[Flags()]
public enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>The device is part of the desktop.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x16,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000
}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct DISPLAY_DEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string DeviceKey;
}


}
"@

add-type -typedefinition $source

$test=new-object my5.display_device
$test.cb=[system.runtime.interopservices.marshal]::sizeof($test)

#The following line errors
[my5.stuff]::EnumDisplayDevices($null,1,$test,0)
#Argument: '3' should be a System.Management.Automation.PSReference. Use [ref].

#The following line returns False and $test is not set to anything - this is due to the $null being cast as ""
[my5.stuff]::EnumDisplayDevices($null,1,[ref]$test,0)

$obj=(new-object -typename "my5.stuff")
#The following method was suggested to get round the 'null' issue
#but, while it returns True, $test is not set.
#Presumably this is because [my5.DISPLAY_DEVICE]$test is not a reference
$obj.gettype().getmethod("EnumDisplayDevices").invoke($obj,@($null,[uint32]0,[my5.DISPLAY_DEVICE]$test,[uint32]0))


$obj.gettype().getmethod("EnumDisplayDevices").getparameters()


#ParameterType : System.String
#Name : lpDevice
#DefaultValue :
#RawDefaultValue :
#Position : 0
#Attributes : None
#Member : Boolean EnumDisplayDevices(System.String, UInt32, My5.DISPLAY_DEVICE ByRef, UInt32)
#IsIn : False
#IsOut : False
#IsLcid : False
#IsRetval : False
#IsOptional : False
#MetadataToken : 134217729

#ParameterType : System.UInt32
#Name : iDevNum
#DefaultValue :
#RawDefaultValue :
#Position : 1
#Attributes : None
#Member : Boolean EnumDisplayDevices(System.String, UInt32, My5.DISPLAY_DEVICE ByRef, UInt32)
#IsIn : False
#IsOut : False
#IsLcid : False
#IsRetval : False
#IsOptional : False
#MetadataToken : 134217730

#ParameterType : My5.DISPLAY_DEVICE&
#Name : lpDisplayDevice
#DefaultValue :
#RawDefaultValue :
#Position : 2
#Attributes : None
#Member : Boolean EnumDisplayDevices(System.String, UInt32, My5.DISPLAY_DEVICE ByRef, UInt32)
#IsIn : False
#IsOut : False
#IsLcid : False
#IsRetval : False
#IsOptional : False
#MetadataToken : 134217731

#ParameterType : System.UInt32
#Name : dwFlags
#DefaultValue :
#RawDefaultValue :
#Position : 3
#Attributes : None
#Member : Boolean EnumDisplayDevices(System.String, UInt32, My5.DISPLAY_DEVICE ByRef, UInt32)
#IsIn : False
#IsOut : False
#IsLcid : False
#IsRetval : False
#IsOptional : False
#MetadataToken : 134217732
 

My Computer

B

Bob Landau

1) I don't see where you've declared the function. Down where you've used
reflection on the $obj variable it appears to look correct but you need to
verify this

Check out this site

http://pinvoke.net/default.aspx/user32/EnumDisplayDevices.html

2) Why are you using 1 for the id. It starts at 0 and will fail if "id" is >
# of devices

3) The way the function is defined the first parameter is a string. If you
need to make certain "null' and not "" is passed change it to an IntPtr

4) You're to Invoke is not marking $test as a [ref]. I believe this is a
parameter where you can specify the direction when making this call but all
of that is a pain.

try this I'll let you provide the correct PS syntax

[DllImport("user32.dll")]
static extern bool EnumDisplayDevices(IntPtr lpDevice, uint iDevNum, ref
DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);


[my5.stuff]::EnumDisplayDevices($null,1,[ref]$test,0)
^^^^

I'm assuming that "EnumXXX" is placed in the "Stuff" namespace


"Whisperer" wrote:

>
> In the code below [my5.stuff]::EnumDisplayDevices($null,1,[ref]$test,0)
> does not work because the $null is cast as ""
>
> The following line does return true but $test is not populated with the
> expected details.
> Presumably this is because [my5.DISPLAY_DEVICE]$test is not a reference
> $obj.gettype().getmethod("EnumDisplayDevices").invoke($obj,@($null,[uint32]0,[my5.DISPLAY_DEVICE]$test,[uint32]0))
>
> HOW CAN I PASS A REFERENCE TYPE TO THE INVOKED METHOD SO THAT $TEST IS
> POPULATED WITH THE DETAILS FOR DISPLAY DEVICE 0?
>
> I have tried all sorts of different ways can cannot get $test set as
> needed.
>
> (Watch out for line wrapping in the code)
>
> Thanks
>
> ####Code####
>
> [email protected]"
> using System;
> using System.Runtime.InteropServices;
> using System.Threading;
>
> namespace My5
> {
> // Remove the next flags line and the flags will be returned as
> integers
> [Flags()]
> public enum DisplayDeviceStateFlags : int
> {
> /// <summary>The device is part of the desktop.</summary>
> AttachedToDesktop = 0x1,
> MultiDriver = 0x2,
> /// <summary>The device is part of the desktop.</summary>
> PrimaryDevice = 0x4,
> /// <summary>Represents a pseudo device used to mirror application
> drawing for remoting or other purposes.</summary>
> MirroringDriver = 0x8,
> /// <summary>The device is VGA compatible.</summary>
> VGACompatible = 0x16,
> /// <summary>The device is removable; it cannot be the primary
> display.</summary>
> Removable = 0x20,
> /// <summary>The device has more display modes than its output
> devices support.</summary>
> ModesPruned = 0x8000000,
> Remote = 0x4000000,
> Disconnect = 0x2000000
> }
>
> [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
> public struct DISPLAY_DEVICE
> {
> [MarshalAs(UnmanagedType.U4)]
> public int cb;
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
> public string DeviceName;
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
> public string DeviceString;
> [MarshalAs(UnmanagedType.U4)]
> public DisplayDeviceStateFlags StateFlags;
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
> public string DeviceID;
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
> public string DeviceKey;
> }
>
>
> }
> "@
>
> add-type -typedefinition $source
>
> $test=new-object my5.display_device
> $test.cb=[system.runtime.interopservices.marshal]::sizeof($test)
>
> #The following line errors
> [my5.stuff]::EnumDisplayDevices($null,1,$test,0)
> #Argument: '3' should be a System.Management.Automation.PSReference. Use
> [ref].
>
> #The following line returns False and $test is not set to anything -
> this is due to the $null being cast as ""
> [my5.stuff]::EnumDisplayDevices($null,1,[ref]$test,0)
>
> $obj=(new-object -typename "my5.stuff")
> #The following method was suggested to get round the 'null' issue
> #but, while it returns True, $test is not set.
> #Presumably this is because [my5.DISPLAY_DEVICE]$test is not a
> reference
> $obj.gettype().getmethod("EnumDisplayDevices").invoke($obj,@($null,[uint32]0,[my5.DISPLAY_DEVICE]$test,[uint32]0))
>
>
> $obj.gettype().getmethod("EnumDisplayDevices").getparameters()
>
>
> #ParameterType : System.String
> #Name : lpDevice
> #DefaultValue :
> #RawDefaultValue :
> #Position : 0
> #Attributes : None
> #Member : Boolean EnumDisplayDevices(System.String, UInt32,
> My5.DISPLAY_DEVICE ByRef, UInt32)
> #IsIn : False
> #IsOut : False
> #IsLcid : False
> #IsRetval : False
> #IsOptional : False
> #MetadataToken : 134217729
>
> #ParameterType : System.UInt32
> #Name : iDevNum
> #DefaultValue :
> #RawDefaultValue :
> #Position : 1
> #Attributes : None
> #Member : Boolean EnumDisplayDevices(System.String, UInt32,
> My5.DISPLAY_DEVICE ByRef, UInt32)
> #IsIn : False
> #IsOut : False
> #IsLcid : False
> #IsRetval : False
> #IsOptional : False
> #MetadataToken : 134217730
>
> #ParameterType : My5.DISPLAY_DEVICE&
> #Name : lpDisplayDevice
> #DefaultValue :
> #RawDefaultValue :
> #Position : 2
> #Attributes : None
> #Member : Boolean EnumDisplayDevices(System.String, UInt32,
> My5.DISPLAY_DEVICE ByRef, UInt32)
> #IsIn : False
> #IsOut : False
> #IsLcid : False
> #IsRetval : False
> #IsOptional : False
> #MetadataToken : 134217731
>
> #ParameterType : System.UInt32
> #Name : dwFlags
> #DefaultValue :
> #RawDefaultValue :
> #Position : 3
> #Attributes : None
> #Member : Boolean EnumDisplayDevices(System.String, UInt32,
> My5.DISPLAY_DEVICE ByRef, UInt32)
> #IsIn : False
> #IsOut : False
> #IsLcid : False
> #IsRetval : False
> #IsOptional : False
> #MetadataToken : 134217732
>
>
> --
> Whisperer
> .
>
 

My Computer

Top