PageRenderTime 29ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/CRSyncFiles/CrSyncFilesUtils/CrSyncFilesUtility.cs

http://crsyncfiles.codeplex.com
C# | 904 lines | 683 code | 121 blank | 100 comment | 59 complexity | 29c61ef6bc66d5febe84bd3d4d9402fd MD5 | raw file
  1. /*
  2. * Copyright (c) 2011 Connection Road. All rights reserved.
  3. * This program and the accompanying material are made available
  4. * under the terms of the Eclipse Public Licnese v1.0 which is
  5. * available at http://www.eclipse.org/legal/epl-v10.html
  6. */
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Globalization;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Net.Sockets;
  15. using System.Runtime.InteropServices;
  16. using System.Runtime.Serialization;
  17. using System.Runtime.Serialization.Formatters.Binary;
  18. using CrSyncFilesUtils.Enums;
  19. using Microsoft.Win32;
  20. using SyncToy;
  21. namespace CrSyncFilesUtils
  22. {
  23. /// <summary>
  24. /// A collection of static methods for CrSyncFiles.
  25. /// </summary>
  26. public partial class CrSyncFilesUtility
  27. {
  28. [DllImport("user32.dll", CharSet=CharSet.Auto)]
  29. public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); // Works but hard to debug on different arch
  30. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  31. public static extern IntPtr BringWindowToTop(IntPtr hwnd); // Does not work
  32. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  33. public static extern void SwitchToThisWindow(IntPtr hwnd, bool altTab); // Too annoying
  34. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  35. public static extern bool SetForegroundWindow(IntPtr hWnd); // Works
  36. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  37. public static extern IntPtr DestroyWindow(IntPtr hwnd); //Works but applicable only to child window.
  38. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  39. public static extern IntPtr EndTask(IntPtr hwnd, bool ignore, bool force);
  40. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  41. public static extern IntPtr GetForegroundWindow();
  42. [DllImport("user32")]
  43. public static extern IntPtr RemoveMenu(int systemMenu, int itemPosition, int flag); // Removes control box. .Net have already have them.
  44. public static string SyncToyRegKey = @"Software\Microsoft\Synctoy";
  45. public static string SyncFramework32RegKey = @"SOFTWARE\Microsoft\Microsoft Sync Framework\v2.1";
  46. public static string SyncFramework64RegKey = @"SOFTWARE\Wow6432Node\Microsoft\Microsoft Sync Framework\v2.1";
  47. //public static string SyncFrameworkAssemblyName = "Microsoft.Synchronization, Version=2.1.0.0, Culture=neutral, PublicKeyToken=89845DCD8080CC91";
  48. //public static string SyncFileProviderAssemblyName = "Microsoft.Synchronization.Files, Version=2.1.0.0, Culture=neutral, PublicKeyToken=89845DCD8080CC91";
  49. public static string DefaultHost = "www.connectionroad.com";
  50. /// <summary>
  51. /// Verifies if the Sync framework is installed
  52. /// </summary>
  53. /// <returns></returns>
  54. public static bool IsSyncFrameworkInstalled()
  55. {
  56. try
  57. {
  58. RegistryKey registrySyncFramework;
  59. switch (GetArch())
  60. {
  61. case CrSyncArchs.X86:
  62. registrySyncFramework = Registry.LocalMachine.OpenSubKey(SyncFramework32RegKey);
  63. break;
  64. case CrSyncArchs.X64:
  65. registrySyncFramework = Registry.LocalMachine.OpenSubKey(SyncFramework64RegKey);
  66. break;
  67. default:
  68. registrySyncFramework = Registry.LocalMachine.OpenSubKey(SyncFramework32RegKey);
  69. break;
  70. }
  71. return registrySyncFramework != null;
  72. }
  73. catch (Exception)
  74. {
  75. return false;
  76. }
  77. }
  78. public static bool IsSyncToyInstalled()
  79. {
  80. var synctoyRegKey = Registry.CurrentUser.OpenSubKey(SyncToyRegKey);
  81. return synctoyRegKey != null;
  82. }
  83. /// <summary>
  84. /// Gets the absolute path of SyncToy's database file.
  85. /// </summary>
  86. /// <returns></returns>
  87. public static string GetSyncToyStorageFilePath()
  88. {
  89. return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\SyncToy\\2.0\\SyncToyDirPairs.bin");
  90. }
  91. public static string GetSyncToyMetaDataDirectory()
  92. {
  93. return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\SyncToy\\2.0");
  94. }
  95. /// <summary>
  96. /// Get a lists of available SyncToy folder pairs.
  97. /// </summary>
  98. /// <exception cref="ApplicationException"></exception>
  99. /// <returns></returns>
  100. public static List<SyncEngineConfig> GetSyncToyFolderPairs()
  101. {
  102. var synctoyLocalAppData = GetSyncToyStorageFilePath();
  103. var configfiles = new List<SyncEngineConfig>();
  104. if (File.Exists(synctoyLocalAppData))
  105. {
  106. IFormatter binaryFormmater = new BinaryFormatter();
  107. using (Stream fileStream = new FileStream(synctoyLocalAppData, FileMode.Open))
  108. {
  109. while (fileStream.Position < fileStream.Length)
  110. {
  111. var currentConfig = (SyncEngineConfig)binaryFormmater.Deserialize(fileStream);
  112. configfiles.Add(currentConfig);
  113. }
  114. }
  115. }
  116. return configfiles;
  117. }
  118. /// <summary>
  119. /// Generally saves ( actually overwrites SyncToy's store file ) the given lists of SynToy folder pairs.
  120. /// </summary>
  121. /// <exception cref="ApplicationException"></exception>
  122. /// <param name="synctoyPairs"></param>
  123. public static void SetSyncToyFolderPairs(List<SyncEngineConfig> synctoyPairs)
  124. {
  125. var synctoyLocalAppData = GetSyncToyStorageFilePath();
  126. IFormatter formatter = new BinaryFormatter();
  127. using (Stream fileStream = new FileStream(synctoyLocalAppData, FileMode.Create))
  128. {
  129. foreach (var pair in synctoyPairs)
  130. {
  131. formatter.Serialize(fileStream, pair);
  132. }
  133. }
  134. }
  135. /// <summary>
  136. /// Converts a SyncToy folder pair to CrSyncFiles compatible folder pair. All meta files import are taken care by this method.
  137. /// </summary>
  138. /// <param name="synctoyPair"></param>
  139. /// <param name="prefix"></param>
  140. /// <param name="metaDataDirectory"></param>
  141. /// <returns></returns>
  142. public static FileSyncPairInfo ConvertToCrSyncFile(SyncEngineConfig synctoyPair, string prefix, string metaDataDirectory)
  143. {
  144. var newFolderPair = FileSyncPairManager.CreateFolderPair(synctoyPair.Name);
  145. newFolderPair.ActiveForRunAll = synctoyPair.Active;
  146. newFolderPair.DateTimeLastSync = synctoyPair.DateTimeLastSync;
  147. newFolderPair.LeftFolder = FileSyncPairManager.CreateFileLocation(synctoyPair.LeftDriveType,synctoyPair.LeftDir,
  148. prefix,
  149. synctoyPair.LeftGuid.ToString(),
  150. metaDataDirectory);
  151. newFolderPair.RightFolder = FileSyncPairManager.CreateFileLocation(synctoyPair.RightDriveType,synctoyPair.RightDir,
  152. prefix,
  153. synctoyPair.RightGuid.ToString(),
  154. metaDataDirectory);
  155. newFolderPair.OptionsCompareFileStreams = synctoyPair.ComputeHash;
  156. newFolderPair.OptionsBackupOlderFiles = synctoyPair.BackupOlderFile;
  157. // Get excluded subfodlers)
  158. if (synctoyPair.ExceptionalDirs != null)
  159. {
  160. var synctoySubfolders = synctoyPair.ExceptionalDirs.LeftDirectories;
  161. synctoySubfolders.AddRange(synctoyPair.ExceptionalDirs.RightDirectories);
  162. foreach (var relativeSubFolderPath in from string synctoySubfolder in synctoySubfolders
  163. select new FileNode(synctoySubfolder)
  164. into fileNode select fileNode.GetRelativePathFromFolderPair(newFolderPair)
  165. into relativeSubFolderPath where relativeSubFolderPath != null where !newFolderPair.SubDirectoryExclusionList.Contains(relativeSubFolderPath) select relativeSubFolderPath)
  166. {
  167. newFolderPair.SubDirectoryExclusionList.Add(relativeSubFolderPath);
  168. }
  169. }
  170. // Excluded files
  171. newFolderPair.SetSearchPattern(synctoyPair.SearchPattern);
  172. // Included files
  173. newFolderPair.SetExcludePattern(synctoyPair.ExcludedPattern);
  174. switch (synctoyPair.SyncMode)
  175. {
  176. case SyncMode.Synchronize:
  177. newFolderPair.FolderPairActionType = FolderPairActionTypeEnum.Synchronize;
  178. break;
  179. case SyncMode.Echo:
  180. newFolderPair.FolderPairActionType = FolderPairActionTypeEnum.Echo;
  181. break;
  182. case SyncMode.Contribute:
  183. newFolderPair.FolderPairActionType = FolderPairActionTypeEnum.Contribute;
  184. break;
  185. default:
  186. newFolderPair.FolderPairActionType = FolderPairActionTypeEnum.Synchronize;
  187. break;
  188. }
  189. // Import synctoy meta data
  190. var syncToyLeftMetaData = GetSyncToyMetaFilePath(synctoyPair.LeftGuid);
  191. var syncToyRightMetaData = GetSyncToyMetaFilePath(synctoyPair.RightGuid);
  192. // Generate the absolute path for our metadata
  193. var crSyncLeftMetaFile = newFolderPair.LeftFolder.MetaFilePath;
  194. var crSyncRightMetaFile = newFolderPair.RightFolder.MetaFilePath;
  195. // Create markers when necessary
  196. newFolderPair.LeftFolder.CreateMarker();
  197. newFolderPair.RightFolder.CreateMarker();
  198. if (syncToyLeftMetaData != crSyncLeftMetaFile)
  199. {
  200. if (File.Exists(syncToyLeftMetaData) && (!File.Exists(crSyncLeftMetaFile)))
  201. {
  202. File.Copy(syncToyLeftMetaData, crSyncLeftMetaFile,true);
  203. }
  204. }
  205. if (syncToyRightMetaData != crSyncRightMetaFile)
  206. {
  207. if (File.Exists(syncToyRightMetaData) && (!File.Exists(crSyncRightMetaFile)))
  208. {
  209. File.Copy(syncToyRightMetaData, crSyncRightMetaFile,true);
  210. }
  211. }
  212. if ((synctoyPair.ExcludedFileAttributes & FileAttributes.ReadOnly) != 0)
  213. {
  214. newFolderPair.FileExcludeAttrReadOnly = true;
  215. }
  216. if ((synctoyPair.ExcludedFileAttributes & FileAttributes.Hidden) != 0)
  217. {
  218. newFolderPair.FileExcludeAttrHidden = true;
  219. }
  220. if ((synctoyPair.ExcludedFileAttributes & FileAttributes.System) != 0)
  221. {
  222. newFolderPair.FileExcludeAttrSystem = true;
  223. }
  224. newFolderPair.ImportedFromSyncToy = true;
  225. return newFolderPair;
  226. }
  227. public static SyncEngineConfig ConvertToSyncToy(FileSyncPairInfo crsyncPair)
  228. {
  229. var synctoyPair = new SyncEngineConfig
  230. {
  231. Name = crsyncPair.FolderPairName,
  232. Active = crsyncPair.ActiveForRunAll,
  233. DateTimeLastSync = crsyncPair.DateTimeLastSync
  234. };
  235. // Synchronize some options
  236. crsyncPair.RemoveMarkerFiles();
  237. crsyncPair.RemoveMetaData();
  238. crsyncPair.LeftFolder.FileName = string.Format("SyncToy_{0}.dat",synctoyPair.LeftGuid);
  239. crsyncPair.RightFolder.FileName = string.Format("SyncToy_{0}.dat", synctoyPair.RightGuid);
  240. crsyncPair.LeftFolder.UniqueIdentifier = string.Format("{0}", synctoyPair.LeftGuid);
  241. crsyncPair.RightFolder.UniqueIdentifier = string.Format("{0}", synctoyPair.RightGuid);
  242. synctoyPair.LeftDir = crsyncPair.LeftFolder.Path;
  243. synctoyPair.RightDir = crsyncPair.RightFolder.Path;
  244. synctoyPair.ComputeHash = crsyncPair.OptionsCompareFileStreams;
  245. synctoyPair.BackupOlderFile = crsyncPair.OptionsBackupOlderFiles;
  246. // File filters
  247. synctoyPair.SearchPattern = crsyncPair.GetSearchPattern();
  248. synctoyPair.ExcludedPattern = crsyncPair.GetExcludePattern();
  249. crsyncPair.ExtendedInfo.AddObjectForKey(true,"HAS_MIRROR");
  250. switch (crsyncPair.FolderPairActionType)
  251. {
  252. case FolderPairActionTypeEnum.Synchronize:
  253. synctoyPair.SyncMode = SyncMode.Synchronize;
  254. break;
  255. case FolderPairActionTypeEnum.Echo:
  256. synctoyPair.SyncMode = SyncMode.Echo;
  257. break;
  258. case FolderPairActionTypeEnum.Contribute:
  259. synctoyPair.SyncMode = SyncMode.Contribute;
  260. break;
  261. default:
  262. synctoyPair.SyncMode = SyncMode.Synchronize;
  263. break;
  264. }
  265. return synctoyPair;
  266. }
  267. /// <summary>
  268. /// Ensures that the destination object pair contains the most recent data from the target object pair.
  269. /// </summary>
  270. /// <param name="crsyncPair">Destination</param>
  271. /// <param name="synctoyPair">Target</param>
  272. public static void SynchronizePairsFrom(FileSyncPairInfo crsyncPair, SyncEngineConfig synctoyPair)
  273. {
  274. crsyncPair.FolderPairName = synctoyPair.Name;
  275. crsyncPair.ActiveForRunAll = synctoyPair.Active;
  276. crsyncPair.DateTimeLastSync = synctoyPair.DateTimeLastSync;
  277. crsyncPair.OptionsCompareFileStreams = synctoyPair.ComputeHash;
  278. crsyncPair.OptionsBackupOlderFiles = synctoyPair.BackupOlderFile;
  279. // Get excluded subfolders
  280. crsyncPair.SubDirectoryExclusionList.Clear();
  281. if(synctoyPair.ExceptionalDirs == null)
  282. {
  283. crsyncPair.SubDirectoryExclusionList = new List<string>();
  284. }
  285. else
  286. {
  287. var excludedSynctoyFolders = new ArrayList();
  288. if ((synctoyPair.ExceptionalDirs.LeftDirectories != null) && (synctoyPair.ExceptionalDirs.LeftDirectories.Count >= 1))
  289. {
  290. excludedSynctoyFolders.AddRange(synctoyPair.ExceptionalDirs.LeftDirectories);
  291. }
  292. if ((synctoyPair.ExceptionalDirs.RightDirectories != null) && (synctoyPair.ExceptionalDirs.RightDirectories.Count >= 1))
  293. {
  294. excludedSynctoyFolders.AddRange(synctoyPair.ExceptionalDirs.RightDirectories);
  295. }
  296. if(excludedSynctoyFolders.Count >= 1)
  297. {
  298. foreach (var relativePath in excludedSynctoyFolders.Cast<string>().Select(subfolder => new FileNode(subfolder)).Select(fileNode => fileNode.GetRelativePathFromFolderPair(crsyncPair)).Where(relativePath => !crsyncPair.SubDirectoryExclusionList.Contains(relativePath)))
  299. {
  300. crsyncPair.SubDirectoryExclusionList.Add(relativePath);
  301. }
  302. }
  303. else
  304. {
  305. crsyncPair.SubDirectoryExclusionList = new List<string>();
  306. }
  307. }
  308. crsyncPair.SetSearchPattern(synctoyPair.SearchPattern);
  309. crsyncPair.SetExcludePattern(synctoyPair.ExcludedPattern);
  310. // Sync action);
  311. switch (synctoyPair.SyncMode)
  312. {
  313. case SyncMode.Synchronize:
  314. crsyncPair.FolderPairActionType = FolderPairActionTypeEnum.Synchronize;
  315. break;
  316. case SyncMode.Echo:
  317. crsyncPair.FolderPairActionType = FolderPairActionTypeEnum.Echo;
  318. break;
  319. case SyncMode.Contribute:
  320. crsyncPair.FolderPairActionType = FolderPairActionTypeEnum.Contribute;
  321. break;
  322. default:
  323. crsyncPair.FolderPairActionType = FolderPairActionTypeEnum.Synchronize;
  324. break;
  325. }
  326. // Attribute files
  327. crsyncPair.FileExcludeAttrReadOnly = (synctoyPair.ExcludedFileAttributes & FileAttributes.ReadOnly) != 0;
  328. crsyncPair.FileExcludeAttrHidden = (synctoyPair.ExcludedFileAttributes & FileAttributes.Hidden) != 0;
  329. crsyncPair.FileExcludeAttrSystem = (synctoyPair.ExcludedFileAttributes & FileAttributes.System) != 0;
  330. }
  331. /// <summary>
  332. /// Ensures that the destination object pair contains the most recent data from the target object pair.
  333. /// </summary>
  334. /// <param name="synctoyPair">Destination</param>
  335. /// <param name="crsyncPair">Target</param>
  336. public static void SynchronizePairsFrom(SyncEngineConfig synctoyPair, FileSyncPairInfo crsyncPair)
  337. {
  338. synctoyPair.Name = crsyncPair.FolderPairName;
  339. synctoyPair.Active = crsyncPair.ActiveForRunAll;
  340. synctoyPair.DateTimeLastSync = crsyncPair.DateTimeLastSync;
  341. synctoyPair.ComputeHash = crsyncPair.OptionsCompareFileStreams;
  342. synctoyPair.BackupOlderFile = crsyncPair.OptionsBackupOlderFiles;
  343. // Get excluded subfodlers
  344. if(crsyncPair.SubDirectoryExclusionList.Count >= 1)
  345. {
  346. synctoyPair.ExceptionalDirs = new ExceptionalDirList();
  347. var excludedSubfolders = crsyncPair.SubDirectoryExclusionList;
  348. foreach (var excludedSubfolder in excludedSubfolders)
  349. {
  350. var leftSubfolder = new FileNode(crsyncPair.LeftFolder.Path).Join(excludedSubfolder).Path;
  351. var rightSubfolder = new FileNode(crsyncPair.RightFolder.Path).Join(excludedSubfolder).Path;
  352. synctoyPair.ExceptionalDirs.LeftDirectories.Add(leftSubfolder);
  353. synctoyPair.ExceptionalDirs.RightDirectories.Add(rightSubfolder);
  354. }
  355. }
  356. else
  357. {
  358. synctoyPair.ExceptionalDirs = new ExceptionalDirList();
  359. }
  360. synctoyPair.SearchPattern = crsyncPair.GetSearchPattern();
  361. synctoyPair.ExcludedPattern = crsyncPair.GetExcludePattern();
  362. switch (crsyncPair.FolderPairActionType)
  363. {
  364. case FolderPairActionTypeEnum.Synchronize:
  365. synctoyPair.SyncMode = SyncMode.Synchronize;
  366. break;
  367. case FolderPairActionTypeEnum.Echo:
  368. synctoyPair.SyncMode = SyncMode.Echo;
  369. break;
  370. case FolderPairActionTypeEnum.Contribute:
  371. synctoyPair.SyncMode = SyncMode.Contribute;
  372. break;
  373. default:
  374. synctoyPair.SyncMode = SyncMode.Synchronize;
  375. break;
  376. }
  377. var excludeFileAttr = (FileAttributes)0;
  378. if (crsyncPair.FileExcludeAttrReadOnly)
  379. {
  380. excludeFileAttr = excludeFileAttr | FileAttributes.ReadOnly;
  381. }
  382. if (crsyncPair.FileExcludeAttrSystem)
  383. {
  384. excludeFileAttr = excludeFileAttr | FileAttributes.System;
  385. }
  386. if (crsyncPair.FileExcludeAttrHidden)
  387. {
  388. excludeFileAttr = excludeFileAttr | FileAttributes.Hidden;
  389. }
  390. synctoyPair.ExcludedFileAttributes = excludeFileAttr;
  391. }
  392. /// <summary>
  393. /// Ensures that CRSyncFiles has the most recent copy of SyncToy's folder pair.
  394. /// </summary>
  395. /// <param name="prefix"></param>
  396. /// <param name="metaDataDirectory"></param>
  397. /// <param name="crsyncPairManager"></param>
  398. /// <param name="synctoyPairManager"></param>
  399. public static void ImportAvailableSyncToyFolderPairs(string prefix,string metaDataDirectory, FileSyncPairManager crsyncPairManager, CrSyncToyManager synctoyPairManager)
  400. {
  401. if (IsSyncToyInstalled())
  402. {
  403. var synctoyFolderPairs = GetSyncToyFolderPairs();
  404. foreach (var synctoyFolderPair in synctoyFolderPairs)
  405. {
  406. if (crsyncPairManager.HasFolderPair(synctoyFolderPair))
  407. {
  408. // Update CRSyncFiles folder pair
  409. var crsyncPair = crsyncPairManager.CurrentFolderPair;
  410. SynchronizePairsFrom(crsyncPair, synctoyFolderPair);
  411. crsyncPairManager.UpdateFolderPair(crsyncPair);
  412. synctoyPairManager.UpdateFolderPair(synctoyFolderPair);
  413. }
  414. else
  415. {
  416. // Create new CRSyncFiles folder pair
  417. var newFolderPair = ConvertToCrSyncFile(synctoyFolderPair, prefix,metaDataDirectory);
  418. // Add only if folder pair name is different from the one already exsits.
  419. if (!crsyncPairManager.HasFolderPairNamed(newFolderPair.FolderPairName))
  420. {
  421. var availablePairs = crsyncPairManager.AvailableFolderPairs();
  422. availablePairs.Add(newFolderPair.UniqueIdentifier, newFolderPair);
  423. crsyncPairManager.UpdateFolderPairs(availablePairs);
  424. synctoyPairManager.UpdateFolderPair(synctoyFolderPair);
  425. }
  426. }
  427. }
  428. }
  429. }
  430. /// <summary>
  431. /// Auto import and synchronizes existing CrSyncFiles' folder pairs to SyncToy's database.
  432. /// This ensures that both store files contain the most recent data to prevent any metadata corruption.
  433. /// </summary>
  434. /// <param name="metaDataDirectory"></param>
  435. /// <param name="crsyncPairManager"></param>
  436. /// <param name="synctoyPairManager"></param>
  437. public static void ImportAvailableCrSyncFiles(string metaDataDirectory, FileSyncPairManager crsyncPairManager, CrSyncToyManager synctoyPairManager)
  438. {
  439. if(IsSyncToyInstalled())
  440. {
  441. var crsynFolderPairs = crsyncPairManager.AvailableFolderPairs();
  442. var synctoyFolderPairs = GetSyncToyFolderPairs();
  443. if (synctoyFolderPairs.Count >= 1)
  444. {
  445. foreach (var fileSyncPairInfo in crsynFolderPairs.Where(fileSyncPairInfo => !synctoyPairManager.HasFolderPair(fileSyncPairInfo.Value)))
  446. {
  447. // Since SyncToy doesn't have it.. we should probably delete it.
  448. crsyncPairManager.RemoveFolderPair(fileSyncPairInfo.Value);
  449. }
  450. }
  451. else
  452. {
  453. // Synctoy's database is empty so we should copy everything in CrSyncFiles
  454. foreach (var fileSyncPairInfo in crsynFolderPairs)
  455. {
  456. synctoyPairManager.AddFolderPair(fileSyncPairInfo.Value);
  457. }
  458. }
  459. }
  460. }
  461. /// <summary>
  462. /// This is a supplementary method after calling various synchronization method for synchronizing both SyncToy and CrSyncFiles folder pairs.
  463. /// While the other method ensures the both store files must contain what others doesn't have, this ensures no orphaned pairs are left in both stores.
  464. /// </summary>
  465. /// <param name="metaDataDirectory"></param>
  466. /// <param name="crsyncPairManager"></param>
  467. /// <param name="synctoyManager"></param>
  468. public static void CheckForUnavailableSyncToyFolderPairs(string metaDataDirectory, FileSyncPairManager crsyncPairManager, CrSyncToyManager synctoyManager)
  469. {
  470. if(IsSyncToyInstalled())
  471. {
  472. var synctoyFolderPairs = GetSyncToyFolderPairs();
  473. if(synctoyFolderPairs.Count >= 1)
  474. {
  475. var crsyncFolderPairs = crsyncPairManager.AvailableFolderPairs();
  476. foreach(var pairInfo in crsyncFolderPairs)
  477. {
  478. var hasFolderPair = synctoyManager.HasFolderPair(pairInfo.Value);
  479. if(!hasFolderPair)
  480. {
  481. crsyncPairManager.RemoveFolderPair(pairInfo.Value);
  482. }
  483. }
  484. }
  485. else
  486. {
  487. // SyncToy's store file is empty
  488. var allCrSyncFolderPairs = new List<FileSyncPairInfo>();
  489. crsyncPairManager.UpdateFolderPairs(allCrSyncFolderPairs);
  490. }
  491. }
  492. }
  493. /// <summary>
  494. /// Just a helper method to delete marker files and meta data generated by SyncToy.
  495. /// </summary>
  496. /// <param name="synctoyPair"></param>
  497. public static void RemoveSupplementaryFiles(SyncEngineConfig synctoyPair)
  498. {
  499. // Remove marker files
  500. var leftMarker = GetSyncToyMarkerFilePath(synctoyPair.LeftDir, synctoyPair.LeftGuid);
  501. var rigthMarker = GetSyncToyMarkerFilePath(synctoyPair.RightDir, synctoyPair.RightGuid);
  502. var leftMetaFile = new FileNode(GetSyncToyMetaFilePath(synctoyPair.LeftGuid));
  503. var rightMetaFile = new FileNode(GetSyncToyMetaFilePath(synctoyPair.RightGuid));
  504. if (File.Exists(leftMarker))
  505. {
  506. File.Delete(leftMarker);
  507. }
  508. if (File.Exists(rigthMarker))
  509. {
  510. File.Delete(rigthMarker);
  511. }
  512. if(File.Exists(leftMetaFile.Path))
  513. {
  514. File.Delete(leftMetaFile.Path);
  515. }
  516. if(File.Exists(rightMetaFile.Path))
  517. {
  518. File.Delete(rightMetaFile.Path);
  519. }
  520. }
  521. public static void WriteLog(string message, string fileName)
  522. {
  523. using (var streamWriter = !File.Exists(fileName) ? new StreamWriter(fileName) : File.AppendText(fileName))
  524. {
  525. var dateTime = string.Format("{0:MM/dd/yyyy hh:mm:ss tt}", DateTime.Now);
  526. if(message.Trim().Length >= 1)
  527. {
  528. streamWriter.WriteLine("[" + dateTime + "] " + message);
  529. }
  530. else
  531. {
  532. streamWriter.WriteLine(message);
  533. }
  534. streamWriter.Close();
  535. }
  536. }
  537. public static string GetSyncToyMarkerFilePath(string rootReplica,Guid guid)
  538. {
  539. return Path.Combine(rootReplica, string.Format("SyncToy_{0}.dat", guid));
  540. }
  541. public static string GetSyncToyMetaFilePath(Guid guid)
  542. {
  543. return new FileNode(GetSyncToyMetaDataDirectory()).Join(string.Format("SyncToy_{0}.dat", guid)).Path;
  544. }
  545. public static bool IsSyncToyWindowPresent()
  546. {
  547. var processes = Process.GetProcessesByName("SyncToy");
  548. return processes.Length >= 1;
  549. }
  550. /// <summary>
  551. /// Retrieves synctoy's last selected/ran folder pair name.
  552. /// </summary>
  553. /// <returns></returns>
  554. public static string GetSyncToyLastFolderPair()
  555. {
  556. try
  557. {
  558. var syncToyReg = Registry.CurrentUser.OpenSubKey(SyncToyRegKey);
  559. if (syncToyReg != null)
  560. {
  561. return (string)syncToyReg.GetValue("LastFolderPair");
  562. }
  563. return null;
  564. }
  565. catch (Exception)
  566. {
  567. return null;
  568. }
  569. }
  570. public static bool SetSyncToyLastFolderPair(string lastFolderPair)
  571. {
  572. try
  573. {
  574. var syncToyReg = Registry.CurrentUser.CreateSubKey(SyncToyRegKey);
  575. if (syncToyReg != null)
  576. {
  577. syncToyReg.SetValue("LastFolderPair", lastFolderPair);
  578. return true;
  579. }
  580. return false;
  581. }
  582. catch (Exception)
  583. {
  584. return false;
  585. }
  586. }
  587. /// <summary>
  588. /// Convenience method for getting the CRSyncFile's store file.
  589. /// </summary>
  590. /// <param name="companyName"></param>
  591. /// <param name="version"></param>
  592. /// <returns></returns>
  593. public static string GetStoreFilePath(string companyName, string version)
  594. {
  595. return new FileNode(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)).Join(companyName).Join("CrSyncFiles\\" + version).Join("CrSyncFiles.xml").Path;
  596. }
  597. public static string FormatBytes(long bytes)
  598. {
  599. // 1000 is no longer used by the server.
  600. const int scale = 1024;
  601. var orders = new[] { "GB", "MB", "KB", "Bytes" };
  602. var max = (long)Math.Pow(scale, orders.Length - 1);
  603. foreach (string order in orders)
  604. {
  605. if (bytes > max)
  606. {
  607. var formatedString = string.Format("{0:##.##} {1}", decimal.Divide(bytes, max), order);
  608. return formatedString;
  609. }
  610. max /= scale;
  611. }
  612. return "0 Bytes";
  613. }
  614. /// <summary>
  615. /// This Function is specifically handling the Product Offerings of 50MB, 2GB, 5GB and 30GB.
  616. /// This Function will be cleaned up later, when rounding rules are determined. (Miles)
  617. /// </summary>
  618. /// <param name="bytes"></param>
  619. /// <returns></returns>
  620. public static string FormatBytesProducts(long bytes)
  621. {
  622. // 1000 is no longer used by the server
  623. const int scale = 1024;
  624. var orders = new[] { "GB", "MB", "KB", "Bytes" };
  625. var max = (long)Math.Pow(scale, orders.Length - 1);
  626. foreach (string order in orders)
  627. {
  628. if (bytes > max)
  629. {
  630. var totalBytes = decimal.Divide(bytes, max);
  631. // 2GB Plan
  632. if (totalBytes >= 1 && totalBytes <= 3)
  633. {
  634. totalBytes = 2;
  635. }
  636. // 5GB Plan
  637. if (totalBytes >= 4 && totalBytes <= 6)
  638. {
  639. totalBytes = 5;
  640. }
  641. // 30GB Plan
  642. if (totalBytes >= 29 && totalBytes <= 32)
  643. {
  644. totalBytes = 30;
  645. }
  646. // Free 50MB Plan
  647. if (totalBytes >= 49 && totalBytes <= 51)
  648. {
  649. totalBytes = 50;
  650. }
  651. var formatedString = string.Format("{0:##} {1}", totalBytes , order);
  652. return formatedString;
  653. }
  654. max /= scale;
  655. }
  656. return "0 Bytes";
  657. }
  658. /// <summary>
  659. /// Converts a string to hexadecimal values in form of string separated by a dot "."
  660. /// </summary>
  661. /// <param name="stringToConvert"></param>
  662. /// <param name="separator"></param>
  663. /// <returns></returns>
  664. public static string ConvertToHex(string stringToConvert, string separator = ".")
  665. {
  666. try
  667. {
  668. var hextString = "";
  669. var charArray = stringToConvert.ToCharArray();
  670. foreach(var c in charArray)
  671. {
  672. var num = Convert.ToInt32(c);
  673. hextString += string.Format("{0:X}{1}", num + 1, separator);
  674. }
  675. if (hextString.StartsWith(separator))
  676. {
  677. hextString = hextString.Substring(0);
  678. }
  679. if (hextString.EndsWith(separator))
  680. {
  681. hextString = hextString.Substring(0, hextString.Length - 1);
  682. }
  683. return hextString;
  684. }
  685. catch (Exception)
  686. {
  687. return "";
  688. }
  689. }
  690. /// <summary>
  691. /// Converts a series of hexadecimal separated by "." back to the actual string value.
  692. /// </summary>
  693. /// <param name="stringOfHex"></param>
  694. /// <param name="separator"></param>
  695. /// <returns></returns>
  696. public static string ConvertHexToString(string stringOfHex, char separator = '.')
  697. {
  698. try
  699. {
  700. if (!string.IsNullOrEmpty(stringOfHex))
  701. {
  702. var splitHex = stringOfHex.Split(separator);
  703. //var stringValue = splitHex.Select(s => (char)int.Parse(s, NumberStyles.HexNumber)).Aggregate("", (current, c) => current + string.Format("{0}", c));
  704. var stringValue = "";
  705. foreach (var s in splitHex)
  706. {
  707. var num = int.Parse(s, NumberStyles.HexNumber);
  708. var c = (char)(num - 1);
  709. stringValue += string.Format("{0}", c);
  710. }
  711. return stringValue;
  712. }
  713. return "";
  714. }
  715. catch (Exception)
  716. {
  717. return "";
  718. }
  719. }
  720. public static CrSyncArchs GetArch()
  721. {
  722. return IntPtr.Size >= 8 ? CrSyncArchs.X64 : CrSyncArchs.X86;
  723. }
  724. public static void WriteEventLog(string message, EventLogEntryType entryType)
  725. {
  726. // Check if we have registered an event log name and source
  727. var regKey = Registry.LocalMachine.OpenSubKey(@"\SYSTEM\CurrentControlSet\services\eventlog\ConnectionRoad");
  728. if(regKey == null)
  729. {
  730. Registry.LocalMachine.CreateSubKey(@"\SYSTEM\CurrentControlSet\services\eventlog\ConnectionRoad");
  731. }
  732. const string eventSource = "CRSyncFiles";
  733. const string eventLogName = "ConnectionRoad";
  734. if (!EventLog.SourceExists(eventSource))
  735. {
  736. EventLog.CreateEventSource(eventSource, eventLogName);
  737. }
  738. //Logs
  739. EventLog.WriteEntry(eventSource, message, entryType);
  740. }
  741. }
  742. }