Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing ref type to methods using invocation within Powershell

48 views
Skip to first unread message

Whisperer

unread,
May 13, 2010, 1:33:26 PM5/13/10
to

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####

$source=@"
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

Bob Landau

unread,
May 14, 2010, 9:52:06 AM5/14/10
to
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:

> .
>

0 new messages