esihistoria
Yksi lääketieteen organisaatio toteutti Orthancin PACS-palvelimiin ja Radiant DICOM -asiakasohjelmaan perustuvia ratkaisuja. Asennuksen aikana havaitsimme, että jokainen DICOM-asiakas on kuvattava PACS-palvelimissa seuraavasti:
- Asiakkaan Nimi
- AE-nimi (täytyy olla yksilöllinen)
- TCP-portti, joka avautuu automaattisesti asiakaspuolella ja vastaanottaa DICOM-kyselyjä PACS-palvelimelta (eli palvelin työntää ne asiakasta kohti - muodostaen ensin yhteyden)
- IP-osoite
Radiantin käyttöönoton jälkeen asiakkaat saivat seuraavan ajatuksen aiheen: jokaiselle asiakkaalle ohjelmiston asetus yllä olevilla parametreilla johti tiedoston täyttymiseen pacs.xml, joka sijaitsi käyttäjäprofiilissa (polku: %APPDATA%RadiantViewerpacs.xml). Samanaikaisesti yhden asiakkaan konfiguraatio erosi toisesta ainakin kahdella parametrilla (AE-nimi on kaikilla erilainen ja portti on periaatteessa sama, paitsi samalla palvelimella toimivilla pääteasiakkailla - siellä porteissa oli myös määritettävä eri).
Esimerkki pacs.xml-tiedostosta
Noin kuuden kuukauden ajan kaikki oli hyvin, järjestelmä alkoi toimia... ja sitten se tuli meille "vedenalainen kivet»:
- Meidän on otettava käyttöön useita uusia PACS-palvelimia, jotka korvaavat vanhat (joissa levytila on alkanut loppua). PACS-palvelimet virtuaalikoneen, mutta siitä emme puhu;
- Meidän täytyy jotenkin keskitetysti muuttaa ainutlaatuisia konfiguraatioita (kahdella eri parametrilla) 200 koneessa (niiden määrä kasvoi säännöllisesti);
- Tutkimusvolyymien kasvuvauhti huomioon ottaen ratkaisua ei tarvita vain kerran, vaan toistettuna ja säännöllisesti (esimerkiksi 1-3 kuukauden välein).
Työkalujen valitseminen ongelman ratkaisemiseksi
Aluksi yritettiin löytää ratkaisu, joka muuttaisi pacs.xml-tiedostoa asiakaspuolella ja tekisi muutoksia PACS-palvelimien luetteloon vaikuttamatta AE-nimeen ja TCP-portin asetuksiin. Windows-asiakkaat perustuivat tuolloin sekä Windows XP:hen että Windows 7:ään – joten jotain tällaista yritettiin kirjoittaa VBScriptin pohjalta. Mutta valitettavasti tällaista tehtävää ei ollut mahdollista hallita, koska hänellä ei ollut kokemusta kirjoittaa mitään monimutkaista ja kattavaa tällä kielellä. Myös etsimis- ja uudelleenkirjoitusyritykset epäonnistuivat (on huomioitava, että minulla oli jo erilainen suunnitelma päässäni, joten en viitsinyt VBScriptillä yli 3-4 tuntia).
Lopulta päädyin seuraavaan ratkaisuun:
- Kerää ryhmäkäytännön avulla kaikki pacs.xml-tiedostot yhteen paikkaan millä tahansa verkkoresurssin palvelimella.
- Muuta tiedostoja massaksi (minulla oli jo kokemusta tällaisten ongelmien ratkaisemisesta Perlillä);
- Käytä myös ryhmäkäytäntöjä asiakasasetusten päivittämiseen.
Tiedostojen kerääminen ryhmäkäytännön avulla
Yksinkertaisin osa on, että kun asiakas kirjautuu profiiliinsa, hän suorittaa oikeuksillaan tietyn .bat-tiedoston, joka sanoo:
echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
Siten pacs.xml-tiedostot kerääntyvät palvelimelle piilotettuun resurssiin, jonka nimi sisältää tiedot, mistä tietokoneesta ja keneltä käyttäjältä tämä asetus kopioitiin.
Vaikeinta oli odottaa, kunnes tämä käytäntö toimi kaikille käyttäjille.
Kokoonpanojen muuttaminen Perl-komentosarjalla
Tarvitsemme
Itse käsikirjoitus osoittautui melko yksinkertaiseksi:
use XML::Writer;
# Открываем папку с отчетами, обрабатываем ссписок (удаляем лишнее):
$report_dir = "C:Perl64WORKPACS-xml3";
opendir(DIR, "$report_dir") or die "Не могу открыть папку с отчетами!";
@report_files = readdir DIR;
shift (@report_files); # удаляем точку из элементов массива (.)
shift (@report_files); # удаляем две точки из элементов массива (..)
# print "@report_files";
closedir(DIR);
# Начинаем обрабатывать файлы - по одному за раз. Нужно считать параметр AET и номер порта в переменные.
foreach $analiz_file (@report_files)
{
$full_path_to_file="C:Perl64WORKPACS-xml3".$analiz_file;
open (INFO, $full_path_to_file);
while ($line = <INFO>)
{
# Переменные $aet и $port содержат уникальные данные для каждого XML файла:
my ($other1, $aet, $other2, $port, $other3) = split /"/, $line, 5;
# Если встречается строка listener - то мы дошли до нужной строчки и можно формировать новый XML:
if ($other1 =~ 'listener')
{
# Формируем новый XML c нужными полями и данными:
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');
# Помещаем готовый XML в переменную:
my $xml = $writer->end();
# Подготавливаем файл для перезаписи:
$rewritexml = $full_path_to_file;
# Переписываем XML файлы новыми данными:
open (NEWXML, ">$rewritexml");
print NEWXML $xml;
close (NEWXML);
}
}
}
Sen toimintaperiaate:
- Avaamme hakemiston, johon olemme keränneet asiakkailta pacs.xml-määritykset, ja sijoitamme tiedostoluettelon skalaarien joukkoon (@report_files);
- Käsittelemme silmukassa yhden tiedoston kerrallaan ja luemme sen rivi riviltä;
- Splitin avulla jaamme jokaisen rivin 5 osaan käyttämällä lainausmerkkejä erottimena;
- Etsimme rivin sanan kuuntelija ja asetamme kunkin tiedoston yksilölliset tiedot (AE-asiakkaan nimi ja TCP-portin numero) kahteen muuttujaan;
- Tämän jälkeen luomme vain uuden XML-tiedoston, syötämme siihen yksilölliset parametrit ja lisäämme sitten tarvittavan määrän PACS-palvelimia parametreineen - nuo. mistä kaikki alkoi)
- Kirjoitamme uuden XML-tiedoston vanhan päälle.
On huomattava, että itse asiassa en käytä tätä skriptiä täysin automaattisesti - itse asiassa kopioin kerätyt konfiguraatiot erilliseen hakemistoon ja suoritan sitten skriptin ja muutan niitä kaikkia massaksi. Seuraavaksi satunnainen tarkistus - ja konfiguraatiot voidaan jakaa takaisin koneille.
Muokattujen pacs.xml-tiedostojen jakaminen asiakkaille
Yksinkertaisin mieleen tullut asia oli tehdä muutoksia jo toimivaan .bat-tiedostoon, joka kerää asiakkaiden määritykset ja lisätä rivin:
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
Lopullinen .bat-tiedosto näyttää tältä:
@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
Johtopäätös
Se on näin "polvi" ratkaisu. Olemme jo kahdesti kokeilleet (syyskuussa 2018 ja helmikuussa 2019), toistaiseksi lento on normaali. Ei tietenkään 100% asiakkaista päivitä, mutta se on lähellä tätä arvoa - teemme loput etänä. Käsikirjoitus
Lähde: will.com