public async Task <bool> StoreScp(int taskID, DcmtkConnection connection) { Connection = connection; var stopWatch = new Stopwatch(); stopWatch.Start(); var proc = new Process(); var procinfo = new ProcessStartInfo(); var taskInfo = $"task: {taskID} connection: {Connection.name}"; var profile = _profileStorage.Current; try { var dir = profile.tempPath + Path.DirectorySeparatorChar + Connection.name + Path.DirectorySeparatorChar + "toScanner"; Directory.CreateDirectory(dir); string args = $"-xf \"{Connection.storescpCfgFile}\" Default -od \"{dir}\" -aet {Connection.localAETitle} {Connection.localPort}"; procinfo.UseShellExecute = false; procinfo.RedirectStandardError = true; procinfo.RedirectStandardOutput = true; procinfo.CreateNoWindow = true; if (profile.dcmtkLibPath != null) { procinfo.WorkingDirectory = profile.dcmtkLibPath; procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "storescp"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "storescp"; } procinfo.Arguments = args; proc.StartInfo = procinfo; proc.OutputDataReceived += OutputHandler; proc.ErrorDataReceived += ErrorHandler; proc.EnableRaisingEvents = true; proc.Exited += OnProcExit; _logger.Log(LogLevel.Information, $"{taskInfo} starting {procinfo.FileName} {procinfo.Arguments}"); if (proc.Start()) { proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} is listening on {procinfo.Arguments}..."); while (!proc.HasExited) { await Task.Delay(10000, _taskManager.cts.Token).ConfigureAwait(false); if (_taskManager.cts.IsCancellationRequested) { //proc.Kill(); _logger.Log(LogLevel.Debug, $"{taskInfo} {procinfo.FileName} is not killed due to potential crash.Trace AMG1"); } } if (proc.ExitCode != 0) { _logger.Log(LogLevel.Warning, $"{taskInfo} {procinfo.FileName} ExitCode: {proc.ExitCode}"); _logger.Log(LogLevel.Debug, $"{taskInfo} {procinfo.FileName} trace AMG2"); return(false); } _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} status: {proc.ExitCode} elapsed: {stopWatch.Elapsed}"); return(true); } return(false); } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); return(false); } catch (Exception e) { _logger.LogFullException(e); return(false); } finally { try { if (!proc.HasExited) { proc.Kill(); } } catch (Exception) { //eat it } _taskManager.Stop($"{Connection.name}.storescp"); } }
//try and determine type of file. dcmtk can convert pdf, img, dump to dicom public async Task <bool> Dicomize(int taskID, RoutedItem routedItem, DcmtkConnection connection) { Connection = connection; var taskInfo = $"task: {taskID} connection: {Connection.name}"; var stopWatch = new Stopwatch(); stopWatch.Start(); var proc = new Process(); var procinfo = new ProcessStartInfo(); try { string args = $"{routedItem.sourceFileName} {routedItem.destFileName}"; procinfo.UseShellExecute = false; procinfo.RedirectStandardError = true; procinfo.RedirectStandardOutput = true; procinfo.CreateNoWindow = true; procinfo.Arguments = args; proc.StartInfo = procinfo; proc.OutputDataReceived += OutputHandler; proc.ErrorDataReceived += ErrorHandler; proc.EnableRaisingEvents = true; proc.Exited += OnProcExit; var profile = _profileStorage.Current; if (routedItem.sourceFileName.EndsWith("pdf") || routedItem.sourceFileType == "pdf") { if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "pdf2dcm"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "pdf2dcm"; } } else if (routedItem.sourceFileName.EndsWith("xml") || routedItem.sourceFileType == "xml") { if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "xml2dcm"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "xml2dcm"; } } else if (routedItem.sourceFileName.EndsWith("jpg") || routedItem.sourceFileType == "jpg" || routedItem.sourceFileName.EndsWith("bmp") || routedItem.sourceFileType == "bmp") { if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "img2dcm"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "img2dcm"; } } else if (routedItem.sourceFileName.EndsWith("dump") || routedItem.sourceFileType == "dump") { if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "dump2dcm"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "dump2dcm"; } } _logger.Log(LogLevel.Information, $"{taskInfo} starting {procinfo.FileName} {procinfo.Arguments}"); proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); //proc.WaitForExit(); while (!proc.HasExited) { _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} is running..."); await Task.Delay(10000, _taskManager.cts.Token).ConfigureAwait(false); } if (proc.ExitCode != 0) { _logger.Log(LogLevel.Warning, $"{taskInfo} {procinfo.FileName} ExitCode: {proc.ExitCode}"); return(false); } } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e); return(false); } _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} Response id: {routedItem.id} status: {proc.ExitCode} elapsed: {stopWatch.Elapsed}"); return(true); }
public async Task <bool> EchoSCU(int taskID, DcmtkConnection connection) { Connection = connection; var taskInfo = $"task: {taskID} connection: {Connection.name}"; var stopWatch = new Stopwatch(); stopWatch.Start(); var proc = new Process(); var procinfo = new ProcessStartInfo(); var profile = _profileStorage.Current; try { string args = $"{Connection.remoteHostname} {Connection.remotePort} -aec {Connection.remoteAETitle} -aet {Connection.localAETitle}"; procinfo.UseShellExecute = false; procinfo.RedirectStandardError = true; procinfo.RedirectStandardOutput = true; procinfo.CreateNoWindow = true; if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "echoscu"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "echoscu"; } procinfo.Arguments = args; proc.StartInfo = procinfo; proc.OutputDataReceived += OutputHandler; proc.ErrorDataReceived += ErrorHandler; proc.EnableRaisingEvents = true; proc.Exited += OnProcExit; _logger.Log(LogLevel.Information, $"{taskInfo} starting {procinfo.FileName} {procinfo.Arguments}"); proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); //proc.WaitForExit(); while (!proc.HasExited) { _logger.Log(LogLevel.Information, $"{taskInfo} echoscu is running..."); await Task.Delay(1000, _taskManager.cts.Token).ConfigureAwait(false); } if (proc.ExitCode != 0) { _logger.Log(LogLevel.Warning, $"{taskInfo} {procinfo.FileName} ExitCode: {proc.ExitCode}"); return(false); } } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.Log(LogLevel.Critical, $"{e.Message} {e.StackTrace}"); return(false); } finally { _taskManager.Stop($"{Connection.name}.echoscu"); } _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} status: {proc.ExitCode.ToString()} elapsed: {stopWatch.Elapsed}"); return(true); }
public async Task <RoutedItem> MoveSCU(int taskID, RoutedItem routedItem, DcmtkConnection dcmtkConnection) { Connection = dcmtkConnection; //EX: movescu -S -k "0008,0052=STUDY" -k "0020,000d=1.2.840.113696.688101.520.428718.2009042602391" -aec DCMTK -aem dcmqrscp localhost 11120 var taskInfo = $"task: {taskID} connection: {Connection.name}"; var stopWatch = new Stopwatch(); stopWatch.Start(); Dictionary <string, string> args = new Dictionary <string, string>(); var proc = new Process(); var procinfo = new ProcessStartInfo(); try { //cloud cmove is not formatted the same as cFind, though dcmtk takes the same format // LiCloudRequest cFindParams = LiCloudRequest.FromJson(routedItem.request); // foreach (var tag in cFindParams.searchTags) // { // _logger.Log(LogLevel.Debug, $"{taskInfo} id: {routedItem.id} tag: {tag.Key} {tag.Value}"); // } // string cfindlevel = ""; // cFindParams.searchTags.TryGetValue("0008,0052", out cfindlevel); // switch (cfindlevel) // { // case "PATIENT": // args.TryAdd("level", "-P"); // break; // case "WORKLIST": // args.TryAdd("level", "-W"); // break; // case "STUDY": // default: args.TryAdd("level", "-S"); args.TryAdd("0008,0052", "-k 0008,0052=STUDY"); //QueryRetrieveLevel args.TryAdd("0020,000d", $"-k 0020,000d={routedItem.request}"); //StudyInstanceUID // break; // } //MessageID: {cFind.MessageID} _logger.Log(LogLevel.Information, $"{taskInfo} Request id: {routedItem.id} attempt: {routedItem.attempts}"); // //default return tags // args.TryAdd("0008,0050", "-k \"(0008,0050)\""); //AccessionNumber // args.TryAdd("0020,1208", "-k \"(0020,1208)\""); //NumberOfStudyRelatedInstances // args.TryAdd("0020,1209", "-k \"(0020,1209)\""); //NumberOfSeriesRelatedInstances // args.TryAdd("0008,0060", "-k \"(0008,0060)\""); //Modality // args.TryAdd("0008,0061", "-k \"(0008,0061)\""); //ModalitiesInStudy // args.TryAdd("0010,0020", "-k \"(0010,0020)\""); //PatientID // args.TryAdd("0010,0010", "-k \"(0010,0010)\""); //PatientName // args.TryAdd("0010,0030", "-k \"(0010,0030)\""); //PatientBirthDate // args.TryAdd("0010,0040", "-k \"(0010,0040)\""); //PatientSex // args.TryAdd("0008,0020", "-k \"(0008,0020)\""); //StudyDate // args.TryAdd("0020,0010", "-k \"(0020,0010)\""); //StudyID // args.TryAdd("0020,000d", "-k \"(0020,000d)\""); //StudyInstanceUID // args.TryAdd("0008,1030", "-k \"(0008,1030)\""); //StudyDescription // // add the search tags // foreach (KeyValuePair<string, string> tag in cFindParams.searchTags) // { // try // { // string arg = null; // var exists = args.TryGetValue(tag.Key, out arg); // var newArg = $"-k \"({tag.Key})={tag.Value}\""; // if (exists) // { // args[tag.Key] = newArg; // } // else // { // args[tag.Key] = newArg; // } // } // catch (Exception e) // { // _logger.Log(LogLevel.Critical, $"{taskInfo} Exception: {e.Message} {e.StackTrace}"); // if (e.InnerException != null) // { // _logger.Log(LogLevel.Critical, $"Inner Exception: {e.InnerException}"); // } // } // } args.TryAdd("host", $"-aec {Connection.remoteAETitle} -aet {Connection.localAETitle} -aem {Connection.localAETitle} {Connection.remoteHostname} {Connection.remotePort}"); //connect the cFind to the RoutedItem that originated the request //the cache was already primed in GetRequests routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); routedItem.status = RoutedItem.Status.PENDING; procinfo.UseShellExecute = false; procinfo.RedirectStandardError = true; procinfo.RedirectStandardOutput = true; procinfo.CreateNoWindow = true; var profile = _profileStorage.Current; if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "movescu"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "movescu"; } procinfo.Arguments = string.Join(" ", args.Values.ToArray());; proc.StartInfo = procinfo; List <string> response = new List <string>(); proc.OutputDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => { try { if (!string.IsNullOrEmpty(outLine.Data)) { response.Add(outLine.Data); } } catch (Exception e) { _logger.Log(LogLevel.Information, $"{e.Message}{e.StackTrace}"); } }; proc.ErrorDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => { try { if (!string.IsNullOrEmpty(outLine.Data)) { response.Add(outLine.Data); } } catch (Exception e) { _logger.Log(LogLevel.Information, $"{e.Message}{e.StackTrace}"); } }; proc.EnableRaisingEvents = true; proc.Exited += OnProcExit; _logger.Log(LogLevel.Information, $"{taskInfo} starting {procinfo.FileName} {procinfo.Arguments}"); proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); //proc.WaitForExit(); while (!proc.HasExited) { _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} is running..."); await Task.Delay(1000, _taskManager.cts.Token).ConfigureAwait(false); } // if (proc.ExitCode != 0) // { // _logger.Log(LogLevel.Warning, $"{taskInfo} {procinfo.FileName} ExitCode: {proc.ExitCode}"); // //return false; // } _logger.Log(LogLevel.Information, $"{taskInfo} Response id: {routedItem.id} status: {proc.ExitCode.ToString()} elapsed: {stopWatch.Elapsed}"); Dictionary <string, string> returnTagData = new Dictionary <string, string>(); string key = "response"; Dictionary <string, Dictionary <string, string> > results = new Dictionary <string, Dictionary <string, string> >(); if (response != null) { // scrape the stdout/stderr responses for the answers int i = 0; foreach (var responseItem in response) { _logger.Log(LogLevel.Debug, $"{taskInfo} Response id: {routedItem.id}, {responseItem}"); if (responseItem != null) { returnTagData.Add($"raw{++i}", responseItem); if (responseItem.Length >= 12) { if (responseItem.StartsWith("I: ---------------------------")) { } var test1 = responseItem.Substring(4, 9); var result = args.Keys.Any(e => e.Contains(test1)); if (args.Keys.Any(e => e.Contains(responseItem.Substring(4, 9)))) { string data = null; if (responseItem.Contains("no value available")) { data = ""; } else { data = responseItem.Substring(responseItem.IndexOf("[") + 1, responseItem.LastIndexOf("]") - responseItem.IndexOf("[") - 1).Trim(); } returnTagData.Add(responseItem.Substring(4, 9), data); } if (responseItem.Contains("0020,000d"))//StudyInstanceUID { key = responseItem.Substring(responseItem.IndexOf("[") + 1, responseItem.LastIndexOf("]") - responseItem.IndexOf("[") - 1).Trim(); } } else { if (responseItem.Equals("I: ") && key != "response") { if (proc.ExitCode != 0) { returnTagData.Add("StatusCode", proc.ExitCode.ToString()); } // if (response.Completed != 0 || response.Remaining != 0) // { // returnTagData.Add("Completed", response.Completed.ToString()); // returnTagData.Add("Remaining", response.Remaining.ToString()); // } results.Add(key, new Dictionary <string, string>(returnTagData)); returnTagData.Clear(); key = "response"; } } } } } if (results.Count == 0) { if (proc.ExitCode != 0) { returnTagData.Add("StatusCode", proc.ExitCode.ToString()); } results.Add(key, returnTagData); } string jsonResults = JsonSerializer.Serialize(results); // set results in RoutedItem routedItem.response.Add(jsonResults); RoutedItem toCache = null; switch (proc.ExitCode) { case 0: routedItem.status = RoutedItem.Status.COMPLETED; routedItem.resultsTime = DateTime.Now; _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toMoveSCU, nameof(Connection.toMoveSCU), error: false); toCache = _routedItemManager.Clone(); toCache.fromConnection = Connection.name; toCache.toConnections.Clear(); //BOUR-863 the toConnections on the toCache object weren't being cleared before rules so it contained DICOMConnection which toCache.attempts = 0; toCache.lastAttempt = DateTime.MinValue; toCache.type = RoutedItem.Type.RPC; _routedItemManager.Init(toCache); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); break; default: routedItem.status = RoutedItem.Status.FAILED; routedItem.resultsTime = DateTime.Now; _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toMoveSCU, nameof(Connection.toMoveSCU), error: true); toCache = (RoutedItem)_routedItemManager.Clone(); toCache.fromConnection = Connection.name; toCache.toConnections.Clear(); //BOUR-863 the toConnections on the toCache object weren't being cleared before rules so it contained DICOMConnection which toCache.attempts = 0; toCache.lastAttempt = DateTime.MinValue; toCache.type = RoutedItem.Type.RPC; _routedItemManager.Init(toCache); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); break; } } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e, taskInfo); Dictionary <string, string> returnTagData = new Dictionary <string, string> { { "StatusCode", "-1" }, { "StatusDescription", $"Error: {e.Message}" }, { "StatusErrorComment", $"Error: {e.StackTrace}" } }; string key = "response"; Dictionary <string, Dictionary <string, string> > results = new Dictionary <string, Dictionary <string, string> > { { key, returnTagData } }; string jsonResults = JsonSerializer.Serialize(results); routedItem.response.Add(jsonResults); if (routedItem.attempts > Connection.maxAttempts) { routedItem.status = RoutedItem.Status.FAILED; routedItem.resultsTime = DateTime.Now; _logger.Log(LogLevel.Debug, $"{taskInfo} id: {routedItem.id} exceeded max attempts."); _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toMoveSCU, nameof(Connection.toMoveSCU), true); } routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); _routedItemManager.Init(routedItem); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); return(routedItem); } return(routedItem); }
public async Task <RoutedItem> DcmDump(int taskID, RoutedItem routedItem, DcmtkConnection connection) { Connection = connection; /* * EX: dcmdump +P "0008,0050" +P "0010,0010" ~/Public/00011001.dcm * Returns: * (0008,0050) SH [3972022] # 8, 1 AccessionNumber * (0010,0010) PN [HADDAD WILLIE] # 14, 1 PatientName */ var taskInfo = $"task: {taskID} connection: {Connection.name}"; var stopWatch = new Stopwatch(); stopWatch.Start(); Dictionary <string, string> args = new Dictionary <string, string>(); var proc = new Process(); var procinfo = new ProcessStartInfo(); try { //default return tags args.TryAdd("0008,0050", "+P \"0008,0050\""); //AccessionNumber args.TryAdd("0008,0060", "+P \"0008,0060\""); //Modality args.TryAdd("0010,0020", "+P \"0010,0020\""); //PatientID args.TryAdd("0020,0010", "+P \"0020,0010\""); //Study ID args.TryAdd("0020,000d", "+P \"0020,000d\""); //Study Instance UID args.TryAdd("file", $"\"{routedItem.sourceFileName}\""); //connect the cFind to the RoutedItem that originated the request //the cache was already primed in GetRequests routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); routedItem.status = RoutedItem.Status.PENDING; procinfo.UseShellExecute = false; procinfo.RedirectStandardError = true; procinfo.RedirectStandardOutput = true; procinfo.CreateNoWindow = true; var profile = _profileStorage.Current; if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "dcmdump"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "dcmdump"; } procinfo.Arguments = string.Join(" ", args.Values.ToArray());; proc.StartInfo = procinfo; List <string> response = new List <string>(); proc.OutputDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => { try { if (!string.IsNullOrEmpty(outLine.Data)) { response.Add(outLine.Data); } } catch (Exception e) { _logger.Log(LogLevel.Information, $"{e.Message}{e.StackTrace}"); } }; proc.ErrorDataReceived += (object sendingProcess, DataReceivedEventArgs outLine) => { try { if (!string.IsNullOrEmpty(outLine.Data)) { response.Add(outLine.Data); } } catch (Exception e) { _logger.Log(LogLevel.Information, $"{e.Message}{e.StackTrace}"); } }; proc.EnableRaisingEvents = true; proc.Exited += OnDcmDumpExit; _logger.Log(LogLevel.Information, $"{taskInfo} starting {procinfo.FileName} {procinfo.Arguments}"); proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); proc.WaitForExit(); // while (!proc.HasExited) // { // //_logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} is running..."); // await Task.Delay(1000, LITETask.cts.Token).ConfigureAwait(false); // } if (proc.ExitCode != 0) { _logger.Log(LogLevel.Warning, $"{taskInfo} {procinfo.FileName} ExitCode: {proc.ExitCode}"); return(routedItem); } _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} Response id: {routedItem.id} status: {proc.ExitCode.ToString()} elapsed: {stopWatch.Elapsed}"); if (response != null) { // scrape the stdout/stderr responses for the answers foreach (var responseItem in response) { _logger.Log(LogLevel.Debug, $"{taskInfo} Response id: {routedItem.id}, {responseItem}"); if (responseItem != null) { if (responseItem.Length >= 12 && !responseItem.StartsWith("W:")) { if (responseItem.StartsWith("I: ---------------------------")) { } var test1 = responseItem.Substring(1, 9); var result = args.Keys.Any(e => e.Contains(test1)); if (args.Keys.Any(e => e.Contains(responseItem.Substring(1, 9)))) { string data = null; if (responseItem.Contains("no value available")) { data = ""; } else { data = responseItem.Substring(responseItem.IndexOf("[") + 1, responseItem.LastIndexOf("]") - responseItem.IndexOf("[") - 1).Trim().Trim('\0'); } var success = routedItem.TagData.TryAdd(responseItem.Substring(1, 9), data); if (!success) { //concatenate multiple tags if present success = routedItem.TagData[responseItem.Substring(1, 9)] == routedItem.TagData[responseItem.Substring(1, 9)] + "+" + data; } } } } } } routedItem.TagData.TryGetValue("0010,0020", out routedItem.PatientID); routedItem.TagData.TryGetValue("0008,0050", out routedItem.AccessionNumber); routedItem.TagData.TryGetValue("0020,000d", out routedItem.Study); //studyinstanceuid routedItem.TagData.TryGetValue("0020,0010", out routedItem.StudyID); //routedItem.TagData.TryGetValue("0008,0060", out routedItem.Modality); //construct an id with the standard fields routedItem.id = $"PID:{routedItem.PatientID}, AN:{routedItem.AccessionNumber}"; //, UID:{routedItem.Study}"; //var md = new ModalityDetection(); // md.ModalityFiltering(routedItem, ModalityList); } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e, taskInfo); Dictionary <string, string> returnTagData = new Dictionary <string, string> { { "StatusCode", "-1" }, { "StatusDescription", $"Error: {e.Message}" }, { "StatusErrorComment", $"Error: {e.StackTrace}" } }; string key = "response"; Dictionary <string, Dictionary <string, string> > results = new Dictionary <string, Dictionary <string, string> > { { key, returnTagData } }; string jsonResults = JsonSerializer.Serialize(results); routedItem.response.Add(jsonResults); if (routedItem.attempts > Connection.maxAttempts) { routedItem.status = RoutedItem.Status.FAILED; routedItem.resultsTime = DateTime.Now; _logger.Log(LogLevel.Debug, $"{taskInfo} id: {routedItem.id} exceeded max attempts."); _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toDicom, nameof(Connection.toDicom), true); } routedItem.fromConnection = Connection.name; routedItem.toConnections.Clear(); routedItem.type = RoutedItem.Type.DICOM; _routedItemManager.Init(routedItem); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); return(routedItem); } return(routedItem); }
public async Task <bool> DcmSend(int taskID, DcmtkConnection connection) { Throw.IfNull(connection); this.Connection = connection; var stopWatch = new Stopwatch(); stopWatch.Start(); var profile = _profileStorage.Current; bool scan = true, recurse = false, nohalt = true; string path = profile.tempPath + Path.DirectorySeparatorChar + Connection.name + Path.DirectorySeparatorChar + "toDcmsend"; var taskInfo = $"task: {taskID} connection: {Connection.name}"; var proc = new Process(); var procinfo = new ProcessStartInfo(); try { Directory.CreateDirectory(path); string args = $"{Connection.remoteHostname} {Connection.remotePort} \"{path}\" {(scan ? "+sd" : "")} {(recurse ? "+r" : "")} {(nohalt ? "-nh" : "")} -aec {Connection.remoteAETitle} -aet {Connection.localAETitle}"; procinfo.UseShellExecute = false; procinfo.RedirectStandardError = true; procinfo.RedirectStandardOutput = true; procinfo.CreateNoWindow = true; if (profile.dcmtkLibPath != null) { procinfo.FileName = profile.dcmtkLibPath + Path.DirectorySeparatorChar + "bin" + Path.DirectorySeparatorChar + "dcmsend"; var DCMDICTPATH = profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "dicom.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "acrnema.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "diconde.dic"; DCMDICTPATH += _util.EnvSeparatorChar() + profile.dcmtkLibPath + Path.DirectorySeparatorChar + Constants.Dirs.share + Path.DirectorySeparatorChar + Constants.Dirs.dcmtk + Path.DirectorySeparatorChar + "private.dic"; procinfo.Environment.Add("DCMDICTPATH", DCMDICTPATH); } else { procinfo.FileName = "dcmsend"; } procinfo.Arguments = args; proc.StartInfo = procinfo; proc.OutputDataReceived += OutputHandler; proc.ErrorDataReceived += ErrorHandler; proc.EnableRaisingEvents = true; proc.Exited += OnProcExit; _logger.Log(LogLevel.Information, $"{taskInfo} starting {procinfo.FileName} {procinfo.Arguments}"); proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); //proc.WaitForExit(); while (!proc.HasExited) { _logger.Log(LogLevel.Information, $"{taskInfo} dcmsend is running..."); await Task.Delay(10000, _taskManager.cts.Token).ConfigureAwait(false); } if (proc.ExitCode != 0) { _logger.Log(LogLevel.Warning, $"{taskInfo} {procinfo.FileName} ExitCode: {proc.ExitCode}"); return(false); } } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e); return(false); } _logger.Log(LogLevel.Information, $"{taskInfo} {procinfo.FileName} status: {proc.ExitCode.ToString()} elapsed: {stopWatch.Elapsed}"); return(true); }