تغيير إعدادات البرنامج مع حفظ المعلمات الشخصية

قبل التاريخ

نفذت إحدى المؤسسات الطبية حلولاً تعتمد على خوادم 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. لكن للأسف، لم يكن من الممكن إتقان مثل هذه المهمة، بسبب النقص التام في الخبرة في كتابة أي شيء معقد وشامل بهذه اللغة. لم تنجح محاولات البحث وإعادة الكتابة أيضًا (تجدر الإشارة إلى أنه كان لدي بالفعل خطة مختلفة في رأسي، لذلك لم أعبث بـ 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 النصي

سوف نحتاج بيرل نشط لنظام التشغيل Windows من ActiveState، بالإضافة إلى وحدة XML::Writer، والتي يمكن تثبيتها باستخدام الأمر جزء في المليون تثبيت كاتب XML.

تبين أن البرنامج النصي نفسه بسيط للغاية:

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)؛
  • في الحلقة، نقوم بمعالجة ملف واحد في كل مرة وقراءته سطرًا تلو الآخر؛
  • باستخدام التقسيم، نقوم بتقسيم كل سطر إلى 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% من العملاء، لكنه قريب من هذه القيمة - نكمل الباقي عن بعد. البرنامج النصي بواسطة صلة.

المصدر: www.habr.com

إضافة تعليق