Промяна на настройките на програмите със запазване на персонализирани параметри

Предистория

В една медицинска организация внедриха решения на база PACS-сървъри Orthanc и DICOM-клиент Radiant. По време на настройката установихме, че всеки DICOM-клиент трябва да бъде описан в PACS-сървърите по следния начин:

  • Име на клиента
  • AE-име (трябва да бъде уникално)
  • TCP-порт, който автоматично се отваря от страната на клиента и приема DICOM-изследвания от PACS-сървъра (т.е. сървърът както дава на клиента – иницира връзката първи)
  • IP адрес

След настройката на Radiant клиентите получиха следната информация за размисъл – при всеки клиент настройката на софтуера с посочените по-горе параметри водеше до запълване на файла pacs.xml, който се намираше в профила на потребителя (пътят: %APPDATA%RadiantViewerpacs.xml). При това конфигурацията на един клиент се отличаваше от друга минимум с два параметъра (AE-името при всички е различно, а портът е предимно един и същ, освен при терминалните клиенти, работещи на един и същи сървър – там портовете също трябваше да бъдат задавани различно).

Пример на файла pacs.xml по връзката:

Приблизително половин година всичко беше добре, системата заработи... и тук до нас достигнаха „подводни камъни»:

  • Трябва да въведем в експлоатация няколко нови PACS-сървъра, които да заменят старите (където свършваше мястото на дисковете). PACS сървърите са във виртуални машини, но не става въпрос за това;
  • Трябва по някакъв начин централизирано да променим уникалните конфигурации (с два отличаващи се параметъра) на 200 машини (броят им редовно нарастваше);
  • Като се имат предвид темповете на растеж на обемите на изследванията, решението трябва да бъде не еднократен, а тиражируем и редовен (например, 1 път на 3-5 месеца).

Решението е по-долу.

Избор на инструменти за решаване на задачата

В началото имаше опити да се намери някакво решение, което на страната на клиента променяше файла pacs.xml и внасяше в него промени в списъка на PACS-сървърите, без да докосва настройките на AE-името и TCP-порта. Windows клиентите по онова време бяха на база както Windows XP, така и Windows 7 – затова имаше опити да се напише нещо на база VBScript. Но, за съжаление, не успях да се справя с такава задача, поради напълно отсъстващ опит в писането на нещо сложно и комплексно на този език. Опитите да намеря и пренапиша също не увенчаха с успех (тук трябва да се отбележи, че в главата ми вече имаше друг план, така че не се занимавах с VBScript повече от 3-4 часа).

В крайна сметка се спрях на следното решение:

  • Съберете всички файлове 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 скрипт

Нужно е Active Perl под Windows от компанията ActiveState, както и модулът XML::Writer, който може да се инсталира с командата ppm install XML-Writer.

Самият скрипт се оказа доста прост:

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 = )
	{
		# Променливите $aet и $port съдържат уникални данни за всеки XML файл:
		my ($other1, $aet, $other2, $port, $other3) = split /"\/, $line, 5;
		# Ако се срещне редът listener - достигнали сме нужния ред и можем да формируем нов XML:
		if ($other1 =~ 'listener')
			{
				# Формируем нов XML с нужните полета и данни:
				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 части, използвайки кавичките като разделител;
  • Намираме строката с думата listener и слагаме в две променливи уникални за всеки файл данни (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% от клиентите, но близо до това значение — останалите дооправяме дистанционно. Скриптът по връзката.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster