Scripting

<< Click to Display Table of Contents >>

Navigation:  Allgemeine Fragen >

Scripting

 

Fragen und Antworten zum Thema OMNITRACKER ↦ Allgemeine Fragen ↦ Scripting:

 

Error in WRP_ConfigurationMapping at line 350, char 2: Unbekannter Wert '56' eines "Drop-Down"-Feldes (IOtUserField)

Ausgangssituation: das Globale Skript WRP_ConfigurationMapping.

$INCLUDE 'WRP_ConfigurationMapping'
Call main()

soll gestartet werden, da ein Konfigurationsupdate der Struktur aller Request Folder und deren Felder erforderlich ist. Das Ergebnis wird durch das Script in diesen OMNITRACKER Folder geschrieben:

14. Ausgabe nach Word\ 03. Einstellungen\ 01. OT-Konfiguration \01. Felddefinitionen

Das Skript bricht mit folgendem Fehler ab: Error in WRP_ConfigurationMapping at line 350, char 2: Unbekannter Wert '56' eines "Drop-Down"-Feldes (IOtUserField)

Die Lösung:

Öffnen Sie die Folder Definition in Folder 01. Felddefinitionen und ergänzen einen Wert des Feldes Typ:

Value: otUfImage
Alias: 56
Description: Image field

 

Wie fügt man im Message-Template einen Link auf das aktuelles Objekt für den Web-Client ein?

Ein direkter Link zu einem Objekt per Web-Client sieht folgendermaßen aus:

http://<hostname>/<virtualroot>/Login.aspx?id=<id>&singleton=<singleton>[&guestlogin_id=<gid>][&lang=<xx>]

Näheres dazu entnehmen Sie bitte der WebGW-Hilfe: Start -> Alle Programme -> OmniTracker -> Dokumentation -> ...

Die ID des Objektes muss im Message-Template per Inline-Skript hinzugefügt werden. Im Message-Template sähe das dann in etwa so aus:

http://MyOT-Server/OTWG/Login.aspx?id=<%%Output ActiveRequest.UniqueId %%>&singleton=1

 

Wie kann der folgende Laufzeitfehler im Microsoft VBScript: "ActiveX-Komponenten kann kein Objekt erstellen: 'OtAut.OtApplication' in Windows 7?" behoben werden?

OtAut.dll ist 32-bit, dagegen verwendet Windows 7 standardmässig die 64-bit ScriptEngine. Bitte verwenden Sie C:\Windows\SysWOW64\cscript.exe (32bit) anstelle von C:\Windows\System32\cscript.exe (64bit).

 

Was bedeutet der Laufzeit-Fehler: "Invalid procedure call or argument: 'Left' (or 'Right' respectively)"?

Dieses Verhalten der VB-Script Engine lässt sich leider nicht ändern. Wenn ein Event-Handler an ein Control gebunden ist, dann sind innerhalb des Event-Handlers alle Control-Properties als lokale Variablen vorhanden. Dies bedeutet, dass bei einem Button-Skript "Left" der Wert der Property "Left" des Buttons ist.

In Formular-Skripten sollte also immer die Funktion "Mid" verwendet werden, um die Funktionen "Left" und "Right" zu ersetzen. Dies ist in jedem Fall möglich.

Beispiel:

Left(MyString, 4)

kann ersetzt werden durch:

Mid(MyString, 1, 4)

 

Wie ergänzt man auf einem Formular im Namen des Reiters die Anzahl der Elemente dynamisch?

Ergänzen Sie die ff. Codezeilen in einem OnOpen (OnChange) Script der Form:

TabControl.Pages(7).Name = TabControl.Pages(7).Name & " (" & _
ActiveRequest.Fields("Comments").TValue.Count & ")"
TabControl.Pages(8).Name = TabControl.Pages(8).Name & " (" & _
ActiveRequest.Fields("Attachments").TValue.Count & ")"

