-
Notifications
You must be signed in to change notification settings - Fork 2
/
Extractor.cs
165 lines (138 loc) · 4.77 KB
/
Extractor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.BizTalk.Operations;
using static Ox.BizTalk.TrackedMessageExtractor.ConsoleTools;
namespace Ox.BizTalk.TrackedMessageExtractor
{
/// <summary>
/// Extracts messages from BizTalk tracking database
/// </summary>
public class Extractor
{
private readonly Settings _settings;
private BizTalkOperations _btsOps;
private TrackingDatabase _trackingDatabase;
public Extractor(Settings settings)
{
this._settings = settings;
this._btsOps = new BizTalkOperations(settings.BizTalkMgmtHost, settings.BizTalkMgmtDb);
this._trackingDatabase = new TrackingDatabase(settings.BizTalkDTAHost, settings.BizTalkDTADb);
}
private string CleanFilename(string filename)
{
if(!String.IsNullOrEmpty(filename))
{
foreach(char c in Path.GetInvalidFileNameChars())
{
filename = filename.Replace(c.ToString(), String.Empty);
}
}
return filename;
}
/// <summary>
/// Saves out a message to a file, using tracked filename and timestamp where possible.
/// </summary>
/// <param name="messageIdentifier">Message guid</param>
public void ExtractMessage(string messageIdentifier)
{
bool retry = false;
messageIdentifier = messageIdentifier.Trim();
Guid messageId = new Guid(messageIdentifier);
Console.Write("Processing {0}. ", messageIdentifier);
do
{
try
{
retry = false;
Microsoft.BizTalk.Message.Interop.IBaseMessage msg = _btsOps.GetTrackedMessage(messageId, _trackingDatabase);
// Build an output filename
string saveFileName = msg.MessageID.ToString();
string saveFileExtension = ".txt";
string receivedFileName = (string)msg.Context.Read(_settings.FilenameProperty, _settings.FilenameSchema);
// If we've obtained a filename from the context
if (receivedFileName != null)
{
saveFileName = Path.GetFileNameWithoutExtension(receivedFileName);
saveFileExtension = Path.GetExtension(receivedFileName);
}
// Loop each message part
for (int i = 0; i < msg.PartCount; i++)
{
string partName;
Microsoft.BizTalk.Message.Interop.IBaseMessagePart part = msg.GetPartByIndex(i, out partName);
if (part != null && part.Data != null)
{
// Attempt to construct a file name based on part data
string fileName = String.Empty;
string partFileName = part.PartProperties.Read("FileName", "http://schemas.microsoft.com/BizTalk/2003/mime-properties") as String;
string partFileExtension = saveFileExtension;
// Use the partName if there is no mime name
if (partFileName == null)
{
partFileName = partName;
}
else
// Use the extension from the filename for this part
{
partFileExtension = Path.GetExtension(partFileName);
partFileName = Path.GetFileNameWithoutExtension(partFileName);
}
// Handle duplicate files names with an incrementing counter
int fileNameDuplicate = -1;
do
{
fileName = CleanFilename(String.Format("{0}_{1}{3}{2}", saveFileName, partFileName, partFileExtension, fileNameDuplicate++ >= 0 ? fileNameDuplicate.ToString() : String.Empty));
} while (File.Exists(fileName));
Console.WriteLine("Saving message to {0}", fileName);
using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
{
byte[] buffer = new byte[1024];
int length = 0;
while ((length = part.Data.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, length);
}
fs.Flush();
}
DateTime createdTime = DateTime.Now;
// Try to get the file created time
object prop = msg.Context.Read("FileCreationTime", "http://schemas.microsoft.com/BizTalk/2003/file-properties");
if (prop == null)
{
// If there was no file created time (e.g. it was a SOAP message), get the adapter finished time
prop = msg.Context.Read("AdapterReceiveCompleteTime", "http://schemas.microsoft.com/BizTalk/2003/messagetracking-properties");
}
if (prop != null)
{
createdTime = (DateTime)prop;
}
File.SetLastWriteTime(fileName, createdTime);
}
}
}
catch (Exception ex)
{
WriteError(ex);
do
{
string prompt = PromptFor<string>("Would you like to retry this message? [Y/N]");
switch (prompt.ToUpper().Trim())
{
case "N":
return;
case "Y":
retry = true;
break;
default:
WriteColourfulLine(CON_COLOUR_WARN, "Invalid answer, Y or N please.");
break;
}
} while (!retry); // impossible for a false retry as we'll return on a N
}
} while (retry);
}
}
}