springstil
Goto Top

Mit Powershell Farbe aus Fenster auslesen

Hallo zusammen,

ich schreib mir in Powershell zur zeit nen Watchdog der aufpassen soll ob ein Programm noch läuft. Das Programm ist teil einer alten Warenwirtschaft und läuft in einem Dos Fenster (Clipper)

um es kurz zu machen :D würde ich gerne ein bestimmtes Fenster so auslesen und abfragen ob sich ein Rotes Fenster darin befindet. Dieses Rote Fenster ist quasi eine Fehlermeldung. Darauf hin würde ich mich dann benachrichtigen lassen. Aber gibt es überhaupt die Möglichkeit die Farbe mit Hilfe von Powershell auszulesen?

Content-ID: 6369435598

Url: https://administrator.de/contentid/6369435598

Ausgedruckt am: 24.11.2024 um 10:11 Uhr

godlie
godlie 14.03.2023 um 21:07:38 Uhr
Goto Top
Hallo,

hm da würde mir folgendes einfallen:

Alle x mins einen Screenshot erstellen, Bereich beschneiden, auswerten ob Rot im Bereich vorkommt

grüße
Springstil
Springstil 14.03.2023 um 21:17:21 Uhr
Goto Top
wie kann ich denn den Bereich nach einer farbe "absuchen"?
godlie
godlie 14.03.2023 um 21:32:35 Uhr
Goto Top
Crusher79
Crusher79 14.03.2023 um 21:44:59 Uhr
Goto Top
Screenshot selber schreiben doer was von ratiopharm nehmen:

https://www.powershellgallery.com/packages/RoughDraft/0.1/Content/Get-Sc ...

Das wäre es schon fast.

https://www.nirsoft.net/utils/gui_prop_view.html

/Action Command-Line Option
/Action is a powerful command that allows you to do many things (Hide, show, disable, enable, and more...) on the desired windows, according to their properties (Class Name, Title, Process, and so on...) 


Naja wäre ja cool wenn das Ding immer an der gleichen Stelle ist. Ginge auch mit PS. Nirsoft hat aber schöne kleine Tools. Ggf. magst du es kombinieren.
6247018886
Lösung 6247018886 14.03.2023 um 22:40:43 Uhr
Goto Top
Springstil
Springstil 14.03.2023 um 22:55:41 Uhr
Goto Top
Zitat von @6247018886:

Bildschirmbereich überwachen - E-Mail

Cheers briggs

Danke :D Ich habe gehoft das es ohne Autoit hin bekomme. AutoIt ist dann schon was länger her bei mir ^^ aber werds mir mal anschauen vielen dank. Vermutlich ist das dass einfachste.
6247018886
6247018886 14.03.2023 aktualisiert um 23:31:41 Uhr
Goto Top
Klar kannst du auch PS nehmen
PS kann sich ja sämtlicher .NET Funktionen bedienen
Graphics.CopyFromScreen Methode
add-type -a System.Drawing
$bm = New-Object System.Drawing.Bitmap 1,1
[System.Drawing.Graphics]::FromImage($bm).CopyFromScreen(200,200,0,0,[System.Drawing.Size]::new(1,1))
$pixel = $bm.GetPixel(0,0)
Rest solltest du dann auch noch hin bekommen, soll dir ja keiner den Spaß verderben 😉
colinardo
Lösung colinardo 15.03.2023 aktualisiert um 11:47:48 Uhr
Goto Top
Servus @Springstil,
gerade mal schnell was mit Powershell zusammengelötet (Prozess und abzufragende Pixel-Koordinate weiter unten anpassen / Kommentare siehe Code).
Add-Type -A System.Drawing
# function to get pixel color from main application window
function Get-PixelColorFromAppWindow {
    [cmdletbinding()]
    param(
        [Parameter(mandatory=$true,ValueFromPipelineByPropertyName=$true)][Alias('Name')][string]$application,  
        [Parameter(mandatory=$true)][System.Drawing.Point]$point
    )
    begin{
        $ErrorActionPreference = 'Stop'  
        if (!('w32.tools' -as [type])){  
            Add-Type -Namespace w32 -Name tools -ReferencedAssemblies 'System.Drawing' –MemberDefinition '  
                [StructLayout(LayoutKind.Sequential)]
                public struct RECT
                {
                    public int left;
                    public int top;
                    public int right;
                    public int bottom;
                }
                [StructLayout(LayoutKind.Sequential)]
                public struct WINDOWPLACEMENT
                {
                    public int length;
                    public int flags;
                    public int showCmd;
                    public System.Drawing.Point ptMinPosition;
                    public System.Drawing.Point ptMaxPosition;
                    public RECT rcNormalPosition;
                    public RECT rcDevice;
                }
                [DllImport("user32.dll")] public static extern bool SetForegroundWindow (IntPtr hWnd);  
                [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow ();  
                [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);  
                [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);  
                [DllImport("user32.dll")] public static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);  
            '  
        }
        $img = [System.Drawing.Bitmap]::new(1,1)
    }
    process{
        try{
            # try get application process
            $app = Get-Process -Name ([IO.Path]::GetFileNameWithoutExtension($application)) -EA Stop | ? MainWindowhandle -ne 0 | select -F 1
            # get main window handle
            $winhandle = $app.MainWindowHandle
            if(!$winhandle){
                throw "No main window handle found for process '$application'."  
                return
            }
            # get current top window and state (to restore it's state) 
            $orig_tophandle = [W32.Tools]::GetForegroundWindow()
            $orig_state = New-Object w32.tools+WINDOWPLACEMENT
            [void][W32.Tools]::GetWindowPlacement($winhandle,[ref]$orig_state)

            # set applications window on top
            [void][W32.Tools]::ShowWindow($winhandle,9)
            [void][W32.Tools]::SetForegroundWindow($winhandle)
            sleep -Milliseconds 50
    
            # get window position on screen 
            $winpos = New-Object w32.tools+RECT
            [void][W32.Tools]::GetWindowRect($winhandle,[ref]$winpos)
            # copy desired pixel of window to image
            [System.Drawing.Graphics]::FromImage($img).CopyFromScreen($winpos.left+$point.X,$winpos.top+$point.Y,0,0,[System.Drawing.Size]::new(1,1))
            $pixel = $img.GetPixel(0,0)
            # restore top window and state of app
            if ($orig_tophandle -ne [System.IntPtr]::Zero){
                [void][W32.Tools]::SetForegroundWindow($orig_tophandle)
            }
            if ($orig_state.showCmd){
                [void][W32.Tools]::ShowWindow($winhandle,$orig_state.showCmd)
            }
            return $pixel | select @{n='Application';e={$application}},*  
        }catch{
            Write-Error -Message $_.Exception.Message
        }finally{
            if ($img){$img.Dispose()}
        }
    }
}
# define process of window
$app = 'cmd.exe'  
# define pixel coordinates (x,y) inside applications main window (coords are relative to windows top left corner)
$app_coordinates = '200,200'  
# get color from application window at defined position
$color = Get-PixelColorFromAppWindow $app -point $app_coordinates
# check if color meets the requirements (this example matches the color to be at most red)
if ($color.R -gt 200 -and $color.G -lt 100 -and $color.B -lt 100){
    write-host "Red color detected at Pixel $app_coordinates of application" -F Green  
}else{
    write-host "No red color found at Pixel '$app_coordinates' of application" -F Yellow  
}
# output detected color for reference
$color
Grüße Uwe