Achtung: Der Index fängt bei "0" an, daher ist "7" der achte Reiter auf der Form.

Für weitere Informationen siehe auch OMNITRACKER Form Editor > Scripting Reference > Button control > Properties > Name Property.

 

Wie versteckt man auf einem Formular einen bestimmten Reiter?

Ergänzen Sie die folgenden Codezeilen in einem OnOpen Script der Form:

TabControl.Pages(2).Hidden = True

Achtung: der Index fängt bei "0" an, daher ist "2" der dritte Reiter auf der Form.

Siehe auch OMNITRACKER Form Editor > Scripting Reference > Page object > Properties > Hidden Property für weitere Informationen..

 

OTClientAut.InvokeAction in VBA-Script: Was bedeutet der Fehlercode 0x8001010D?

Der Fehldercode 0x8001010D steht für An outgoing call cannot be made since the application is dispatching an input-synchronous call.

Der Aufruf von InvokeAction() führt zu einer Kommunikation zwischen dem COM-Objekt der OtClient.OTClientAut und dem OMNITRACKER Client. Windows lässt es während der synchronen Abarbeitung einer Windows Kommunikation nicht zu, dass ein externes COM-Objekt erzeugt wird.

Bei einem Excel-Import ist jedoch genau dies der Fall: Der OMNITRACKER-Client erhält den Aufruf, führt das globale, clientseitige Script aus und liefert das Ergebnis zurück. Wenn nun ein zusätzliches COM-Objekt in diesem clientseitigen Script nicht innerhalb der DLL, sondern als eine unabhängige Applikation erzeugt wird, dann wird der Fehlercode 0x8001010D provoziert.

Anregungen zu alternativen Lösungen finden Sie in der OMNITRACKER Automation Interface Help: Navigation: Getting Started > Visual Basic for Applications (VBA) > Example: Visual Basic for Applications (VBA).

 

Wie kann man eine Fehlerbehandlung in VB-Script umsetzen?

VB-Script bietet grundsätzlich zwei unterschiedliche "On Error"-Anweisungen:

On Error {Goto 0|Resume Next}

On Error Goto xyz wird NICHT durch VB-Script unterstützt.

Beispiel:

On Error Resume Next ' -> trigger error handling
[get error number and corresponding error handling in an if or case statement related to Err.Number, get information about error message by using Err.Description & Err.Source]
[reset error by using Err.Clear]
[continue with the script]
On Error Goto 0 ' -> stop error handling

Soll die Fehlerbehandlung nicht innerhalb des Scripts codiert werden, so kann man dies beispielsweise auch durch eine Subroutine "HandleErrorInfo" erledigen:

On Error Resume Next
[statement with error]
If Err.Number = 0 Then
[go on]
Else
HandleErrorInfo
End If

Sub HandleErrorInfo
WScript.Echo Err.Number
[Error Handling]
Err.Clear
End Sub

 

Wie lässt sich ein Bild per Script-Anweisung in ein Formular einbinden?

Um dies zu bewerkstelligen, bitte einen Befehl wie folgt auf einem Static Control ausführen:

StaticControl.Picture = LoadPicture(C:\Temp\mypicture.jpg)

 

External Script: Wie versendet man Reports ohne den OMNITRACKER Server zu belasten?

Ein serverseitiges Skript startet ein externes VB-Skript und wird direkt nach dem Start beendet. Das externe VB-Skript eröffnet eine Session am OMNITRACKER-Server (per MakeSessionEx) und erzeugt die Report-Aufgabe per OtTask.Execute.

Dadurch wird eine normale Client-Anwendung "simuliert" ohne dabei jedoch den Server zu belasten. Im Fehlerfall ist nur die Client-Anwendung betroffen und nicht die Serverumgebung.

Nachfolgend ein Beispiel wie die Skripte in etwa aufgebaut werden:

