diff --git a/Deploy/NAppUpdate/FeedBuilder.config b/Deploy/NAppUpdate/FeedBuilder.config deleted file mode 100644 index 4e99a397fd..0000000000 --- a/Deploy/NAppUpdate/FeedBuilder.config +++ /dev/null @@ -1,16 +0,0 @@ - - - http://127.0.0.1:8888 - True - False - True - False - <?xml version="1.0" encoding="utf-16"?> - <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" /> - True - False - ..\..\Output\Release - True - False - ..\..\Output\Update\Update.xml - diff --git a/Deploy/NAppUpdate/FeedBuilder.exe b/Deploy/NAppUpdate/FeedBuilder.exe deleted file mode 100644 index 278eea2032..0000000000 Binary files a/Deploy/NAppUpdate/FeedBuilder.exe and /dev/null differ diff --git a/Deploy/NAppUpdate/FeedBuilder.exe.config b/Deploy/NAppUpdate/FeedBuilder.exe.config deleted file mode 100644 index ae58790841..0000000000 --- a/Deploy/NAppUpdate/FeedBuilder.exe.config +++ /dev/null @@ -1,54 +0,0 @@ - - - - -
- - - - - - - - - True - - - False - - - True - - - False - - - True - - - True - - - - - - True - - - - - *.pdb - *.config - - - - - True - - - - - - - \ No newline at end of file diff --git a/Deploy/NAppUpdate/build.bat b/Deploy/NAppUpdate/build.bat deleted file mode 100644 index a9b07cb047..0000000000 --- a/Deploy/NAppUpdate/build.bat +++ /dev/null @@ -1,2 +0,0 @@ -cd /d %~dp0 -%~dp0FeedBuilder.exe "%~dp0FeedBuilder.config" -Build diff --git a/Deploy/NAppUpdate/gui.bat b/Deploy/NAppUpdate/gui.bat deleted file mode 100644 index 6c8eaf13e7..0000000000 --- a/Deploy/NAppUpdate/gui.bat +++ /dev/null @@ -1 +0,0 @@ -FeedBuilder.exe "FeedBuilder.config" -ShowGUI diff --git a/Deploy/NAppUpdate/NAppUpdate.Framework.dll b/Deploy/UpdateGenerator/NAppUpdate.Framework.dll similarity index 50% rename from Deploy/NAppUpdate/NAppUpdate.Framework.dll rename to Deploy/UpdateGenerator/NAppUpdate.Framework.dll index 60fac8ffc9..398d46b810 100644 Binary files a/Deploy/NAppUpdate/NAppUpdate.Framework.dll and b/Deploy/UpdateGenerator/NAppUpdate.Framework.dll differ diff --git a/Deploy/UpdateGenerator/Newtonsoft.Json.dll b/Deploy/UpdateGenerator/Newtonsoft.Json.dll new file mode 100644 index 0000000000..0a61735d26 Binary files /dev/null and b/Deploy/UpdateGenerator/Newtonsoft.Json.dll differ diff --git a/Deploy/UpdateGenerator/Wox.Infrastructure.dll b/Deploy/UpdateGenerator/Wox.Infrastructure.dll new file mode 100644 index 0000000000..ba780a7d22 Binary files /dev/null and b/Deploy/UpdateGenerator/Wox.Infrastructure.dll differ diff --git a/Deploy/UpdateGenerator/Wox.Plugin.dll b/Deploy/UpdateGenerator/Wox.Plugin.dll new file mode 100644 index 0000000000..92111aea88 Binary files /dev/null and b/Deploy/UpdateGenerator/Wox.Plugin.dll differ diff --git a/Deploy/UpdateGenerator/Wox.UpdateFeedGenerator.exe b/Deploy/UpdateGenerator/Wox.UpdateFeedGenerator.exe new file mode 100644 index 0000000000..88284908a3 Binary files /dev/null and b/Deploy/UpdateGenerator/Wox.UpdateFeedGenerator.exe differ diff --git a/Deploy/UpdateGenerator/build.bat b/Deploy/UpdateGenerator/build.bat new file mode 100644 index 0000000000..f51873e12d --- /dev/null +++ b/Deploy/UpdateGenerator/build.bat @@ -0,0 +1,2 @@ +cd /d %~dp0 +%~dp0Wox.UpdateFeedGenerator.exe diff --git a/Deploy/UpdateGenerator/config.json b/Deploy/UpdateGenerator/config.json new file mode 100644 index 0000000000..0e0afce156 --- /dev/null +++ b/Deploy/UpdateGenerator/config.json @@ -0,0 +1,10 @@ +{ + "OutputDirectory": "..\\..\\Output\\Update", + "SourceDirectory": "..\\..\\Output\\Release", + "BaseURL": "http://127.0.0.1:8888", + "FeedXMLName": "update.xml", + "CheckVersion": false, + "CheckSize": false, + "CheckDate": false, + "CheckHash": true +} diff --git a/Wox.UpdateFeedGenerator/ConfigStorage.cs b/Wox.UpdateFeedGenerator/ConfigStorage.cs new file mode 100644 index 0000000000..bdc6a30f3a --- /dev/null +++ b/Wox.UpdateFeedGenerator/ConfigStorage.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Newtonsoft.Json; +using Wox.Infrastructure.Storage; + +namespace Wox.UpdateFeedGenerator +{ + public class ConfigStorage : JsonStrorage + { + [JsonProperty] + public string OutputDirectory { get; set; } + + [JsonProperty] + public string SourceDirectory { get; set; } + + [JsonProperty] + public string BaseURL { get; set; } + + [JsonProperty] + public string FeedXMLName { get; set; } + + [JsonProperty] + public bool CheckVersion { get; set; } + + [JsonProperty] + public bool CheckSize { get; set; } + + [JsonProperty] + public bool CheckDate { get; set; } + + [JsonProperty] + public bool CheckHash { get; set; } + + protected override void OnAfterLoad(ConfigStorage config) + { + if (string.IsNullOrEmpty(config.OutputDirectory)) + { + config.OutputDirectory = @"Update"; + ConfigStorage.Instance.Save(); + } + } + + protected override string ConfigFolder + { + get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } + } + + protected override string ConfigName + { + get { return "config"; } + } + } +} diff --git a/Wox.UpdateFeedGenerator/FileInfoEx.cs b/Wox.UpdateFeedGenerator/FileInfoEx.cs new file mode 100644 index 0000000000..ff707162eb --- /dev/null +++ b/Wox.UpdateFeedGenerator/FileInfoEx.cs @@ -0,0 +1,38 @@ +using System.Diagnostics; +using System.IO; + +namespace Wox.UpdateFeedGenerator +{ + public class FileInfoEx + { + private readonly FileInfo myFileInfo; + private readonly string myFileVersion; + private readonly string myHash; + + public FileInfo FileInfo + { + get { return myFileInfo; } + } + + public string FileVersion + { + get { return myFileVersion; } + } + + public string Hash + { + get { return myHash; } + } + + public string RelativeName { get; private set; } + + public FileInfoEx(string fileName,int rootDirectoryLength) + { + myFileInfo = new FileInfo(fileName); + myFileVersion = FileVersionInfo.GetVersionInfo(fileName).FileVersion; + if (myFileVersion != null) myFileVersion = myFileVersion.Replace(", ", "."); + myHash = NAppUpdate.Framework.Utils.FileChecksum.GetSHA256Checksum(fileName); + RelativeName = fileName.Substring(rootDirectoryLength + 1); + } + } +} diff --git a/Wox.UpdateFeedGenerator/FileSystemEnumerator.cs b/Wox.UpdateFeedGenerator/FileSystemEnumerator.cs new file mode 100644 index 0000000000..e7ef75d5f2 --- /dev/null +++ b/Wox.UpdateFeedGenerator/FileSystemEnumerator.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security.Permissions; +using System.Text.RegularExpressions; +using Microsoft.Win32.SafeHandles; +using Wox.UpdateFeedGenerator.Win32; + +namespace Wox.UpdateFeedGenerator +{ + namespace Win32 + { + /// + /// Structure that maps to WIN32_FIND_DATA + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + internal sealed class FindData + { + public int fileAttributes; + public int creationTime_lowDateTime; + public int creationTime_highDateTime; + public int lastAccessTime_lowDateTime; + public int lastAccessTime_highDateTime; + public int lastWriteTime_lowDateTime; + public int lastWriteTime_highDateTime; + public int nFileSizeHigh; + public int nFileSizeLow; + public int dwReserved0; + public int dwReserved1; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public String fileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public String alternateFileName; + } + + /// + /// SafeHandle class for holding find handles + /// + internal sealed class SafeFindHandle : SafeHandleMinusOneIsInvalid + { + /// + /// Constructor + /// + public SafeFindHandle() : base(true) {} + + /// + /// Release the find handle + /// + /// true if the handle was released + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + protected override bool ReleaseHandle() + { + return SafeNativeMethods.FindClose(handle); + } + } + + /// + /// Wrapper for P/Invoke methods used by FileSystemEnumerator + /// + [SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)] + internal static class SafeNativeMethods + { + [DllImport("Kernel32.dll", CharSet = CharSet.Auto)] + public static extern SafeFindHandle FindFirstFile(String fileName, [In, Out] FindData findFileData); + + [DllImport("kernel32", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FindNextFile(SafeFindHandle hFindFile, [In, Out] FindData lpFindFileData); + + [DllImport("kernel32", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool FindClose(IntPtr hFindFile); + } + } + + /// + /// File system enumerator. This class provides an easy to use, efficient mechanism for searching a list of + /// directories for files matching a list of file specifications. The search is done incrementally as matches + /// are consumed, so the overhead before processing the first match is always kept to a minimum. + /// + public sealed class FileSystemEnumerator : IDisposable + { + /// + /// Information that's kept in our stack for simulated recursion + /// + private struct SearchInfo + { + /// + /// Find handle returned by FindFirstFile + /// + public readonly SafeFindHandle Handle; + + /// + /// Path that was searched to yield the find handle. + /// + public readonly string Path; + + /// + /// Constructor + /// + /// Find handle returned by FindFirstFile. + /// Path corresponding to find handle. + public SearchInfo(SafeFindHandle h, string p) + { + Handle = h; + Path = p; + } + } + + /// + /// Stack of open scopes. This is a member (instead of a local variable) + /// to allow Dispose to close any open find handles if the object is disposed + /// before the enumeration is completed. + /// + private readonly Stack m_scopes; + + /// + /// Array of paths to be searched. + /// + private readonly string[] m_paths; + + /// + /// Array of regular expressions that will detect matching files. + /// + private readonly List m_fileSpecs; + + /// + /// If true, sub-directories are searched. + /// + private readonly bool m_includeSubDirs; + + #region IDisposable implementation + + /// + /// IDisposable.Dispose + /// + public void Dispose() + { + while (m_scopes.Count > 0) { + SearchInfo si = m_scopes.Pop(); + si.Handle.Close(); + } + } + + #endregion + + /// + /// Constructor. + /// + /// Semicolon- or comma-delimitted list of paths to search. + /// Semicolon- or comma-delimitted list of wildcard filespecs to match. + /// If true, subdirectories are searched. + public FileSystemEnumerator(string pathsToSearch, string fileTypesToMatch, bool includeSubDirs) + { + m_scopes = new Stack(); + + // check for nulls + if (null == pathsToSearch) throw new ArgumentNullException("pathsToSearch"); + if (null == fileTypesToMatch) throw new ArgumentNullException("fileTypesToMatch"); + + // make sure spec doesn't contain invalid characters + if (fileTypesToMatch.IndexOfAny(new[] { ':', '<', '>', '/', '\\' }) >= 0) throw new ArgumentException("invalid cahracters in wildcard pattern", "fileTypesToMatch"); + + m_includeSubDirs = includeSubDirs; + m_paths = pathsToSearch.Split(new[] { ';', ',' }); + + string[] specs = fileTypesToMatch.Split(new[] { ';', ',' }); + m_fileSpecs = new List(specs.Length); + foreach (string spec in specs) { + // trim whitespace off file spec and convert Win32 wildcards to regular expressions + string pattern = spec.Trim().Replace(".", @"\.").Replace("*", @".*").Replace("?", @".?"); + m_fileSpecs.Add(new Regex("^" + pattern + "$", RegexOptions.IgnoreCase)); + } + } + + /// + /// Get an enumerator that returns all of the files that match the wildcards that + /// are in any of the directories to be searched. + /// + /// An IEnumerable that returns all matching files one by one. + /// + /// The enumerator that is returned finds files using a lazy algorithm that + /// searches directories incrementally as matches are consumed. + /// + public IEnumerable Matches() + { + foreach (string rootPath in m_paths) { + string path = rootPath.Trim(); + + // we "recurse" into a new directory by jumping to this spot + top: + + // check security - ensure that caller has rights to read this directory + new FileIOPermission(FileIOPermissionAccess.PathDiscovery, Path.Combine(path, ".")).Demand(); + + // now that security is checked, go read the directory + FindData findData = new FindData(); + SafeFindHandle handle = SafeNativeMethods.FindFirstFile(Path.Combine(path, "*"), findData); + m_scopes.Push(new SearchInfo(handle, path)); + bool restart = false; + + // we "return" from a sub-directory by jumping to this spot + restart: +// ReSharper disable InvertIf + if (!handle.IsInvalid) { +// ReSharper restore InvertIf + do { + // if we restarted the loop (unwound a recursion), fetch the next match + if (restart) { + restart = false; + continue; + } + + // don't match . or .. + if (findData.fileName.Equals(@".") || findData.fileName.Equals(@"..")) continue; + + if ((findData.fileAttributes & (int)FileAttributes.Directory) != 0) { + if (m_includeSubDirs) { + // it's a directory - recurse into it + path = Path.Combine(path, findData.fileName); + goto top; + } + } else { + // it's a file, see if any of the filespecs matches it + foreach (Regex fileSpec in m_fileSpecs) { + // if this spec matches, return this file's info + if (fileSpec.IsMatch(findData.fileName)) yield return new FileInfo(Path.Combine(path, findData.fileName)); + } + } + } while (SafeNativeMethods.FindNextFile(handle, findData)); + + // close this find handle + handle.Close(); + + // unwind the stack - are we still in a recursion? + m_scopes.Pop(); + if (m_scopes.Count > 0) { + SearchInfo si = m_scopes.Peek(); + handle = si.Handle; + path = si.Path; + restart = true; + goto restart; + } + } + } + } + } +} diff --git a/Wox.UpdateFeedGenerator/Generator.cs b/Wox.UpdateFeedGenerator/Generator.cs new file mode 100644 index 0000000000..9444254895 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Generator.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Xml; + +namespace Wox.UpdateFeedGenerator +{ + public class Generator + { + private string OutputDirectory; + private string SourceDirectory; + private string BaseURL = ConfigStorage.Instance.BaseURL; + private string feedXMLPath; + private bool checkVersion = ConfigStorage.Instance.CheckVersion; + private bool checkSize = ConfigStorage.Instance.CheckSize; + private bool checkDate = ConfigStorage.Instance.CheckDate; + private bool checkHash = ConfigStorage.Instance.CheckHash; + + public Generator() + { + OutputDirectory = Path.GetFullPath(ConfigStorage.Instance.OutputDirectory); + SourceDirectory = Path.GetFullPath(ConfigStorage.Instance.SourceDirectory); + feedXMLPath = Path.Combine(ConfigStorage.Instance.OutputDirectory, ConfigStorage.Instance.FeedXMLName); + } + + private List ReadSourceFiles() + { + List files = new List(); + FileSystemEnumerator enumerator = new FileSystemEnumerator(SourceDirectory, "*.*", true); + foreach (FileInfo fi in enumerator.Matches()) + { + string file = fi.FullName; + if ((IsIgnorable(file))) continue; + FileInfoEx thisInfo = new FileInfoEx(file, SourceDirectory.Length); + files.Add(thisInfo); + } + return files; + } + + private bool IsIgnorable(string thisFile) + { + return false; + } + + public void Build() + { + Console.WriteLine("Building Wox update feed"); + if (!Directory.Exists(OutputDirectory)) + { + Directory.CreateDirectory(OutputDirectory); + } + + XmlDocument doc = new XmlDocument(); + XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); + + doc.AppendChild(dec); + XmlElement feed = doc.CreateElement("Feed"); + feed.SetAttribute("BaseUrl", BaseURL.Trim()); + doc.AppendChild(feed); + + XmlElement tasks = doc.CreateElement("Tasks"); + + foreach (FileInfoEx file in ReadSourceFiles()) + { + Console.WriteLine("adding {0} to feed xml.", file.FileInfo.FullName); + XmlElement task = doc.CreateElement("FileUpdateTask"); + task.SetAttribute("localPath", file.RelativeName); + + // generate FileUpdateTask metadata items + task.SetAttribute("lastModified", file.FileInfo.LastWriteTime.ToFileTime().ToString(CultureInfo.InvariantCulture)); + task.SetAttribute("fileSize", file.FileInfo.Length.ToString(CultureInfo.InvariantCulture)); + if (!string.IsNullOrEmpty(file.FileVersion)) task.SetAttribute("version", file.FileVersion); + + XmlElement conds = doc.CreateElement("Conditions"); + XmlElement cond; + bool hasFirstCondition = false; + + //File Exists + cond = doc.CreateElement("FileExistsCondition"); + cond.SetAttribute("type", "or"); + conds.AppendChild(cond); + + //Version + if (checkVersion && !string.IsNullOrEmpty(file.FileVersion)) + { + cond = doc.CreateElement("FileVersionCondition"); + cond.SetAttribute("what", "below"); + cond.SetAttribute("version", file.FileVersion); + conds.AppendChild(cond); + hasFirstCondition = true; + } + + //Size + if (checkSize) + { + cond = doc.CreateElement("FileSizeCondition"); + cond.SetAttribute("type", hasFirstCondition ? "or-not" : "not"); + cond.SetAttribute("what", "is"); + cond.SetAttribute("size", file.FileInfo.Length.ToString(CultureInfo.InvariantCulture)); + conds.AppendChild(cond); + } + + //Date + if (checkDate) + { + cond = doc.CreateElement("FileDateCondition"); + if (hasFirstCondition) cond.SetAttribute("type", "or"); + cond.SetAttribute("what", "older"); + // local timestamp, not UTC + cond.SetAttribute("timestamp", file.FileInfo.LastWriteTime.ToFileTime().ToString(CultureInfo.InvariantCulture)); + conds.AppendChild(cond); + } + + //Hash + if (checkHash) + { + cond = doc.CreateElement("FileChecksumCondition"); + cond.SetAttribute("type", hasFirstCondition ? "or-not" : "not"); + cond.SetAttribute("checksumType", "sha256"); + cond.SetAttribute("checksum", file.Hash); + conds.AppendChild(cond); + } + + task.AppendChild(conds); + tasks.AppendChild(task); + string destFile = Path.Combine(OutputDirectory, file.RelativeName); + CopyFile(file.FileInfo.FullName, destFile); + } + feed.AppendChild(tasks); + doc.Save(feedXMLPath); + } + + private bool CopyFile(string sourceFile, string destFile) + { + // If the target folder doesn't exist, create the path to it + var fi = new FileInfo(destFile); + var d = Directory.GetParent(fi.FullName); + if (!Directory.Exists(d.FullName)) CreateDirectoryPath(d.FullName); + + // Copy with delayed retry + int retries = 3; + while (retries > 0) + { + try + { + if (File.Exists(destFile)) File.Delete(destFile); + File.Copy(sourceFile, destFile); + retries = 0; // success + return true; + } + catch (IOException) + { + // Failed... let's try sleeping a bit (slow disk maybe) + if (retries-- > 0) Thread.Sleep(200); + } + catch (UnauthorizedAccessException) + { + // same handling as IOException + if (retries-- > 0) Thread.Sleep(200); + } + } + return false; + } + + private void CreateDirectoryPath(string directoryPath) + { + // Create the folder/path if it doesn't exist, with delayed retry + int retries = 3; + while (retries > 0 && !Directory.Exists(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + if (retries-- < 3) Thread.Sleep(200); + } + } + + } +} diff --git a/Wox.UpdateFeedGenerator/Program.cs b/Wox.UpdateFeedGenerator/Program.cs new file mode 100644 index 0000000000..62953a2a63 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Xml; + +namespace Wox.UpdateFeedGenerator +{ + class Program + { + static void Main(string[] args) + { + new Generator().Build(); + } + } +} diff --git a/Wox.UpdateFeedGenerator/Properties/AssemblyInfo.cs b/Wox.UpdateFeedGenerator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..d0f4268282 --- /dev/null +++ b/Wox.UpdateFeedGenerator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Wox.UpdateFeedGenerator")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Wox.UpdateFeedGenerator")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2f3420c0-2c21-4f71-a45d-a47b5305fe20")] + +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Wox.UpdateFeedGenerator/README.md b/Wox.UpdateFeedGenerator/README.md new file mode 100644 index 0000000000..00741d2ac0 --- /dev/null +++ b/Wox.UpdateFeedGenerator/README.md @@ -0,0 +1 @@ +NAppUpdate feed generator for Wox. It's something like [FeedBuilder](https://github.com/synhershko/NAppUpdate/tree/master/FeedBuilder) \ No newline at end of file diff --git a/Wox.UpdateFeedGenerator/Wox.UpdateFeedGenerator.csproj b/Wox.UpdateFeedGenerator/Wox.UpdateFeedGenerator.csproj new file mode 100644 index 0000000000..2752c0e04e --- /dev/null +++ b/Wox.UpdateFeedGenerator/Wox.UpdateFeedGenerator.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F} + Exe + Properties + Wox.UpdateFeedGenerator + Wox.UpdateFeedGenerator + v3.5 + 512 + ..\ + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\References\NAppUpdate.Framework.dll + + + False + ..\packages\Newtonsoft.Json.6.0.8\lib\net35\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + {4fd29318-a8ab-4d8f-aa47-60bc241b8da3} + Wox.Infrastructure + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。启用“NuGet 程序包还原”可下载这些程序包。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + \ No newline at end of file diff --git a/Wox.UpdateFeedGenerator/packages.config b/Wox.UpdateFeedGenerator/packages.config new file mode 100644 index 0000000000..7a13476a54 --- /dev/null +++ b/Wox.UpdateFeedGenerator/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Wox.sln b/Wox.sln index cd2007ff85..3125875e5f 100644 --- a/Wox.sln +++ b/Wox.sln @@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.CrashReporter", "Wox.Cr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.QueryHistory", "Plugins\Wox.Plugin.QueryHistory\Wox.Plugin.QueryHistory.csproj", "{B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.UpdateFeedGenerator", "Wox.UpdateFeedGenerator\Wox.UpdateFeedGenerator.csproj", "{D120E62B-EC59-4FB4-8129-EFDD4C446A5F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -119,6 +121,10 @@ Global {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {B552DCB6-692E-4B1D-9E0B-9096A2A7E6B0}.Release|Any CPU.Build.0 = Release|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D120E62B-EC59-4FB4-8129-EFDD4C446A5F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE