namespace WebReports {
using System;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;
using EnvDTE;
using SHDocVw;
using mshtml;
#region Read me for Add-in installation and setup information.
// When run, the Add-in wizard prepared the registry for the Add-in.
// At a later time, if the Add-in becomes unavailable for reasons such as:
// 1) You moved this project to a computer other than which is was originally created on.
// 2) You chose 'Yes' when presented with a message asking if you wish to remove the Add-in.
// 3) Registry corruption.
// you will need to re-register the Add-in by building the MyAddin21Setup project
// by right clicking the project in the Solution Explorer, then choosing install.
#endregion
public interface IReport {
int GetArgumentCount();
void RenderStyle(_DTE applicationObject, StreamWriter output);
void Render(_DTE applicationObject, StreamWriter output, params string[] args);
}
/// <summary>
/// The object for implementing an Add-in.
/// </summary>
/// <seealso class='IDTExtensibility2' />
[GuidAttribute("CAFF8E86-0517-442B-9E00-E4C37419244B"), ProgId("WebReports")]
public class Connect : Object, Extensibility.IDTExtensibility2, IDTCommandTarget {
EnvDTE.Window windowToolWindow;
SHDocVw.WebBrowser Browser = null;
string HeaderHtml1, HeaderHtml2, FooterHtml;
string tempFileName;
object nullObj = null;
object oMissing = System.Reflection.Missing.Value;
const string COMMANDBARNAME = "WebReports";
const string WEBTOOLSMENU = "Web Reports";
const string DIFFMENU = "Diff Tools";
bool registerCommandBar = false;
/// <summary>
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method.
/// </summary>
public Connect() {
HeaderHtml1 = @"<html><head>"
+ "<META HTTP-EQUIV='Expires' CONTENT='0'>\n"
+ "<style>\n"
+ "BODY, TD, INPUT, TEXTAREA, SELECT {FONT-FAMILY: Arial,Verdana; FONT-SIZE: 9pt; COLOR: black;}"
+ "BODY {margin:2px;padding:0px;BACKGROUND-COLOR:#dbe7f3}"
+ "H1 {FONT-SIZE: 11pt}"
+ "TABLE {EMPTY-CELLS:show;BORDER-COLLAPSE:collapse;}"
+ ".error {COLOR:red}"
+ "HR {COLOR:#395d9a}";
HeaderHtml2 = "</style></head>\n<body>";
FooterHtml = "</body></html>";
tempFileName = Path.GetTempFileName();
}
/// <summary>
/// Implements the OnConnection method of the IDTExtensibility2 interface.
/// Receives notification that the Add-in is being loaded.
/// </summary>
/// <param term='application'>
/// Root object of the host application.
/// </param>
/// <param term='connectMode'>
/// Describes how the Add-in is being loaded.
/// </param>
/// <param term='addInInst'>
/// Object representing this Add-in.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) {
applicationObject = (_DTE)application;
addInInstance = (AddIn)addInInst;
Object nil = System.Reflection.Missing.Value;
if (connectMode == Extensibility.ext_ConnectMode.ext_cm_UISetup) {
object []contextGUIDS = new object[] { };
// When run, the Add-in wizard prepared the registry for the Add-in.
// At a later time, the Add-in or its commands may become unavailable for reasons such as:
// 1) You moved this project to a computer other than which is was originally created on.
// 2) You chose 'Yes' when presented with a message asking if you wish to remove the Add-in.
// 3) You add new commands or modify commands already defined.
// You will need to re-register the Add-in by building the WebReports project,
// right-clicking the project in the Solution Explorer, and then choosing install.
// Alternatively, you could execute the ReCreateCommands.reg file the Add-in Wizard generated in
// the project directory, or run 'devenv /setup' from a command prompt.
} else if (connectMode == Extensibility.ext_ConnectMode.ext_cm_Startup) {
CommandBar ToolsCmdBar = applicationObject.CommandBars["Tools"];
CommandBarPopup popUp;
CommandBar cmdBar = null;
CommandBar webMenu = null;
CommandBar diffMenu = null;
if (registerCommandBar)
cmdBar = AddCommandBar(COMMANDBARNAME);
popUp = (CommandBarPopup)ToolsCmdBar.Controls.Add(MsoControlType.msoControlPopup, oMissing, oMissing, 1, oMissing);
popUp.Caption = DIFFMENU;
diffMenu = popUp.CommandBar;
popUp = (CommandBarPopup)ToolsCmdBar.Controls.Add(MsoControlType.msoControlPopup, oMissing, oMissing, 2, oMissing);
popUp.Caption = WEBTOOLSMENU;
webMenu = popUp.CommandBar;
AddCommand("FileByType", 2, "File Types", "Lists all used file types of the current project.", "", cmdBar, webMenu);
AddCommand("Oldest", 2, "Oldest files", "List the oldest 50 files.", "", cmdBar, webMenu);
AddCommand("Newest", 2, "Recently changed files", "List the 50 recently changed files.", "", cmdBar, webMenu);
Command cmd = AddCommand("Diff", 3, "File Differences", "Report the file differences.", "", cmdBar, diffMenu);
// and add command to the contextmenu of files in solution explorer
cmd.AddControl(applicationObject.CommandBars["Item"], 3);
cmd = AddCommand("DiffFolder", 3, "Folder Differences", "Report the differences of 2 folders.", "", cmdBar, diffMenu);
// and add command to the contextmenu of folders in solution explorer
cmd.AddControl(applicationObject.CommandBars["Folder"], 2);
cmd = AddCommand("Explore", 4, "Explore", "Open this folder in the standard windows Explorer.", "");
// and add command to the contextmenu of folders and projects in solution explorer
cmd.AddControl(applicationObject.CommandBars["Folder"], 3);
cmd.AddControl(applicationObject.CommandBars["Project"], 10);
cmd.AddControl(applicationObject.CommandBars["Project Node"], 11);
} // if
}
/// <summary>
/// Implements the OnDisconnection method of the IDTExtensibility2 interface.
/// Receives notification that the Add-in is being unloaded.
/// </summary>
/// <param term='disconnectMode'>
/// Describes how the Add-in is being unloaded.
/// </param>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom) {
Command cmd;
if (disconnectMode == ext_DisconnectMode.ext_dm_HostShutdown) {
File.Delete(tempFileName);
try {
cmd = applicationObject.Commands.Item("WebReports.Diff", -1);
if (cmd != null) cmd.Delete();
cmd = applicationObject.Commands.Item("WebReports.DiffFolder", -1);
if (cmd != null) cmd.Delete();
if (registerCommandBar)
applicationObject.Commands.RemoveCommandBar(applicationObject.CommandBars[COMMANDBARNAME]);
} catch (Exception ex) {
ex = ex;
} // try
}
} // OnDisconnection
/// <summary>
/// Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
/// Receives notification that the collection of Add-ins has changed.
/// </summary>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnAddInsUpdate(ref System.Array custom) {
}
/// <summary>
/// Implements the OnStartupComplete method of the IDTExtensibility2 interface.
/// Receives notification that the host application has completed loading.
/// </summary>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnStartupComplete(ref System.Array custom) {
object objTemp = null;
if ((applicationObject != null) && (windowToolWindow == null)) {
try {
windowToolWindow = applicationObject.Windows.CreateToolWindow (
addInInstance, "{8856F961-340A-11D0-A96B-00C04FD705A2}",
"WebReports", "{CAFF8E86-0517-442B-9E00-E4C37419244C}", ref objTemp);
} catch (Exception ex) {
ex = ex;
}
}
// windowToolWindow.Visible = true;
Browser = (SHDocVw.WebBrowser)objTemp;
Browser.Navigate("about:blank", ref nullObj, ref nullObj, ref nullObj, ref nullObj);
DWebBrowserEvents2_BeforeNavigate2EventHandler
DBeforeNavigateE = new DWebBrowserEvents2_BeforeNavigate2EventHandler(OnBeforeNavigate2);
Browser.BeforeNavigate2 += DBeforeNavigateE;
} // OnStartupComplete
/// <summary>
/// Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
/// Receives notification that the host application is being unloaded.
/// </summary>
/// <param term='custom'>
/// Array of parameters that are host application specific.
/// </param>
/// <seealso class='IDTExtensibility2' />
public void OnBeginShutdown(ref System.Array custom) {
// close the window.
// VS.NET then remembers where it had been docked.
windowToolWindow.Visible = false;
windowToolWindow.Close(EnvDTE.vsSaveChanges.vsSaveChangesNo);
}
/// <summary>
/// Implements the QueryStatus method of the IDTCommandTarget interface.
/// This is called when the command's availability is updated
/// </summary>
/// <param term='commandName'>
/// The name of the command to determine state for.
/// </param>
/// <param term='neededText'>
/// Text that is needed for the command.
/// </param>
/// <param term='status'>
/// The state of the command in the user interface.
/// </param>
/// <param term='commandText'>
/// Text requested by the neededText parameter.
/// </param>
/// <seealso class='Exec' />
public void QueryStatus(string commandName, EnvDTE.vsCommandStatusTextWanted neededText, ref EnvDTE.vsCommandStatus status, ref object commandText) {
if (neededText == EnvDTE.vsCommandStatusTextWanted.vsCommandStatusTextWantedNone) {
if (commandName == "WebReports.FileByType") {
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
} else if (commandName == "WebReports.Oldest") {
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
} else if (commandName == "WebReports.Newest") {
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
} else if (commandName == "WebReports.Diff") {
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
} else if (commandName == "WebReports.DiffFolder") {
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
} else if (commandName == "WebReports.Explore") {
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
}
} else {
status = status;
}
}
/// <summary>
/// Implements the Exec method of the IDTCommandTarget interface.
/// This is called when the command is invoked.
/// </summary>
/// <param term='commandName'>
/// The name of the command to execute.
/// </param>
/// <param term='executeOption'>
/// Describes how the command should be run.
/// </param>
/// <param term='varIn'>
/// Parameters passed from the caller to the command handler.
/// </param>
/// <param term='varOut'>
/// Parameters passed from the command handler to the caller.
/// </param>
/// <param term='handled'>
/// Informs the caller if the command was handled or not.
/// </param>
/// <seealso class='Exec' />
public void Exec(string commandName, EnvDTE.vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled) {
handled = false;
StreamWriter output = null;
IReport Report = null;
int ExpectedArgs = 0;
string [] args = null;
int argc = 0;
if (executeOption == EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault) {
if ((applicationObject != null) && (Browser != null)) {
try {
if (commandName == "WebReports.FileByType") {
Report = new WebReports.ReportFileTypes();
} else if (commandName == "WebReports.Newest") {
Report = new WebReports.ReportNewest();
} else if (commandName == "WebReports.Oldest") {
Report = new WebReports.ReportOldest();
} else if (commandName == "WebReports.Diff") {
Report = new WebReports.ReportDiffFiles();
} else if (commandName == "WebReports.DiffFolder") {
Report = new WebReports.ReportDiffFolder();
} else if (commandName == "WebReports.Explore") {
ProjectItem p = (ProjectItem)applicationObject.SelectedItems.Item(1).ProjectItem;
string fName;
if (p != null) {
fName = p.get_FileNames(0);
} else {
Project pro = applicationObject.SelectedItems.Item(1).Project;
fName = pro.FullName;
fName = fName.Substring(0, fName.LastIndexOf('\\'));
} // if
openExplorer(fName);
} // if
if (Report != null) {
ExpectedArgs = Report.GetArgumentCount();
if (ExpectedArgs > 0) {
// find written pparameters
args = new string[ExpectedArgs];
if (varIn != null) {
string [] cmdArgs = ((string)varIn).Split(' ');
for (int n = 0; (n < cmdArgs.Length) && (argc < ExpectedArgs); n++) {
cmdArgs[n] = cmdArgs[n].Trim();
if (cmdArgs[n].Length > 0)
args[argc++] = cmdArgs[n];
} // for
} // if
// append up to 2 selected files
if ((argc < ExpectedArgs) && (applicationObject.SelectedItems.Count > 0)) {
ProjectItem p = (ProjectItem)applicationObject.SelectedItems.Item(1).ProjectItem;
args[argc++] = p.get_FileNames(0);
}
if ((argc < ExpectedArgs) && (applicationObject.SelectedItems.Count > 1)) {
ProjectItem p = (ProjectItem)applicationObject.SelectedItems.Item(2).ProjectItem;
args[argc++] = p.get_FileNames(0);
}
} // if
windowToolWindow.Visible = true;
output = new StreamWriter(tempFileName, false, Encoding.UTF8);
output.WriteLine(HeaderHtml1);
Report.RenderStyle(applicationObject, output);
output.WriteLine(HeaderHtml2);
if (ExpectedArgs == 0)
Report.Render(applicationObject, output);
else if (ExpectedArgs == 1)
Report.Render(applicationObject, output, args[0]);
else if (ExpectedArgs == 2)
Report.Render(applicationObject, output, args[0], args[1]);
output.WriteLine(FooterHtml);
} // if
} catch (ArgumentException ae) {
System.Windows.Forms.MessageBox.Show(ae.Message, COMMANDBARNAME);
} catch (Exception e) {
e = e;
} // try
if (output != null) {
output.Close();
output = null;
string s2 = Browser.LocationURL;
if (Browser.LocationURL != "about:blank") {
object Level = 3; // REFRESH_COMPLETELY
Browser.Refresh2(ref Level);
} else {
Browser.Navigate(tempFileName, ref nullObj, ref nullObj, ref nullObj, ref nullObj);
}
} // if
handled = true;
return;
}
}
} // Exec
private void OnBeforeNavigate2(Object ob1, ref Object URL,
ref Object Flags, ref Object Name, ref Object da,
ref Object Head, ref bool Cancel) {
int p;
EnvDTE.Window win;
if (URL != null) {
string url = URL.ToString().ToLower();
url = url.Replace("%20", " ");
// analyse url
StringDictionary urlParams = new StringDictionary();
string urlPath;
p = url.IndexOf('?');
if (p < 0) {
urlPath = url;
} else {
urlPath = url.Substring(0, p);
foreach (string s in url.Substring(p+1).Split('&')) {
string [] param = s.Split('=');
urlParams.Add(param[0].ToLower(), System.Web.HttpUtility.UrlDecode(param[1]));
} // foreach
} // if
if (urlPath == "dte:file") {
string fName = urlParams["file"];
win = applicationObject.ItemOperations.OpenFile(fName, null);
if (urlParams["line"] != null) {
// a line number is given
int fLine = int.Parse(urlParams["line"]);
EnvDTE.TextSelection sel = (EnvDTE.TextSelection)win.Document.Selection;
sel.GotoLine(fLine, false);
} // if
Cancel = true;
} else if (urlPath == "dte:folder") {
openExplorer(urlParams["folder"]);
Cancel = true;
} else if (urlPath == "dte:diff") {
string oldFile = urlParams["old"];
string newFile = urlParams["new"];
object param = newFile + " " + oldFile;
bool retBool = false;
Exec("WebReports.Diff", EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault,
ref param, ref nullObj, ref retBool);
Cancel = true;
} else if (urlPath == "dte:html") {
System.Windows.Forms.MessageBox.Show("catch:<" + url + ">", "OnBeforeNavigate2");
// applicationObject.ItemOperations.Navigate(url.Substring(9), null);
Cancel = true;
} // if
} // if
} // OnBeforeNavigate2
private void openExplorer (string folderName) {
System.Diagnostics.Process newProcess = new System.Diagnostics.Process();
newProcess.StartInfo.FileName = folderName;
newProcess.StartInfo.UseShellExecute = true;
newProcess.StartInfo.ErrorDialog = true;
newProcess.Start();
} // openExplorer
#region Comfortable Command Bar functions
private static _DTE applicationObject; // why static ?
private AddIn addInInstance;
private CommandBar AddCommandBar (String szName) {
object []contextGUIDS = new object[] { };
Commands commands = applicationObject.Commands;
CommandBar cmdBar = null;
try {
CommandBar oldCmdBar = applicationObject.CommandBars[szName];
commands.RemoveCommandBar(oldCmdBar);
} catch(System.ArgumentException ex) {
ex = ex; // Thrown if command doesn't already exist.
}
try {
cmdBar = (CommandBar)commands.AddCommandBar(szName, vsCommandBarType.vsCommandBarTypeToolbar, null, 0);
} catch(System.ArgumentException ex) {
ex = ex; // Thrown if command doesn't already exist.
}
return(cmdBar);
}
/// <summary>
/// Add one of the commands, dealing with the errors that might result.
/// </summary>
/// <remarks>First version from MSDN Magazin 02/02</remarks>
/// <param name="szName">name of the command being added</param>
/// <param name="szButtonText">text displayed on menu or button</param>
/// <param name="szToolTip">text displayed in tool tip</param>
/// <param name="szKey">default key assignment, or empty string if none</param>
/// <param name="szMenuToAddTo">default menu to place on, or empty if none</param>
private Command AddCommand (String szName, int IconNr, String szButtonText, String szToolTip, String szKey, params CommandBar [] CmdBars) {
Command cmd = null;
object []GuidArray = new object[] { };
// The IDE identifies commands by their full name, which include the add-in name
try {
cmd = applicationObject.Commands.Item ("WebReports." + szName, -1);
cmd.Delete();
} catch(System.ArgumentException ex) {
ex = ex; // Thrown if command doesn't already exist.
}
try {
cmd = applicationObject.Commands.AddNamedCommand (addInInstance, szName, szButtonText, szToolTip,
false, IconNr, ref GuidArray,
(int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled);
} catch(System.ArgumentException ex) {
ex = ex; // Thrown if command already exist.
}
if ((szKey != null) && (szKey != "")) {
// a default keybinding specified
object [] bindings;
bindings = (object [])cmd.Bindings;
if (0 >= bindings.Length) {
// there is no preexisting key binding, so add the default
bindings = new object[1];
bindings[0] = (object)szKey;
cmd.Bindings = (object)bindings;
} // if
} // if
// Append Control at end of CommandBar
foreach (CommandBar c in CmdBars) {
if (c != null)
cmd.AddControl(c, c.Controls.Count+1);
} // foreach
return(cmd);
} // AddCommand
#endregion
}
}