Array mit Prozessen
Moderator: wriedmann
Array mit Prozessen
ich versuche meine VO apps mit dem XPorter nach X# zu transportieren, bei den Spielerei apps kein Problem. Jetzt bin ich aber bei einer etwas anspruchsvolleren app angelangt, wo ich an 2 Stellen Probleme bekomme:
1) Delegate bei EnumWindows
aWindows := ArrayCreate(1024)
aWindows[1] := 0 // Anzahl der ermittelten Elemente
aWindows[2] := 1024 // maximale Anzahl der Elemente
aWindows[3] := 3 // Startelement-1
#warning Callback function modified to use a DELEGATE by xPorter. Please review.
// EnumWindows(@OGS_EnumAddItemToArray(),LONGINT(_CAST,aWindows))
STATIC LOCAL oOGS_EnumAddItemToArrayDelegate := OGS_EnumAddItemToArray AS OGS_EnumAddItemToArray_Delegate
EnumWindows(System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(oOGS_EnumAddItemToArrayDelegate),LONGINT(_CAST,aWindows))
Die XIDE Meldungen dazu:
warning XS1030: Callback function modified to use a delegate ...
error XS0030 Cannot convert type ARRAY to INT
2) Die Umformung auf Delegate erhalte ich auch bei einer anderen Callback-Methode mit der ich ein Verzeichnis überwache:
#warning Callback function modified to use a DELEGATE by xPorter. Please review.
// ptrCallBack := @RunMethodWaitForChanges()
STATIC LOCAL oRunMethodWaitForChangesDelegate := RunMethodWaitForChanges AS RunMethodWaitForChanges_Delegate
ptrCallBack := System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(oRunMethodWaitForChangesDelegate)
Was genau machen die Delegates, kann man den Code so lassen wie ihn der XPorter erstellt hat oder ist da noch etwas zu machen?
Wie ist der Fehler XS0030 zu korrigieren?
1) Delegate bei EnumWindows
aWindows := ArrayCreate(1024)
aWindows[1] := 0 // Anzahl der ermittelten Elemente
aWindows[2] := 1024 // maximale Anzahl der Elemente
aWindows[3] := 3 // Startelement-1
#warning Callback function modified to use a DELEGATE by xPorter. Please review.
// EnumWindows(@OGS_EnumAddItemToArray(),LONGINT(_CAST,aWindows))
STATIC LOCAL oOGS_EnumAddItemToArrayDelegate := OGS_EnumAddItemToArray AS OGS_EnumAddItemToArray_Delegate
EnumWindows(System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(oOGS_EnumAddItemToArrayDelegate),LONGINT(_CAST,aWindows))
Die XIDE Meldungen dazu:
warning XS1030: Callback function modified to use a delegate ...
error XS0030 Cannot convert type ARRAY to INT
2) Die Umformung auf Delegate erhalte ich auch bei einer anderen Callback-Methode mit der ich ein Verzeichnis überwache:
#warning Callback function modified to use a DELEGATE by xPorter. Please review.
// ptrCallBack := @RunMethodWaitForChanges()
STATIC LOCAL oRunMethodWaitForChangesDelegate := RunMethodWaitForChanges AS RunMethodWaitForChanges_Delegate
ptrCallBack := System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(oRunMethodWaitForChangesDelegate)
Was genau machen die Delegates, kann man den Code so lassen wie ihn der XPorter erstellt hat oder ist da noch etwas zu machen?
Wie ist der Fehler XS0030 zu korrigieren?
Delegates
Hallo Franz,
das, was man in VO mit Callbacks so machen konnte, war sehr gefährlich. Daher lässt .NET das so auch nicht mehr zu.
Ein Delegate ist im Prinzip die Typisierung eines Funktions-Pointers, die sicherstellt, dass nur eine passende Funktionsadresse zurückgegeben werden kann.
Der XPorter macht hier, was er kann - und setzt explizit ein Warning an diese Stelle, mit der Aufforderung, diesen Code zu überprüfen. Denn eine komplett automatisierte Umsetzung ist nicht möglich - da eben auf VO-Seite diese Typisierung fehlt.
Kannst Du mal Deinen VO-Code zeigen?
Dann wird Dir sicher jemand zeigen, wie man den korrekt nach X# umsetzt.
Wolfgang
P.S. mein Code für EnumWindows schaut so aus (mit Hilfe von Chris):
das, was man in VO mit Callbacks so machen konnte, war sehr gefährlich. Daher lässt .NET das so auch nicht mehr zu.
Ein Delegate ist im Prinzip die Typisierung eines Funktions-Pointers, die sicherstellt, dass nur eine passende Funktionsadresse zurückgegeben werden kann.
Der XPorter macht hier, was er kann - und setzt explizit ein Warning an diese Stelle, mit der Aufforderung, diesen Code zu überprüfen. Denn eine komplett automatisierte Umsetzung ist nicht möglich - da eben auf VO-Seite diese Typisierung fehlt.
Kannst Du mal Deinen VO-Code zeigen?
Dann wird Dir sicher jemand zeigen, wie man den korrekt nach X# umsetzt.
Wolfgang
P.S. mein Code für EnumWindows schaut so aus (mit Hilfe von Chris):
Code: Select all
function XSGetWindowsArray() as array pascal
local aWindows as array
local oGCHandle as System.Runtime.InteropServices.GCHandle
local oPtr as IntPtr
local oDelegate as EnumWindowsProc_delegate
static local oEnumWindowsProcDelegate := EnumWindowsProc as EnumWindowsProc_Delegate
aWindows := {}
oDelegate := EnumWindowsProc
oGCHandle := System.Runtime.InteropServices.GCHandle.Alloc( aWindows )
oPtr := System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( oDelegate )
EnumWindows( oPtr, System.Runtime.InteropServices.GCHandle.ToIntPtr( oGCHandle ) )
return aWindows
delegate EnumWindowsProc_delegate( hWnd as ptr, aWindows as array ) as word
function EnumWindowsProc(hwnd as ptr, lParam as IntPtr) as logic
local aWindows as array
local gch as System.Runtime.InteropServices.GCHandle
gch := System.Runtime.InteropServices.GCHandle.FromIntPtr(LParam)
aWindows := (array)gch:Target
AAdd( aWindows, hwnd )
return true
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Delegates
Wolfgang,
Your code does not show that so I am not sure if you have it, but when you call GCHandle.Alloc() you also need to call GcHandle.Free() on the oGcHandle that was returned by GcHandle.Alloc(), or otherwise you have introduced a memory leak.
Robert
Your code does not show that so I am not sure if you have it, but when you call GCHandle.Alloc() you also need to call GcHandle.Free() on the oGcHandle that was returned by GcHandle.Alloc(), or otherwise you have introduced a memory leak.
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
Delegates
Hi Robert,
you can be sure that there is no GcHandle.Free - clearly an error of mine.
Thank you very much!
I will add it immediatly.
Wolfgang
P.S. this is the fixed code:
you can be sure that there is no GcHandle.Free - clearly an error of mine.
Thank you very much!
I will add it immediatly.
Wolfgang
P.S. this is the fixed code:
Code: Select all
function XSGetWindowsArray() as array pascal
local aWindows as array
local oGCHandle as System.Runtime.InteropServices.GCHandle
local oPtr as IntPtr
local oDelegate as EnumWindowsProc_delegate
static local oEnumWindowsProcDelegate := EnumWindowsProc as EnumWindowsProc_Delegate
aWindows := {}
oDelegate := EnumWindowsProc
oGCHandle := System.Runtime.InteropServices.GCHandle.Alloc( aWindows )
oPtr := System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( oDelegate )
EnumWindows( oPtr, System.Runtime.InteropServices.GCHandle.ToIntPtr( oGCHandle ) )
oGCHandle:Free()
return aWindows
delegate EnumWindowsProc_delegate( hWnd as ptr, aWindows as array ) as word
function EnumWindowsProc(hwnd as ptr, lParam as IntPtr) as logic
local aWindows as array
local gch as System.Runtime.InteropServices.GCHandle
gch := System.Runtime.InteropServices.GCHandle.FromIntPtr(LParam)
aWindows := (array)gch:Target
AAdd( aWindows, hwnd )
return true
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Delegates
Hallo Wolfgang,
ich ermittle mit dieser Funktion in VO die Titel der laufenden Programme, vielleicht gibt es dafür bereits eine fertige Funktion für X#, der Aufruf gibt ein Array der Titel zurück: aWin := OGS_EnumWindows()
ich ermittle mit dieser Funktion in VO die Titel der laufenden Programme, vielleicht gibt es dafür bereits eine fertige Funktion für X#, der Aufruf gibt ein Array der Titel zurück: aWin := OGS_EnumWindows()
Code: Select all
FUNCTION OGS_EnumWindows() AS ARRAY PASCAL // ohne Fehlerabfrage bei mehr als 1024 Tasks!
LOCAL aWindows AS ARRAY
aWindows := ArrayCreate(1024)
aWindows[1] := 0 // Anzahl der ermittelten Elemente
aWindows[2] := 1024 // maximale Anzahl der Elemente
aWindows[3] := 3 // Startelement-1
EnumWindows(@OGS_EnumAddItemToArray(),LONGINT(_CAST,aWindows))
aWindows := ADel(aWindows,1) // Vorspann entfernen (3 Elemente)
aWindows := ADel(aWindows,1)
aWindows := ADel(aWindows,1)
aWindows := ASize(aWindows,ALen(aWindow)-3)
RETURN aWindows
STATIC FUNCTION OGS_EnumAddItemToArray(ptrWnd AS PTR , aWindows AS ARRAY) AS WORD CALLBACK
IF aWindows[1] <= aWindows[2] // Anzahl Elemente <= Max. Anzahl Elemente?
aWindows[++aWindows[3]] := ptrWnd // Handle abspeichern
aWindows[1] := ++aWindows[1] // Anzahl erhöhen
ELSE // Array zu klein dimensioniert?
aWindows[1] := -1 // Fehlercode retour
RETURN 0
ENDIF
RETURN 1
Delegates
Hallo Franz,
die Funktion, die ich weiter oben reingeschrieben habe, gibt Dir ein Array aller Handles aller Fenster zurück. Und das ist genau das, was Deine Funktion auch macht.
Wolfgang
die Funktion, die ich weiter oben reingeschrieben habe, gibt Dir ein Array aller Handles aller Fenster zurück. Und das ist genau das, was Deine Funktion auch macht.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Delegates
Franz,
One of the very good things about .Net, is that there is a huge amount of people using it, so any question you have, has already been answered somewhere before. So, for whatever you are looking for, just search for it, I guarantee you you will find it! Just a tip, it usually helps to include "c#' as a term in your search, to make sure you get results regarding .Net. The results will be showing c# code, but it will be usually very easy to translate to X#.
So for this specific case, I opened googled and entered this search text: "c# get all apps working". This gave those results to me:
https://www.google.gr/search?ei=8Gz6XYK ... CAo&uact=5
The very first search results is: https://stackoverflow.com/questions/204 ... in-windows
Follow this, and you will see immediately the solution, you need to use Process.GetProcesses() to get an array of all processes currently running in the system. Admittedly, this specific answer is incomplete, it does not mention that the namespace of the Process class is System.Diagnostics, so you would actually need to use System.Diagnostics.Process.GetProcesses() or
USING System.Diagnostics
Process.GetProcesses()
And here's a "complete" sample:
As you can see, a lot of things (with some very notable exceptions though) can be done in .Net in A LOT easier and in a more intuitive way than what we were used to in VO!
One of the very good things about .Net, is that there is a huge amount of people using it, so any question you have, has already been answered somewhere before. So, for whatever you are looking for, just search for it, I guarantee you you will find it! Just a tip, it usually helps to include "c#' as a term in your search, to make sure you get results regarding .Net. The results will be showing c# code, but it will be usually very easy to translate to X#.
So for this specific case, I opened googled and entered this search text: "c# get all apps working". This gave those results to me:
https://www.google.gr/search?ei=8Gz6XYK ... CAo&uact=5
The very first search results is: https://stackoverflow.com/questions/204 ... in-windows
Follow this, and you will see immediately the solution, you need to use Process.GetProcesses() to get an array of all processes currently running in the system. Admittedly, this specific answer is incomplete, it does not mention that the namespace of the Process class is System.Diagnostics, so you would actually need to use System.Diagnostics.Process.GetProcesses() or
USING System.Diagnostics
Process.GetProcesses()
And here's a "complete" sample:
Code: Select all
USING System.Diagnostics
FUNCTION Start() AS VOID
FOREACH oProcess AS Process IN Process.GetProcesses()
? "Process name:", oProcess:ProcessName
? "Process title:", oProcess:MainWindowTitle
NEXT
RETURN
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Delegates
Hi Chris,
I cannot agree more.... and therefore my VO applications are using more and more COM modules.
One of the latest things is that I'm using COM modules to access data from different SQL engines, from SQLite, MS SQL, MySQL to PostgreSQL. And why? Because using a .NET connection I don't need any configuration on the cxlient machine - only a few .NET DLLs. No more ODBC hassles or driver installations....
Wolfgang
I cannot agree more.... and therefore my VO applications are using more and more COM modules.
One of the latest things is that I'm using COM modules to access data from different SQL engines, from SQLite, MS SQL, MySQL to PostgreSQL. And why? Because using a .NET connection I don't need any configuration on the cxlient machine - only a few .NET DLLs. No more ODBC hassles or driver installations....
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Delegates
Hi Chris
is there a FOREACH in XSharp? How can I do this without FOREACH?
This is my code but I think its not the best
is there a FOREACH in XSharp? How can I do this without FOREACH?
This is my code but I think its not the best
Code: Select all
LOCAL oProcess AS OBJECT
LOCAL x AS DWORD
FOR x := 1 TO ALen(Process.GetProcesses())
oProcess := Process.GetProcesses()[x]
? oProcess:ProcessName
NEXT
Delegates
Hi Franz,
there is a foreach in X# - the code Chris has given you IS X# code.
Process.GetProcesses() is documented here:
https://docs.microsoft.com/en-us/dotnet ... mework-4.8
It returns an array - but a .NET array, ALen() does not works.
Wolfgang
there is a foreach in X# - the code Chris has given you IS X# code.
Process.GetProcesses() is documented here:
https://docs.microsoft.com/en-us/dotnet ... mework-4.8
It returns an array - but a .NET array, ALen() does not works.
Code: Select all
local aProcess as Process[]
local nI as int
local nLen as int
aProcess := Process.GetProcesses()
nLen := aProcess:Length
for nI := 1 upto nLen
? "Process name:", aProcess[nI]:ProcessName
? "Process title:", aProcess[nI]:MainWindowTitle
next
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it