bool FWmfMediaPlayer::Open( const FString& Url ) { if (Url.IsEmpty()) { return false; } TComPtr<IMFSourceResolver> SourceResolver; if (FAILED(::MFCreateSourceResolver(&SourceResolver))) { return false; } // resolve the media source from the given URL MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; TComPtr<IUnknown> SourceObject; if (FAILED(SourceResolver->CreateObjectFromURL(*Url, MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &SourceObject))) { UE_LOG(LogWmfMedia, Error, TEXT("Failed to create source object from URL for %s"), *Url); return false; } return InitializeMediaSession(SourceObject, Url); }
bool FWmfMediaPlayer::Open( const TSharedRef<TArray<uint8>>& Buffer, const FString& OriginalUrl ) { if ((Buffer->Num() == 0) || OriginalUrl.IsEmpty()) { return false; } TComPtr<IMFSourceResolver> SourceResolver; if (FAILED(::MFCreateSourceResolver(&SourceResolver))) { return false; } // create the media source from the given buffer TComPtr<FWmfMediaByteStream> ByteStream = new FWmfMediaByteStream(Buffer); MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID; TComPtr<IUnknown> SourceObject; if (FAILED(SourceResolver->CreateObjectFromByteStream(ByteStream, *OriginalUrl, MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &SourceObject))) { UE_LOG(LogWmfMedia, Error, TEXT("Failed to create source object from buffer for %s"), *OriginalUrl); return false; } return InitializeMediaSession(SourceObject, OriginalUrl); }
bool FVisualStudioSourceCodeAccessor::OpenVisualStudioSolutionViaDTE() { // Initialize the com library, if not already by this thread if (!FWindowsPlatformMisc::CoInitialize()) { UE_LOG(LogVSAccessor, Error, TEXT( "ERROR - Could not initialize COM library!" )); return false; } bool bSuccess = false; TComPtr<EnvDTE::_DTE> DTE; const FString SolutionPath = GetSolutionPath(); switch (AccessVisualStudioViaDTE(DTE, SolutionPath, GetPrioritizedVisualStudioVersions(SolutionPath))) { case EAccessVisualStudioResult::VSInstanceIsOpen: { // Set Focus on Visual Studio TComPtr<EnvDTE::Window> MainWindow; if (SUCCEEDED(DTE->get_MainWindow(&MainWindow)) && SUCCEEDED(MainWindow->Activate())) { bSuccess = true; } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't set focus on Visual Studio.")); } } break; case EAccessVisualStudioResult::VSInstanceIsNotOpen: { // Automatically fail if there's already an attempt in progress if (!IsVSLaunchInProgress()) { bSuccess = RunVisualStudioAndOpenSolution(); } } break; default: // Do nothing if we failed the VS detection, otherwise we could get stuck in a loop of constantly // trying to open a VS instance since we can't detect that one is already running break; } // Uninitialize the com library, if we initialized it above (don't call if S_FALSE) FWindowsPlatformMisc::CoUninitialize(); return bSuccess; }
void FWindowsTextInputMethodSystem::Terminate() { HRESULT Result; // Get source from thread manager, needed to uninstall profile processor related sinks. TComPtr<ITfSource> TSFSource; Result = TSFSource.FromQueryInterface(IID_ITfSource, TSFThreadManager); if(FAILED(Result) || !TSFSource) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Terminating failed while acquiring the TSF source from the TSF thread manager.")); } if(TSFSource && TSFActivationProxy) { // Uninstall language notification sink. if(TSFActivationProxy->TSFLanguageCookie != TF_INVALID_COOKIE) { Result = TSFSource->UnadviseSink(TSFActivationProxy->TSFLanguageCookie); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Terminating failed while unadvising the language notification sink from the TSF source.")); } } // Uninstall profile notification sink. if(TSFActivationProxy->TSFProfileCookie != TF_INVALID_COOKIE) { Result = TSFSource->UnadviseSink(TSFActivationProxy->TSFProfileCookie); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Terminating failed while unadvising the profile notification sink from the TSF source.")); } } } TSFActivationProxy.Reset(); Result = TSFThreadManager->Deactivate(); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Terminating failed while deactivating the TSF thread manager.")); } TSFThreadManager.Reset(); ::ImmDestroyContext(IMMContextId); }
bool FVisualStudioSourceCodeAccessor::SaveAllOpenDocuments() const { bool bSuccess = false; // Initialize the com library, if not already by this thread if (!FWindowsPlatformMisc::CoInitialize()) { UE_LOG(LogVSAccessor, Error, TEXT( "ERROR - Could not initialize COM library!" )); return bSuccess; } TComPtr<EnvDTE::_DTE> DTE; const FString SolutionPath = GetSolutionPath(); if (AccessVisualStudioViaDTE(DTE, SolutionPath, GetPrioritizedVisualStudioVersions(SolutionPath)) == EAccessVisualStudioResult::VSInstanceIsOpen) { // Save all documents TComPtr<EnvDTE::Documents> Documents; if (SUCCEEDED(DTE->get_Documents(&Documents)) && SUCCEEDED(Documents->SaveAll())) { bSuccess = true; } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't save all documents")); } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't access Visual Studio")); } // Uninitialize the com library, if we initialized it above (don't call if S_FALSE) FWindowsPlatformMisc::CoUninitialize(); return bSuccess; }
bool FWindowsTextInputMethodSystem::InitializeTSF() { UE_LOG(LogWindowsTextInputMethodSystem, Verbose, TEXT("Initializing TSF...")); HRESULT Result = S_OK; // Input Processors { // Get input processor profiles. ITfInputProcessorProfiles* RawPointerTSFInputProcessorProfiles; Result = ::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles, reinterpret_cast<void**>(&(RawPointerTSFInputProcessorProfiles))); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while creating the TSF input processor profiles.")); return false; } TSFInputProcessorProfiles.Attach(RawPointerTSFInputProcessorProfiles); // Get input processor profile manager from profiles. Result = TSFInputProcessorProfileManager.FromQueryInterface(IID_ITfInputProcessorProfileMgr, TSFInputProcessorProfiles); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while acquiring the TSF input processor profile manager.")); TSFInputProcessorProfiles.Reset(); return false; } } // Thread Manager { // Create thread manager. ITfThreadMgr* RawPointerTSFThreadManager; Result = ::CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast<void**>(&(RawPointerTSFThreadManager))); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Warning, TEXT("Initialzation failed while creating the TSF thread manager.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); return false; } TSFThreadManager.Attach(RawPointerTSFThreadManager); // Activate thread manager. Result = TSFThreadManager->Activate(&(TSFClientId)); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while activating the TSF thread manager.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); TSFThreadManager.Reset(); return false; } // Get source from thread manager, needed to install profile processor related sinks. TComPtr<ITfSource> TSFSource; Result = TSFSource.FromQueryInterface(IID_ITfSource, TSFThreadManager); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while acquiring the TSF source from TSF thread manager.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); TSFThreadManager.Reset(); return false; } TSFActivationProxy = new FTSFActivationProxy(this); #pragma warning(push) #pragma warning(disable : 4996) // 'function' was was declared deprecated CA_SUPPRESS(28159) const DWORD WindowsVersion = ::GetVersion(); #pragma warning(pop) const DWORD WindowsMajorVersion = LOBYTE(LOWORD(WindowsVersion)); const DWORD WindowsMinorVersion = HIBYTE(LOWORD(WindowsVersion)); static const DWORD WindowsVistaMajorVersion = 6; static const DWORD WindowsVistaMinorVersion = 0; // Install profile notification sink for versions of Windows Vista and after. if(WindowsMajorVersion > WindowsVistaMajorVersion || (WindowsMajorVersion == WindowsVistaMajorVersion && WindowsMinorVersion >= WindowsVistaMinorVersion)) { Result = TSFSource->AdviseSink(IID_ITfInputProcessorProfileActivationSink, static_cast<ITfInputProcessorProfileActivationSink*>(TSFActivationProxy), &(TSFActivationProxy->TSFProfileCookie)); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while advising the profile notification sink to the TSF source.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); TSFThreadManager.Reset(); TSFActivationProxy.Reset(); return false; } } // Install language notification sink for versions before Windows Vista. else { Result = TSFSource->AdviseSink(IID_ITfActiveLanguageProfileNotifySink, static_cast<ITfActiveLanguageProfileNotifySink*>(TSFActivationProxy), &(TSFActivationProxy->TSFLanguageCookie)); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while advising the language notification sink to the TSF source.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); TSFThreadManager.Reset(); TSFActivationProxy.Reset(); return false; } } } // Disabled Document Manager Result = TSFThreadManager->CreateDocumentMgr(&(TSFDisabledDocumentManager)); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Warning, TEXT("Initialzation failed while creating the TSF thread manager.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); TSFThreadManager.Reset(); TSFActivationProxy.Reset(); return false; } // Default the focus to the disabled document manager. Result = TSFThreadManager->SetFocus(TSFDisabledDocumentManager); if(FAILED(Result)) { UE_LOG(LogWindowsTextInputMethodSystem, Error, TEXT("Initialzation failed while activating the TSF thread manager.")); TSFInputProcessorProfiles.Reset(); TSFInputProcessorProfileManager.Reset(); TSFThreadManager.Reset(); TSFActivationProxy.Reset(); TSFThreadManager.Reset(); return false; } UE_LOG(LogWindowsTextInputMethodSystem, Verbose, TEXT("Initialized TSF!")); return true; }
bool FWmfMediaPlayer::InitializeMediaSession( IUnknown* SourceObject, const FString& SourceUrl ) { Close(); if (SourceObject == nullptr) { return false; } UE_LOG(LogWmfMedia, Verbose, TEXT("Initializing media session for %s"), *SourceUrl); // create presentation descriptor TComPtr<IMFMediaSource> MediaSource; if (FAILED(SourceObject->QueryInterface(IID_PPV_ARGS(&MediaSource)))) { UE_LOG(LogWmfMedia, Error, TEXT("Failed to query media source")); return false; } TComPtr<IMFPresentationDescriptor> PresentationDescriptor; if (FAILED(MediaSource->CreatePresentationDescriptor(&PresentationDescriptor))) { UE_LOG(LogWmfMedia, Error, TEXT("Failed to create presentation descriptor")); return false; } // create playback topology DWORD StreamCount = 0; if (FAILED(PresentationDescriptor->GetStreamDescriptorCount(&StreamCount))) { UE_LOG(LogWmfMedia, Error, TEXT("Failed to get stream count")); return false; } TComPtr<IMFTopology> Topology; if (FAILED(::MFCreateTopology(&Topology))) { UE_LOG(LogWmfMedia, Error, TEXT("Failed to create playback topology")); return false; } for (uint32 StreamIndex = 0; StreamIndex < StreamCount; ++StreamIndex) { AddStreamToTopology(StreamIndex, Topology, PresentationDescriptor, MediaSource); } UE_LOG(LogWmfMedia, Verbose, TEXT("Added a total of %i tracks"), Tracks.Num()); UINT64 PresentationDuration = 0; PresentationDescriptor->GetUINT64(MF_PD_DURATION, &PresentationDuration); Duration = FTimespan(PresentationDuration); // create session MediaSession = new FWmfMediaSession(Duration, Topology); MediaUrl = SourceUrl; OpenedEvent.Broadcast(SourceUrl); return (MediaSession->GetState() != EMediaStates::Error); }
void FWmfMediaPlayer::AddStreamToTopology( uint32 StreamIndex, IMFTopology* Topology, IMFPresentationDescriptor* PresentationDescriptor, IMFMediaSource* MediaSource ) { // get stream descriptor TComPtr<IMFStreamDescriptor> StreamDescriptor; BOOL Selected = FALSE; if (FAILED(PresentationDescriptor->GetStreamDescriptorByIndex(StreamIndex, &Selected, &StreamDescriptor))) { UE_LOG(LogWmfMedia, Warning, TEXT("Skipping missing stream descriptor for stream index %i"), StreamIndex); return; } // fetch media type TComPtr<IMFMediaTypeHandler> Handler; if (FAILED(StreamDescriptor->GetMediaTypeHandler(&Handler))) { return; } GUID MajorType; if (FAILED(Handler->GetMajorType(&MajorType))) { return; } // skip unsupported types if ((MajorType != MFMediaType_Audio) && (MajorType != MFMediaType_SAMI) && (MajorType != MFMediaType_Video)) { return; } // prepare input and output types TComPtr<IMFMediaType> OutputType; { if (FAILED(Handler->GetCurrentMediaType(&OutputType))) { return; } } TComPtr<IMFMediaType> InputType; { if (FAILED(::MFCreateMediaType(&InputType))) { return; } if (FAILED(InputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE))) { return; } } if (MajorType == MFMediaType_Audio) { if (FAILED(InputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio)) || FAILED(InputType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM)))/* || FAILED(InputType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_BLOCK, 16384u)))*/ { return; } } else if (MajorType == MFMediaType_SAMI) { if (FAILED(InputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_SAMI))) { return; } } else if (MajorType == MFMediaType_Video) { if (FAILED(InputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) || FAILED(InputType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32))) { return; } } // create sample grabber callback and add to topology TComPtr<FWmfMediaSampler> Sampler = new FWmfMediaSampler(); { TComPtr<IMFActivate> MediaSamplerActivator; if (FAILED(::MFCreateSampleGrabberSinkActivate(InputType, Sampler, &MediaSamplerActivator))) { return; } TComPtr<IMFTopologyNode> SourceNode; { if (FAILED(::MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &SourceNode)) || FAILED(SourceNode->SetUnknown(MF_TOPONODE_SOURCE, MediaSource)) || FAILED(SourceNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, PresentationDescriptor)) || FAILED(SourceNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, StreamDescriptor)) || FAILED(Topology->AddNode(SourceNode))) { return; } } TComPtr<IMFTopologyNode> OutputNode; { if (FAILED(::MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &OutputNode)) || FAILED(OutputNode->SetObject(MediaSamplerActivator)) || FAILED(OutputNode->SetUINT32(MF_TOPONODE_STREAMID, 0)) || FAILED(OutputNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE)) || FAILED(Topology->AddNode(OutputNode))) { return; } } if (FAILED(SourceNode->ConnectOutput(0, OutputNode, 0))) { return; } } // create and add track if (MajorType == MFMediaType_Audio) { Tracks.Add(MakeShareable(new FWmfMediaAudioTrack(OutputType, PresentationDescriptor, Sampler, StreamDescriptor, StreamIndex))); } else if (MajorType == MFMediaType_SAMI) { Tracks.Add(MakeShareable(new FWmfMediaCaptionTrack(OutputType, PresentationDescriptor, Sampler, StreamDescriptor, StreamIndex))); } else if (MajorType == MFMediaType_Video) { Tracks.Add(MakeShareable(new FWmfMediaVideoTrack(OutputType, PresentationDescriptor, Sampler, StreamDescriptor, StreamIndex))); } }
bool FVisualStudioSourceCodeAccessor::AddSourceFiles(const TArray<FString>& AbsoluteSourcePaths, const TArray<FString>& AvailableModules) { // This requires DTE - there is no fallback for this operation when DTE is not available #if VSACCESSOR_HAS_DTE bool bSuccess = true; struct FModuleNameAndPath { FString ModuleBuildFilePath; FString ModulePath; FName ModuleName; }; TArray<FModuleNameAndPath> ModuleNamesAndPaths; ModuleNamesAndPaths.Reserve(AvailableModules.Num()); for (const FString& AvailableModule : AvailableModules) { static const int32 BuildFileExtensionLen = FString(TEXT(".Build.cs")).Len(); // AvailableModule is the relative path to the .Build.cs file FModuleNameAndPath ModuleNameAndPath; ModuleNameAndPath.ModuleBuildFilePath = FPaths::ConvertRelativePathToFull(AvailableModule); ModuleNameAndPath.ModulePath = FPaths::GetPath(ModuleNameAndPath.ModuleBuildFilePath); ModuleNameAndPath.ModuleName = *FPaths::GetCleanFilename(ModuleNameAndPath.ModuleBuildFilePath).LeftChop(BuildFileExtensionLen); ModuleNamesAndPaths.Add(ModuleNameAndPath); } struct FModuleNewSourceFiles { FModuleNameAndPath ModuleNameAndPath; TArray<FString> NewSourceFiles; }; // Work out which module each source file will be in TMap<FName, FModuleNewSourceFiles> ModuleToNewSourceFiles; { const FModuleNameAndPath* LastSourceFilesModule = nullptr; for (const FString& SourceFile : AbsoluteSourcePaths) { // First check to see if this source file is in the same module as the last source file - this is usually the case, and saves us a lot of string compares if (LastSourceFilesModule && SourceFile.StartsWith(LastSourceFilesModule->ModulePath)) { FModuleNewSourceFiles& ModuleNewSourceFiles = ModuleToNewSourceFiles.FindChecked(LastSourceFilesModule->ModuleName); ModuleNewSourceFiles.NewSourceFiles.Add(SourceFile); continue; } // Look for the module which will contain this file LastSourceFilesModule = nullptr; for (const FModuleNameAndPath& ModuleNameAndPath : ModuleNamesAndPaths) { if (SourceFile.StartsWith(ModuleNameAndPath.ModulePath)) { LastSourceFilesModule = &ModuleNameAndPath; FModuleNewSourceFiles& ModuleNewSourceFiles = ModuleToNewSourceFiles.FindOrAdd(ModuleNameAndPath.ModuleName); ModuleNewSourceFiles.ModuleNameAndPath = ModuleNameAndPath; ModuleNewSourceFiles.NewSourceFiles.Add(SourceFile); break; } } // Failed to find the module for this source file? if (!LastSourceFilesModule) { UE_LOG(LogVSAccessor, Warning, TEXT("Cannot add source file '%s' as it doesn't belong to a known module"), *SourceFile); bSuccess = false; } } } TComPtr<EnvDTE::_DTE> DTE; const FString SolutionPath = GetSolutionPath(); if (AccessVisualStudioViaDTE(DTE, SolutionPath, GetPrioritizedVisualStudioVersions(SolutionPath)) == EAccessVisualStudioResult::VSInstanceIsOpen) { TComPtr<EnvDTE::_Solution> Solution; if (SUCCEEDED(DTE->get_Solution(&Solution)) && Solution) { // Process each module for (const auto& ModuleNewSourceFilesKeyValue : ModuleToNewSourceFiles) { const FModuleNewSourceFiles& ModuleNewSourceFiles = ModuleNewSourceFilesKeyValue.Value; const FString& ModuleBuildFilePath = ModuleNewSourceFiles.ModuleNameAndPath.ModuleBuildFilePath; auto ANSIModuleBuildFilePath = StringCast<ANSICHAR>(*ModuleBuildFilePath); FComBSTR COMStrModuleBuildFilePath(ANSIModuleBuildFilePath.Get()); TComPtr<EnvDTE::ProjectItem> BuildFileProjectItem; if (SUCCEEDED(Solution->FindProjectItem(COMStrModuleBuildFilePath, &BuildFileProjectItem)) && BuildFileProjectItem) { // We found the .Build.cs file in the existing solution - now we need its parent ProjectItems as that's what we'll be adding new content to TComPtr<EnvDTE::ProjectItems> ModuleProjectFolder; if (SUCCEEDED(BuildFileProjectItem->get_Collection(&ModuleProjectFolder)) && ModuleProjectFolder) { for (const FString& SourceFile : AbsoluteSourcePaths) { const FString ProjectRelativeSourceFilePath = SourceFile.Mid(ModuleNewSourceFiles.ModuleNameAndPath.ModulePath.Len()); TArray<FString> SourceFileParts; ProjectRelativeSourceFilePath.ParseIntoArray(SourceFileParts, TEXT("/"), true); if (SourceFileParts.Num() == 0) { // This should never happen as it means we somehow have no filename within the project directory bSuccess = false; continue; } TComPtr<EnvDTE::ProjectItems> CurProjectItems = ModuleProjectFolder; // Firstly we need to make sure that all the folders we need exist - this also walks us down to the correct place to add the file for (int32 FilePartIndex = 0; FilePartIndex < SourceFileParts.Num() - 1 && CurProjectItems; ++FilePartIndex) { const FString& SourceFilePart = SourceFileParts[FilePartIndex]; auto ANSIPart = StringCast<ANSICHAR>(*SourceFilePart); FComBSTR COMStrFilePart(ANSIPart.Get()); ::VARIANT vProjectItemName; vProjectItemName.vt = VT_BSTR; vProjectItemName.bstrVal = COMStrFilePart; TComPtr<EnvDTE::ProjectItem> ProjectItem; if (SUCCEEDED(CurProjectItems->Item(vProjectItemName, &ProjectItem)) && !ProjectItem) { // Add this part CurProjectItems->AddFolder(COMStrFilePart, nullptr, &ProjectItem); } if (ProjectItem) { ProjectItem->get_ProjectItems(&CurProjectItems); } else { CurProjectItems = nullptr; } } if (!CurProjectItems) { // Failed to find or add all the path parts bSuccess = false; continue; } // Now we add the file to the project under the last folder we found along its path auto ANSIPath = StringCast<ANSICHAR>(*SourceFile); FComBSTR COMStrFileName(ANSIPath.Get()); TComPtr<EnvDTE::ProjectItem> FileProjectItem; if (SUCCEEDED(CurProjectItems->AddFromFile(COMStrFileName, &FileProjectItem))) { bSuccess &= true; } } // Save the updated project to avoid a message when closing VS TComPtr<EnvDTE::Project> Project; if (SUCCEEDED(ModuleProjectFolder->get_ContainingProject(&Project)) && Project) { Project->Save(nullptr); } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Cannot add source files as we failed to get the parent items container for the '%s' item"), *ModuleBuildFilePath); bSuccess = false; } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Cannot add source files as we failed to find '%s' in the solution"), *ModuleBuildFilePath); bSuccess = false; } } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Cannot add source files as Visual Studio failed to return a solution when queried")); bSuccess = false; } } else { UE_LOG(LogVSAccessor, Verbose, TEXT("Cannot add source files as Visual Studio is either not open or not responding")); bSuccess = false; } return bSuccess; #endif return false; }
bool FVisualStudioSourceCodeAccessor::OpenVisualStudioFilesInternalViaDTE(const TArray<FileOpenRequest>& Requests, bool& bWasDeferred) { ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>(TEXT("SourceCodeAccess")); // Initialize the com library, if not already by this thread if (!FWindowsPlatformMisc::CoInitialize()) { UE_LOG(LogVSAccessor, Error, TEXT( "ERROR - Could not initialize COM library!" )); return false; } bool bDefer = false, bSuccess = false; TComPtr<EnvDTE::_DTE> DTE; const FString SolutionPath = GetSolutionPath(); switch (AccessVisualStudioViaDTE(DTE, SolutionPath, GetPrioritizedVisualStudioVersions(SolutionPath))) { case EAccessVisualStudioResult::VSInstanceIsOpen: { // Set Focus on Visual Studio TComPtr<EnvDTE::Window> MainWindow; if (SUCCEEDED(DTE->get_MainWindow(&MainWindow)) && SUCCEEDED(MainWindow->Activate())) { // Get ItemOperations TComPtr<EnvDTE::ItemOperations> ItemOperations; if (SUCCEEDED(DTE->get_ItemOperations(&ItemOperations))) { for ( const FileOpenRequest& Request : Requests ) { // Check that the file actually exists first if ( !FPaths::FileExists(Request.FullPath) ) { SourceCodeAccessModule.OnOpenFileFailed().Broadcast(Request.FullPath); bSuccess |= false; continue; } // Open File auto ANSIPath = StringCast<ANSICHAR>(*Request.FullPath); FComBSTR COMStrFileName(ANSIPath.Get()); FComBSTR COMStrKind(EnvDTE::vsViewKindTextView); TComPtr<EnvDTE::Window> Window; if ( SUCCEEDED(ItemOperations->OpenFile(COMStrFileName, COMStrKind, &Window)) ) { // If we've made it this far - we've opened the file. it doesn't matter if // we successfully get to the line number. Everything else is gravy. bSuccess |= true; // Scroll to Line Number TComPtr<EnvDTE::Document> Document; TComPtr<IDispatch> SelectionDispatch; TComPtr<EnvDTE::TextSelection> Selection; if ( SUCCEEDED(DTE->get_ActiveDocument(&Document)) && SUCCEEDED(Document->get_Selection(&SelectionDispatch)) && SelectionDispatch && SUCCEEDED(SelectionDispatch->QueryInterface(&Selection)) && SUCCEEDED(Selection->GotoLine(Request.LineNumber, VARIANT_TRUE)) ) { if ( !SUCCEEDED(Selection->MoveToLineAndOffset(Request.LineNumber, Request.ColumnNumber, false)) ) { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't goto column number '%i' of line '%i' in '%s'"), Request.ColumnNumber, Request.LineNumber, *Request.FullPath); } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't goto line number '%i' in '%s'"), Request.LineNumber, *Request.FullPath); } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't open file '%s'."), *Request.FullPath); } } VSLaunchFinished( true ); } else { UE_LOG(LogVSAccessor, Log, TEXT("Couldn't get item operations. Visual Studio may still be initializing.")); bDefer = true; } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't set focus on Visual Studio.")); } } break; case EAccessVisualStudioResult::VSInstanceIsNotOpen: { bDefer = true; // We can't process until we're in the main thread, if we aren't initially defer until we are if ( IsInGameThread() ) { // If we haven't already attempted to launch VS do so now if ( !IsVSLaunchInProgress() ) { // If there's no valid instance of VS running, run one if we have it installed if ( !RunVisualStudioAndOpenSolution() ) { bDefer = false; } else { VSLaunchStarted(); } } } } break; case EAccessVisualStudioResult::VSInstanceIsBlocked: { // VS may be open for the solution we want, but we can't query it right now as it's blocked for some reason // Defer this operation so we can try it again later should VS become unblocked bDefer = true; } break; default: // Do nothing if we failed the VS detection, otherwise we could get stuck in a loop of constantly // trying to open a VS instance since we can't detect that one is already running bDefer = false; break; } if ( !bSuccess ) { // If we have attempted to launch VS, and it's taken too long, timeout so the user can try again if ( IsVSLaunchInProgress() && ( FPlatformTime::Seconds() - VSLaunchTime ) > 300 ) { // We need todo this in case the process died or was kill prior to the code gaining focus of it bDefer = false; VSLaunchFinished(false); // We failed to open the solution and file, so lets just use the platforms default opener. for ( const FileOpenRequest& Request : Requests ) { FPlatformProcess::LaunchFileInDefaultExternalApplication(*Request.FullPath); } } // Defer the request until VS is available to take hold of if ( bDefer ) { FScopeLock Lock(&DeferredRequestsCriticalSection); DeferredRequests.Append(Requests); } else if ( !bSuccess ) { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't access Visual Studio")); } } // Uninitialize the com library, if we initialized it above (don't call if S_FALSE) FWindowsPlatformMisc::CoUninitialize(); bWasDeferred = bDefer; return bSuccess; }
/** Accesses the correct visual studio instance if possible. */ EAccessVisualStudioResult AccessVisualStudioViaDTE(TComPtr<EnvDTE::_DTE>& OutDTE, const FString& InSolutionPath, const TArray<FVisualStudioSourceCodeAccessor::VisualStudioLocation>& InLocations) { EAccessVisualStudioResult AccessResult = EAccessVisualStudioResult::VSInstanceIsNotOpen; // Open the Running Object Table (ROT) IRunningObjectTable* RunningObjectTable; if(SUCCEEDED(GetRunningObjectTable(0, &RunningObjectTable)) && RunningObjectTable) { IEnumMoniker* MonikersTable; if(SUCCEEDED(RunningObjectTable->EnumRunning(&MonikersTable))) { MonikersTable->Reset(); // Look for all visual studio instances in the ROT IMoniker* CurrentMoniker; while(AccessResult != EAccessVisualStudioResult::VSInstanceIsOpen && MonikersTable->Next(1, &CurrentMoniker, NULL) == S_OK) { IBindCtx* BindContext; LPOLESTR OutName; if(SUCCEEDED(CreateBindCtx(0, &BindContext)) && SUCCEEDED(CurrentMoniker->GetDisplayName(BindContext, NULL, &OutName))) { if(IsVisualStudioDTEMoniker(FString(OutName), InLocations)) { TComPtr<IUnknown> ComObject; if(SUCCEEDED(RunningObjectTable->GetObject(CurrentMoniker, &ComObject))) { TComPtr<EnvDTE::_DTE> TempDTE; if (SUCCEEDED(TempDTE.FromQueryInterface(__uuidof(EnvDTE::_DTE), ComObject))) { // Get the solution path for this instance // If it equals the solution we would have opened above in RunVisualStudio(), we'll take that TComPtr<EnvDTE::_Solution> Solution; BSTR OutPath = nullptr; if (SUCCEEDED(TempDTE->get_Solution(&Solution)) && SUCCEEDED(Solution->get_FullName(&OutPath))) { FString Filename(OutPath); FPaths::NormalizeFilename(Filename); if (Filename == InSolutionPath) { OutDTE = TempDTE; AccessResult = EAccessVisualStudioResult::VSInstanceIsOpen; } SysFreeString(OutPath); } else { UE_LOG(LogVSAccessor, Warning, TEXT("Visual Studio is open but could not be queried - it may be blocked by a modal operation")); AccessResult = EAccessVisualStudioResult::VSInstanceIsBlocked; } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Could not get DTE interface from returned Visual Studio instance")); AccessResult = EAccessVisualStudioResult::VSInstanceIsBlocked; } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't get Visual Studio COM object")); AccessResult = EAccessVisualStudioResult::VSInstanceUnknown; } } } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't get display name")); AccessResult = EAccessVisualStudioResult::VSInstanceUnknown; } BindContext->Release(); CurrentMoniker->Release(); } MonikersTable->Release(); } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't enumerate ROT table")); AccessResult = EAccessVisualStudioResult::VSInstanceUnknown; } RunningObjectTable->Release(); } else { UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't get ROT table")); AccessResult = EAccessVisualStudioResult::VSInstanceUnknown; } return AccessResult; }