1

I have been able to get the following code to work and would like to understand more about STRUCT and New-Object.

If I move the STRUCT (MyRect) inside of the CLASS (MyClass), how would I reference it? Right now, it is as follow (outside of the CLASS and at the same level) and it is works.

$Rectangle = New-Object MyRECT
    

I have tried moving it inside the CLASS but it errored out. Most likely a Struct should always be at the same level as a Class right? Regardless, is there a proper way of declaring this?

$Rectangle = New-Object [MyClass]::MyRECT

If there is anything that you would like to point out, in terms of practices, please let me know, such as which of the two methods below is better to use? Thanks

clear-host

$code = 
@'
    using System;
    using System.Runtime.InteropServices;
    
    public class MyClass
    {
        [DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out MyRECT lpRect);

        public static MyRECT Test3(int intHWND)
        {
            MyRECT TT = new MyRECT();
            GetWindowRect((System.IntPtr) intHWND, out TT);
            
            return TT;
        }
    }

    public struct MyRECT
    {
        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
    }
'@
Add-Type -TypeDefinition $Code

[Int]$HWND = (Get-Process -ID 9768).MainWindowHandle
$HWND

$oTest3 = [MyClass]::Test3($HWND)
$oTest3.Left
$oTest3.Top
$oTest3.Right
$oTest3.Bottom

$Rectangle = New-Object MyRECT
$null = [MyClass]::GetWindowRect([IntPtr]$HWND,[ref]$Rectangle)

$Rectangle.Left
$Rectangle.Top
$Rectangle.Right
$Rectangle.Bottom
7
  • 3
    Moving MyRECT inside the class is perfectly legal, but it would make the type name MyClass+MyRECT, which is then what you have to use in PowerShell (which is clumsy, but by design: you're mostly not expected to use nested types outside their declaring type). Despite how C# makes things appear, MyRECT does not in any way become a "member" of the class, it's just a scoping thing. Commented Sep 8, 2022 at 20:49
  • 1
    If it were me, I'd wrap everything up in the class, exposing its data as properties to the PowerShell code (while keeping the details of the struct private). I don't think you need to P/Invoke GetWindowRect to get the rect of an arbitrary window (though that probably means loading WinForms). You may want to look at my answer here: stackoverflow.com/questions/54834518/… if you want to create a full-on PowerShell module Commented Sep 8, 2022 at 20:55
  • @JeroenMostert and @FlyDog57, I am learning both PowerShell and C#. My main platform is SQL Server. As you can see from this code sample that I have provided, I learned how to do it from PowerShell calling an Win32 API but I spent the entire last night on learning how to do it through C# as well. Pat on my back because was very happy to get it to work and it was a last minute "what if" moment. So some of the terminologies are still new to me. I am not sure what P/Ivoke is but will look into it and your provided link. BTW...MyClass+MyRECT worked. Thank You for providing that! Commented Sep 8, 2022 at 21:26
  • 1
    Yeah, the link is a way to create a full-on PowerShell module (one you load into a PowerShell session just like any other module). If all you are doing is something simple, it's probably not worth the effort. But, if you are building a bunch of functionality, it's a very clean way of working in C#, but letting your users consume your work within PowerShell. The example I show is trivial. The only time I did this was to create a PowerShell configuration scripting language. Each operation updated configuration information inside SQL server that the main application consumed. Commented Sep 8, 2022 at 21:50
  • 1
    Follow the Red Gate link in my linked answer (red-gate.com/simple-talk/dotnet/net-development/…). It's a pretty simple tutorial. If you do it right, PowerShell is a wonderful scripting language that you can coopt to your needs. Commented Sep 8, 2022 at 21:58

1 Answer 1

1

Thanks to Jeroen Mostert, I am now able to move the STRUCT inside the class and reference it in PowerShell as:

$Rectangle = New-Object MyClass+MyRECT

clear-host

$code = 
@'
    using System;
    using System.Runtime.InteropServices;
    
    public class MyClass
    {
        [DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out MyRECT lpRect);

        public struct MyRECT
        {
            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
        }

        public static MyRECT Test3(int intHWND)
        {
            MyRECT TT = new MyRECT();
            GetWindowRect((System.IntPtr) intHWND, out TT);
            
            return TT;
        }
    }

'@
Add-Type -TypeDefinition $Code

[Int]$HWND = (Get-Process -ID 9768).MainWindowHandle
$HWND

$oTest3 = [MyClass]::Test3($HWND)
$oTest3.Left
$oTest3.Top
$oTest3.Right
$oTest3.Bottom

$Rectangle = New-Object MyClass+MyRECT
$null = [MyClass]::GetWindowRect([IntPtr]$HWND,[ref]$Rectangle)

$Rectangle.Left
$Rectangle.Top
$Rectangle.Right
$Rectangle.Bottom
Sign up to request clarification or add additional context in comments.

1 Comment

OK, I made the updates to the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.