separating struct RECT from class Win32

Welcome Forums General PowerShell Q&A separating struct RECT from class Win32

This topic contains 1 reply, has 2 voices, and was last updated by

 
Member
2 years, 1 month ago.

  • Author
    Posts
  • #53987

    Participant
    Points: 0
    Rank: Member

    Ok, guys, flame-off, I'm a newb, but really trying to understand this specific behavior.
    In my pursuit to manipulate windows (browsers, windows explorer, anything else) I came across the "Add-Type" to be able to use some c# types from .net or something (told you newb). The following works fine:

    if( -not ([System.Management.Automation.PSTypeName]'Win32').Type){
        Add-Type @"
          using System;
          using System.Runtime.InteropServices;
          public class Win32 {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
          }
          public struct RECT
          {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
          }
    "@
    }
    
    
    

    but....

    I thought it might be better to declare the struct RECT alone, since I may have it in other Add-Type's and use the "if" statement to not load it multiple times.

    Like this:

    if( -not ([System.Management.Automation.PSTypeName]'RECT').Type){
        Add-Type @"
          using System;
          using System.Runtime.InteropServices;    
          public struct RECT
          {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
          }
    "@
    }
    
    
    

    and then use the other Win32 Add-Type separately as well, like this:

    
    

    if( -not ([System.Management.Automation.PSTypeName]'Win32').Type){
    Add-Type @"
    using System;
    using System.Runtime.InteropServices;
    public class Win32 {
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
    }
    "@
    }

    
    

    However, when I do this I get the following error:

    Add-Type : c:\Users\Mike\AppData\Local\Temp\xh0guzhy.0.cs(6) : The type or namespace name 'RECT' could not be found (are you missing a using directive or
    an assembly reference?)
    c:\Users\Mike\AppData\Local\Temp\xh0guzhy.0.cs(5) : [return: MarshalAs(UnmanagedType.Bool)]
    c:\Users\Mike\AppData\Local\Temp\xh0guzhy.0.cs(6) : >>> public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    c:\Users\Mike\AppData\Local\Temp\xh0guzhy.0.cs(7) : [DllImport("user32.dll")]
    At C:\Users\Mike\Jobs\MeridianLink\Tickets\Tickets\Tickets\special_add_type.ps1:18 char:5
    + Add-Type @"
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidData: (c:\Users\Mike\A...bly reference?):CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    I obviously don't know what is really going on here, and if someone could be kind enough to either explain this or give me a clue, I would be most appreciative.

    I don't like "just" using something because it works and I don't understand why.

    Thanks to the forum upfront.

    Mike

  • #54018

    Member
    Points: 0
    Rank: Member

    When you separate the Add-Type calls like that, PowerShell would be able to use both types just fine, but the Win32 class wouldn't know anything about the RECT structure (which is why you get compilation errors). C# is strict about that sort of thing.

    You technically can make it work by using the -OutputAssembly and -ReferencedAssemblies parameters when calling Add-Type, but that can get kind of ugly:

    if( -not ([System.Management.Automation.PSTypeName]'RECT').Type){
        Add-Type -OutputAssembly $env:temp\RectAssembly.dll @"
          public struct RECT
          {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
          }
    "@
    }
    
    if( -not ([System.Management.Automation.PSTypeName]'Win32').Type){
        Add-Type -ReferencedAssemblies $env:temp\RectAssembly.dll @"
          using System;
          using System.Runtime.InteropServices;
          public class Win32 {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
          }
    "@
    }
    

The topic ‘separating struct RECT from class Win32’ is closed to new replies.