1

Im making a web app that turns of computer everytime its not visible to COM (component object model)

Exception setting "ObjectForScripting": "ObjectForScripting's class must be visible to COM. Verify that the object is public, or consider adding the ComVisible attribute to your class." At C:\Users\kayde\window.ps1:99 char:1

  • $webBrowser.ObjectForScripting = $scriptBlock
  •   + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
      + FullyQualifiedErrorId : ExceptionWhenSetting
    

I tried using C#:

Add-Type -AssemblyName System.Windows.Forms

# Define the .NET class directly in PowerShell with ComVisible attribute
$scriptBlock = {
    Add-Type @"
    using System;
    using System.Runtime.InteropServices;

    [ComVisible(true)]
    public class ActionHandler
    {
        public void HandleAction(string action)
        {
            switch (action)
            {
                case "PowerOff":
                    System.Diagnostics.Process.Start("shutdown.exe", "/s /f /t 0");
                    break;
                case "Reboot":
                    System.Diagnostics.Process.Start("shutdown.exe", "/r /f /t 0");
                    break;
                case "Restart":
                    System.Diagnostics.Process.Start("shutdown.exe", "/r /f /t 0");
                    break;
            }
        }
    }
"@ -PassThru
}

# Create the form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Power options"
$form.MaximumSize = New-Object System.Drawing.Size(300, 240)
$form.Size = New-Object System.Drawing.Size(250, 180) 
$form.MinimumSize = New-Object System.Drawing.Size(250, 180)
$form.ShowIcon = $false

# Create the WebBrowser control
$webBrowser = New-Object System.Windows.Forms.WebBrowser
$webBrowser.Dock = [System.Windows.Forms.DockStyle]::Fill

# Load HTML content into the WebBrowser control
$htmlContent = @"
<!DOCTYPE html>
<html>
<head>
    <title>Power options</title>
</head>
<body>

    <button id="a">
        Power
    </button><br>
    <button id="b">
        Reboot
    </button><br>
    <button id="c">
        Restart
    </button><br>
    <style>
        body {
            font-family: Verdana, Geneva, Tahoma, sans-serif;
            background-color: black;
        }

        button {
            color: blue;
            background-color: black;
            border: 1px solid blue;
            margin-left: 8px;
        }
    </style>
    <script>
        // Function to send message to PowerShell script
        function sendAction(action) {
            window.external.HandleAction(action);
        }

        // Attach click event handlers to the buttons
        document.getElementById("a").attachEvent("onclick", function() {
            sendAction("PowerOff");
        });

        document.getElementById("b").attachEvent("onclick", function() {
            sendAction("Reboot");
        });

        document.getElementById("c").attachEvent("onclick", function() {
            sendAction("Restart");
        });
    </script>
</body>
</html>
"@

# Set the HTML content and object for scripting for the WebBrowser control
$webBrowser.DocumentText = $htmlContent
$webBrowser.ObjectForScripting = $scriptBlock

# Add the WebBrowser control to the form
$form.Controls.Add($webBrowser)

# Show the form
$form.ShowDialog() | Out-Null

maybe instead of using COM I could use ICP(inter communication protocol)

I tried and was expecting it to power of computer on windows 11

1
  • 2
    Why are you assigning $scriptBlock to $webBrowser.ObjectForScripting? Sounds like you'll want to execute the scriptblock, and then create and pass an instance of the ActionHandler type instead (eg. $webBrowser.ObjectForScripting = (&$scriptBlock)::new()) Commented Apr 2, 2024 at 16:59

1 Answer 1

1

As hinted in the comments, the problem here is that you're assigning an object of type [scriptblock] to $webBrowser.ObjectForScripting.

My guess is that you'll want to assign an instance of the ActionHandler class instead - so invoke the scriptblock to compile the type, then create an instance and assign that:

# invoke scriptblock, store resulting type
$handlerType = & $scriptBlock

# create a new instance of the ActionHandler type
$myActionHandler = $handlerType::new()

# assign to target property
$webBrowser.ObjectForScripting = $myActionHandler
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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