Kategorien
Programmierung

XML-Dateien aufhübschen

Genau wie Maschinen oft Probleme haben, etwas für Menschen problemlos verständliches zu verarbeiten, so blickt ein Mensch dann und wann auf den Inhalt einer maschinenlesbaren Datei und kann darin nur wenig erkennen.

Geht es um die Verarbeitung von XML-Dateien, so können wenige Zeilen Perl eine deutliche Verbesserung schaffen – zum Beispiel bei der Aufbereitung einer „SEPA Payments„-XML-Datei.

use strict;
use warnings;
use XML::LibXML;
use XML::LibXML::PrettyPrint;

my $file = $ARGV[0] || die "usage: pretty.pl inputfile.xml\n";

my $document = XML::LibXML->new->parse_file($file);
my $pp = XML::LibXML::PrettyPrint->new(

indent_string => chr(9),
element => {
compact => [qw/MsgId CreDtTm PmtInfId PmtMtd NbOfTxs CtrlSum Cd ReqdExctnDt Nm IBAN BIC ChrgBr EndToEndId InstdAmt Ustrd/],
}
);
$pp->pretty_print($document);

open(sFILE, '>pretty-' . $file);
print sFILE $document->toString;
close (sFILE);

Die hauptsächliche Arbeit übernimmt das Modul XML::LibXML::PrettyPrint, dessen Ausgabe mit Hilfe einer Reihe von Parametern an die jeweiligen Bedürfnisse angepasst werden kann.

Kategorien
Programmierung

ActivePerls „Set up gcc environment“-Meldung unterdrücken

Neuere ActivePerl-Varianten nerven beim Start eines Skripts mit der Meldung „Set up gcc environment“, für deren Deaktivierung es auf den ersten Blick keinen offensichtlichen Schalter gibt.

Die Lösung bringt ein Blick in die Doku des Moduls „ActivePerl::Config“

perldoc ActivePerl::Config

welche die Umgebungsvariable „ACTIVEPERL_CONFIG_SILENT“ ausspuckt, die genau diesen Zweck erfüllt:

ACTIVEPERL_CONFIG_SILENT

If set to a TRUE value (e.g. „1“), suppress warnings on STDERR when new compilation environments are set up. This happens when a supported compiler is detected that is different from the one that perl was originally built with.

Kategorien
Programmierung

Locales ActivePerl Repository anlegen

Da ActiveState den Zugriff auf die Perl Package Manager-Repositories nach einiger Zeit auf die Business Edition beschränkt, bietet sich als vorbeugende Maßnahme das Anlegen eines lokalen Repositories an, was in einigen (wenigen) Schritten erledigt ist:

Ermitteln des aktuellen Repositories

Zum ermitteln des aktuellen Repositories den Perl Package Manager starten, den Menüpunkt „Edit“ / „Preferences“ wählen und auf die Registerkarte „Repositories“ wechseln.

activeperl_repository_01

Das aktuelle Repository kann in der Spalte „URL“ der Zeile „ActiveState“ ausgelesen werden, im Besipielfall

http://ppm4.activestate.com/MSWin32-x86/5.14/1405/package.xml

Erstellen eines lokalen Repositories

Zum erstellen des lokalen Repositories kann entweder ein beliebiges Werkzeug zum Erstellen von Web-Mirrors (z.B. wget) oder das Skript „ppm-local.pl“ verwendet werden.

Zur Ausführung ist lediglich die Angabe der gewünschten Aktion – entweder „load“ oder „reload“ notwendig, alle anderen Parameter sind optional. Sollte im „load“-Modus die Datei „package.xml“ noch nicht vorhanden sein, wird diese einmalig heruntergeladen, im „reload“-Modus wird diese grundsätzlich beim Start aktualisiert.

Sofern das Default-Repository nicht übereinstimmt oder die Anzahl der maximal zu ladenden Pakete oder die maximale Laufzeit geändert werden soll, ist die entsprechenden Option zu setzen. Das Repository ist hierbei immer als URL ohne die Datei „package.xml“ anzugeben.

Bei einem erneuten Aufruf überspringt ppm-local die bereits vorhandenen Pakete und lädt ledglich die noch nicht gespeicherten Pakete nach.

Einbinden des lokalen Repositories

Zum Einbinden des lokalen Repositories wieder in die Ansicht „Repositories“ des Perl Package Managers wechseln.

activeperl_repository_02

Im Feld „Add Repository“ unter „Name“ einen beliebigen Namen für das neue Repository eingeben und rechts das Ordnersymbol neben „Location“ klicken. Im sich öffnenden Dialog das Verzeichnis wählen, in das die Pakete heruntergeladen wurden und bestätigen. Durch Klick auf „Add“  wird das Repository dem Perl Package Manager hinzugefügt.

Abschalten des ActiveState Repositories

Sofern auf das ActiveState Repository nicht mehr zugegriffen werden kann / soll, kann auf der Registerkarte durch Klick auf die kleine braune Box (Enable/Disable Repository) in der Zeile „ActiveState“ das Repository abgeschaltet und lediglich mit dem lokalen Repository gearbeitet werden.

