Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Every couple of weeks, I'll get a question about getting an arbitrary file on disk into a project in VS without asking VS to open in a document window directly. It seems to be pretty hard to find information for (when I needed to do it, it took a few email threads with various other teams to figure it out), so here's a code snippet I use for this. It works by adding the file to the miscellaneous files project (if it isn't already in another project) and then returning the hierarchy/itemid for the file, which can be used with other methods involving the shell, opening documents, locking documents, etc.
///
<summary>
///
If the given file isn't in a project, put it in the miscellaneous files project, and return
///
the project/itemid of the file.
///
</summary>
///
<returns>hresult (failure code)</returns>
static int
EnsureFileInAProject(string
fileName,
out
IVsUIHierarchy hierarchy, out uint itemId)
{
IVsUIShellOpenDocument shellOpenDocument = ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShellOpenDocument))
as
IVsUIShellOpenDocument;
IOleServiceProvider unused;
int
pDocInAProject;
// Before we can take a lock, we need to make sure the given doc data is in a project.
// First, ask the shell if it already is
if
(ErrorHandler.Failed(shellOpenDocument.IsDocumentInAProject(fileName,
out
hierarchy,
out
itemId,
out
unused,
out
pDocInAProject)))
{
Debug.Fail("IsDocumentInAProject failed, which is unexpected.");
return
VSConstants.E_FAIL;
}
// We need to add it to the miscellaneous files project if it isn't in a project.
if
(pDocInAProject == (int)__VSDOCINPROJECT.DOCINPROJ_DocNotInProject)
{
var
externalFilesManager = Shell.Package.GetGlobalService(typeof(SVsExternalFilesManager))
as
IVsExternalFilesManager;
if
(externalFilesManager == null)
{
Debug.Fail("Can't find the miscellaneous files project to use.");
return
VSConstants.E_FAIL;
}
// Make sure the misc files project doesn't actually *open* the document
uint
createFlags = (uint)__VSCREATEDOCWIN.CDW_RDTFLAGS_MASK | (uint)_VSRDTFLAGS.RDT_PlaceHolderDoc;
Guid
emptyGuid = Guid.Empty;
int
unusedPos;
IVsWindowFrame unusedFrame;
if
(ErrorHandler.Failed(externalFilesManager.AddDocument(createFlags, fileName, IntPtr.Zero,
IntPtr.Zero,
ref
emptyGuid,
null, ref emptyGuid,
null, null, out unusedPos,
out
unusedFrame)))
{
Debug.Fail("Couldn't add the document to miscellaneous files project.");
return
VSConstants.E_FAIL;
}
IVsProject miscProject;
if
(ErrorHandler.Failed(externalFilesManager.GetExternalFilesProject(out
miscProject)) ||
(hierarchy = miscProject as IVsUIHierarchy) ==
null
||
ErrorHandler.Failed(hierarchy.ParseCanonicalName(fileName,
out
itemId)))
{
Debug.Fail("Couldn't get the misc files project or item we just added.");
return
VSConstants.E_FAIL;
}
}
return
VSConstants.S_OK;
}