public void Equality() { var projA = new ProjectId("xml", "monkey", null); var projB = new ProjectId("xml", "monkey", null); Assert.AreEqual(FDOBackendProviderType.kXML, projA.Type); Assert.IsTrue(projA.Equals(projB)); Assert.AreEqual(projA.GetHashCode(), projB.GetHashCode()); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Checks to see whether this instance is connected to the requested project. If so, /// starts up the requested app or activates a main window for that app if already /// running. /// </summary> /// <param name="projectId">The requested project ID.</param> /// <param name="args">The application arguments</param> /// <returns>The result of checking to see if the specified project matches the /// project this instance is running</returns> /// ------------------------------------------------------------------------------------ public ProjectMatch HandleOpenProjectRequest(ProjectId projectId, FwAppArgs args) { ProjectMatch isMyProject = FieldWorks.GetProjectMatchStatus(projectId); if (isMyProject != ProjectMatch.ItsMyProject) return isMyProject; FieldWorks.KickOffAppFromOtherProcess(args); return ProjectMatch.ItsMyProject; // The request has been handled at this point }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handles a link request. This handles determining the correct application to start /// up and for the correct project. This method is thread safe. /// </summary> /// <param name="link">The link.</param> /// ------------------------------------------------------------------------------------ internal static void HandleLinkRequest(FwAppArgs link) { s_threadHelper.Invoke(() => { Debug.Assert(s_projectId != null, "We shouldn't try to handle a link request until an application is started"); ProjectId linkedProject = new ProjectId(link.DatabaseType, link.Database, link.Server); if (IsSharedXmlBackendNeeded(linkedProject)) linkedProject.Type = FDOBackendProviderType.kSharedXML; if (linkedProject.Equals(s_projectId)) FollowLink(link); else if (!TryFindLinkHandler(link)) { // No other FieldWorks process was running that could handle the request, so // start a brand new process for the project requested by the link. // REVIEW: it might look strange to dispose the return value of OpenProjectWithNewProcess. // However, that is a Process that gets started, and it is ok to dispose that // right away if we don't work with the process object. It might be better // though to change the signature of OpenProjectWithNewProcess to return // a boolean (true iff the link was successfully handled). using (OpenProjectWithNewProcess(linkedProject, link.AppAbbrev, "-" + FwLinkArgs.kLink, link.ToString())) { } } }); }
public void CheckProperties() { string expectedProjectDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "SomeTest"); m_mockFileOs.ExistingDirectories.Add(expectedProjectDir); const string type = "db4ocs"; const string host = "127.0.0.1"; string filename = FdoFileHelper.GetDb4oDataFileName("SomeTest"); var proj = new ProjectId(type, filename, host); proj.AssertValid(); Assert.AreEqual(Path.Combine(expectedProjectDir, filename), proj.Path); proj = new ProjectId(filename, host); proj.AssertValid(); Assert.AreEqual(Path.Combine(expectedProjectDir, filename), proj.Path); }
public void AssertValid_InvalidProjectType() { var proj = new ProjectId(FDOBackendProviderType.kInvalid, FdoFileHelper.GetXmlDataFileName("invalid"), null); try { proj.AssertValid(); Assert.Fail("FwStartupException expected"); } catch (StartupException exception) { Assert.IsTrue(exception.ReportToUser); } }
public void AssertValid_Invalid_NoName() { var proj = new ProjectId(string.Empty, null); try { proj.AssertValid(); Assert.Fail("FwStartupException expected"); } catch (StartupException exception) { Assert.IsFalse(exception.ReportToUser); } }
public void CleanUpNameForType_XML_RelativePath() { string relativePath = Path.Combine("primate", FdoFileHelper.GetXmlDataFileName("monkey")); string expectedPath = Path.Combine(FwDirectoryFinder.ProjectsDirectory, relativePath); m_mockFileOs.AddExistingFile(expectedPath); ProjectId proj = new ProjectId(relativePath, null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); }
public void CleanUpNameForType_XML_NameWithPeriod_NotExist() { string expectedPath = GetXmlProjectFilename("my.monkey"); m_mockFileOs.AddExistingFile(expectedPath); var proj = new ProjectId("my.monkey", null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); }
private static FdoCache CreateCache(ProjectId projectId) { Debug.Assert(projectId.IsValid); WriteSplashScreen(string.Format(Properties.Resources.kstidLoadingProject, projectId.UiName)); Form owner = s_splashScreen != null ? s_splashScreen.Form : Form.ActiveForm; using (var progressDlg = new ProgressDialogWithTask(owner)) { FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, s_ui, FwDirectoryFinder.FdoDirectories, CreateFdoSettings(), progressDlg); EnsureValidLinkedFilesFolder(cache); // Make sure every project has one of these. (Getting it has a side effect if it does not exist.) // Crashes have been caused by trying to create it at an unsafe time (LT-15695). var dummy = cache.LangProject.DefaultPronunciationWritingSystem; cache.ProjectNameChanged += ProjectNameChanged; cache.ServiceLocator.GetInstance<IUndoStackManager>().OnSave += FieldWorks_OnSave; SetupErrorPropertiesNeedingCache(cache); return cache; } }
private static bool IsSharedXmlBackendNeeded(ProjectId projectId) { return projectId.Type == FDOBackendProviderType.kXML && ParatextHelper.GetAssociatedProject(projectId) != null; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Launches the application when requested from the command-line. /// </summary> /// <param name="appArgs">The application command-line arguments.</param> /// ------------------------------------------------------------------------------------ private static bool LaunchApplicationFromCommandLine(FwAppArgs appArgs) { // Get the application requested on the command line if (!CreateApp(appArgs)) return false; // Get the project the user wants to open and attempt to launch it. ProjectId projectId = DetermineProject(appArgs); if (projectId != null && IsSharedXmlBackendNeeded(projectId)) projectId.Type = FDOBackendProviderType.kSharedXML; // s_projectId can be non-null if the user decided to restore a project from // the Welcome to Fieldworks dialog. (FWR-2146) if (s_projectId == null && !LaunchProject(appArgs, ref projectId)) return false; // The project was successfully loaded so store it. This will let any other // FieldWorks processes that are waiting on us be able to continue. s_projectId = projectId; WarnUserAboutFailedLiftImportIfNecessary(GetOrCreateApplication(appArgs)); if (s_noUserInterface) { // We should have a main window by now, so the help button on the dialog // will work if needed. CheckForMovingExternalLinkDirectory(GetOrCreateApplication(appArgs)); } return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines the match status for the project used by this FieldWorks process and /// the specified project. This method is thread-safe. /// </summary> /// <param name="projectId">The project to test.</param> /// <returns> /// The result of checking to see if the specified project matches the project used /// by this FieldWorks processinstance is running /// </returns> /// ------------------------------------------------------------------------------------ internal static ProjectMatch GetProjectMatchStatus(ProjectId projectId) { if (s_fSingleProcessMode) return ProjectMatch.SingleProcessMode; if (s_fWaitingForUserOrOtherFw) return ProjectMatch.WaitingForUserOrOtherFw; ProjectId thisProjectId = s_projectId; // Store in temp variable for thread safety if (thisProjectId == null) return ProjectMatch.DontKnowYet; return thisProjectId.Equals(projectId) ? ProjectMatch.ItsMyProject : ProjectMatch.ItsNotMyProject; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Executes the requested action with all FW applications temporarily shut down and /// then (re)starts the applications in a sensible order. At the end, we're guaranteed /// to have at least one app started or FieldWorks will be shut down. /// </summary> /// <param name="abbrevOfDefaultAppToStart">The abbreviation of the default application /// to start.</param> /// <param name="action">The action to execute.</param> /// ------------------------------------------------------------------------------------ private static void ExecuteWithAppsShutDown(string abbrevOfDefaultAppToStart, Func<ProjectId> action) { bool allowFinalShutdownOrigValue = s_allowFinalShutdown; s_allowFinalShutdown = false; // don't shutdown when we close all windows! // Remember which apps were running (and the order in which to restore them) List<string> appsToRestore = new List<string>(); // If the requested default application is running, then add it as the first app to restore if (GetAppFromAppNameOrAbbrev(abbrevOfDefaultAppToStart) != null) appsToRestore.Add(abbrevOfDefaultAppToStart); if (s_flexApp != null && !appsToRestore.Contains(FwUtils.ksFlexAbbrev)) appsToRestore.Add(FwUtils.ksFlexAbbrev); if (s_teApp != null && !appsToRestore.Contains(FwUtils.ksTeAbbrev)) appsToRestore.Add(FwUtils.ksTeAbbrev); if (appsToRestore.Count == 0) { if (abbrevOfDefaultAppToStart.Equals(FwUtils.ksTeAbbrev, StringComparison.InvariantCultureIgnoreCase) && FwUtils.IsTEInstalled) { appsToRestore.Add(FwUtils.ksTeAbbrev); } else appsToRestore.Add(FwUtils.ksFlexAbbrev); } // Now shut down everything (windows, apps, cache, etc.) GracefullyShutDown(); if (s_applicationExiting) { // Something bad must have happened because we are shutting down. There is no point in // executing the action or in restarting the applications since we have no idea what // state the applications/data are in. (FWR-3179) Debug.Assert(s_allowFinalShutdown, "If something bad happened, we should be allowing application shutdown"); return; } try { // Run the action ProjectId projId = action(); if (projId == null) return; s_projectId = null; // Needs to be null in InitializeFirstApp // Restart the default app from which the action was kicked off FwApp app = GetOrCreateApplication(new FwAppArgs(appsToRestore[0], projId.Handle, projId.ServerName, string.Empty, Guid.Empty)); if (!InitializeFirstApp(app, projId)) return; s_projectId = projId; // Process needs to know its project // Reopen other apps if necessary (shouldn't ever be more then one) :P for (int i = 1; i < appsToRestore.Count; i++) { app = GetOrCreateApplication(new FwAppArgs(appsToRestore[i], projId.Handle, projId.ServerName, string.Empty, Guid.Empty)); InitializeApp(app, null); } } finally { s_allowFinalShutdown = allowFinalShutdownOrigValue; // mustn't suppress any longer (unless we already were). ExitIfNoAppsRunning(); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Tries to find an existing FieldWorks process that is running the specified project. /// See the class comment on FwLinkArgs for details on how all the parts of hyperlinking work. /// </summary> /// <param name="project">The project we want to conect to.</param> /// <param name="args">The application arguments.</param> /// <returns> /// True if an existing process was found with the specified project and /// control was released to the found process, false otherwise /// </returns> /// ------------------------------------------------------------------------------------ private static bool TryFindExistingProcess(ProjectId project, FwAppArgs args) { return RunOnRemoteClients(kFwRemoteRequest, requestor => { ProjectMatch isMyProject; Func<ProjectId, FwAppArgs, ProjectMatch> invoker = requestor.HandleOpenProjectRequest; var start = DateTime.Now; do { IAsyncResult ar = invoker.BeginInvoke(project, args, null, null); while (!ar.IsCompleted) { s_fWaitingForUserOrOtherFw = true; // Wait until this process knows which project it is loading. if (!ar.AsyncWaitHandle.WaitOne(9000, false)) { // timed out. if (MessageBox.Show(Properties.Resources.kstidFieldWorksDidNotRespond, Properties.Resources.kstidStartupProblem, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No) { return true; } } } // We can now ask for the answer. isMyProject = invoker.EndInvoke(ar); if (isMyProject == ProjectMatch.SingleProcessMode) { Logger.WriteEvent("WEIRD! Detected single FW process mode while this process is trying to open a project."); Debug.Fail("We don't think this can happen, but it's no big deal."); return true; // Should kill this process } if (DateTime.Now - start > new TimeSpan(0, 0, 10)) { // Some other process apparently keeps telling us it doesn't know. It's probably stuck in this same loop, // waiting for us! MessageBox.Show(Properties.Resources.kstidFieldWorksRespondedNotSure, Properties.Resources.kstidStartupProblem, MessageBoxButtons.OK, MessageBoxIcon.Warning); return true; // pretends some other process has the project opened and is handling the request; this process will quit } } while (isMyProject == ProjectMatch.DontKnowYet); s_fWaitingForUserOrOtherFw = false; return (isMyProject == ProjectMatch.ItsMyProject); }); }
private static bool InitializeFirstApp(FwApp app, ProjectId projectId) { Debug.Assert(s_cache == null && s_projectId == null, "This should only get called once"); Debug.Assert(projectId != null, "Should have exited the program"); using (var process = Process.GetCurrentProcess()) { app.RegistrySettings.LoadingProcessId = process.Id; } if (String.IsNullOrEmpty(app.RegistrySettings.LatestProject)) { // Until something gets saved, we will keep track of the first project opened. app.RegistrySettings.LatestProject = projectId.Handle; app.RegistrySettings.LatestServer = projectId.ServerName ?? string.Empty; } UsageEmailDialog.IncrementLaunchCount(app.SettingsKey); // count launches for bug reporting ShowSplashScreen(app); try { // Create the cache and let the application init the cache for what it needs s_cache = CreateCache(projectId); Debug.Assert(s_cache != null, "At this point we should know which project to load and have loaded it!"); if (s_noUserInterface || InitializeApp(app, s_splashScreen)) { app.RegistrySettings.LoadingProcessId = 0; #if !__MonoCS__ if (!WindowsInstallerQuery.IsThisInstalled() || app.ActiveMainWindow == null) return true; // Initialize NetSparkle to check for updates: Settings.Default.IsBTE = WindowsInstallerQuery.IsThisBTE(); var appCastUrl = Settings.Default.IsBTE ? (Settings.Default.CheckForBetaUpdates ? CoreImpl.Properties.Resources.ResourceManager.GetString("kstidAppcastBteBetasUrl") : CoreImpl.Properties.Resources.ResourceManager.GetString("kstidAppcastBteUrl")) : (Settings.Default.CheckForBetaUpdates ? CoreImpl.Properties.Resources.ResourceManager.GetString("kstidAppcastSeBetasUrl") : CoreImpl.Properties.Resources.ResourceManager.GetString("kstidAppcastSeUrl")); var sparkle = SingletonsContainer.Get("Sparkle", () => new Sparkle(appCastUrl, app.ActiveMainWindow.Icon)); sparkle.AboutToExitForInstallerRun += delegate(object sender, CancelEventArgs args) { CloseAllMainWindows(); if(app.ActiveMainWindow != null) { args.Cancel = true; } }; if (Settings.Default.AutoCheckForUpdates) sparkle.CheckOnFirstApplicationIdle(); #endif return true; } } catch (UnauthorizedAccessException uae) { if (MiscUtils.IsUnix) { // Tell Mono user he/she needs to logout and log back in MessageBox.Show(ResourceHelper.GetResourceString("ksNeedToJoinFwGroup")); } throw; } catch (FdoDataMigrationForbiddenException) { // tell the user to close all other applications using this project MessageBox.Show(ResourceHelper.GetResourceString("kstidDataMigrationProhibitedText"), ResourceHelper.GetResourceString("kstidDataMigrationProhibitedCaption"), MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { CloseSplashScreen(); } return false; }
public void CleanUpNameForType_Default_NameWithPeriod_Exists() { string expectedPath = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "my.monkey"), "my.monkey"); m_localCsSvcs.Stub(cs => cs.IdForLocalProject("my.monkey")).Return(expectedPath); m_mockFileOs.AddExistingFile(expectedPath); ProjectId proj = new ProjectId("my.monkey", null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); }
public void CleanUpNameForType_XML_NameWithPeriod_FilesWithAndWithoutExtensionExist() { string myMonkeyProjectFolder = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "my.monkey"); string expectedPath = Path.Combine(myMonkeyProjectFolder, FdoFileHelper.GetXmlDataFileName("my.monkey")); m_mockFileOs.AddExistingFile(expectedPath); m_mockFileOs.AddExistingFile(Path.Combine(myMonkeyProjectFolder, "my.monkey")); var proj = new ProjectId("my.monkey", null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); }
public void IsValid_NullType() { const string sProjectName = "monkey"; string sFile = FdoFileHelper.GetXmlDataFileName(sProjectName); m_mockFileOs.AddExistingFile(GetXmlProjectFilename(sProjectName)); ProjectId proj = new ProjectId(null, sFile, null); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); }
public void CleanUpNameForType_XML_onlyNameWithExtension() { string expectedPath = GetXmlProjectFilename("monkey"); m_mockFileOs.AddExistingFile(expectedPath); var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName("monkey"), null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); }
public void IsValid_XML_False() { ProjectId proj = new ProjectId("xml", "notThere", null); Assert.IsFalse(proj.IsValid); }
public void AssertValid_Valid() { string projFile = GetXmlProjectFilename("monkey"); m_mockFileOs.AddExistingFile(projFile); var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName("monkey"), null); proj.AssertValid(); // no exception should be thrown here for a valid project. }
public void IsValid_XML_True() { const string sProjectName = "monkey"; string sFile = FdoFileHelper.GetXmlDataFileName(sProjectName); m_mockFileOs.AddExistingFile(GetXmlProjectFilename(sProjectName)); ProjectId proj = new ProjectId("xml", sFile, null); Assert.IsTrue(proj.IsValid); }
public void AssertValid_Invalid_FileNotFound() { var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName("notfound"), null); try { proj.AssertValid(); Assert.Fail("FwStartupException expected"); } catch (StartupException exception) { Assert.IsTrue(exception.ReportToUser); } }
public void IsValid_XML_NullProjectName() { ProjectId proj = new ProjectId("xml", null, null); Assert.IsFalse(proj.IsValid); }
public void AssertValid_Invalid_SharedFolderNotFound() { var proj = new ProjectId(FdoFileHelper.GetDb4oDataFileName("monkey"), FwLinkArgs.kLocalHost); try { proj.AssertValid(); Assert.Fail("FwStartupException expected"); } catch (StartupException exception) { Assert.IsTrue(exception.ReportToUser); } }
public void CleanUpNameForType_EmptyName() { var proj = new ProjectId(string.Empty, null); Assert.IsNull(proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsFalse(proj.IsValid); }
public void NameAndPath() { string myProjectFolder = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "My.Project"); ProjectId projId = new ProjectId(FDOBackendProviderType.kXML, "My.Project", null); Assert.AreEqual(Path.Combine(myProjectFolder, FdoFileHelper.GetXmlDataFileName("My.Project")), projId.Path); Assert.AreEqual("My.Project", projId.Name); projId = new ProjectId(FDOBackendProviderType.kDb4oClientServer, "My.Project", null); Assert.AreEqual(Path.Combine(myProjectFolder, FdoFileHelper.GetDb4oDataFileName("My.Project")), projId.Path); Assert.AreEqual("My.Project", projId.Name); }
public void CleanUpNameForType_Default_onlyName() { m_defaultBepType = FDOBackendProviderType.kDb4oClientServer; string expectedPath = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "ape"), FdoFileHelper.GetDb4oDataFileName("ape")); m_localCsSvcs.Stub(cs => cs.IdForLocalProject("ape")).Return(expectedPath); m_mockFileOs.AddExistingFile(expectedPath); ProjectId proj = new ProjectId("ape", null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kDb4oClientServer, proj.Type); Assert.IsTrue(proj.IsValid); }
public void IsValid_BogusType() { ProjectId proj = new ProjectId("bogus", "rogus", null); Assert.AreEqual(FDOBackendProviderType.kInvalid, proj.Type); Assert.IsFalse(proj.IsValid); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Moves all of the projects in the specified old project folder (including any /// subfolders) to the specified new project folder. /// </summary> /// <param name="oldFolderForProjects">The old folder that held the projects.</param> /// <param name="newFolderForProjects">The new folder that will hold the projects.</param> /// <param name="projectPath">The project path.</param> /// <param name="oldProjectId">The Id of the old project (to use if it has not moved)</param> /// <returns>The ProjectId for the project to load after the move is completed</returns> /// ------------------------------------------------------------------------------------ private static ProjectId MoveProjectFolders(string oldFolderForProjects, string newFolderForProjects, string projectPath, ProjectId oldProjectId) { List<string> rgErrors = new List<string>(); bool fCopy = MustCopyFoldersAndFiles(oldFolderForProjects, newFolderForProjects); using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(s_threadHelper)) { string[] subDirs = Directory.GetDirectories(oldFolderForProjects); progressDlg.Maximum = subDirs.Length; progressDlg.AllowCancel = false; progressDlg.Title = string.Format(Properties.Resources.ksMovingProjectsCaption, oldFolderForProjects, newFolderForProjects); // Move all of the files and folders progressDlg.RunTask(true, (progressDialog, dummy) => { foreach (string subdir in subDirs) { try { string sub = Path.GetFileName(subdir); // If the project folder is not known to be ours don't move the folder. // This is some protection against moving vital folders if the user does something silly like // making C:\ the project folder. See FWR-3371. var destDirName = Path.Combine(newFolderForProjects, sub); if (!IsFieldWorksProjectFolder(subdir)) { // It might still be a folder which is the name of a remote server, // and contains local settings for projects on that server. // Check each of its subfolders, and move/copy the ones that appear to be settings, if any. bool movedSomething = false; foreach (string subsubdir in Directory.GetDirectories(subdir)) { if (!IsFieldWorksSettingsFolder(subsubdir)) continue; // We found a project folder one level down. This ought not so to be. // Maybe we are doing some bizarre move into one of our own subfolders, and this // was already moved earlier in the main loop? Anyway don't move it, it's not just a settings folder. if (IsFieldWorksProjectFolder(subsubdir)) continue; movedSomething = true; var leafName = Path.GetFileName(subsubdir); var subDirDest = Path.Combine(destDirName, leafName); Directory.CreateDirectory(destDirName); // may be redundant (will be after first time) but cheap. if (fCopy) { CopyDirectory(subsubdir, subDirDest); Directory.Delete(subsubdir, true); } else { Directory.Move(subsubdir, subDirDest); } } // If we moved something and left nothing behind delete the parent folder. // (We do a fresh GetDirectories just in case bizarrely we are moving INTO one of our own subfolders, // and thus even though we moved everything something is still there). if (movedSomething && Directory.GetDirectories(subdir).Length == 0) Directory.Delete(subdir); continue; // with more top-level directories in the projects folder. } progressDialog.Message = string.Format(Properties.Resources.ksMovingProject, sub); progressDialog.Step(1); if (fCopy) { // Recursively copy each subfolder. CopyDirectory(subdir, destDirName); Directory.Delete(subdir, true); } else { Directory.Move(subdir, destDirName); } } catch (Exception e) { rgErrors.Add(String.Format("{0} - {1}", Path.GetFileNameWithoutExtension(subdir), e.Message)); } } return null; }); } if (rgErrors.Count > 0) { // Show the user any errors that occured while doing the move StringBuilder bldr = new StringBuilder(); bldr.AppendLine(Properties.Resources.ksCannotMoveProjects); foreach (var err in rgErrors) bldr.AppendLine(err); bldr.Append(Properties.Resources.ksYouCanTryToMoveProjects); MessageBox.Show(bldr.ToString(), Properties.Resources.ksProblemsMovingProjects); } if (MiscUtils.IsUnix) { if (projectPath.StartsWith(oldFolderForProjects)) { // This is perhaps a temporary workaround. On Linux, FwDirectoryFinder.ProjectsDirectory // isn't returning the updated value, but rather the original value. This seems to // last for the duration of the program, but if you exit and restart the program, it // gets the correct (updated) value!? // (On the other hand, I somewhat prefer this code which is fairly straightforward and // obvious to depending on calling some static method hidden in the depths of FDO.) string projFileName = Path.GetFileName(projectPath); string projName = Path.GetFileNameWithoutExtension(projectPath); string path = Path.Combine(Path.Combine(newFolderForProjects, projName), projFileName); return new ProjectId(path, null); } } else { if (projectPath.StartsWith(oldFolderForProjects, StringComparison.InvariantCultureIgnoreCase)) { return new ProjectId(ClientServerServices.Current.Local.IdForLocalProject( Path.GetFileNameWithoutExtension(projectPath)), null); } } return oldProjectId; }