separating struct RECT from class Win32

Tagged: 

This topic contains 1 reply, has 2 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 2 weeks, 4 days ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #53987
    Profile photo of Mike Muller
    Mike Muller
    Participant

    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

    • This topic was modified 2 weeks, 5 days ago by Profile photo of Mike Muller Mike Muller. Reason: added
    #54018
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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);
          }
    "@
    }
    
Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.