更改程式設定同時儲存個人參數

一個醫療組織實施了基於 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%的客戶端更新,但已經接近這個值了——我們遠端完成剩下的工作。 腳本由 鏈接.

來源: www.habr.com

添加評論