Set WshShell = CreateObject("WScript.Shell")
WshShell.Run ("C:\myexternalscript.vbs")
und das externe VB-Skript: (C:\myexternalscript.vbs)

Set objApp = CreateObject("OtAut.OtApplication")
Set objSess = objApp.MakeSession("MyOT-Server.com", 5085, "DailyReportUser", "Password")

' Task "daily report incidents"

Set objFso = CreateObject("Scripting.FileSystemObject")
strTmpName = objFso.GetTempName + ".xls"

Set objFld = objSess.RequestFolders("Incidents")
Set objTask = objFld.Tasks("daily report incidents")
objTask.Execute objFld.CreateRequestList, strTmpName, 3

Mail to group "Recipients daily incident report"

Set recipients = objSess.CreateEmailAddresses
recipients.AddUserOrGroup objSess.Groups("Recipients daily incident report"), 1

Set attachments = objSess.CreateEmailAttachments
attachments.AddFile strTmpName, "DailyIncidentReport.xls"

objSess.SendEmailToMultipleRecipients recipients, "Daily Incident Report", _
"Attachment: Daily Incident Report.", attachments

objFso.DeleteFile strTmpName

 

Was unterscheidet die OMNINET Scripting Engine und die MS Scripting Engine?

OMNITRACKER verwendet ab der Version 10.1.100 eine neue Skript-Engine. Bitte sehen Sie sich dazu die Dokumentation für weitere Details an.

Unser Ziel ist es, eine Skripting-Engine anzubieten, die sich hundertprozentig wie die ursprüngliche Microsoft-Engine verhält.

Während einer Übergangsphase kann die alte Skripting-Engine mit dem speziellen Konfigurationsparameter UseOldScriptingEngine = 0 (Ganzzahl) reaktiviert werden. Es gibt jedoch einige kleine Unterschiede, die jedoch die obige Aussage für praktische Zwecke nicht ungültig machen sollten.

  • Zeilennummern beginnen sowohl in der neuen Engine als auch im Skripteditor bei "1" statt "0" . Es gibt eine Zeilenverschiebung von 1, wenn der neue Skripteditor in Verbindung mit der ursprünglichen Microsoft-Engine verwendet wird, da diese Engine Zeilennummern ohne Basis verwendet.
  • Syntaxfehler können unterschiedlich sein, beispielsweise können sie zusätzliche Informationen enthalten. Die Laufzeit-Fehlercodes bleiben gleich.
  • Zufallszahlengenerator: Wir verwenden einen anderen Zufallszahlengenerator, sodass die Reihe der Pseudozufallszahlen ebenfalls unterschiedlich ist.
  • Der Aufrufstapel der neuen Engine kann zehnmal tiefer sein als der Aufrufstapel in der ursprünglichen Microsoft Engine.
OMNINET-Skripting-Engine:

  • Die Implementierung wurde von OMNINET durchgeführt.
  • Die Vorgabe war die Spezifikation des Verhaltens von Microsoft und der Microsoft-Engine.
Dort, wo die Microsoft-Engine "buggy" hätte sein sollen (insbesondere bei Abweichungen von der Spezifikation), haben wir die Fehler 1 : 1 reproduziert. Jeder Unterschied (mit Ausnahme der in den Release Notes gezeigten) wäre ein Fehler im Verhalten der neuen Engine. Die Implementierung war aus folgenden Gründen notwendig:
  • Unterstützung von Microsoft
  • Neuer Herausgeber (10.1)
  • Profilierungswerkzeug (10.2)
  • Debugger (10.4)
  • Skripterstellung im Web (10.x, 11.x)
  • Skripte werden nicht interpretiert, sondern (vor-)kompiliert.

 

Scripting: Wie modifiziert man die Beschreibung eines Attachments?
Set objAttachments = ActiveRequest.Userfields("Attachments").TValue
For i = 0 To objAttachments.Count - 1
Set Attachment = objAttachments(i)
Attachment.Comment = "New 123"
objAttachments(i) = Attachment
Next
ActiveRequest.Userfields("Attachments").TValue = objAttachments
ActiveRequest.Save

 