Kategorien
Programmierung

Perl Package Manager meldet ‚ERROR: 401 Authorization Required‘

Sollte der ActivePerl Package Manager den Versuch, einer Paketinstallation nur noch mit einem ‚ERROR: 401 Authorization Required‘ quittieren, so liegt dies u.U. am Alter der verwendeten Version.

Wie die ActiveState PPM Availability policy erläutert, wird zum Zugriff auf die PPM-Archive von Perl 5.8 und 5.10 seit 2010, zum Zugriff auf die Archive von Perl 5.12 seit September 2012 eine Lizenz der Business Edition benötigt.

Zeit, beim anstehenden Upgrade der Perl-Installation über einen Wechsel zu Strawberry Perl nachzudenken.

Kategorien
Programmierung

Remoteprozess auf einem Windows-Rechner mittels PERL starten

Um mittels PERL einen Remoteprozess auf einem entfernten Windows-Rechner zu starten, gibt es mehrere Alternativen:

Eine Möglichkeit ist die Verwendung von „PsExec.exe“ aus der PsTools-Suite von Microsoft, die allerdings den Nachteil hat, daß über einen „system“-Call ein externes Programm aufgerufen wird und die Einfluss- und Kontrollmöglichkeiten sehr beschränkt sind.

Soll der Start in PERL durchgeführt werden, so ist zwischen zwei Anwendungsszenarien zu unterscheiden:

Sofern lediglich unter dem Kontext des aufrufenden Benutzers ein Prozess gestartet werden soll, reichen 2 Zeilen PERL-Code (aus Gründen der Übersichtlichkeit wurde auf Fehlerbehandlung verzichtet):

use strict;
use warnings;
use Win32::OLE;

my $remoteHost = 'myHost';
my $remoteCmd = 'c:\windows\notepad.exe';

my $wmi = Win32::OLE->GetObject("winmgmts:{ImpersonationLevel=Impersonate,(security)}//$remoteHost\\root\\cimv2:Win32_Process");
$wmi->Create($remoteCmd);

Weitaus flexibler ist hingegen die Möglichkeit, den Prozess unter einem anderen Benutzer zu starten und ggf. auch noch auf Daten eines weiteren Rechners zugreifen zu lassen:

use strict;
use warnings;
use Win32::OLE;
use Win32::OLE::Variant;

my $remoteDomain= 'myDomain';
my $remoteHost = 'myHost';
my $remoteUser = 'myDomain\myUser';
my $remotePwd = 'myPassword';
my $remoteCmd = 'c:\windows\notepad.exe';

my $locator = Win32::OLE->new('WbemScripting.SWbemLocator');
my $service = $locator->ConnectServer($remoteHost, 'root\cimv2', $remoteUser, $remotePwd, 'MS_409', "kerberos:$remoteDomain\\$remoteHost");

$service->{Security_}->{AuthenticationLevel} = 6; # PktPrivacy
$service->{Security_}->{ImpersonationLevel} = 4; # Delegate

my $process = $service->Get('Win32_Process');

my $vPid = Variant(VT_I4 | VT_BYREF, 0);

$process->Create($remoteCmd, undef, undef, $vPid);

print "process running - pid: $vPid\n";

Beim Remotehost ist darauf zu achten, daß der tatsächliche Rechnername und kein DNS-Alias verwendet wird da sonst der Verbindungsaufbau mit dem Fehler 0x800706ba „Der RPC-Server ist nicht verfügbar“ scheitert.

Sofern tatsächlich im Rahmen des Remoteaufrufs ein dritter Rechner miteinbezogen werden soll, sind hierbei einige Einschränkungen zu beachten, wie der TechNet-Artikel „Geheimnisse von Windows Management Instrumentation“ erklärt:

Wenn ein Clientcomputer (Computer A) Anmeldeinformationen für die Domäne von einem Remoteserver (Computer B) an einen dritten Computer (Computer C) weiterleiten muss, ist Delegierung erforderlich. Dies trifft zu, wenn zwei oder mehr Netzwerkhops für einen bestimmten Vorgang ausgeführt werden müssen. Ohne Delegierung kann Computer B keine von Computer A empfangenen Anmeldeinformationen weiterleiten; deshalb schlägt die Verbindung mit Computer C fehl.

Die genauen Schritte zur Einrichtung der Delegierung sowie ein vbs-Skript zum Testen des Aufrufs sind in dem Artikel erläutert.

windows-delegierung

Wichtig ist der Hinweis, dass zur erfolgreichen Durchführung die Delegierung für Computer B in Active Directory aktiviert werden muss. Hierzu ist in den Eigenschaften des Computer-Kontos im Active Directory die Option „Computer für Delegierungszwecke vertrauen“ zu aktivieren, ansonsten scheitert der Aufruf mit dem Fehler 0x80070721: „Fehler im Sicherheitspaket“.

Literaturhinweise:

Update 05.05.2015: Zusätzliche Informationen bezüglich Rechnernamen und Delegierung hinzugefügt.