底
一個醫療組織實施了基於 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 腳本更改配置
我們會需要
腳本本身非常簡單:
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