public event EventHandler <CancelEventArgs <CacheItem> > RetryResourceCheck = delegate { }; // raised before attempting to reconnect to server to check for resource info public SpringScanner(SpringPaths springPaths) { this.springPaths = springPaths; MetaData = new MetaDataCache(springPaths, this); foreach (var folder in springPaths.DataDirectories) { var modsPath = Utils.MakePath(folder, "games"); if (Directory.Exists(modsPath)) { modsWatchers.Add(new FileSystemWatcher(modsPath)); } var mapsPath = Utils.MakePath(folder, "maps"); if (Directory.Exists(mapsPath)) { mapsWatchers.Add(new FileSystemWatcher(mapsPath)); } var packagesPath = Utils.MakePath(folder, "packages"); if (Directory.Exists(packagesPath)) { packagesWatchers.Add(new FileSystemWatcher(packagesPath)); } } SetupWatcherEvents(mapsWatchers); SetupWatcherEvents(modsWatchers); SetupWatcherEvents(packagesWatchers); Directory.CreateDirectory(springPaths.Cache); cachePath = Utils.MakePath(springPaths.Cache, "ScannerCache.json"); Directory.CreateDirectory(Utils.MakePath(springPaths.Cache, "Resources")); }
public Main(string path) { RootWorkPath = path; LoadConfig(); Config.RestartCounter++; if (Config.RestartCounter > 3) Config.RestartCounter = 0; SaveConfig(); paths = new SpringPaths(Path.GetDirectoryName(Config.ExecutableName), writableFolderOverride: Config.DataDir); if (!string.IsNullOrEmpty(Config.ExecutableName)) paths.OverrideDedicatedServer(Config.ExecutableName); paths.MakeFolders(); MetaCache = new MetaDataCache(paths); timer = new Timer(30000); timer.Elapsed += timer_Elapsed; timer.AutoReset = true; timer.Start(); Downloader = new PlasmaDownloader.PlasmaDownloader(Config, null, paths); }
public event EventHandler<CancelEventArgs<CacheItem>> RetryResourceCheck = delegate { }; // raised before attempting to reconnect to server to check for resource info public SpringScanner(SpringPaths springPaths) { this.springPaths = springPaths; MetaData = new MetaDataCache(springPaths, this); foreach (var folder in springPaths.DataDirectories) { var modsPath = Utils.MakePath(folder, "games"); if (Directory.Exists(modsPath)) modsWatchers.Add(new FileSystemWatcher(modsPath)); var mapsPath = Utils.MakePath(folder, "maps"); if (Directory.Exists(mapsPath)) mapsWatchers.Add(new FileSystemWatcher(mapsPath)); var packagesPath = Utils.MakePath(folder, "packages"); if (Directory.Exists(packagesPath)) packagesWatchers.Add(new FileSystemWatcher(packagesPath)); } SetupWatcherEvents(mapsWatchers); SetupWatcherEvents(modsWatchers); SetupWatcherEvents(packagesWatchers); Directory.CreateDirectory(springPaths.Cache); cachePath = Utils.MakePath(springPaths.Cache, "ScannerCache.json"); Directory.CreateDirectory(Utils.MakePath(springPaths.Cache, "Resources")); }
public event EventHandler<CancelEventArgs<CacheItem>> RetryResourceCheck = delegate { }; // raised before attempting to reconnect to server to check for resource info public SpringScanner(SpringPaths springPaths) { this.SpringPaths = springPaths; MetaData = new MetaDataCache(springPaths, this); foreach (var folder in springPaths.DataDirectories) { var modsPath = Utils.MakePath(folder, "games"); if (Directory.Exists(modsPath)) modsWatchers.Add(new FileSystemWatcher(modsPath)); var mapsPath = Utils.MakePath(folder, "maps"); if (Directory.Exists(mapsPath)) mapsWatchers.Add(new FileSystemWatcher(mapsPath)); var packagesPath = Utils.MakePath(folder, "packages"); if (Directory.Exists(packagesPath)) packagesWatchers.Add(new FileSystemWatcher(packagesPath)); } SetupWatcherEvents(mapsWatchers); SetupWatcherEvents(modsWatchers); SetupWatcherEvents(packagesWatchers); Directory.CreateDirectory(springPaths.Cache); cachePath = Utils.MakePath(springPaths.Cache, "ScannerCache.json"); Directory.CreateDirectory(Utils.MakePath(springPaths.Cache, "Resources")); if (UseUnitSync) { try { unitSync = new UnitSync(springPaths); } catch (Exception ex) { Trace.TraceWarning("UnitSync init failed: {0}",ex); } } }
public AutoHost(MetaDataCache cache, AhConfig config, int hostingPort, SpawnConfig spawn) { this.config = config; Commands = new CommandList(config); this.cache = cache; SpawnConfig = spawn; this.hostingPort = hostingPort; string version = config.SpringVersion ?? Program.main.Config.SpringVersion ?? GlobalConst.DefaultEngineOverride; springPaths = new SpringPaths(Program.main.paths.GetEngineFolderByVersion(version), Program.main.Config.DataDir); springPaths.SpringVersionChanged += (s, e) => { if (!String.IsNullOrEmpty(requestedEngineChange) && requestedEngineChange == springPaths.SpringVersion) { config.SpringVersion = requestedEngineChange; springPaths.SetEnginePath(Program.main.paths.GetEngineFolderByVersion(requestedEngineChange)); requestedEngineChange = null; tas.Say(SayPlace.Battle, "", "rehosting to engine version " + springPaths.SpringVersion, true); ComRehost(TasSayEventArgs.Default, new string[] { }); } }; spring = new Spring(springPaths) { UseDedicatedServer = true }; bool isManaged = SpawnConfig == null && config.Mode != AutohostMode.None; tas = new TasClient(MainConfig.SpringieVersion, isManaged ? Login.ClientTypes.SpringieManaged : Login.ClientTypes.Springie, Program.main.Config.IpOverride); pollTimer = new Timer(PollTimeout*1000); pollTimer.Enabled = false; pollTimer.AutoReset = false; pollTimer.Elapsed += pollTimer_Elapsed; spring.SpringExited += spring_SpringExited; spring.GameOver += spring_GameOver; spring.SpringExited += spring_SpringExited; spring.SpringStarted += spring_SpringStarted; spring.PlayerSaid += spring_PlayerSaid; spring.BattleStarted += spring_BattleStarted; tas.BattleUserLeft += tas_BattleUserLeft; tas.UserStatusChanged += tas_UserStatusChanged; tas.BattleUserJoined += tas_BattleUserJoined; tas.MyBattleMapChanged += tas_MyBattleMapChanged; tas.BattleOpened += tas_BattleOpened; tas.UserAdded += (o, u) => { if (u.Name == GetAccountName()) OpenBattleRoom(null, null); }; tas.RegistrationDenied += (s, e) => { Trace.TraceWarning("Registration denied: {0} {1}", e.ResultCode.Description(), e.Reason); CloneNumber++; tas.Login(GetAccountName(), config.Password); }; tas.RegistrationAccepted += (s, e) => tas.Login(GetAccountName(), config.Password); tas.ConnectionLost += tas_ConnectionLost; tas.Connected += tas_Connected; tas.LoginDenied += tas_LoginDenied; tas.LoginAccepted += tas_LoginAccepted; tas.Said += tas_Said; tas.MyBattleStarted += tas_MyStatusChangedToInGame; linkSpringieClient = new ResourceLinkSpringieClient(this); // queue autohost if (config != null && config.MinToJuggle != null && SpawnConfig == null) { queue = new MatchMakerQueue(this); } Program.main.Downloader.PackagesChanged += Downloader_PackagesChanged; timer = new Timer(15000); timer.Elapsed += (s, e) => { try { timer.Stop(); timerTick++; // auto update engine branch if (!String.IsNullOrEmpty(config.AutoUpdateSpringBranch) && timerTick%4 == 0) CheckEngineBranch(); // auto verify pw map if (!spring.IsRunning && config.Mode != AutohostMode.None) if (SpawnConfig == null && config.Mode == AutohostMode.Planetwars) ServerVerifyMap(false); // auto start split vote if (!spring.IsRunning && config.SplitBiggerThan != null && tas.MyBattle != null && config.SplitBiggerThan < tas.MyBattle.NonSpectatorCount) { if (DateTime.Now.Subtract(spring.GameExited).TotalSeconds >= GameExitSplitDelay) ComSplitPlayers(TasSayEventArgs.Default, new string[]{}); /* int cnt = tas.MyBattle.NonSpectatorCount; if (cnt > lastSplitPlayersCountCalled && cnt%2 == 0) { StartVote(new VoteSplitPlayers(tas, spring, this), TasSayEventArgs.Default, new string[] { }); lastSplitPlayersCountCalled = cnt; }*/ } // auto rehost to latest mod version if (!string.IsNullOrEmpty(config.AutoUpdateRapidTag) && SpawnConfig == null) UpdateRapidMod(config.AutoUpdateRapidTag); } catch (Exception ex) { Trace.TraceError(ex.ToString()); } finally { timer.Start(); } }; timer.Start(); }
public static void Main(string[] args) { try { //Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); Trace.Listeners.Add(new ConsoleTraceListener()); if (Environment.OSVersion.Platform != PlatformID.Unix) { var ver = GetNetVersionFromRegistry(); if (ver < 378675) { MessageBox.Show(new Form { TopMost = true }, "Zero-K launcher needs Microsoft .NET framework 4.5.1\nPlease download and install it first", "Program is unable to run", MessageBoxButtons.OK, MessageBoxIcon.Error); } } Directory.SetCurrentDirectory(StartupPath); // extract fonts EmbeddedResourceExtractor.ExtractFile("ZeroKLobby.NativeLibs.SM.ttf", "SM.ttf"); EmbeddedResourceExtractor.ExtractFile("ZeroKLobby.NativeLibs.OpenSans-Regular.ttf", "OpenSans-Regular.ttf"); Conf = new Config(); IsSteamFolder = File.Exists(Path.Combine(StartupPath, "steamfolder.txt")); SelfUpdater = new SelfUpdater("Zero-K"); StartupArgs = args; try { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); } catch (Exception ex) { Trace.TraceWarning("Failed to set rendering compatibility: {0}", ex); } if (!Debugger.IsAttached) { try { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; Thread.GetDomain().UnhandledException += UnhandledException; Application.ThreadException += Application_ThreadException; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); } catch (Exception ex) { Trace.TraceWarning("Failed to set exception handling :{0}", ex); } } //HttpWebRequest.DefaultCachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); Trace.TraceInformation("Starting with version {0}", SelfUpdater.CurrentVersion); WebRequest.DefaultWebProxy = null; ThreadPool.SetMaxThreads(500, 2000); ServicePointManager.Expect100Continue = false; LoadConfig(); Trace.Listeners.Add(new LogTraceListener()); if (Environment.OSVersion.Platform != PlatformID.Unix && !Conf.UseExternalBrowser) Utils.SetIeCompatibility(); //set to current IE version var contentDir = !string.IsNullOrEmpty(Conf.DataFolder) ? Conf.DataFolder : StartupPath; if (!Directory.Exists(contentDir) || !SpringPaths.IsDirectoryWritable(contentDir)) { var dc = new SelectWritableFolder { SelectedPath = SpringPaths.GetMySpringDocPath() }; if (dc.ShowDialog() != DialogResult.OK) return; contentDir = dc.SelectedPath; } if (Conf.DataFolder != StartupPath) Conf.DataFolder = contentDir; else Conf.DataFolder = null; if (!SpringPaths.IsDirectoryWritable(StartupPath)) { var newTarget = Path.Combine(contentDir, "Zero-K.exe"); if (SelfUpdater.CheckForUpdate(newTarget, true)) { Conf.Save(Path.Combine(contentDir, Config.ConfigFileName)); Process.Start(newTarget); return; } MessageBox.Show(new Form { TopMost = true }, "Move failed, please copy Zero-K.exe to a writable folder"); return; } SpringPaths = new SpringPaths(contentDir); if ( MessageBox.Show(new Form() { TopMost = true }, "Would you like to try the new lobby program for Zero-K: Chobby?", "New launcher option available", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { var targetPath = Path.Combine(SpringPaths.WritableDirectory, "Chobby.exe"); if (!File.Exists(targetPath)) { var wc = new WebClient(); wc.DownloadFile(GlobalConst.BaseSiteUrl + "/lobby/Chobby.exe", targetPath); } Process.Start(targetPath); Environment.Exit(0); } // speed up spring start SpringPaths.SpringVersionChanged += (sender, engine) => { ZkData.Utils.StartAsync( () => { UnitSync unitSync = null; try { unitSync = new UnitSync(SpringPaths, engine); // initialize unitsync to avoid slowdowns when starting if (unitSync.UnitsyncWritableFolder != SpringPaths.WritableDirectory) { // unitsync created its cache in different folder than is used to start spring -> move it var fi = ArchiveCache.GetCacheFile(unitSync.UnitsyncWritableFolder); if (fi != null) File.Copy(fi.FullName, Path.Combine(SpringPaths.WritableDirectory, "cache", fi.Name), true); } } finally { unitSync?.Dispose(); } }); }; SaveConfig(); // write license files try { var path = SpringPaths.WritableDirectory; var pathGPL = Utils.MakePath(path, "license_GPLv3"); var gpl = Encoding.UTF8.GetString(License.GPLv3); if (!File.Exists(pathGPL)) File.WriteAllText(pathGPL, gpl); var pathMIT = Utils.MakePath(path, "license_MIT"); var mit = Encoding.UTF8.GetString(License.MITlicense); if (!File.Exists(pathMIT)) File.WriteAllText(pathMIT, mit); } catch (Exception ex) { Trace.TraceError(ex.ToString()); } if (Conf.IsFirstRun) { if (!IsSteamFolder) { Utils.CreateDesktopShortcut(); } if (Environment.OSVersion.Platform != PlatformID.Unix) Utils.RegisterProtocol(); } MetaData = new MetaDataCache(SpringPaths); AutoJoinManager = new AutoJoinManager(); EngineConfigurator = new EngineConfigurator(SpringPaths.WritableDirectory); SpringScanner = new PlasmaResourceChecker(SpringPaths); SpringScanner.LocalResourceAdded += (s, e) => Trace.TraceInformation("New resource found: {0}", e.Item.InternalName); SpringScanner.LocalResourceRemoved += (s, e) => Trace.TraceInformation("Resource removed: {0}", e.Item.InternalName); Downloader = new PlasmaDownloader.PlasmaDownloader(SpringScanner, SpringPaths); //rapid Downloader.DownloadAdded += (s, e) => Trace.TraceInformation("Download started: {0}", e.Data.Name); //Downloader.GetResource(DownloadType.ENGINE, GlobalConst.DefaultEngineOverride); var isLinux = Environment.OSVersion.Platform == PlatformID.Unix; TasClient = new TasClient(string.Format("ZK {0}{1}", SelfUpdater.CurrentVersion, isLinux ? " linux" : "")); SayCommandHandler = new SayCommandHandler(TasClient); ServerImages = new ServerImagesHandler(SpringPaths, TasClient); // log, for debugging TasClient.Connected += (s, e) => Trace.TraceInformation("TASC connected"); TasClient.LoginAccepted += (s, e) => { Trace.TraceInformation("TASC login accepted"); Trace.TraceInformation("Server is using Spring version {0}", TasClient.ServerSpringVersion); if (Environment.OSVersion.Platform == PlatformID.Unix || Conf.UseExternalBrowser) if (MainWindow != null) MainWindow.navigationControl.Path = "battles"; }; TasClient.LoginDenied += (s, e) => Trace.TraceInformation("TASC login denied"); TasClient.ChannelJoined += (s, e) => { Trace.TraceInformation("TASC channel joined: " + e.Name); }; TasClient.ConnectionLost += (s, e) => Trace.TraceInformation("Connection lost"); TasClient.WelcomeReceived += (s, e) => { Downloader.GetResource(DownloadType.ENGINE, e.Engine); Downloader.GetResource(DownloadType.RAPID, e.Game); }; Program.AreYouReadyDialog = new AreYouReadyDialog(TasClient); // special handling TasClient.PreviewSaid += (s, e) => { var tas = (TasClient)s; User user = null; if (e.Data.UserName != null) { tas.ExistingUsers.TryGetValue(e.Data.UserName, out user); if ((user != null && user.BanMute) || TasClient.Ignores.Contains(e.Data.UserName)) e.Cancel = true; } }; TasClient.SiteToLobbyCommandReceived += (eventArgs, o) => { if (MainWindow != null) { MainWindow.navigationControl.Path = o.Command; MainWindow.PopupSelf(); } }; ModStore = new ModStore(); ConnectBar = new ConnectBar(TasClient); ToolTip = new ToolTipHandler(); BrowserInterop = new BrowserInterop(TasClient, Conf); BattleIconManager = new BattleIconManager(); Application.AddMessageFilter(ToolTip); SteamHandler = new ZklSteamHandler(TasClient); MainWindow = new MainWindow(); Application.AddMessageFilter(new ScrollMessageFilter()); MainWindow.Size = new Size( Math.Min(SystemInformation.VirtualScreen.Width - 30, MainWindow.Width), Math.Min(SystemInformation.VirtualScreen.Height - 30, MainWindow.Height)); //in case user have less space than 1024x768 BattleBar = new BattleBar(); VoteBar = new VoteBar(); PwBar = new PwBar(); MatchMakerBar = new MatchMakerBar(TasClient); SelfUpdater.ProgramUpdated += s => { Program.MainWindow.InvokeFunc( () => WarningBar.DisplayWarning($"New version of Zero-K launcher downloaded, restart it to apply changes", "Restart", Restart)); }; if (!Debugger.IsAttached && !Conf.DisableAutoUpdate && !IsSteamFolder) SelfUpdater.StartChecking(); if (GlobalConst.Mode != ModeType.Local) SteamHandler.Connect(); Application.Run(MainWindow); ShutDown(); } catch (Exception ex) { ErrorHandling.HandleException(ex, true); if (Debugger.IsAttached) Debugger.Break(); } finally { ShutDown(); } if (ErrorHandling.HasFatalException && !CloseOnNext) { if (Debugger.IsAttached) Debugger.Break(); Application.Restart(); } }
public void UpdateMission(ZkDataContext db, Mission mission, Mod modInfo) { var file = mission.Mutator.ToArray(); var tempName = Path.GetTempFileName() + ".zip"; File.WriteAllBytes(tempName, file); using (var zf = new ZipFile(tempName)) { zf.UpdateEntry("modinfo.lua", Encoding.UTF8.GetBytes(GetModInfo(mission.NameWithVersion, mission.Mod, mission.Name, "ZK"))); // FIXME hardcoded crap FixScript(mission, zf, "script.txt"); var script = FixScript(mission, zf, GlobalConst.MissionScriptFileName); modInfo.MissionScript = script; //modInfo.ShortName = mission.Name; modInfo.Name = mission.NameWithVersion; zf.Save(); } mission.Mutator = File.ReadAllBytes(tempName); mission.Script = Regex.Replace(mission.Script, "GameType=([^;]+);", (m) => { return(string.Format("GameType={0};", mission.NameWithVersion)); }); File.Delete(tempName); var resource = db.Resources.FirstOrDefault(x => x.MissionID == mission.MissionID); if (resource == null) { resource = new Resource() { DownloadCount = 0, TypeID = ZkData.ResourceType.Mod }; db.Resources.Add(resource); } resource.InternalName = mission.NameWithVersion; resource.MissionID = mission.MissionID; resource.ResourceDependencies.Clear(); resource.ResourceDependencies.Add(new ResourceDependency() { NeedsInternalName = mission.Map }); resource.ResourceDependencies.Add(new ResourceDependency() { NeedsInternalName = mission.Mod }); resource.ResourceContentFiles.Clear(); // generate torrent var tempFile = Path.Combine(Path.GetTempPath(), mission.SanitizedFileName); File.WriteAllBytes(tempFile, mission.Mutator.ToArray()); var creator = new TorrentCreator(); creator.Path = tempFile; var torrentStream = new MemoryStream(); creator.Create(torrentStream); try { File.Delete(tempFile); } catch { } var md5 = Hash.HashBytes(mission.Mutator.ToArray()).ToString(); resource.ResourceContentFiles.Add(new ResourceContentFile() { FileName = mission.SanitizedFileName, Length = mission.Mutator.Length, LinkCount = 1, Links = string.Format(MissionFileUrl, mission.MissionID), Md5 = md5 }); var basePath = GlobalConst.SiteDiskPath + @"\resources\"; if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); } File.WriteAllBytes(string.Format(@"{2}\{0}_{1}.torrent", resource.InternalName.EscapePath(), md5, basePath), torrentStream.ToArray()); File.WriteAllBytes(string.Format(@"{1}\{0}.metadata.xml.gz", resource.InternalName.EscapePath(), basePath), MetaDataCache.SerializeAndCompressMetaData(modInfo)); var imgPath = GlobalConst.SiteDiskPath + @"\img\missions\"; if (!Directory.Exists(imgPath)) { Directory.CreateDirectory(imgPath); } File.WriteAllBytes(string.Format(imgPath + "{0}.png", mission.MissionID, basePath), mission.Image.ToArray()); }
void PerformUnitSyncOperation(WorkItem workItem) { Trace.TraceInformation("PerformUnitSyncOperation"); VerifyUnitSync(); if (unitSync == null) { Trace.TraceError("Skipping file after unitsync loading errors: {0}", workItem.CacheItem.ShortPath); CacheMarkFailedUnitSync(workItem.CacheItem.ShortPath); return; } var info = GetUnitSyncData(workItem.CacheItem.FileName); UnInitUnitsync(); if (info != null) { workItem.CacheItem.InternalName = info.Name; workItem.CacheItem.ResourceType = info is Map ? ResourceType.Map : ResourceType.Mod; CacheItemAdd(workItem.CacheItem); var args = new CancelEventArgs <IResourceInfo>(info); UploadUnitsyncData.Invoke(this, args); if (args.Cancel) { return; } var serializedData = MetaDataCache.SerializeAndCompressMetaData(info); var map = info as Map; object userState = null; try { var creator = new TorrentCreator(); creator.Path = GetFullPath(workItem); var ms = new MemoryStream(); creator.Create(ms); byte[] minimap = null; byte[] metalMap = null; byte[] heightMap = null; if (map != null) { minimap = map.Minimap.ToBytes(ImageSize); metalMap = map.Metalmap.ToBytes(ImageSize); heightMap = map.Heightmap.ToBytes(ImageSize); userState = new MapRegisteredEventArgs(info.Name, map, minimap, metalMap, heightMap, serializedData); } var mod = info as Mod; if (mod != null) { userState = new KeyValuePair <Mod, byte[]>(mod, serializedData); } Trace.TraceInformation("uploading {0} to server", info.Name); Task.Factory.StartNew(() => { ReturnValue e; try { e = service.RegisterResource(PlasmaServiceVersion, springPaths.SpringVersion, workItem.CacheItem.Md5.ToString(), workItem.CacheItem.Length, info is Map ? ResourceType.Map : ResourceType.Mod, workItem.CacheItem.FileName, info.Name, serializedData, mod != null ? mod.Dependencies.ToList() : null, minimap, metalMap, heightMap, ms.ToArray()); } catch (Exception ex) { Trace.TraceError("Error uploading data to server: {0}", ex); return; } finally { Interlocked.Decrement(ref itemsSending); } if (e != ReturnValue.Ok) { Trace.TraceWarning("Resource registering failed: {0}", e); return; } var mapArgs = userState as MapRegisteredEventArgs; if (mapArgs != null) { var mapName = mapArgs.MapName; MetaData.SaveMinimap(mapName, mapArgs.Minimap); MetaData.SaveMetalmap(mapName, mapArgs.MetalMap); MetaData.SaveHeightmap(mapName, mapArgs.HeightMap); MetaData.SaveMetadata(mapName, mapArgs.SerializedData); MapRegistered(this, mapArgs); } else { var kvp = (KeyValuePair <Mod, byte[]>)userState; var modInfo = kvp.Key; var serializedDataRet = kvp.Value; MetaData.SaveMetadata(modInfo.Name, serializedDataRet); ModRegistered(this, new EventArgs <Mod>(mod)); } }); Interlocked.Increment(ref itemsSending); } catch (Exception e) { Trace.TraceError("Error registering new resource {0}: {1}", workItem.CacheItem.ShortPath, e); } } else { Trace.TraceError("Could not unitsync file {0}", workItem.CacheItem.ShortPath); CacheMarkFailedUnitSync(workItem.CacheItem.ShortPath); } return; }