namespace P4VSNetAddIn
{
using System;
using System.IO;
using System.Collections;
using Microsoft.Office.Core;
using Extensibility;
using System.Runtime.InteropServices;
using EnvDTE;
using Microsoft.VisualStudio.VCProjectEngine;
using System.Diagnostics;
#region Read me for Add-in installation and setup information.
#endregion
///
/// The object for implementing an Add-in.
///
///
[GuidAttribute("38F5632B-809F-4B7E-B3ED-580665020BC1"), ProgId("P4VSNetAddIn.Connect")]
public class Connect : Object, IDTExtensibility2, IDTCommandTarget
{
///
/// Implements the constructor for the Add-in object.
/// Place your initialization code within this method.
///
public Connect()
{
}
///
/// Implements the OnConnection method of the IDTExtensibility2 interface.
/// Receives notification that the Add-in is being loaded.
///
///
/// Root object of the host application.
///
///
/// Describes how the Add-in is being loaded.
///
///
/// Object representing this Add-in.
///
///
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
applicationObject = (_DTE)application;
addInInstance = (AddIn)addInInst;
OutputWindow outputWindow = (OutputWindow)applicationObject.Windows.Item(Constants.vsWindowKindOutput).Object;
outputWindowPane = outputWindow.OutputWindowPanes.Add("Perforce");
//outputWindowPane.OutputString("Connect\n");
lastProjectItemAdded = DateTime.Now;
try
{
if(connectMode == Extensibility.ext_ConnectMode.ext_cm_UISetup)
AddGUIElements(addInInst);
RegisterSolutionEvents();
}
catch (SystemException e)
{
outputWindowPane.OutputString (e.ToString() + "\n");
}
//outputWindowPane.OutputString("Done with connect\n");
}
private void AddGUIElements(object addInInst)
{
//outputWindowPane.OutputString("Adding GUI\n");
object []contextGUIDS = new object[] { };
AddIn objAddIn = (AddIn)addInInst;
commandEdit = applicationObject.Commands.AddNamedCommand(
objAddIn, "P4EditItem", "P4 edit",
"Opens item for edit",
true, 0, ref contextGUIDS, 1 + 2); //1+2 == vsCommandStatusSupported+vsCommandStatusEnabled
commandEdit.AddControl(applicationObject.CommandBars["Item"], 3);
commandEdit.AddControl(applicationObject.CommandBars["Project"], 3);
commandEdit.AddControl(applicationObject.CommandBars["Solution"], 7);
// This only works if we have some custom keybindings
try
{
commandEdit.Bindings = "Global::ctrl+shift+enter";
}
catch (SystemException)
{
}
commandRevert = applicationObject.Commands.AddNamedCommand(
objAddIn, "P4Revert", "P4 revert",
"Reverts the a document opened for edit",
true, 0, ref contextGUIDS, 1 + 2);
commandDiff = applicationObject.Commands.AddNamedCommand(
objAddIn, "P4Diff", "P4 diff",
"Diffs the item against the head of the depot",
true, 0, ref contextGUIDS, 1 + 2);
commandDiff.AddControl(applicationObject.CommandBars["Item"], 4);
commandDiff.AddControl(applicationObject.CommandBars["Project"], 4);
commandDiff.AddControl(applicationObject.CommandBars["Solution"], 8);
commandBar = (CommandBar)applicationObject.Commands.AddCommandBar("P4",
vsCommandBarType.vsCommandBarTypeToolbar,
null, 1);
commandEdit.AddControl(commandBar,1);
commandDiff.AddControl(commandBar,2);
commandRevert.AddControl(commandBar,3);
//outputWindowPane.OutputString("Done adding GUI\n");
}
///
/// Implements the OnDisconnection method of the IDTExtensibility2 interface.
/// Receives notification that the Add-in is being unloaded.
///
///
/// Describes how the Add-in is being unloaded.
///
///
/// Array of parameters that are host application specific.
///
///
public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
{
UnregisterSolutionEvents();
}
private void RegisterSolutionEvents()
{
solutionEvents = (EnvDTE.SolutionEvents)applicationObject.Events.SolutionEvents;
solutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(this.SolutionOpened);
solutionEvents.BeforeClosing += new _dispSolutionEvents_BeforeClosingEventHandler(this.SolutionClosed);
}
private void UnregisterSolutionEvents()
{
if (solutionEvents != null)
{
solutionEvents.Opened -= new _dispSolutionEvents_OpenedEventHandler(this.SolutionOpened);
solutionEvents.BeforeClosing -= new _dispSolutionEvents_BeforeClosingEventHandler(this.SolutionClosed);
}
}
///
/// Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
/// Receives notification that the collection of Add-ins has changed.
///
///
/// Array of parameters that are host application specific.
///
///
public void OnAddInsUpdate(ref System.Array custom)
{
}
///
/// Implements the OnStartupComplete method of the IDTExtensibility2 interface.
/// Receives notification that the host application has completed loading.
///
///
/// Array of parameters that are host application specific.
///
///
public void OnStartupComplete(ref System.Array custom)
{
}
///
/// Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
/// Receives notification that the host application is being unloaded.
///
///
/// Array of parameters that are host application specific.
///
///
public void OnBeginShutdown(ref System.Array custom)
{
}
public void Exec(string commandName, vsCommandExecOption executeOption, ref object VariantIn,
ref object VariantOut, ref bool handled)
{
handled = true;
if(executeOption == EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault)
{
ArrayList selectedItems = new ArrayList();
GetSelectedItems(ref selectedItems);
System.Collections.IEnumerator myEnumerator = selectedItems.GetEnumerator();
while ( myEnumerator.MoveNext() )
{
string itemName = (string)myEnumerator.Current;
//outputWindowPane.OutputString("Processing item: " + itemName + "\n");
if (itemName == "")
continue;
if (commandName == "P4VSNetAddIn.Connect.P4EditItem")
{
ActivatePerforceWindow();
ExecuteCommand("p4", "edit \"" + itemName + "\"", Path.GetDirectoryName(itemName));
RestoreActiveWindow();
}
else if (commandName == "P4VSNetAddIn.Connect.P4Revert")
{
ActivatePerforceWindow();
ExecuteCommand("p4", "revert \"" + itemName + "\"", Path.GetDirectoryName(itemName));
RestoreActiveWindow();
}
else if (commandName == "P4VSNetAddIn.Connect.P4Diff")
{
ActivatePerforceWindow();
ExecuteCommand("p4", "diff \"" + itemName + "\"", Path.GetDirectoryName(itemName));
RestoreActiveWindow();
}
else
{
outputWindowPane.OutputString("Unhandled command " + commandName + "\n");
handled = false;
}
}
}
}
private void GetSelectedItems (ref ArrayList selectedItems)
{
Window win = applicationObject.ActiveWindow;
if (win == null ||
win == applicationObject.Windows.Item(Constants.vsWindowKindSolutionExplorer))
GetSelectedItemsInSolutionTree(ref selectedItems);
else
GetSelectedWindow(ref selectedItems);
}
private void GetSelectedWindow (ref ArrayList selectedItems)
{
Window win = applicationObject.ActiveWindow;
Document doc = win.Document;
if (doc != null)
selectedItems.Add(doc.FullName);
}
private void GetSelectedItemsInSolutionTree (ref ArrayList selectedItems)
{
int count = applicationObject.SelectedItems.Count;
for (int i = 1; i <= count; i++)
{
SelectedItem selectedItem = applicationObject.SelectedItems.Item(i);
selectedItems.Add(GetFullSolutionItemName(selectedItem));
}
}
private string GetFullSolutionItemName (SelectedItem item)
{
ProjectItem projectItem = item.ProjectItem;
if (projectItem != null)
return projectItem.get_FileNames(1);
Project project = item.Project;
if (project != null)
return project.FullName;
// Must have been the solution
return applicationObject.Solution.FullName;
}
public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText,
ref vsCommandStatus status, ref object CommandText)
{
if (neededText == EnvDTE.vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
{
if (commandName == "P4VSNetAddIn.Connect.P4EditItem" ||
commandName == "P4VSNetAddIn.Connect.P4Revert" ||
commandName == "P4VSNetAddIn.Connect.P4Diff")
{
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported |
vsCommandStatus.vsCommandStatusEnabled;
}
}
}
public void SolutionOpened()
{
//outputWindowPane.OutputString("Solution opened\n");
VCProjectItem item = (VCProjectItem )applicationObject.Solution.Projects.Item(1).Object;
VCProjectEngine projEngine = (VCProjectEngine)item.VCProjectEngine;
vcprojectEvents = (VCProjectEngineEvents)projEngine.Events;
vcprojectEvents.ItemAdded += new _dispVCProjectEngineEvents_ItemAddedEventHandler (this.ProjectItemAdded);
vcprojectEvents.ItemRemoved += new _dispVCProjectEngineEvents_ItemRemovedEventHandler (this.ProjectItemRemoved);
}
public void SolutionClosed()
{
//outputWindowPane.OutputString("Solution closed\n");
if (vcprojectEvents != null)
{
vcprojectEvents.ItemAdded -= new _dispVCProjectEngineEvents_ItemAddedEventHandler (this.ProjectItemAdded);
vcprojectEvents.ItemRemoved -= new _dispVCProjectEngineEvents_ItemRemovedEventHandler (this.ProjectItemRemoved);
}
}
public void ProjectItemAdded (object item, object parent)
{
outputWindowPane.OutputString("Project item added\n");
// Make sure that a least a second has gone by since the last add of a project item
DateTime currentTime = DateTime.Now;
System.TimeSpan diff = currentTime.Subtract(lastProjectItemAdded);
if (diff.Seconds <= 1)
{
lastProjectItemAdded = currentTime;
return;
}
VCFile file = item as VCFile;
if (file != null)
{
ActivatePerforceWindow();
ExecuteCommand("p4", "add " + file.FullPath, Path.GetDirectoryName(file.FullPath));
RestoreActiveWindow();
}
else
{
VCProject project = item as VCProject;
if (project != null)
{
outputWindowPane.OutputString("Added project " + project.Name + "\n");
lastProjectItemAdded = DateTime.Now;
}
else
outputWindowPane.OutputString("Unknown project item added\n");
}
}
public void ProjectItemRemoved (object item, object parent)
{
outputWindowPane.OutputString("Project item removed\n");
VCFile file = item as VCFile;
if (file == null)
return;
ActivatePerforceWindow();
ExecuteCommand("p4", "delete " + file.FullPath, Path.GetDirectoryName(file.FullPath));
RestoreActiveWindow();
}
private void ActivatePerforceWindow ()
{
activeWindow = applicationObject.ActiveWindow;
outputWindowPane.Activate();
OutputWindow outputWindow = (OutputWindow)applicationObject.Windows.Item(Constants.vsWindowKindOutput).Object;
outputWindow.Parent.Activate();
}
private void RestoreActiveWindow ()
{
activeWindow.Activate();
}
private bool ExecuteCommand (string command, string arguments, string workingPath)
{
ProcessStartInfo pi = new ProcessStartInfo(command, arguments);
pi.CreateNoWindow = true;
pi.RedirectStandardOutput = true;
pi.RedirectStandardError = true;
pi.UseShellExecute = false;
pi.WorkingDirectory = workingPath;
outputWindowPane.OutputString(command + " " + pi.Arguments + "\n");
System.Diagnostics.Process process = System.Diagnostics.Process.Start (pi);
process.WaitForExit();
outputWindowPane.OutputString (process.StandardOutput.ReadToEnd());
outputWindowPane.OutputString (process.StandardError.ReadToEnd());
return (process.ExitCode == 0);
}
private _DTE applicationObject;
private AddIn addInInstance;
private Command commandEdit;
private Command commandRevert;
private Command commandDiff;
private CommandBar commandBar;
private EnvDTE.SolutionEvents solutionEvents;
private VCProjectEngineEvents vcprojectEvents;
private DateTime lastProjectItemAdded;
private Window activeWindow;
static private OutputWindowPane outputWindowPane;
}
}