Antefatti
In una organizzazione medica sono state implementate soluzioni basate su server PACS Orthanc e DICOM-client Radiant. Durante la configurazione è emerso che ogni DICOM-client deve essere descritto nei server PACS nel seguente modo:
- Nome cliente
- Nome AE (deve essere unico)
- Porto TCP, che si apre automaticamente sul lato client e riceve gli esami DICOM dal server PACS (cioè, il server li invia al cliente – avviando prima la connessione)
- indirizzo IP
Dopo la configurazione dei client Radiant abbiamo ricevuto le seguenti informazioni da considerare: per ogni cliente, la configurazione del software con i parametri sopra indicati portava alla creazione del file pacs.xml, che si trovava nel profilo utente (percorso: %APPDATA%RadiantViewerpacs.xml). Tuttavia, la configurazione di un cliente differiva da un altro in almeno due parametri (il nome AE era diverso per tutti, mentre la porta era principalmente la stessa, tranne per i client terminali che operavano sullo stesso server – lì le porte dovevano anche essere assegnate in modo diverso).
Esempio del file pacs.xml secondo :
Circa sei mesi tutto andava bene, il sistema funzionava… e poi ci siamo imbattuti in “muri invisibili»:
- Dobbiamo introdurre diversi nuovi server PACS che sostituiranno quelli vecchi (dove lo spazio su disco stava per terminare). I server PACS sono in macchine virtuali, ma non è di questo che parliamo;
- Dobbiamo in qualche modo modificare centralmente le configurazioni uniche (con due parametri differenti) su 200 macchine (il loro numero aumentava regolarmente);
- Considerando il ritmo di crescita dei volumi di esami, la soluzione non deve essere occasionale, ma replicabile e regolare (ad esempio, una volta ogni 3-5 mesi).
La soluzione è qui sotto.
Scelta degli strumenti per risolvere il problema
Inizialmente ci sono stati tentativi di trovare una soluzione che, sul lato client, modificasse il file pacs.xml, apportando modifiche all'elenco dei server PACS, senza toccare le impostazioni del nome AE e del porto TCP. Al momento i client Windows erano sia su Windows XP sia su Windows 7 – quindi ci sono stati tentativi di scrivere qualcosa basato su VBScript. Ma purtroppo – non siamo riusciti a portare a termine un compito del genere, a causa della totale mancanza di esperienza nella scrittura di qualcosa di complesso e articolato in questo linguaggio. Anche i tentativi di trovare e riscrivere non hanno avuto successo (qui va notato che avevo già in mente un altro piano, quindi non ho continuato a trascorrere tempo con VBScript per più di 3-4 ore).
In definitiva, mi sono fermato alla seguente soluzione:
- Raccogliere tramite politiche di gruppo tutti i file pacs.xml in un unico posto su un server in una risorsa di rete;
- Modificare i file in blocco (abbiamo già esperienza nella risoluzione di tali problemi, usando Perl);
- Inoltre, tramite politiche di gruppo, aggiornare le impostazioni dei client.
Raccolta di file tramite politica di gruppo
La parte più semplice è che, all'accesso del client al proprio profilo, con i propri diritti, esegue un file .bat in cui è scritto:
echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
In questo modo, sul server in una risorsa nascosta, si accumuleranno file pacs.xml, il cui nome conterrà informazioni su quale computer e quale utente ha copiato questa configurazione.
La parte più difficile è stata aspettare che questa politica venisse applicata a tutti gli utenti.
Modifica delle configurazioni tramite script Perl
Avremo bisogno di per Windows di ActiveState, e del modulo XML::Writer, che può essere installato con il comando ppm install XML-Writer.
Lo script stesso è risultato piuttosto semplice:
use XML::Writer;
# Apriamo la cartella con i report, elaboriamo l'elenco (rimuoviamo il superfluo):
$report_dir = "C:Perl64WORKPACS-xml3";
opendir(DIR, "$report_dir") or die "Non posso aprire la cartella con i report!";
@report_files = readdir DIR;
shift (@report_files); # rimuove il punto dagli elementi dell'array (.)
shift (@report_files); # rimuove i due punti dagli elementi dell'array (..)
# print "@report_files";
closedir(DIR);
# Iniziamo a elaborare i file - uno alla volta. È necessario leggere il parametro AET e il numero di porta in variabili.
foreach $analiz_file (@report_files)
{
$full_path_to_file="C:Perl64WORKPACS-xml3".$analiz_file;
open (INFO, $full_path_to_file);
while ($line = )
{
# Le variabili $aet e $port contengono dati unici per ogni file XML:
my ($other1, $aet, $other2, $port, $other3) = split "/", $line, 5;
# Se incontriamo la stringa listener - allora siamo arrivati alla riga giusta e possiamo formare un nuovo XML:
if ($other1 =~ 'listener')
{
# Formiamo un nuovo XML con i campi e i dati necessari:
my $writer = XML::Writer->new(OUTPUT => 'self', DATA_MODE => 1, DATA_INDENT => 2, );
$writer->xmlDecl('utf-8');
$writer->startTag('pacs');
$writer->startTag('listener', ae => $aet, port => $port);
$writer->endTag();
$writer->startTag('hosts');
$writer->startTag('host', name => 'MRT', ae => 'ORTHANC', ip => 'XX.YY.214.17', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'KT', ae => 'ORTHANC2', ip => 'XX.YY.215.253', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'R', ae => 'ORTHANC3', ip => 'XX.YY.215.252', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'KT-20180501-20180831', ae => 'ORTHANC4', ip => 'XX.YY.215.251', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->startTag('host', name => 'KT-20180901-20181130', ae => 'ORTHANC5', ip => 'XX.YY.215.250', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
$writer->endTag();
$writer->endTag('hosts');
$writer->startTag('presets');
$writer->endTag();
$writer->startTag('lastsearch', dt => '4', mfid => '1048592');
$writer->endTag();
$writer->endTag('pacs');
# Mettiamo l'XML pronto nella variabile:
my $xml = $writer->end();
# Prepariamo il file per la riscrittura:
$rewritexml = $full_path_to_file;
# Riscriviamo i file XML con i nuovi dati:
open (NEWXML, "> $rewritexml");
print NEWXML $xml;
close (NEWXML);
}
}
}
Il principio del suo funzionamento:
- Apriamo il catalogo in cui abbiamo raccolto le configurazioni pacs.xml dai clienti e poniamo l'elenco dei file in un array scalare (@report_files);
- In un ciclo elaboriamo un file alla volta e lo leggiamo riga per riga;
- Utilizziamo split per suddividere ogni riga in 5 parti, usando le virgolette come delimitatore;
- Troviamo la riga con la parola listener e inseriamo in due variabili uniche per ogni file i dati (AE-nome cliente e numero della porta TCP);
- Dopo di che formiamo semplicemente un nuovo file XML, scriviamo i parametri unici e poi inseriamo il numero necessario di server PACS con i loro parametri – cioè, ciò per cui tutto è stato concepito)
- Riscriviamo il nuovo file XML sopra quello vecchio.
Va notato che in realtà non utilizzo questo script completamente in automatico: in sostanza copio le configurazioni raccolte in un catalogo separato e poi, eseguendo lo script, le modifico tutte insieme. Successivamente, una verifica selettiva – e le configurazioni possono essere ripristinate sulle macchine.
Distribuzione dei file pacs.xml modificati ai clienti
La cosa più semplice che mi è venuta in mente è stata modificare un file .bat già operativo, che raccoglie le configurazioni dai clienti e aggiungere la riga:
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
Il file .bat finale appare così:
@echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
Conclusione
Ecco una soluzione "fatta in casa". L'abbiamo già testata due volte (a settembre 2018 e a febbraio 2019), al momento funziona bene. Certamente non aggiorna il 100% dei clienti, ma ci si avvicina – gli altri li completiamo da remoto. Lo script è .
Fonte: habr.com