OtAut: Ist es möglich, mehrere OtSessions in einem Thread zu verwenden?

Es ist nicht möglich, aus mehreren Threads heraus ein und dasselbe OtSession Objekt zu verwenden. Innerhalb ein- und demselben Thread ist es nicht möglich, eine OtSession-Methode asynchron auszuführen und gleichzeitig eine weitere Methode auszuführen.

 

Wie werden Felder des Typs Schedule verwendet?

Bei Ausführung von automatischen Aktionen unter Verwendung des Datentyps Schedule ist das folgende Vorgehen empfehlenswert:

  • Erstellen Sie einen neuen Folder Scheduled Tasks
  • .
  • Darin werden nur zwei Felder benötigt: Titel (Text) und Zeitplan (Schedule).
  • In der Feld-Definition des Feldes Zeitplan, implementieren Sie ein Skript, welches in einer select Case Anweisung den Titel des ActiveRequests (also der Aufgabe) prüft, und dann die zugehörigen Aktionen ausführt.

Definieren Sie im neuen Folder Scheduled Tasks mehrere Aufgaben. Jede Aufgabe wird in diesem Folder als Objekt dargestellt. Diese Aufgaben haben einen Titel, beispielsweise Export FolderX nach Access oder Recreate Index. All diese Aufgaben verwenden dasselbe Skript, welches in der Feld-Definition des Schedule-Feldes definiert ist. Da aber jede Aufgabe unterschiedliche Dinge tun soll, muss im Script der Aufgabentitel geprüft werden, um dann die zugehörigen Aktionen auszuführen.

Das Schedule Skript für alle Aktionen sieht dann in etwa folgendermaßen aus:

Select Case ActiveRequest.Fields("Title").Value
Case "Export FolderX nach Access"
Set fld = ActiveSession.RequestFolders("FolderX")

'hier folgen Aktionen im FolderX

Case "Recreate Index"
ActiveSession.GetIndex().RecreateIndex()
Case Else
LogMessage "Kein gültiger Titel --> " & ActiveRequest.Fields("Title").Value
End Select

Weitere Hilfe dazu findet sich in der Online Administrator-Hilfe unter Schedule.

 

Wie lässt sich der Speicherverbrauch bei Verwendung von For Each-Schleifen beeinflussen?

Bei Verwendung einer For Each-Schleife werden die Daten solange gecached, bis die Schleife endet. Wenn eine große Liste von Objekten abgearbeitet werden soll, kann es zu Speicherproblemen kommen.

Dies lässt sich jedoch recht einfach umgehen, indem man alternativ mit einer For Next-Schleife arbeitet:

For i = 0 To reqs.count -1
Set req= reqs(i)
'... do your stuff, here
Next

Eine For - Next-Schleife gibt den Speicher nach jedem Objektzugriff frei.

 

OtAut: Kann man mehrere OtSession Objekte in ein- und demselben Thread nutzen?

Es ist nicht möglich aus mehreren Threads heraus ein und dasselbe OtSession Objekt zu verwenden. Innerhalb ein- und demselben Thread ist es nicht möglich, eine OtSession-Methode asynchron auszuführen und gleichzeitig eine weitere Methode auszuführen.

 

Wie kann man sprachunabhängig den Wert eines DropDown-Feldes setzen?

Um sprachunabhängig zu sein, müssen Sie den Alias-Namen des DropDown-Wertes aus der Feld-Definition verwenden.

Beispiel:

Das Feld vom Typ Drop-Down heisst mit Aliasnamen = RequestType; ein DropDown-Wert heisst mit Aliasnamen = StandardRequest

Die Code-Zeilen zum Belegen eines Objekts mit diesem Drop-Down Wert lauten dann:

