նախապատմությանը
Բժշկական կազմակերպություններից մեկը լուծումներ է կիրառել Orthanc PACS սերվերների և Radiant DICOM հաճախորդի վրա: Կարգավորման ընթացքում մենք պարզեցինք, որ յուրաքանչյուր DICOM հաճախորդ պետք է նկարագրվի PACS սերվերներում հետևյալ կերպ.
- Հաճախորդի անունը
- AE անունը (պետք է եզակի լինի)
- TCP նավահանգիստ, որն ավտոմատ կերպով բացվում է հաճախորդի կողմից և ստանում DICOM հարցումներ PACS սերվերից (այսինքն՝ սերվերը դրանք մղում է դեպի հաճախորդը՝ նախ սկսելով կապը)
- IP հասցե
Radiant-ը կարգավորելուց հետո հաճախորդները ստացան հետևյալ միտքը. յուրաքանչյուր հաճախորդի համար վերը նշված պարամետրերով ծրագրային ապահովումը կարգավորելու արդյունքում ֆայլը լցվեց pacs.xml, որը գտնվում էր օգտվողի պրոֆիլում (ուղի. %APPDATA%RadiantViewerpacs.xml) Միևնույն ժամանակ, մեկ հաճախորդի կազմաձևը մյուսից տարբերվում էր առնվազն երկու պարամետրով (AE անունը տարբեր է բոլորի համար, և նավահանգիստը հիմնականում նույնն է, բացառությամբ տերմինալային հաճախորդների, որոնք աշխատում են նույն սերվերի վրա. այնտեղ պորտերը նույնպես ունեին նշանակվել տարբեր):
pacs.xml ֆայլի օրինակ՝ ըստ
Մոտ վեց ամիս ամեն ինչ լավ էր, համակարգը սկսեց աշխատել… և հետո այն եկավ մեզ մոտ»:ստորջրյա քարերը»:
- Մենք պետք է գործարկենք մի քանի նոր PACS սերվերներ, որոնք կփոխարինեն հիններին (որտեղ սկավառակի տարածքը սկսել է սպառվել): PACS սերվերներ վիրտուալ մեքենաներում, բայց դա այն չէ, ինչի մասին մենք խոսում ենք.
- Մենք պետք է ինչ-որ կերպ կենտրոնական կերպով փոխենք եզակի կոնֆիգուրացիաները (երկու տարբեր պարամետրերով) 200 մեքենաների վրա (դրանց թիվը պարբերաբար աճում էր);
- Հաշվի առնելով հետազոտության ծավալների աճի տեմպերը, լուծումը անհրաժեշտ է ոչ միայն մեկ անգամ, այլ կրկնվող և պարբերաբար (օրինակ՝ 1-3 ամիսը մեկ անգամ):
Խնդիրը լուծելու համար գործիքների ընտրություն
Սկզբում փորձեր եղան գտնել ինչ-որ լուծում, որը կփոփոխեր pacs.xml ֆայլը հաճախորդի կողմից և փոփոխություններ կկատարի PACS սերվերների ցանկում՝ առանց ազդելու AE անվանման և TCP պորտի կարգավորումների վրա: Windows-ի հաճախորդներն այն ժամանակ հիմնված էին և՛ Windows XP-ի, և՛ Windows 7-ի վրա, ուստի փորձեր եղան գրել նման բան VBScript-ի հիման վրա: Բայց ավաղ, հնարավոր չեղավ տիրապետել նման առաջադրանքին՝ այս լեզվով բարդ ու բարդ բան գրելու փորձի իսպառ բացակայության պատճառով։ Գտնելու և վերաշարադրելու փորձերը նույնպես անհաջող էին (հարկ է նշել, որ ես արդեն այլ ծրագիր ունեի իմ գլխում, ուստի 3-4 ժամից ավելի չէի շփոթում VBScript-ի հետ):
Ի վերջո, ես որոշեցի հետևյալ լուծումը.
- Օգտագործելով խմբի քաղաքականությունը, հավաքեք բոլոր pacs.xml ֆայլերը մեկ տեղում ցանցային ռեսուրսի ցանկացած սերվերի վրա;
- Զանգվածային փոխեք ֆայլերը (ես արդեն ունեի Perl-ի միջոցով նման խնդիրների լուծման փորձ);
- Հաճախորդի կարգավորումները թարմացնելու համար օգտագործեք նաև խմբի քաղաքականությունը:
Ֆայլերի հավաքում խմբային քաղաքականության միջոցով
Ամենապարզն այն է, որ երբ հաճախորդը մուտք է գործում իր պրոֆիլ, նա իր իրավունքներով կատարում է որոշակի .bat ֆայլ, որն ասում է.
echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
Այսպիսով, pacs.xml ֆայլերը սերվերի վրա կկուտակվեն թաքնված ռեսուրսում, որի անունը պարունակում է տեղեկատվություն, թե որ համակարգչից և որ օգտվողից է պատճենվել այս կոնֆիգուրը:
Ամենադժվարը սպասելն էր, մինչև այս քաղաքականությունը գործի բոլոր օգտատերերի համար:
Փոխելով կազմաձևերը՝ օգտագործելով Perl սցենարը
Մեզ պետք կգա
Սցենարն ինքնին պարզվեց, որ բավականին պարզ է.
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);
}
}
}
Դրա գործողության սկզբունքը.
- Մենք բացում ենք գրացուցակը, որտեղ մենք հավաքել ենք pacs.xml կոնֆիգուրացիաները հաճախորդներից և տեղադրում ենք ֆայլերի ցանկը սկալյարների զանգվածում (@report_files);
- Մի օղակում մենք միաժամանակ մշակում ենք մեկ ֆայլ և կարդում այն տող առ տող;
- Օգտագործելով split, մենք բաժանում ենք յուրաքանչյուր տող 5 մասի, օգտագործելով չակերտները որպես բաժանարար;
- Մենք գտնում ենք ունկնդիր բառով տող և յուրաքանչյուր ֆայլի համար եզակի տվյալները (AE հաճախորդի անունը և TCP պորտի համարը) տեղադրում ենք երկու փոփոխականների մեջ.
- Դրանից հետո մենք պարզապես ստեղծում ենք նոր XML ֆայլ, մուտքագրում ենք դրա մեջ եզակի պարամետրեր և այնուհետև տեղադրում ենք անհրաժեշտ թվով PACS սերվերներ իրենց պարամետրերով. դրանք. ինչի համար է ամեն ինչ սկսվել)
- Մենք վերագրում ենք նոր XML ֆայլը հինի վրա:
Պետք է նշել, որ իրականում ես այս սկրիպտը ամբողջովին ինքնաբերաբար չեմ օգտագործում. իրականում ես հավաքագրված կոնֆիգուրսները պատճենում եմ առանձին գրացուցակի մեջ, այնուհետև գործարկում սկրիպտը և զանգվածաբար փոխում դրանք: Հաջորդը, պատահական ստուգում - և կազմաձևերը կարող են հետ բաշխվել մեքենաներին:
Փոփոխված pacs.xml ֆայլերի բաշխում հաճախորդներին
Ամենապարզ բանը, որ մտքովս անցավ, փոփոխություններ կատարելն էր արդեն գործող .bat ֆայլում, որը հավաքում է կոնֆիգուրացիաներ հաճախորդներից և ավելացնում տողը.
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml
Վերջնական .bat ֆայլն ունի հետևյալ տեսքը.
@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
Ամփոփում
Սա այսպիսին է»ծունկը«լուծում. Մենք արդեն երկու անգամ փորձել ենք (2018թ. սեպտեմբերին և 2019թ. փետրվարին), առայժմ թռիչքը նորմալ է։ Իհարկե, ոչ թե հաճախորդների 100%-ը թարմացվում է, բայց դա մոտ է այս արժեքին. մնացածը մենք ավարտում ենք հեռակա կարգով: Սցենարի հեղինակ
Source: www.habr.com