public void TestSaveAsSameLocation() { UIThreadInvoker.Invoke((ThreadInvoker) delegate() { //Get the global service provider and the dte IServiceProvider sp = VsIdeTestHostContext.ServiceProvider; DTE dte = (DTE)sp.GetService(typeof(DTE)); //Create a project and get the first filenode string destination = Path.Combine(TestContext.TestDir, TestContext.TestName); ProjectNode project = Utilities.CreateMyNestedProject(sp, dte, TestContext.TestName, destination, true); FileNode fileNode = GetFirstFileNode(project); //open the item before we can do the SaveAs op ProjectItem item = ((OAFileItem)fileNode.GetAutomationObject()); Window window = item.Open(EnvDTE.Constants.vsViewKindPrimary); Assert.IsNotNull(window, "Did not get a reference to the window for the file just opened"); if (!window.Visible) { window.Visible = true; } //SaveAs string newNameOfFile = "Test.cs"; string updatedFileName = Path.Combine(project.ProjectFolder, newNameOfFile); item.SaveAs(updatedFileName); //Verify Caption in window of the file renamed Assert.IsTrue(string.Compare(window.Caption, newNameOfFile, true) == 0, "Caption of window does not match the new filename"); //Verify full path to document Assert.IsTrue(string.Compare(window.Document.FullName, updatedFileName, true) == 0, "FullName of document is not as expected"); }); }
protected virtual string UpdateGeneratedCodeFile(FileNode fileNode, byte[] data, int size, string fileName, HierarchyNode dependentNode) { string filePath = Path.Combine(Path.GetDirectoryName(fileNode.GetMkDocument()), fileName); IVsRunningDocumentTable rdt = this.ProjectMgr.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable; // (kberes) Shouldn't this be an InvalidOperationException instead with some not to annoying errormessage to the user? if (rdt == null) { ErrorHandler.ThrowOnFailure(VSConstants.E_FAIL); } IVsHierarchy hier; uint cookie; uint itemid; IntPtr docData = IntPtr.Zero; ErrorHandler.ThrowOnFailure(rdt.FindAndLockDocument((uint)(_VSRDTFLAGS.RDT_NoLock), filePath, out hier, out itemid, out docData, out cookie)); if (docData != IntPtr.Zero) { Marshal.Release(docData); IVsTextStream srpStream; string inputFileContents = this.GetBufferContents(filePath, out srpStream); if (srpStream != null) { int oldLen = 0; int hr = srpStream.GetSize(out oldLen); if (ErrorHandler.Succeeded(hr)) { IntPtr dest = IntPtr.Zero; try { if (data.Length > 2 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) { // the data is in UTF-8 format and must be converted to Unicode, since the IVsTextStream // buffer is always Unicode // // The ResXCodeGenerator generates UTF-8 code, other SingleFileGenerators might do the same thing, who knows? string txt = new System.Text.UTF8Encoding().GetString(data, 3, data.Length - 3); // skip over encoding preamble UnicodeEncoding enc = new UnicodeEncoding(); int len = enc.GetByteCount(txt); Byte[] unicodeData = new Byte[len]; enc.GetBytes(txt, 0, txt.Length, unicodeData, 0); dest = Marshal.AllocCoTaskMem(len); Marshal.Copy(unicodeData, 0, dest, unicodeData.Length); ErrorHandler.ThrowOnFailure(srpStream.ReplaceStream(0, oldLen, dest, len / 2)); // Note: 4th param is # of chars, not bytes! } // end of changes else { dest = Marshal.AllocCoTaskMem(data.Length); Marshal.Copy(data, 0, dest, data.Length); ErrorHandler.ThrowOnFailure(srpStream.ReplaceStream(0, oldLen, dest, size / 2)); } // for now, always save the generated file. Otherwise we have issues when the source file is dirty and the user // builds the project. The generator runs (because of the overridden SaveItem() in the project node) but the generated // file ends up dirty and when the project is built, everything should be saved. // We could probably force a save on that node, but it seems cleaner to always save the generated file. int canceled; ErrorHandler.ThrowOnFailure(this.ProjectMgr.SaveItem(VSSAVEFLAGS.VSSAVE_SilentSave, filePath, dependentNode.ID, docData, out canceled)); } finally { if (dest != IntPtr.Zero) { Marshal.Release(dest); } } } } } else { using (FileStream generatedFileStream = File.Open(filePath, FileMode.OpenOrCreate)) { generatedFileStream.Write(data, 0, size); // adjust length, in case the file shrinks in size.. generatedFileStream.SetLength(size); } EnvDTE.ProjectItem projectItem = fileNode.GetAutomationObject() as EnvDTE.ProjectItem; if (projectItem != null && (this.ProjectMgr.FindChild(fileNode.FileName) == null)) { projectItem.ProjectItems.AddFromFile(filePath); } } return(filePath); }
/// <summary> /// This is called after the single file generator has been invoked to create or update the code file. /// </summary> /// <param name="fileNode">The node associated to the generator</param> /// <param name="data">data to update the file with</param> /// <param name="size">size of the data</param> /// <param name="fileName">Name of the file to update or create</param> /// <returns>full path of the file</returns> /*protected, but public for FSharp.Project.dll*/ public virtual string UpdateGeneratedCodeFile(FileNode fileNode, byte[] data, int size, string fileName) { string filePath = Path.Combine(Path.GetDirectoryName(fileNode.GetMkDocument()), fileName); IVsRunningDocumentTable rdt = this.projectMgr.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable; // (kberes) Shouldn't this be an InvalidOperationException instead with some not to annoying errormessage to the user? if (rdt == null) { ErrorHandler.ThrowOnFailure(VSConstants.E_FAIL); } IVsHierarchy hier; uint cookie; uint itemid; IntPtr docData = IntPtr.Zero; try { ErrorHandler.ThrowOnFailure(rdt.FindAndLockDocument((uint)(_VSRDTFLAGS.RDT_NoLock), filePath, out hier, out itemid, out docData, out cookie)); } catch (Exception) { if (docData != IntPtr.Zero) Marshal.Release(docData); throw; } if (docData != IntPtr.Zero) { Marshal.Release(docData); IVsTextStream srpStream; string inputFileContents = this.GetBufferContents(filePath, out srpStream); if (srpStream != null) { int oldLen = 0; int hr = srpStream.GetSize(out oldLen); if (ErrorHandler.Succeeded(hr)) { IntPtr dest = IntPtr.Zero; try { dest = Marshal.AllocCoTaskMem(data.Length); Marshal.Copy(data, 0, dest, data.Length); ErrorHandler.ThrowOnFailure(srpStream.ReplaceStream(0, oldLen, dest, size / 2)); } finally { if (dest != IntPtr.Zero) { Marshal.FreeCoTaskMem(dest); } } } } } else { using (FileStream generatedFileStream = File.Open(filePath, FileMode.OpenOrCreate)) { generatedFileStream.Write(data, 0, size); } EnvDTE.ProjectItem projectItem = fileNode.GetAutomationObject() as EnvDTE.ProjectItem; if (projectItem != null && (this.projectMgr.FindChild(fileNode.FileName) == null)) { projectItem.ProjectItems.AddFromFile(filePath); } } return filePath; }