void FFeaturePackContentSourceProvider::StartUpDirectoryWatcher() { FDirectoryWatcherModule& DirectoryWatcherModule = FModuleManager::LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher")); IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get(); if (DirectoryWatcher) { // If the path doesn't exist on disk, make it so the watcher will work. IFileManager::Get().MakeDirectory(*FeaturePackPath); DirectoryChangedDelegate = IDirectoryWatcher::FDirectoryChanged::CreateRaw(this, &FFeaturePackContentSourceProvider::OnFeaturePackDirectoryChanged); DirectoryWatcher->RegisterDirectoryChangedCallback_Handle(FeaturePackPath, DirectoryChangedDelegate, DirectoryChangedDelegateHandle); } }
void UDirectoryWatcher::Watch(const FString& InDirectory) { Unwatch(); FDirectoryWatcherModule& DirectoryWatcherModule = FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher")); IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get(); Directory = FPaths::IsRelative(InDirectory) ? FPaths::ConvertRelativePathToFull(InDirectory) : InDirectory; Changed = IDirectoryWatcher::FDirectoryChanged::CreateLambda([&](const TArray<FFileChangeData>& FileChanges){ for (auto Change : FileChanges) { FPaths::NormalizeFilename(Change.Filename); switch (Change.Action) { case FFileChangeData::FCA_Added: Added.Add(Change.Filename); break; case FFileChangeData::FCA_Modified: Modified.Add(Change.Filename); break; case FFileChangeData::FCA_Removed: Removed.Add(Change.Filename); break; } } OnChanged.Broadcast(); Added.Empty(); Modified.Empty(); Removed.Empty(); }); if (IFileManager::Get().DirectoryExists(*Directory)) { DirectoryWatcher->RegisterDirectoryChangedCallback_Handle(Directory, Changed, DelegateHandle, true); } }
/** * Kicks directory watcher test/ */ int32 DirectoryWatcherTest(const TCHAR* CommandLine) { FPlatformMisc::SetCrashHandler(NULL); FPlatformMisc::SetGracefulTerminationHandler(); GEngineLoop.PreInit(CommandLine); UE_LOG(LogTestPAL, Display, TEXT("Running directory watcher test.")); IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); FString TestDir = FString::Printf(TEXT("%sDirectoryWatcherTest%d"), FPlatformProcess::UserTempDir(), FPlatformProcess::GetCurrentProcessId()); if (PlatformFile.CreateDirectory(*TestDir) && PlatformFile.CreateDirectory(*(TestDir + TEXT("/subtest")))) { FChangeDetector Detector; FDelegateHandle DirectoryChangedHandle; IDirectoryWatcher* DirectoryWatcher = FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher")).Get(); if (DirectoryWatcher) { auto Callback = IDirectoryWatcher::FDirectoryChanged::CreateRaw(&Detector, &FChangeDetector::OnDirectoryChanged); DirectoryWatcher->RegisterDirectoryChangedCallback_Handle(TestDir, Callback, DirectoryChangedHandle); UE_LOG(LogTestPAL, Display, TEXT("Registered callback for changes in '%s'"), *TestDir); } else { UE_LOG(LogTestPAL, Fatal, TEXT("Could not get DirectoryWatcher module")); } FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // create and remove directory UE_LOG(LogTestPAL, Display, TEXT("Creating DIRECTORY '%s'"), *(TestDir + TEXT("/test"))); verify(PlatformFile.CreateDirectory(*(TestDir + TEXT("/test")))); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); UE_LOG(LogTestPAL, Display, TEXT("Deleting DIRECTORY '%s'"), *(TestDir + TEXT("/test"))); verify(PlatformFile.DeleteDirectory(*(TestDir + TEXT("/test")))); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // create and remove in a sub directory UE_LOG(LogTestPAL, Display, TEXT("Creating DIRECTORY '%s'"), *(TestDir + TEXT("/subtest/blah"))); verify(PlatformFile.CreateDirectory(*(TestDir + TEXT("/subtest/blah")))); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); UE_LOG(LogTestPAL, Display, TEXT("Deleting DIRECTORY '%s'"), *(TestDir + TEXT("/subtest/blah"))); verify(PlatformFile.DeleteDirectory(*(TestDir + TEXT("/subtest/blah")))); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); { // create file FString DummyFileName = TestDir + TEXT("/test file.bin"); UE_LOG(LogTestPAL, Display, TEXT("Creating FILE '%s'"), *DummyFileName); IFileHandle* DummyFile = PlatformFile.OpenWrite(*DummyFileName); check(DummyFile); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // modify file UE_LOG(LogTestPAL, Display, TEXT("Modifying FILE '%s'"), *DummyFileName); uint8 Contents = 0; DummyFile->Write(&Contents, sizeof(Contents)); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // close the file UE_LOG(LogTestPAL, Display, TEXT("Closing FILE '%s'"), *DummyFileName); delete DummyFile; DummyFile = nullptr; DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // delete file UE_LOG(LogTestPAL, Display, TEXT("Deleting FILE '%s'"), *DummyFileName); verify(PlatformFile.DeleteFile(*DummyFileName)); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); } // now the same in a grandchild directory { FString GrandChildDir = TestDir + TEXT("/subtest/grandchild"); UE_LOG(LogTestPAL, Display, TEXT("Creating DIRECTORY '%s'"), *GrandChildDir); verify(PlatformFile.CreateDirectory(*GrandChildDir)); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); { // create file FString DummyFileName = GrandChildDir + TEXT("/test file.bin"); UE_LOG(LogTestPAL, Display, TEXT("Creating FILE '%s'"), *DummyFileName); IFileHandle* DummyFile = PlatformFile.OpenWrite(*DummyFileName); check(DummyFile); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // modify file UE_LOG(LogTestPAL, Display, TEXT("Modifying FILE '%s'"), *DummyFileName); uint8 Contents = 0; DummyFile->Write(&Contents, sizeof(Contents)); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // close the file UE_LOG(LogTestPAL, Display, TEXT("Closing FILE '%s'"), *DummyFileName); delete DummyFile; DummyFile = nullptr; DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); // delete file UE_LOG(LogTestPAL, Display, TEXT("Deleting FILE '%s'"), *DummyFileName); PlatformFile.DeleteFile(*DummyFileName); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); } UE_LOG(LogTestPAL, Display, TEXT("Deleting DIRECTORY '%s'"), *GrandChildDir); verify(PlatformFile.DeleteDirectory(*GrandChildDir)); DirectoryWatcher->Tick(1.0f); FPlatformProcess::Sleep(1.0f); DirectoryWatcher->Tick(1.0f); } // clean up verify(DirectoryWatcher->UnregisterDirectoryChangedCallback_Handle(TestDir, DirectoryChangedHandle)); // remove dirs as well verify(PlatformFile.DeleteDirectory(*(TestDir + TEXT("/subtest")))); verify(PlatformFile.DeleteDirectory(*TestDir)); UE_LOG(LogTestPAL, Display, TEXT("End of test")); } else { UE_LOG(LogTestPAL, Fatal, TEXT("Could not create test directory %s."), *TestDir); } FEngineLoop::AppPreExit(); FEngineLoop::AppExit(); return 0; }