Set objReq = ActiveSession.GetRequestByUniqueId(ActiveRequest.UniqueId)
objReq.Fields("RequestType").TValue.Alias = "StandardRequest"
objReq.Save

 

Die 3 goldenen Regeln in Bezug auf Action- bzw. Form-Scripting.

Regel 1:

In After Creation/Modification Action – Skripts immer auf einer lokalen Kopie des ActiveRequest arbeiten und die Änderungen dann zurückschreiben.

Beispiel:

Set objReq = ActiveSession.GetRequestByUniqueId(ActiveRequest.UniqueId) ' erzeugt eine lokale Kopie
objReq.UserFields("Title").Value = "Modification Script 1"
objReq.Save ' schreibt die Änderungen zurück in die Datenbank

Regel 2:

In Before Creation/Modification Action –Scripts direkt auf dem ActiveRequest arbeiten. Dabei werden Änderungen mit der Funktion UseModifiedRequest durchgeführt. Diese geänderten Inhalte werden dann auch direkt im geöffneten Formular angezeigt.

Regel 3:

In Formular-Skripten (OnOpen, OnChange, OnAfterFieldChanged, ...) immer Save verwenden. Nie ActiveRequest.Save oder ActiveRequest.SaveEx.

Dagegen in Scripten zu Regel 1 immer über:

Set objReq = ActiveSession.GetRequestByUniqueId(ActiveRequest.UniqueId).
objReq.Save / bzw. objReq.SaveEx ....

 

Wie kann man eine bestimmte (vorgefilterte) Ansicht in einem Auswahlfenster einstellen?

Will man eine bestimmte Ansicht in einem Auswahlfenster erzwingen, so muss man einen Standard-Ansicht definieren mit ff. View Condition:

view context = 255

Siehe hierzu im OMNITRACKER Administrator Guide: Navigation: User Interface > Views > The View Context.

Beachten Sie dabei das Folgende: Wenn ein Restriction Filter in der Feld Definition des jeweiligen Feldes definiert ist, so wird die Ansicht im Auswahlfenster durch diesen Filter festgelegt. Ist zusätzlich das Flag Only use restriction Filter for selecting Objects gesetzt, so werden initial alle Objekte im Auswahlfenster gelistet, die diesem Filter genügen. In diesem Fall wird <user defined> / <benutzerdefiniert> im Filter-DropDown angezeigt. Dadurch wird dem Anwedner signalisiert, dass er den Filter individuell anpassen kann. Siehe hierzu im OMNITRACKER Administrator Guide: Navigation: User Interface > Fields > Field Types > Reference >>> Restrictions.

 

Warum werden in meinem Filter verwendete Klammern einfach entfernt?

OMNITRACKER entfernt automatisch überflüssige Klammern. Es werden hier die allgemein gültigen Logik-Regeln für arithmetische Operatoren beachtet, in denen eine Rangfolge für Operatoren definiert ist:

Siehe: http://de.wikibooks.org/wiki/C-Programmierung:_Operatoren

Beispiel: A OR (B AND C) ist gleich A OR B AND C

 

Warum kann man nicht nach <Name des Objekts> sortieren?

Der Objektname von Objekten eines Folders wird nicht in der Datenbank-Tabelle als Feld gespeichert, sondern erst zur Laufzeit für die Anzeige aus den Regeln im Naming-Scheme zusammengebaut. Dies ermöglicht ein schnelles einfaches Ändern der Objektnamen auch bei bereits existierenden Objekten. Ein Sortieren ist danach jedoch nicht möglich.

Wenn Sie nach dem ObjektNamen sortieren wollen, so würden wir Ihnen empfehlen, stattdessen einzelne Spalten des entsprechenden (Referenz-)Objektes einzublenden und dann danach zu sortieren. Denn auch ein Sortieren nach mehreren Spalten ist möglich.