using System; using System.IO; using System.Text; using System.Reflection; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design; using System.Runtime.InteropServices; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Shell; using EnvDTE; using EnvDTE80; using Microsoft.Win32; using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VSSDK.Tools.VsIdeTesting; using Microsoft.VisualStudio; namespace Microsoft.VsSDK.IntegrationTestLibrary { /// /// public class TestUtils { #region Methods: Handling embedded resources /// /// Gets the embedded file identified by the resource name, and converts the /// file into a string. /// /// In VS, is DefaultNamespace.FileName? /// public static string GetEmbeddedStringResource(Assembly assembly, string resourceName) { string result = null; // Use the .NET procedure for loading a file embedded in the assembly Stream stream = assembly.GetManifestResourceStream(resourceName); if (stream != null) { // Convert bytes to string byte[] fileContentsAsBytes = new byte[stream.Length]; stream.Read(fileContentsAsBytes, 0, (int)stream.Length); result = Encoding.Default.GetString(fileContentsAsBytes); } else { // Embedded resource not found - list available resources Debug.WriteLine("Unable to find the embedded resource file '" + resourceName + "'."); Debug.WriteLine(" Available resources:"); foreach (string aResourceName in assembly.GetManifestResourceNames()) { Debug.WriteLine(" " + aResourceName); } } return result; } /// /// /// /// /// /// /// public static void WriteEmbeddedResourceToFile(Assembly assembly, string embeddedResourceName, string fileName) { // Get file contents string fileContents = GetEmbeddedStringResource(assembly, embeddedResourceName); if (fileContents == null) throw new ApplicationException("Failed to get embedded resource '" + embeddedResourceName + "' from assembly '" + assembly.FullName); // Write to file StreamWriter sw = new StreamWriter(fileName); sw.Write(fileContents); sw.Close(); } /// /// Writes an embedded resource to a file. /// /// The name of the assembly that the embedded resource is defined. /// The name of the embedded resource. /// The file to write the embedded resource's content. public static void WriteEmbeddedResourceToBinaryFile(Assembly assembly, string embeddedResourceName, string fileName) { // Get file contents Stream stream = assembly.GetManifestResourceStream(embeddedResourceName); if (stream == null) throw new InvalidOperationException("Failed to get embedded resource '" + embeddedResourceName + "' from assembly '" + assembly.FullName); // Write to file BinaryWriter sw = null; FileStream fs = null; try { byte[] fileContentsAsBytes = new byte[stream.Length]; stream.Read(fileContentsAsBytes, 0, (int)stream.Length); FileMode mode = FileMode.CreateNew; if (File.Exists(fileName)) { mode = FileMode.Truncate; } fs = new FileStream(fileName, mode); sw = new BinaryWriter(fs); sw.Write(fileContentsAsBytes); } finally { if (fs != null) { fs.Close(); } if (sw != null) { sw.Close(); } } } #endregion #region Methods: Handling temporary files and directories /// /// Returns the first available file name on the form /// [baseFileName]i.[extension] /// where [i] starts at 1 and increases until there is an available file name /// in the given directory. Also creates an empty file with that name to mark /// that file as occupied. /// /// Directory that the file should live in. /// /// may be null, in which case the .[extension] part /// is not added. /// Full file name. public static string GetNewFileName(string directory, string baseFileName, string extension) { // Get the new file name string fileName = GetNewFileOrDirectoryNameWithoutCreatingAnything(directory, baseFileName, extension); // Create an empty file to mark it as taken StreamWriter sw = new StreamWriter(fileName); sw.Write(""); sw.Close(); return fileName; } /// /// Returns the first available directory name on the form /// [baseDirectoryName]i /// where [i] starts at 1 and increases until there is an available directory name /// in the given directory. Also creates the directory to mark it as occupied. /// /// Directory that the file should live in. /// /// Full directory name. public static string GetNewDirectoryName(string directory, string baseDirectoryName) { // Get the new file name string directoryName = GetNewFileOrDirectoryNameWithoutCreatingAnything(directory, baseDirectoryName, null); // Create an empty directory to make it as occupied Directory.CreateDirectory(directoryName); return directoryName; } /// /// /// /// /// /// /// private static string GetNewFileOrDirectoryNameWithoutCreatingAnything(string directory, string baseFileName, string extension) { // - get a file name that we can use string fileName; int i = 1; string fullFileName = null; while (true) { // construct next file name fileName = baseFileName + i; if (extension != null) fileName += '.' + extension; // check if that file exists in the directory fullFileName = Path.Combine(directory, fileName); if (!File.Exists(fullFileName) && !Directory.Exists(fullFileName)) break; else i++; } return fullFileName; } #endregion #region Methods: Handling solutions /// /// Closes the currently open solution (if any), and creates a new solution with the given name. /// /// Name of new solution. public void CreateEmptySolution(string directory, string solutionName) { CloseCurrentSolution(__VSSLNSAVEOPTIONS.SLNSAVEOPT_NoSave); string solutionDirectory = GetNewDirectoryName(directory, solutionName); // Create and force save solution IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)); solutionService.CreateSolution(solutionDirectory, solutionName, (uint)__VSCREATESOLUTIONFLAGS.CSF_SILENT); solutionService.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0); DTE dte = VsIdeTestHostContext.Dte; Assert.AreEqual(solutionName + ".sln", Path.GetFileName(dte.Solution.FileName), "Newly created solution has wrong Filename"); } public void CloseCurrentSolution(__VSSLNSAVEOPTIONS saveoptions) { // Get solution service IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)); // Close already open solution solutionService.CloseSolutionElement((uint)saveoptions, null, 0); } public void ForceSaveSolution() { // Get solution service IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)); // Force-save the solution solutionService.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0); } /// /// Get current number of open project in solution /// /// public int ProjectCount() { // Get solution service IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)); object projectCount; solutionService.GetProperty((int)__VSPROPID.VSPROPID_ProjectCount, out projectCount); return (int)projectCount; } #endregion #region Methods: Handling projects /// /// Creates a project. /// /// Name of new project. /// Name of project template to use /// language /// New project. public void CreateProjectFromTemplate(string projectName, string templateName, string language, bool exclusive) { DTE dte = (DTE)VsIdeTestHostContext.ServiceProvider.GetService(typeof(DTE)); Solution2 sol = dte.Solution as Solution2; string projectTemplate = sol.GetProjectTemplate(templateName, language); // - project name and directory string solutionDirectory = Directory.GetParent(dte.Solution.FullName).FullName; string projectDirectory = GetNewDirectoryName(solutionDirectory, projectName); dte.Solution.AddFromTemplate(projectTemplate, projectDirectory, projectName, false); } #endregion #region Methods: Handling project items /// /// Create a new item in the project /// /// the parent collection for the new item /// /// /// /// public ProjectItem AddNewItemFromVsTemplate(ProjectItems parent, string templateName, string language, string name) { if (parent == null) throw new ArgumentException("project"); if (name == null) throw new ArgumentException("name"); DTE dte = (DTE)VsIdeTestHostContext.ServiceProvider.GetService(typeof(DTE)); Solution2 sol = dte.Solution as Solution2; string filename = sol.GetProjectItemTemplate(templateName, language); parent.AddFromTemplate(filename, name); return parent.Item(name); } /// /// Save an open document. /// /// for filebased documents this is the full path to the document public void SaveDocument(string documentMoniker) { // Get document cookie and hierarchy for the file IVsRunningDocumentTable runningDocumentTableService = (IVsRunningDocumentTable)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsRunningDocumentTable)); uint docCookie; IntPtr docData; IVsHierarchy hierarchy; uint itemId; runningDocumentTableService.FindAndLockDocument( (uint)Microsoft.VisualStudio.Shell.Interop._VSRDTFLAGS.RDT_NoLock, documentMoniker, out hierarchy, out itemId, out docData, out docCookie); // Save the document IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)); solutionService.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, hierarchy, docCookie); } public void CloseInEditorWithoutSaving(string fullFileName) { // Get the RDT service IVsRunningDocumentTable runningDocumentTableService = (IVsRunningDocumentTable)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsRunningDocumentTable)); Assert.IsNotNull(runningDocumentTableService, "Failed to get the Running Document Table Service"); // Get our document cookie and hierarchy for the file uint docCookie; IntPtr docData; IVsHierarchy hierarchy; uint itemId; runningDocumentTableService.FindAndLockDocument( (uint)Microsoft.VisualStudio.Shell.Interop._VSRDTFLAGS.RDT_NoLock, fullFileName, out hierarchy, out itemId, out docData, out docCookie); // Get the SolutionService IVsSolution solutionService = VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)) as IVsSolution; Assert.IsNotNull(solutionService, "Failed to get IVsSolution service"); // Close the document solutionService.CloseSolutionElement( (uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_NoSave, hierarchy, docCookie); } #endregion #region Methods: Handling Toolwindows public bool CanFindToolwindow(Guid persistenceGuid) { IVsUIShell uiShellService = VsIdeTestHostContext.ServiceProvider.GetService(typeof(SVsUIShell)) as IVsUIShell; Assert.IsNotNull(uiShellService); IVsWindowFrame windowFrame; int hr = uiShellService.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fFindFirst, ref persistenceGuid, out windowFrame); Assert.IsTrue(hr == VSConstants.S_OK); return (windowFrame != null); } #endregion #region Methods: Loading packages public IVsPackage LoadPackage(Guid packageGuid) { IVsShell shellService = (IVsShell)VsIdeTestHostContext.ServiceProvider.GetService(typeof(SVsShell)); IVsPackage package; shellService.LoadPackage(ref packageGuid, out package); Assert.IsNotNull(package, "Failed to load package"); return package; } #endregion /// /// Executes a Command (menu item) in the given context /// public void ExecuteCommand(CommandID cmd) { object Customin = null; object Customout = null; string guidString = cmd.Guid.ToString("B").ToUpper(); int cmdId = cmd.ID; DTE dte = VsIdeTestHostContext.Dte; dte.Commands.Raise(guidString, cmdId, ref Customin, ref Customout); } } }