|
Please note: The FiddlerAPI is still under construction,
and future releases may require changes to your code. Thanks for your
patience.
Importers and Exporters
Introduction
Fiddler 2.2.9.5 introduced the ISessionImport and
ISessionExport interfaces, allowing you to import traffic to Fiddler and export
it to other file formats. Fiddler ships with a number of these "transcoders" by
default, but you can also write your own using any .NET language.
Prerequisites
Writing extensions for Fiddler2 requires Visual Studio .NET 2005+ or the free .NET
Framework v2 command-line compilers. Fiddler2 loads
only .NET CLR v2.0 assemblies; use Visual Studio 2005+
to compile your extension. You should also ensure your project targets
AnyCPU to ensure that it works
properly with 64bit Fiddler.
You will also need to have the most recent version of Fiddler2
installed in order to develop Fiddler extensions.
Direct Fiddler2 to load your Transcoder assemblies
Fiddler loads extension assembly DLLs from the
%ProgramFiles%\Fiddler2\ImportExport\ and
%USERPROFILE%\Documents\Fiddler2\ImportExport\ folders.
Install to the %ProgramFiles% location to make your extensions available to all
users on the machine, or the %UserProfile% folder to make the extension
available only to the current user.
In addition to placing your Transcoder DLLs in the appropriate folder, you must also mark your assembly
to indicate the minimum version of Fiddler
required for your Assembly to load correctly.
Set the
Fiddler.RequiredVersion
attribute in your
AssemblyInfo.cs file (or
elsewhere in your code), as follows:
using Fiddler;
// Extension requires Fiddler 2.2.9.7+ because that is when
the // ISessionImport and ISessionExport interfaces were finalized.
[assembly: Fiddler.RequiredVersion("2.2.9.7")]
If Fiddler finds a
RequiredVersion
attribute that indicates a later version of Fiddler is required, the user will
be notified that a later version of Fiddler is required to use your extension.
Assemblies which do not contain a
RequiredVersion
attribute are silently
ignored.
Threading, FiddlerCore, and other notes
Currently, the ISessionImporter and
ISessionExporter interfaces are called on the MAIN UI thread. This is almost
certain to change in the future, so you should ensure that your classes are
thread safe and that they do not attempt to directly manipulate the Fiddler UI.
Manipulation of the Fiddler UI is further ill-advised because Fiddler
itself may not be loaded; FiddlerCore may be
hosting your Importer/Exporter directly. In order to support FiddlerCore, it's
advised that you support the Filename key (with string value of
a fully-qualified path) in the dictOptions parameter, and
consider supporting a Silent key (value as boolean) as well.
The ISessionImporter Interface
Extensions that implement the
ISessionImporter interface (which
implements the IDisposable
interface) are called when the user uses the File > Import menu option.
public
interface
ISessionImporter :
IDisposable
{
Session[] ImportSessions(string
sImportFormat,
Dictionary<string, object>
dictOptions, EventHandler<ProgressCallbackEventArgs>
evtProgressNotifications);
}
The method should return an array of Session objects created
from the Import of the data.
The dictOptions dictionary may be null, or may contain
a set of string-keyed objects. Most importers support specification of a
filename like so dictOptions["Filename"] =
"C:\\test.file"
The ISessionExporter Interface
Extensions that implement the
ISessionExporter interface (which
implements the IDisposable
interface) are called when the user uses the File > Export menu option.
public
interface
ISessionExporter :
IDisposable
{
bool ExportSessions(string
sExportFormat, Session[] oSessions,
Dictionary<string, object> dictOptions, EventHandler<ProgressCallbackEventArgs>
evtProgressNotifications);
}
The method should return True if the export of the sessions
passed via the oSessions parameter is successful.
The dictOptions dictionary may be null, or may contain
a set of string-keyed objects. Most importers support specification of a
filename like so dictOptions["Filename"] =
"C:\\test.file"
The ProgressCallbackEventArgs class
This class is defined by Fiddler and
allows you to report on the progress of an import or export operation.
If the completion ratio cannot be
determined, simply pass 0 or a "guess" between 0 and 1.0.
If the Cancel flag
is set on the ProgressCallbackEventArgs object after being passed to the
evtProgressNotifications callback, import or export should gracefully terminate as soon as possible.
public class ProgressCallbackEventArgs: EventArgs { public
ProgressCallbackEventArgs(float flCompletionRatio, string
sProgressText) public string
ProgressText { get;
} public string
PercentComplete {
get; } public
bool
Cancel { get;
set; } }
Step-by-step Sample Extension
Here's a trivial extension which modifies the User-Agent string of all
outbound requests.
- Start Visual Studio 2005.
- Create a new Project of type Visual C# Class Library
-
Right-click the project's References folder in the
Solution Explorer
- Choose the Browse tab and find Fiddler.exe in the
C:\Program Files\Fiddler2
folder.
- Click Ok to add the reference.
- If you're planning to add to Fiddler's UI
- Right-click the project's References folder in the
Solution Explorer again
- On the .NET tab, choose System.Windows.Forms.
- Click Ok to add the reference.
- In the Solution Explorer, right click the project.
Choose Properties.
- On the Build Events tab, add the following to the
Post-build event command line:
copy $(TargetPath)
"%userprofile%\Documents\Fiddler2\ImportExport\$(TargetFilename)"
- Modify the default class1.cs (or create a new class) in your project as
follows:
using System; using
System.IO; using System.Text; using System.Windows.Forms; using
Fiddler; using System.Diagnostics; using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Fiddler.RequiredVersion("2.2.9.7")]
public class Violin : ISessionExport
// Ensure class is public, or Fiddler
won't see it! { [ProfferFormat("TAB-Separated
Values", "Session List in Tab-Delimited Format")]
[ProfferFormat("Comma-Separated Values", "Session
List in Comma-Delimited Format; import into Excel or other tools")]
public class CSVTranscoder: ISessionExporter { public bool
ExportSessions(string sFormat, Session[] oSessions, Dictionary<string,
object> dictOptions,
EventHandler<ProgressCallbackEventArgs> evtProgressNotifications)
{ bool bResult = false;
//
Determine if we already ahve a filename from the dictOptions collection
string sFilename = null; if (null != dictOptions &&
dictOptions.ContainsKey("Filename")) {
sFilename = dictOptions["Filename"] as string; }
if (sFormat == "Comma-Separated Values") {
chSplit = ","; if
(string.IsNullOrEmpty(sFilename))
sFilename
= Fiddler.Utilities.ObtainSaveFilename("Export As " + sFormat,
"CSV Files (*.csv)|*.csv"); }
else { chSplit =
"\t"; if
(string.IsNullOrEmpty(sFilename))
sFilename
= Fiddler.Utilities.ObtainSaveFilename("Export As " + sFormat,
"TSV Files (*.tsv)|*.tsv"; }
if (String.IsNullOrEmpty(sFilename)) return;
try {
StreamWriter swOutput = new StreamWriter(oFileDialog.FileName, false,
Encoding.UTF8); int iCount = 0;
int iMax = oSessions.Length;
#region
WriteColHeaders bool bFirstCol = true;
foreach (ColumnHeader oLVCol in FiddlerApplication.UI.lvSessions.Columns)
{ if (!bFirstCol)
{ swOutput.Write(chSplit);
} else
{ bFirstCol = false;
}
swOutput.Write(oLVCol.Text.Replace(chSplit, ""));
} swOutput.WriteLine();
#endregion WriteColHeaders
#region WriteEachSession
foreach (Session oS in oSessions)
{ iCount++;
if (null != oS.ViewItem) {
bFirstCol = true; ListViewItem
oLVI = (oS.ViewItem as ListViewItem);
if (null == oLVI) continue;
foreach (ListViewItem.ListViewSubItem oLVC in oLVI.SubItems)
{ if (!bFirstCol)
{
swOutput.Write(chSplit); }
else {
bFirstCol = false; }
swOutput.Write(oLVC.Text.Replace(chSplit, ""));
}
swOutput.WriteLine();
}
if (null !=
evtProgressNotifications) {
evtProgressNotifications(null, new
ProgressCallbackEventArgs(, ));
ProgressCallbackEventArgs PCEA = new
ProgressCallbackEventArgs((iCount/(float)iMax), "wrote " + iCount.ToString()
+ " records.");
evtProgressNotifications(null, PCEA);
if (PCEA.Cancel) { swOutput.Close(); return false; } } }
#endregion WriteEachSession
swOutput.Close();
bResult = true; } catch
(Exception eX) {
MessageBox.Show(eX.Message, "Failed to export");
} } return bResult;
}
public void Dispose() { } }
Debugging your Extensions
Developers should set
the
fiddler.debug.extensions.showerrors preference
to
True to ensure that
exceptions and other extension-related errors are not silently caught.
It's also worthwhile to set the
fiddler.debug.extensions.verbose preference to
True.
Other Examples and Information
Almost done...
If you need help or have questions, please email me using the
Contact link above.
Change Log
6/21/10 - Created 6/28/10 - Updated
with Cancel flag 6/29/10 - Updated Interface signatures with
dictOptions collection introduced in Fiddler 2.2.9.7
©2010 Eric Lawrence
|