更改程序设置同时保存个人参数

史前

一家医疗组织实施了基于 Orthanc PACS 服务器和 Radiant DICOM 客户端的解决方案。 在设置过程中,我们发现每个 DICOM 客户端必须在 PACS 服务器中进行如下描述:

  • 客户名称
  • AE名称(必须是唯一的)
  • 自动在客户端打开并从 PACS 服务器接收 DICOM 调查的 TCP 端口(即服务器将它们推送到客户端 - 首先启动连接)
  • 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 脚本更改配置

我们需要 活跃的 Perl 对于 Windows,来自 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年XNUMX月),目前为止航班正常。 当然,并不是XNUMX%的客户端更新,但已经接近这个值了——我们远程完成剩下的工作。 脚本由 链接.

来源: habr.com

添加评论