");
+ foreach (var movie in orderedMovies)
+ {
+ // We have a try within a try so we can catch the rate limit without ending the loop (finally block)
+ try
+ {
+ try
+ {
+
+ var imdbId = PlexHelper.GetProviderIdFromPlexGuid(movie.Metadata.Video.Guid);
+ var info = MovieApi.GetMovieInformation(imdbId).Result;
+ if (info == null)
+ {
+ throw new Exception($"Movie with Imdb id {imdbId} returned null from the MovieApi");
+ }
+ AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
+
+ sb.Append("
");
+ sb.Append(
+ "
");
+
+ Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/");
+ Header(sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}");
+ EndTag(sb, "a");
+
+ if (info.Genres.Any())
+ {
+ AddParagraph(sb,
+ $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}");
+ }
+
+ AddParagraph(sb, info.Overview);
+ }
+ catch (RequestLimitExceededException limit)
+ {
+ // We have hit a limit, we need to now wait.
+ Thread.Sleep(TimeSpan.FromSeconds(10));
+ Log.Info(limit);
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error(e);
+ Log.Error("Error for movie with IMDB Id = {0}", movie.Metadata.Video.Guid);
+ }
+ finally
+ {
+ EndLoopHtml(sb);
+ }
+
+ }
+ sb.Append("
");
+ }
+
+ private class TvModel
+ {
+ public EmbySeriesInformation Series { get; set; }
+ public List Episodes { get; set; }
+ }
+ private void GenerateTvHtml(IEnumerable recenetlyAddedTv, StringBuilder sb)
+ {
+ var tv = recenetlyAddedTv?.ToList() ?? new List();
+
+ if (!tv.Any())
+ {
+ return;
+ }
+ var orderedTv = tv.OrderByDescending(x => x.Content.AddedAt).ToList();
+
+ // TV
+ sb.Append("
New Episodes:
");
+ sb.Append(
+ "
");
+ foreach (var t in orderedTv)
+ {
+ //var seriesItem = t.EmbyInformation.SeriesInformation;
+ //var relatedEpisodes = t.EpisodeInformation;
+
+
+ try
+ {
+ var info = TvApi.ShowLookupByTheTvDbId(int.Parse(PlexHelper.GetProviderIdFromPlexGuid(t.Metadata.Directory.Guid)));
+
+ var banner = info.image?.original;
+ if (!string.IsNullOrEmpty(banner))
+ {
+ banner = banner.Replace("http", "https"); // Always use the Https banners
+ }
+ AddImageInsideTable(sb, banner);
+
+ sb.Append("
");
+ }
+
+
+
+
+ private void EndLoopHtml(StringBuilder sb)
+ {
+ //NOTE: BR have to be in TD's as per html spec or it will be put outside of the table...
+ //Source: http://stackoverflow.com/questions/6588638/phantom-br-tag-rendered-by-browsers-prior-to-table-tag
+ sb.Append("");
+ sb.Append(" ");
+ sb.Append(" ");
+ sb.Append("");
+ sb.Append("");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Ombi.Services/Jobs/RecentlyAddedNewsletter/RecentlyAddedNewsletter.cs b/Ombi.Services/Jobs/RecentlyAddedNewsletter/RecentlyAddedNewsletter.cs
index e2bbf5ede..330adf60c 100644
--- a/Ombi.Services/Jobs/RecentlyAddedNewsletter/RecentlyAddedNewsletter.cs
+++ b/Ombi.Services/Jobs/RecentlyAddedNewsletter/RecentlyAddedNewsletter.cs
@@ -53,18 +53,19 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
public RecentlyAddedNewsletter(IPlexApi api, ISettingsService plexSettings,
ISettingsService email, IJobRecord rec,
ISettingsService newsletter,
- IPlexReadOnlyDatabase db, IUserHelper userHelper, IEmbyAddedNewsletter embyNews,
- ISettingsService embyS)
+ IUserHelper userHelper, IEmbyAddedNewsletter embyNews,
+ ISettingsService embyS,
+ IPlexNewsletter plex)
{
JobRecord = rec;
Api = api;
PlexSettings = plexSettings;
EmailSettings = email;
NewsletterSettings = newsletter;
- PlexDb = db;
UserHelper = userHelper;
EmbyNewsletter = embyNews;
EmbySettings = embyS;
+ PlexNewsletter = plex;
}
private IPlexApi Api { get; }
@@ -75,9 +76,9 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
private ISettingsService EmailSettings { get; }
private ISettingsService NewsletterSettings { get; }
private IJobRecord JobRecord { get; }
- private IPlexReadOnlyDatabase PlexDb { get; }
private IUserHelper UserHelper { get; }
private IEmbyAddedNewsletter EmbyNewsletter { get; }
+ private IPlexNewsletter PlexNewsletter { get; }
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
@@ -144,331 +145,18 @@ namespace Ombi.Services.Jobs.RecentlyAddedNewsletter
}
else
{
- var sb = new StringBuilder();
var plexSettings = PlexSettings.GetSettings();
- Log.Debug("Got Plex Settings");
-
- var libs = Api.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri);
- Log.Debug("Getting Plex Library Sections");
-
- var tvSections = libs.Directories.Where(x => x.type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase)); // We could have more than 1 lib
- Log.Debug("Filtered sections for TV");
- var movieSection = libs.Directories.Where(x => x.type.Equals(PlexMediaType.Movie.ToString(), StringComparison.CurrentCultureIgnoreCase)); // We could have more than 1 lib
- Log.Debug("Filtered sections for Movies");
-
- var plexVersion = Api.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri).Version;
-
- var html = string.Empty;
- if (plexVersion.StartsWith("1.3"))
- {
- var tvMetadata = new List();
- var movieMetadata = new List();
- foreach (var tvSection in tvSections)
- {
- var item = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri,
- tvSection?.Key);
- if (item?.MediaContainer?.Metadata != null)
- {
- tvMetadata.AddRange(item?.MediaContainer?.Metadata);
- }
- }
- Log.Debug("Got RecentlyAdded TV Shows");
- foreach (var movie in movieSection)
- {
- var recentlyAddedMovies = Api.RecentlyAdded(plexSettings.PlexAuthToken, plexSettings.FullUri, movie?.Key);
- if (recentlyAddedMovies?.MediaContainer?.Metadata != null)
- {
- movieMetadata.AddRange(recentlyAddedMovies?.MediaContainer?.Metadata);
- }
- }
- Log.Debug("Got RecentlyAdded Movies");
-
- Log.Debug("Started Generating Movie HTML");
- GenerateMovieHtml(movieMetadata, plexSettings, sb);
- Log.Debug("Finished Generating Movie HTML");
- Log.Debug("Started Generating TV HTML");
- GenerateTvHtml(tvMetadata, plexSettings, sb);
- Log.Debug("Finished Generating TV HTML");
-
- var template = new RecentlyAddedTemplate();
- html = template.LoadTemplate(sb.ToString());
- Log.Debug("Loaded the template");
- }
- else
- {
- // Old API
- var tvChild = new List();
- var movieChild = new List();
- foreach (var tvSection in tvSections)
- {
- var recentlyAddedTv = Api.RecentlyAddedOld(plexSettings.PlexAuthToken, plexSettings.FullUri, tvSection?.Key);
- if (recentlyAddedTv?._children != null)
- {
- tvChild.AddRange(recentlyAddedTv?._children);
- }
- }
-
- Log.Debug("Got RecentlyAdded TV Shows");
- foreach (var movie in movieSection)
- {
- var recentlyAddedMovies = Api.RecentlyAddedOld(plexSettings.PlexAuthToken, plexSettings.FullUri, movie?.Key);
- if (recentlyAddedMovies?._children != null)
- {
- tvChild.AddRange(recentlyAddedMovies?._children);
- }
- }
- Log.Debug("Got RecentlyAdded Movies");
-
- Log.Debug("Started Generating Movie HTML");
- GenerateMovieHtml(movieChild, plexSettings, sb);
- Log.Debug("Finished Generating Movie HTML");
- Log.Debug("Started Generating TV HTML");
- GenerateTvHtml(tvChild, plexSettings, sb);
- Log.Debug("Finished Generating TV HTML");
-
- var template = new RecentlyAddedTemplate();
- html = template.LoadTemplate(sb.ToString());
- Log.Debug("Loaded the template");
- }
- string escapedHtml = new string(html.Where(c => !char.IsControl(c)).ToArray());
- Log.Debug(escapedHtml);
- SendNewsletter(newletterSettings, escapedHtml, testEmail);
- }
- }
-
- private void GenerateMovieHtml(List movies, PlexSettings plexSettings, StringBuilder sb)
- {
- var orderedMovies = movies.OrderByDescending(x => x?.addedAt.UnixTimeStampToDateTime()).ToList() ?? new List();
- sb.Append("
New Movies:
");
- sb.Append(
- "
");
- foreach (var movie in orderedMovies)
- {
- var plexGUID = string.Empty;
- try
- {
- var metaData = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri,
- movie.ratingKey.ToString());
-
- plexGUID = metaData.Video.Guid;
-
- var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID);
- var info = _movieApi.GetMovieInformation(imdbId).Result;
- if (info == null)
- {
- throw new Exception($"Movie with Imdb id {imdbId} returned null from the MovieApi");
- }
- AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
-
- sb.Append("
");
- sb.Append(
- "
");
-
- Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/");
- Header(sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}");
- EndTag(sb, "a");
-
- if (info.Genres.Any())
- {
- AddParagraph(sb,
- $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}");
- }
-
- AddParagraph(sb, info.Overview);
- }
- catch (Exception e)
- {
- Log.Error(e);
- Log.Error(
- "Exception when trying to process a Movie, either in getting the metadata from Plex OR getting the information from TheMovieDB, Plex GUID = {0}",
- plexGUID);
- }
- finally
- {
- EndLoopHtml(sb);
- }
-
- }
- sb.Append("
");
- foreach (var movie in orderedMovies)
- {
- var plexGUID = string.Empty;
- try
- {
- var metaData = Api.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri,
- movie.ratingKey.ToString());
-
- plexGUID = metaData.Video.Guid;
-
- var imdbId = PlexHelper.GetProviderIdFromPlexGuid(plexGUID);
- var info = _movieApi.GetMovieInformation(imdbId).Result;
- if (info == null)
- {
- throw new Exception($"Movie with Imdb id {imdbId} returned null from the MovieApi");
- }
- AddImageInsideTable(sb, $"https://image.tmdb.org/t/p/w500{info.BackdropPath}");
-
- sb.Append("
");
- sb.Append(
- "
");
-
- Href(sb, $"https://www.imdb.com/title/{info.ImdbId}/");
- Header(sb, 3, $"{info.Title} {info.ReleaseDate?.ToString("yyyy") ?? string.Empty}");
- EndTag(sb, "a");
-
- if (info.Genres.Any())
- {
- AddParagraph(sb,
- $"Genre: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}");
- }
-
- AddParagraph(sb, info.Overview);
- }
- catch (Exception e)
- {
- Log.Error(e);
- Log.Error(
- "Exception when trying to process a Movie, either in getting the metadata from Plex OR getting the information from TheMovieDB, Plex GUID = {0}",
- plexGUID);
- }
- finally
- {
- EndLoopHtml(sb);
- }
-
- }
- sb.Append("
diff --git a/Ombi.Updater/AppType.cs b/Ombi.Updater/AppType.cs
new file mode 100644
index 000000000..a75a95675
--- /dev/null
+++ b/Ombi.Updater/AppType.cs
@@ -0,0 +1,35 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2017 Jamie Rees
+// File: AppType.cs
+// Created By: Jamie Rees
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ************************************************************************/
+#endregion
+namespace Ombi.Updater
+{
+ public enum AppType
+ {
+ Normal,
+ Console,
+ Service
+ }
+}
\ No newline at end of file
diff --git a/Ombi.Updater/DetectApplicationType.cs b/Ombi.Updater/DetectApplicationType.cs
new file mode 100644
index 000000000..73e50231a
--- /dev/null
+++ b/Ombi.Updater/DetectApplicationType.cs
@@ -0,0 +1,39 @@
+using Ombi.Common;
+using Ombi.Common.EnvironmentInfo;
+using Ombi.Common.Processes;
+
+namespace Ombi.Updater
+{
+ public class DetectApplicationType
+ {
+ public DetectApplicationType()
+ {
+ _processProvider = new ProcessProvider();
+ _serviceProvider = new ServiceProvider(_processProvider);
+ }
+
+ private readonly IServiceProvider _serviceProvider;
+ private readonly IProcessProvider _processProvider;
+ public AppType GetAppType()
+ {
+ if (OsInfo.IsNotWindows)
+ {
+ // Technically it is the console, but it has been renamed for mono (Linux/OS X)
+ return AppType.Normal;
+ }
+
+ if (_serviceProvider.ServiceExist(ServiceProvider.OmbiServiceName)
+ )
+ {
+ return AppType.Service;
+ }
+
+ if (_processProvider.Exists(ProcessProvider.OmbiProcessName))
+ {
+ return AppType.Console;
+ }
+
+ return AppType.Normal;
+ }
+ }
+}
diff --git a/Ombi.Updater/InstallService.cs b/Ombi.Updater/InstallService.cs
new file mode 100644
index 000000000..502f2ae39
--- /dev/null
+++ b/Ombi.Updater/InstallService.cs
@@ -0,0 +1,57 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2017 Jamie Rees
+// File: InstallService.cs
+// Created By: Jamie Rees
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ************************************************************************/
+#endregion
+
+using System.Linq;
+using Ombi.Common;
+using Ombi.Common.EnvironmentInfo;
+using Ombi.Common.Processes;
+
+namespace Ombi.Updater
+{
+ public class InstallService
+ {
+ public void Start(string installFolder)
+ {
+ var dector = new DetectApplicationType();
+ var processProvider = new ProcessProvider();
+
+ var processId = processProvider.FindProcessByName(ProcessProvider.OmbiProcessName)?.FirstOrDefault()?.Id ?? -1;
+
+ // Log if process is -1
+
+ var appType = dector.GetAppType();
+ processProvider.FindProcessByName(ProcessProvider.OmbiProcessName);
+
+ if (OsInfo.IsWindows)
+ {
+ var terminator = new TerminateOmbi(new ServiceProvider(processProvider), processProvider);
+ terminator.Terminate(processId);
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ombi.Updater/Ombi.Updater.csproj b/Ombi.Updater/Ombi.Updater.csproj
index 5e0641ded..881b9badd 100644
--- a/Ombi.Updater/Ombi.Updater.csproj
+++ b/Ombi.Updater/Ombi.Updater.csproj
@@ -13,7 +13,7 @@
truefullfalse
- bin\Debug
+ bin\Debug\Updater\DEBUG;prompt4
@@ -22,12 +22,15 @@
fulltrue
- bin\Release
+ bin\Release\Updater\prompt4true
+
+ ..\packages\NLog.4.3.6\lib\net45\NLog.dll
+ ..\packages\Polly-Signed.4.3.0\lib\net45\Polly.dllTrue
@@ -38,12 +41,20 @@
+
+
+
+
+
+ {bfd45569-90cf-47ca-b575-c7b0ff97f67b}
+ Ombi.Common
+ {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}Ombi.Core
diff --git a/Ombi.Updater/TerminateOmbi.cs b/Ombi.Updater/TerminateOmbi.cs
new file mode 100644
index 000000000..f72bc54d2
--- /dev/null
+++ b/Ombi.Updater/TerminateOmbi.cs
@@ -0,0 +1,88 @@
+#region Copyright
+// /************************************************************************
+// Copyright (c) 2017 Jamie Rees
+// File: TerminateOmbi.cs
+// Created By: Jamie Rees
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ************************************************************************/
+#endregion
+
+using System;
+using NLog;
+using Ombi.Common;
+using Ombi.Common.EnvironmentInfo;
+using Ombi.Common.Processes;
+using IServiceProvider = Ombi.Common.IServiceProvider;
+
+namespace Ombi.Updater
+{
+ public interface ITerminateOmbi
+ {
+ void Terminate(int processId);
+ }
+
+ public class TerminateOmbi : ITerminateOmbi
+ {
+ private readonly IServiceProvider _serviceProvider;
+ private readonly IProcessProvider _processProvider;
+
+ private static Logger _logger = LogManager.GetCurrentClassLogger();
+
+ public TerminateOmbi(IServiceProvider serviceProvider, IProcessProvider processProvider)
+ {
+ _serviceProvider = serviceProvider;
+ _processProvider = processProvider;
+ }
+
+ public void Terminate(int processId)
+ {
+ if (OsInfo.IsWindows)
+ {
+ _logger.Info("Stopping all running services");
+
+ if (_serviceProvider.ServiceExist(ServiceProvider.OmbiServiceName))
+ {
+ try
+ {
+ _logger.Info("NzbDrone Service is installed and running");
+ _serviceProvider.Stop(ServiceProvider.OmbiServiceName);
+ }
+ catch (Exception e)
+ {
+ _logger.Error(e, "couldn't stop service");
+ }
+ }
+
+ _logger.Info("Killing all running processes");
+
+ _processProvider.KillAll(ProcessProvider.OmbiProcessName);
+ }
+ else
+ {
+ _logger.Info("Killing all running processes");
+
+ _processProvider.KillAll(ProcessProvider.OmbiProcessName);
+
+ _processProvider.Kill(processId);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ombi.Updater/packages.config b/Ombi.Updater/packages.config
index 4a06c0f59..6bc1f0299 100644
--- a/Ombi.Updater/packages.config
+++ b/Ombi.Updater/packages.config
@@ -1,4 +1,5 @@
+
\ No newline at end of file
diff --git a/Ombi.sln b/Ombi.sln
index 984651728..2eefc0648 100644
--- a/Ombi.sln
+++ b/Ombi.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
+# Visual Studio 15
+VisualStudioVersion = 15.0.26206.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.UI", "Ombi.UI\Ombi.UI.csproj", "{68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}"
EndProject
@@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Helpers.Tests", "Ombi.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Core.Migration", "Ombi.Core.Migration\Ombi.Core.Migration.csproj", "{8406EE57-D533-47C0-9302-C6B5F8C31E55}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Common", "Ombi.Common\Ombi.Common.csproj", "{BFD45569-90CF-47CA-B575-C7B0FF97F67B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -97,6 +99,10 @@ Global
{8406EE57-D533-47C0-9302-C6B5F8C31E55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8406EE57-D533-47C0-9302-C6B5F8C31E55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8406EE57-D533-47C0-9302-C6B5F8C31E55}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BFD45569-90CF-47CA-B575-C7B0FF97F67B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BFD45569-90CF-47CA-B575-C7B0FF97F67B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BFD45569-90CF-47CA-B575-C7B0FF97F67B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BFD45569-90CF-47CA-B575-C7B0FF97F67B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE