تغییر تنظیمات برنامه در حین ذخیره پارامترهای شخصی

ماقبل تاریخ

یک سازمان پزشکی راه حل هایی را بر اساس سرورهای 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 ایجاد می‌کرد. کلاینت های ویندوز در آن زمان مبتنی بر ویندوز XP و ویندوز 7 بودند - بنابراین تلاش هایی برای نوشتن چیزی شبیه به این بر اساس VBScript وجود داشت. اما افسوس که به دلیل عدم تجربه کامل در نوشتن هر چیزی پیچیده و پیچیده به این زبان، تسلط بر چنین کاری ممکن نبود. تلاش‌ها برای یافتن و بازنویسی نیز ناموفق بود (لازم به ذکر است که من قبلاً برنامه متفاوتی در ذهن داشتم، بنابراین بیش از 3-4 ساعت با VBScript سر و کار نداشتم).

در پایان به راه حل زیر اکتفا کردم:

  • با استفاده از خط مشی گروه، همه فایل های pacs.xml را در یک مکان در هر سروری در یک منبع شبکه جمع آوری کنید.
  • فایل ها را به طور انبوه تغییر دهید (من قبلاً در حل چنین مشکلاتی با استفاده از Perl تجربه داشتم).
  • همچنین از خط مشی های گروه برای به روز رسانی تنظیمات مشتری استفاده کنید.

جمع آوری فایل ها با استفاده از Group Policy

ساده ترین قسمت این است که وقتی یک کلاینت وارد پروفایل خود می شود، با حقوق خود، یک فایل bat. معین را اجرا می کند که می گوید:

echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml

بنابراین، فایل‌های pacs.xml در یک منبع مخفی در سرور جمع می‌شوند که نام آن حاوی اطلاعاتی است که این پیکربندی از کدام رایانه و از کدام کاربر کپی شده است.

سخت ترین کار این بود که صبر کنید تا این سیاست برای همه کاربران کار کند.

تغییر تنظیمات با استفاده از اسکریپت پرل

ما نیاز داریم پرل فعال برای ویندوز از ActiveState، و همچنین ماژول XML::Writer، که می تواند با استفاده از دستور نصب شود ppm 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 = <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 قسمت تقسیم می کنیم، با استفاده از نقل قول به عنوان جداکننده.
  • ما یک خط با کلمه 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٪ مشتریان به روز نمی شوند، اما نزدیک به این مقدار است - ما بقیه را از راه دور تکمیل می کنیم. اسکریپت توسط پیوند.

منبع: www.habr.com

اضافه کردن نظر