Zugriff auf COM Methode

  • Hallo und guten Tag,

    auf COM Objekte zuzugreifen ist ja in AutoIt3 normalerweise die kleinste Übung, aber bei der Übersetzung nachfolgenden Matlab- Codes scheitere ich.


    function XYZ = GetXYZCoordinates(filename, point)

    %

    file = actxserver('PolyFile.PolyFile');

    try

    file.Open(filename);

    measpoints = file.Infos.MeasPoints;

    if (point == 0)

    XYZ=zeros(measpoints.count,3);

    for i=1:measpoints.count

    measpoint=measpoints.Item(int32(i));

    [X,Y,Z]=measpoint.CoordXYZ();

    XYZ(i,:)=[X,Y,Z];

    end

    else

    measpoint=measpoints.Item(int32(point));

    [X,Y,Z]=measpoint.CoordXYZ();

    XYZ=[X,Y,Z];

    end

    file.Close();

    delete(file);

    catch

    if file.IsOpen == 1

    file.Close();

    end

    delete(file);

    rethrow(lasterror);

    end

    und zwar an der Stelle [X,Y,Z]=measpoint.CoordXYZ();

    Der Basic Header der Methode sieht so aus

    Public Sub CoordXYZ( _

    ByRef pdX As Double, _

    ByRef pdY As Double, _

    ByRef pdZ As Double _

    )

    Das heisst diese Methode erzeugt drei "Double" die mit "BeRef" übergeben werden.
    Der erste naive Ansatz das mit dem Autoit "ByRef" zu machen funzt natürlich nicht, aber auch wenn man es mit z.B. mit

    Local Const $tagXYZ = "struct;double"

    Local $tX = DllStructCreate($tagXYZ)

    Local $tY = DllStructCreate($tagXYZ)

    Local $tZ = DllStructCreate($tagXYZ)

    &

    $measpoint.CoordXYZ($tX,$tY,$tZ)

    versucht klappt es leider nicht.

    Vielen Dank für dioe Aufmerksamkeit & VG
    Lutz

  • Hab nur kurz draufgeschaut, sollte das nicht in einer Struct landen?

    AutoIt
    $tagXYZ = "double X;double Y;double Z;" 

    Hallo BugFix,

    danke für die schnelle Antwort, ich habe es mal wie nachfolgend probiert:


    $svdfile = "SA_01_left.svd"

    Func GetXYZCoordinates($filename) ;, $domainname, $channelname, $signalname, $displayname, $point, $frame)

    Local $i, $measpoint, $dummy, $X, $Y, $Z

    Local Const $tagXYZ = "double X;double Y;double Z;"

    Local $tXYZ = DllStructCreate($tagXYZ)

    Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")

    Local $file = ObjCreate("PolyFile.PolyFile")

    Local $dummy = $file.Open($filename)

    ; Local $dummy = $file.ReadOnly(0)

    $measpoints = $file.Infos.MeasPoints

    ; $pointdomains = $file.GetPointDomains()

    ; $pointdomain = pointdomains.Item($domainname);

    ; $channel = pointdomain.Channels.Item($channelname);

    ; $signal = channel.Signals.Item($signalname);

    ; $display = signal.Displays.Item(displayname);

    For $i = 1 to $measpoints.Count

    writeln($i)

    $measpoint = $measpoints.Item(Int(2,1))

    $measpoint.CoordXYZ($tXYZ)

    Next

    EndFunc

    GetXYZCoordinates($svdfile)



    Leider mit der Meldung ->

    "O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\00.au3" (34) : ==> The requested action with this object has failed.:

    $measpoint.CoordXYZ($tXYZ)

    $measpoint^ ERROR

    Das heist der Objekt ist da, aber kann nicht angesprochen weden. VG Lutz

  • Hänge mal einen COM Error Handler in Dein Skript. Du kriegst dann viel bessere Fehlerinformationen.

    Wie das geht, steht in der Hilfe unter ObjEvent.

  • Ich nehme mal an, dass die Struktur als Pointer zu übergeben ist.

    AutoIt
    $tagXYZ = "double X;double Y;double Z;" 
    $tXYZ = DllStructCreate($tagXYZ)
    $pXYZ = DllStructGetPtr($tXYZ)
    ; Diesen Pointer kannst du an die Funktion übergeben

    Das heist der Objekt ist da, aber kann nicht angesprochen weden. VG Lutz

    Ob das Objekt vorhanden ist würde ich mit IsObj prüfen. Ich denke da liegt ein Objektfehler vor, weil die Methode nicht als solche erkannt wird. Also bau, wie von water empfohlen, den COM-Error-Handler ein.

    P.S. Bitte nutze für Codeblöcke nicht den Inline-Code, sondern </> aus dem Menü.


    EDIT:

    Ich habe mir jetzt die Matlabfunktion mal näher angeschaut. Vorab: Von Matlab habe ich keine Ahnung. Aber ich würde das so umsetzen (eine Zeile kann ich jedoch nicht interpretieren, da ist mir unklar was in Matlab passiert - ist markiert)

  • BugFix & water

    ich habe eure Vorschläge noch nicht umgesetzt werde es gleich machen und dann berichten. Herzlich bedanken möchte ich mich aber schon jetzt, mit soviel positiver Resonanz habne ich nicht gerechnet. :)

    OT: Diese Funktion und auch andere werden benötigt über COM Messdaten aus einer Datei zu ziehen, die mit einem Laservibrometer-Software erstellt wurden. Phyton, Matlab, .NET Lösungen sind vorhanden, ich möchte aber für so etwas mein Schweizer-Taschenmesser Autoit weiter nutzen. Das ist übrigns so ziemlcih die einzige Anwendung die ich als nun Linux Anwender unter wine weiterhin nutze, da läuft fast alles ausser USB Unterstützung und eben COM was auf .NET (>4.6) aufsetzt.

  • Ich habe gerade mal euere Vorschläge berücksichtigt, und auf Grundllage der Funktion von Bugfix um gesetzt. Herraus kommt eine braucbare Fehlermeldung, die ich so interpretiere das man der Methode GetXYZ() "nur" was sinnvolles in den Klammern vorgeben muss. VG Lutz

    >"C:\Program Files (x86)\AutoIt3\SciTE\..\AutoIt3.exe" "C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\01.au3" /UserParams

    +>07:54:45 Starting AutoIt3Wrapper (21.316.1639.1) from:SciTE.exe (4.4.6.0) Keyboard:00000407 OS:WIN_10/2009 CPU:X64 OS:X64 Environment(Language:0407) CodePage:0 utf8.auto.check:4

    +> SciTEDir => C:\Program Files (x86)\AutoIt3\SciTE UserDir => C:\Users\Lutz\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper SCITE_USERHOME => C:\Users\Lutz\AppData\Local\AutoIt v3\SciTE

    >Running AU3Check (3.3.14.5) from:C:\Program Files (x86)\AutoIt3 input:O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\01.au3

    +>07:54:45 AU3Check ended.rc:0

    >Running:(3.3.14.5):C:\Program Files (x86)\AutoIt3\autoit3.exe "O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\01.au3"

    +>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart or Ctrl+BREAK to Stop.

    01.au3 (20) : ==> COM Error intercepted !

    err.number is: 0x8002000E

    err.windescription: Unzulässige Parameteranzahl.

    err.description is:

    err.source is:

    err.helpfile is:

    err.helpcontext is:

    err.lastdllerror is: 0

    err.scriptline is: 20

    err.retcode is: 0x00000000

    +>07:55:18 AutoIt3.exe ended.rc:0

    +>07:55:18 AutoIt3Wrapper Finished.

    >Exit code: 0 Time: 33.37

  • Poste am Besten auch die Python und .NET Lösung. Damit können wir vermutlich noch mehr anfangen.

    Ausser den Matlab Modulen ist in den anderen Programmiersprachen die Lösung viel zu komlex, die fragen da nämlich nicht nur die Ortskoordinaten eines Messpunkts ab, sondern noch ein paar andere "lustige" sachen, mit dennen ich mich aber erst dann beschäftige wenn das ganz einfache läuft.

    Gefunden habe ich auf github eine relativ einfache Phyton Umsetzung die u.a. anderen auch dieses GetXYZ benutzt.

    EDIT BugFix: Code in Code-Tags gepackt

  • eine relativ einfache Phyton Umsetzung

    Nochmal die dringende Bitte: IMMER Code in Code-Markierung posten! Als Plain Text geht die Formatierung (und somit jeder Indent) verloren, was Python nahezu unleserlich macht.

    Ich habe jetzt mal geraten, wo die Einrückungen hingehören und in deinem Post editiert - bitte prüfe (und ggf. korrigiere) das.

    EDIT: Noch hilfreicher wäre, wenn es eine Objektbeschreibung gäbe (Methods /Parameter, Properties)

  • Hallo nochmal, das Problem scheint gelöst, und zwar mit einer ganz trivialen Umsetzung (einzelner Messpunkt) ->

    Local $X, $Y, $Z

    $measpoint = $measpoints.Item($point)

    $measpoint.CoordXYZ($X,$Y,$Z)

    $aXYZ[0] = $X

    $aXYZ[1] = $Y

    $aXYZ[2] = $Z

    $oPolyFile.Close()

    AutoIt scheint mir hier an dieser Stelle für Menschen die in anderen Sprachen programmieren viel zu einfach zu sein. ;)

  • $measpoint.CoordXYZ($X,$Y,$Z)

    Sehr verwunderlich, zumal in Matlab und Python die Methode ohne Parameter aufgerufen und das Ergebnis in einem Array aufgefangen wird. :/

    Aber wenn es funktioniert, ist ja OK. Kannst den Thread dann ja als "Gelöst" markieren.

    EDIT:

    Das kommt davon, wenn man versucht mit dem Smartphone im Forum "rumzuwerkeln". Dadurch hatte ich überlesen, dass du im Startpost die Beschreibung der Methode gepostet hattest. :Face:

    Somit ist es eher anders herum verwunderlich, denn die Methode erfordert 3 Parameter - wie das Matlab und Python -Skript ohne operieren können ist mir nicht ganz klar.

  • Sehr verwunderlich, zumal in Matlab und Python die Methode ohne Parameter aufgerufen und das Ergebnis in einem Array aufgefangen wird. :/

    Aber wenn es funktioniert, ist ja OK. Kannst den Thread dann ja als "Gelöst" markieren.

    EDIT:

    Das kommt davon, wenn man versucht mit dem Smartphone im Forum "rumzuwerkeln". Dadurch hatte ich überlesen, dass du im Startpost die Beschreibung der Methode gepostet hattest. :Face:

    Somit ist es eher anders herum verwunderlich, denn die Methode erfordert 3 Parameter - wie das Matlab und Python -Skript ohne operieren können ist mir nicht ganz klar.

    Hallo BugFix, das Thema vorläufig als "gelöst" markiert. Mir als technischer Anwender der ab und an ein Schweizer-Taschenmesser braucht reicht die Lösung, auch wenn ich die so nicht erwartet hätte. Ein großes Lob geht ein Dich und auch water; habe damit auch was mit Nährwert gelernt, nämlich wie man COM Fehler konkret ausliest. Im übrigen finde ich es schade, dass ihr im Forum recht wenig los ist, obwohl AutoIt so sehr nützlich ist, im vergleich zu anderen Programmiersprachen. VG Lutz

  • Mir als technischer Anwender der ab und an ein Schweizer-Taschenmesser braucht reicht die Lösung,

    Ich habe trotzdem nochmal meine Funktion umgebaut anhand deiner Lösung und zusätzlich die Variante implementiert, X,Y,Z einer Messstelle als Struktur auszugeben. Ich empfinde das schon aus syntaktischen Gründen recht hilfreich, da $aResult[$i].X aussagekräftiger ist als $aResult[$i][0].

  • Ich habe trotzdem nochmal meine Funktion umgebaut anhand deiner Lösung und zusätzlich die Variante implementiert, X,Y,Z einer Messstelle als Struktur auszugeben. Ich empfinde das schon aus syntaktischen Gründen recht hilfreich, da $aResult[$i].X aussagekräftiger ist als $aResult[$i][0].

    Dankeschön! Und ganz klar kann man es moderner und besser machen in einer modernere Syntax, die mehr Menschen anspricht! Ich alter Sack habe aber mit dem TI59 angefangen zu Programmieren, und später mit FORTRAN IV weiter gem,acht, da kommt mir das einfache Autoit sehr zu pass.

  • Zur Zeit sieht es so aus, ohne Schnickschnal schreibe ich die relavanten Werte (z.Z. sind nur die Ortskoordinaten implementiert) in Felder, dann werden die Felder verbunden und als CSV abgespeichert. Alte Schule Mittelstufe halt. ;)

  • BugFix :

    Code
                        $tXYZ = DllStructCreate($tagXYZ)
                        $tXYZ.X = $X
                        $tXYZ.Y = $Y
                        $tXYZ.Z = $Z
                        $aXYZ[$i-1] = $tXYZ
                        Return $aXYZ
    
    
    ConsoleWrite($aResult[0].X & @CRLF)   

    Wo ist diese Syntax (ohne DllStructGetData()) beschrieben?

  • Hallo in die Runde,

    mir wurde ja bisher sehr gut weitergeholfen, vielen Dank dafür, aber jetzt stehe ich an einer anderen Stelle wie der Ochse vorm Berg. Die Methode GetData braucht das Objekt §display, was augenscheinlich nicht richtig übergeben wird? Bzw. Autoit kennt diesen Mechanismus so gar nicht?

    Fehler Meldung

    >"C:\Program Files (x86)\AutoIt3\SciTE\..\AutoIt3.exe" "C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\polytec01.au3" /UserParams

    +>12:08:56 Starting AutoIt3Wrapper (21.316.1639.1) from:SciTE.exe (4.4.6.0) Keyboard:00000407 OS:WIN_10/2009 CPU:X64 OS:X64 Environment(Language:0407) CodePage:0 utf8.auto.check:4

    +> SciTEDir => C:\Program Files (x86)\AutoIt3\SciTE UserDir => C:\Users\Lutz\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper SCITE_USERHOME => C:\Users\Lutz\AppData\Local\AutoIt v3\SciTE

    >Running AU3Check (3.3.14.5) from:C:\Program Files (x86)\AutoIt3 input:O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\polytec01.au3

    +>12:08:57 AU3Check ended.rc:0

    >Running:(3.3.14.5):C:\Program Files (x86)\AutoIt3\autoit3.exe "O:\archiv\prg\prg\programmieren\sprachen\AutoIt\test\PolyTec\polytec01.au3"

    +>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart or Ctrl+BREAK to Stop.

    polytec01.au3 (98) : ==> COM Error intercepted !

    err.number is: 0x80020009

    err.windescription: Ausnahmefehler aufgetreten.

    err.description is: This condition is false:

    'signalCopyInfo.m_lFrame >= 0 && signalCopyInfo.m_lFrame < psfp->nFrames'

    err.source is: Function: 'CMediaStreamToData::CopyFftMediaSample()'

    File: 'D:\TF\12\s\Main\Vib\Vibcommon\PolyFile\MediaStreamToData.cpp'

    Line: 1016

    err.helpfile is:

    err.helpcontext is: -2143075517

    err.lastdllerror is: 0

    err.scriptline is: 98

    err.retcode is: 0x80434343


    +>12:08:57 AutoIt3.exe ended.rc:0

    +>12:08:57 AutoIt3Wrapper Finished.

    >Exit code: 0 Time: 1.997

    In Phyton sieht eine ähnliche Funktion so aus ->

    def GetPointData(filename, domainname, channelname, signalname, displayname, point, frame):

    """

    % [x,y,usd] = GetPointData(filename, domainname, channelname, signalname, displayname,

    % point, frame)

    %

    % Gets original or user defined data from a polytec file.

    %

    % filename is the path of the .pvd or .svd file

    % domainname is the name of the domain, e.g. 'FFT' or 'Time'

    % channelname is the name of the channel, e.g. 'Vib' or 'Ref1' or 'Vib &

    % Ref1' or 'Vib X' or 'Vib Y' or 'Vib Z'.

    % signalname is the name of the signal, e.g. 'Velocity' or 'Displacement'

    % displayname is the name of the display, e.g. 'Real' or 'Magnitude' or

    % 'Samples'. If the display name is 'Real & Imag.' the data is returned

    % as complex values.

    % point is the (1-based) index of the point to get data from. If point is

    % 0 the data of all points will be returned. y will contain the data of

    % point i at row index i.

    % frame is the frame number of the data. for data acquired in MultiFrame

    % mode, 0 is the averaged frame and 1-n are the other frames. For user

    % defined datasets the frame number is in the range 1-n where n is the

    % number of frames in the user defined dataset. For all other data,

    % use frame number 0.

    %

    % returns x, the x axis values of the data

    % returns y, the data. colomns correspond to the x-axis, rows to the point

    % index. for point = 0: rows for points that have no data are set to zeros.

    % returns usd, a struct describing the signal

    """

    file = win32com.client.Dispatch('PolyFile.PolyFile')

    #Make sure that you can write to the file

    file_path = filename

    # file_path = os.path.join(".", filename)

    file.ReadOnly = False

    file.Open(file_path)

    usd = ClassData


    pointdomains = file.GetPointDomains();

    pointdomain = pointdomains.Item(domainname);

    channel = pointdomain.Channels.Item(channelname);

    signal = channel.Signals.Item(signalname);

    display = signal.Displays.Item(displayname);

    signalDesc = signal.Description;

    xaxis = signalDesc.XAxis;

    yaxis = signalDesc.YAxis;

    x = np.linspace(xaxis.Min, xaxis.Max, xaxis.MaxCount)

    usd.Name = signalDesc.Name;

    usd.Complex = signalDesc.Complex;

    usd.DataType = signalDesc.DataType;

    usd.DomainType = signalDesc.DomainType;

    usd.FunctionType = signalDesc.FunctionType;

    usd.PowerSignal = signalDesc.PowerSignal;

    usd.Is3D = (signalDesc.ResponseDOFs.Count > 0) and (not str(signalDesc.ResponseDOFs.Direction).find('ptcVector'))

    responseDOFs = signalDesc.ResponseDOFs;

    usd.ResponseDOFs = []

    if responseDOFs.Count == 0:

    usd.ResponseDOFs = []

    else:

    for i in range(1,responseDOFs.Count+1):

    usd.ResponseDOFs.append(responseDOFs.Item(i))

    referenceDOFs = signalDesc.ReferenceDOFs

    usd.ReferenceDOFs = []

    if referenceDOFs.Count == 0:

    usd.ReferenceDOFs = []

    else:

    for i in range(1,referenceDOFs.Count):

    usd.ReferenceDOFs.append(referenceDOFs.Item(i))

    usd.DbReference = signalDesc.DbReference

    usd.XName = xaxis.Name

    usd.XUnit = xaxis.Unit

    usd.XMin = xaxis.Min

    usd.XMax = xaxis.Max

    usd.XCount = xaxis.MaxCount

    usd.YName = yaxis.Name

    usd.YUnit = yaxis.Unit

    usd.YMin = yaxis.Min

    usd.YMax = yaxis.Max

    datapoints = pointdomain.datapoints

    if (point == 0):

    # % get data of all points

    y = []

    nr_datapoints = datapoints.count


    # y = np.zeros((int(nr_datapoints),int(usd.XCount)))

    for i in range(nr_datapoints):

    datapoint = datapoints.Item(i+1);


    ytemp = np.array(datapoint.GetData(display, frame));

    # y[i,:] = ytemp

    y.append(ytemp)

    file.Close()

    return (x,y,usd)

    VG Lutz