don't persist lazy loaded paths

This commit is contained in:
Luke Pulverenti 2013-12-29 12:07:29 -05:00
parent 30b29f63c4
commit 04d1a53d19
12 changed files with 61 additions and 145 deletions

View File

@ -124,9 +124,11 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns> /// <returns>System.Object.</returns>
public object Get(GetConfiguration request) public object Get(GetConfiguration request)
{ {
var dateModified = _fileSystem.GetLastWriteTimeUtc(_configurationManager.ApplicationPaths.SystemConfigurationFilePath); var configPath = _configurationManager.ApplicationPaths.SystemConfigurationFilePath;
var cacheKey = (_configurationManager.ApplicationPaths.SystemConfigurationFilePath + dateModified.Ticks).GetMD5(); var dateModified = _fileSystem.GetLastWriteTimeUtc(configPath);
var cacheKey = (configPath + dateModified.Ticks).GetMD5();
return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => _configurationManager.Configuration); return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => _configurationManager.Configuration);
} }

View File

@ -140,10 +140,6 @@ namespace MediaBrowser.Common.Implementations
} }
} }
/// <summary>
/// The _configuration directory path
/// </summary>
private string _configurationDirectoryPath;
/// <summary> /// <summary>
/// Gets the path to the application configuration root directory /// Gets the path to the application configuration root directory
/// </summary> /// </summary>
@ -152,12 +148,7 @@ namespace MediaBrowser.Common.Implementations
{ {
get get
{ {
if (_configurationDirectoryPath == null) return Path.Combine(ProgramDataPath, "config");
{
_configurationDirectoryPath = Path.Combine(ProgramDataPath, "config");
Directory.CreateDirectory(_configurationDirectoryPath);
}
return _configurationDirectoryPath;
} }
} }
@ -218,7 +209,7 @@ namespace MediaBrowser.Common.Implementations
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
private string GetProgramDataPath() private string GetProgramDataPath()
{ {
var programDataPath = _useDebugPath ? ConfigurationManager.AppSettings["DebugProgramDataPath"] : Path.Combine(ConfigurationManager.AppSettings["ReleaseProgramDataPath"], ConfigurationManager.AppSettings["ProgramDataFolderName"]); var programDataPath = _useDebugPath ? ConfigurationManager.AppSettings["DebugProgramDataPath"] : ConfigurationManager.AppSettings["ReleaseProgramDataPath"];
programDataPath = programDataPath.Replace("%ApplicationData%", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); programDataPath = programDataPath.Replace("%ApplicationData%", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

View File

@ -99,9 +99,13 @@ namespace MediaBrowser.Common.Implementations.Configuration
/// </summary> /// </summary>
public void SaveConfiguration() public void SaveConfiguration()
{ {
var path = CommonApplicationPaths.SystemConfigurationFilePath;
Directory.CreateDirectory(Path.GetDirectoryName(path));
lock (_configurationSaveLock) lock (_configurationSaveLock)
{ {
XmlSerializer.SerializeToFile(CommonConfiguration, CommonApplicationPaths.SystemConfigurationFilePath); XmlSerializer.SerializeToFile(CommonConfiguration, path);
} }
OnConfigurationUpdated(); OnConfigurationUpdated();

View File

@ -121,7 +121,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
{ {
LazyInitializer.EnsureInitialized(ref _lastExecutionResult, ref _lastExecutionResultinitialized, ref _lastExecutionResultSyncLock, () => LazyInitializer.EnsureInitialized(ref _lastExecutionResult, ref _lastExecutionResultinitialized, ref _lastExecutionResultSyncLock, () =>
{ {
var path = GetHistoryFilePath(false); var path = GetHistoryFilePath();
try try
{ {
@ -432,43 +432,28 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <summary> /// <summary>
/// Gets the scheduled tasks configuration directory. /// Gets the scheduled tasks configuration directory.
/// </summary> /// </summary>
/// <param name="create">if set to <c>true</c> [create].</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
private string GetScheduledTasksConfigurationDirectory(bool create) private string GetScheduledTasksConfigurationDirectory()
{ {
var path = Path.Combine(ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks"); return Path.Combine(ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
if (create)
{
Directory.CreateDirectory(path);
}
return path;
} }
/// <summary> /// <summary>
/// Gets the scheduled tasks data directory. /// Gets the scheduled tasks data directory.
/// </summary> /// </summary>
/// <param name="create">if set to <c>true</c> [create].</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
private string GetScheduledTasksDataDirectory(bool create) private string GetScheduledTasksDataDirectory()
{ {
var path = Path.Combine(ApplicationPaths.DataPath, "ScheduledTasks"); return Path.Combine(ApplicationPaths.DataPath, "ScheduledTasks");
if (create)
{
Directory.CreateDirectory(path);
}
return path;
} }
/// <summary> /// <summary>
/// Gets the history file path. /// Gets the history file path.
/// </summary> /// </summary>
/// <value>The history file path.</value> /// <value>The history file path.</value>
private string GetHistoryFilePath(bool createDirectory) private string GetHistoryFilePath()
{ {
return Path.Combine(GetScheduledTasksDataDirectory(createDirectory), Id + ".js"); return Path.Combine(GetScheduledTasksDataDirectory(), Id + ".js");
} }
/// <summary> /// <summary>
@ -477,7 +462,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
private string GetConfigurationFilePath() private string GetConfigurationFilePath()
{ {
return Path.Combine(GetScheduledTasksConfigurationDirectory(false), Id + ".js"); return Path.Combine(GetScheduledTasksConfigurationDirectory(), Id + ".js");
} }
/// <summary> /// <summary>
@ -512,9 +497,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
{ {
var path = GetConfigurationFilePath(); var path = GetConfigurationFilePath();
var parentPath = Path.GetDirectoryName(path); Directory.CreateDirectory(Path.GetDirectoryName(path));
Directory.CreateDirectory(parentPath);
JsonSerializer.SerializeToFile(triggers.Select(ScheduledTaskHelpers.GetTriggerInfo), path); JsonSerializer.SerializeToFile(triggers.Select(ScheduledTaskHelpers.GetTriggerInfo), path);
} }
@ -545,7 +528,10 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
result.ErrorMessage = ex.Message; result.ErrorMessage = ex.Message;
} }
JsonSerializer.SerializeToFile(result, GetHistoryFilePath(true)); var path = GetHistoryFilePath();
Directory.CreateDirectory(Path.GetDirectoryName(path));
JsonSerializer.SerializeToFile(result, path);
LastExecutionResult = result; LastExecutionResult = result;

View File

@ -11,7 +11,6 @@ namespace MediaBrowser.Common.Implementations.Security
{ {
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly string _filename;
public string RegKey public string RegKey
{ {
get { return _regKey; } get { return _regKey; }
@ -26,6 +25,14 @@ namespace MediaBrowser.Common.Implementations.Security
} }
} }
private string Filename
{
get
{
return Path.Combine(_appPaths.ConfigurationDirectoryPath, "mb.lic");
}
}
public string LegacyKey { get; set; } public string LegacyKey { get; set; }
private Dictionary<Guid, DateTime> UpdateRecords { get; set; } private Dictionary<Guid, DateTime> UpdateRecords { get; set; }
private readonly object _lck = new object(); private readonly object _lck = new object();
@ -35,8 +42,6 @@ namespace MediaBrowser.Common.Implementations.Security
{ {
_appPaths = appPaths; _appPaths = appPaths;
_filename = Path.Combine(_appPaths.ConfigurationDirectoryPath, "mb.lic");
UpdateRecords = new Dictionary<Guid, DateTime>(); UpdateRecords = new Dictionary<Guid, DateTime>();
Load(); Load();
} }
@ -64,15 +69,16 @@ namespace MediaBrowser.Common.Implementations.Security
private void Load() private void Load()
{ {
string[] contents = null; string[] contents = null;
var licenseFile = Filename;
lock (_lck) lock (_lck)
{ {
try try
{ {
contents = File.ReadAllLines(_filename); contents = File.ReadAllLines(licenseFile);
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
(File.Create(_filename)).Close(); (File.Create(licenseFile)).Close();
} }
} }
if (contents != null && contents.Length > 0) if (contents != null && contents.Length > 0)
@ -100,7 +106,9 @@ namespace MediaBrowser.Common.Implementations.Security
lines.Add(pair.Value.Ticks.ToString()); lines.Add(pair.Value.Ticks.ToString());
} }
lock(_lck) File.WriteAllLines(_filename, lines); var licenseFile = Filename;
Directory.CreateDirectory(Path.GetDirectoryName(licenseFile));
lock (_lck) File.WriteAllLines(licenseFile, lines);
} }
} }
} }

View File

@ -76,14 +76,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary> /// </summary>
private UserRootFolder _rootFolder; private UserRootFolder _rootFolder;
/// <summary> /// <summary>
/// The _user root folder initialized
/// </summary>
private bool _userRootFolderInitialized;
/// <summary>
/// The _user root folder sync lock
/// </summary>
private object _userRootFolderSyncLock = new object();
/// <summary>
/// Gets the root folder. /// Gets the root folder.
/// </summary> /// </summary>
/// <value>The root folder.</value> /// <value>The root folder.</value>
@ -92,17 +84,11 @@ namespace MediaBrowser.Controller.Entities
{ {
get get
{ {
LazyInitializer.EnsureInitialized(ref _rootFolder, ref _userRootFolderInitialized, ref _userRootFolderSyncLock, () => LibraryManager.GetUserRootFolder(RootFolderPath)); return _rootFolder ?? (LibraryManager.GetUserRootFolder(RootFolderPath));
return _rootFolder;
} }
private set private set
{ {
_rootFolder = value; _rootFolder = value;
if (_rootFolder == null)
{
_userRootFolderInitialized = false;
}
} }
} }
@ -153,22 +139,6 @@ namespace MediaBrowser.Controller.Entities
} }
} }
/// <summary>
/// Gets the last date modified of the configuration
/// </summary>
/// <value>The configuration date last modified.</value>
[IgnoreDataMember]
public DateTime ConfigurationDateLastModified
{
get
{
// Ensure it's been lazy loaded
var config = Configuration;
return FileSystem.GetLastWriteTimeUtc(ConfigurationFilePath);
}
}
/// <summary> /// <summary>
/// Reloads the root media folder /// Reloads the root media folder
/// </summary> /// </summary>
@ -203,13 +173,22 @@ namespace MediaBrowser.Controller.Entities
{ {
// Move configuration // Move configuration
var newConfigDirectory = GetConfigurationDirectoryPath(newName); var newConfigDirectory = GetConfigurationDirectoryPath(newName);
var oldConfigurationDirectory = ConfigurationDirectoryPath;
// Exceptions will be thrown if these paths already exist // Exceptions will be thrown if these paths already exist
if (Directory.Exists(newConfigDirectory)) if (Directory.Exists(newConfigDirectory))
{ {
Directory.Delete(newConfigDirectory, true); Directory.Delete(newConfigDirectory, true);
} }
Directory.Move(ConfigurationDirectoryPath, newConfigDirectory);
if (Directory.Exists(oldConfigurationDirectory))
{
Directory.Move(oldConfigurationDirectory, newConfigDirectory);
}
else
{
Directory.CreateDirectory(newConfigDirectory);
}
var customLibraryPath = GetRootFolderPath(Name); var customLibraryPath = GetRootFolderPath(Name);
@ -228,7 +207,6 @@ namespace MediaBrowser.Controller.Entities
Name = newName; Name = newName;
// Force these to be lazy loaded again // Force these to be lazy loaded again
_configurationDirectoryPath = null;
RootFolder = null; RootFolder = null;
// Kick off a task to validate the media library // Kick off a task to validate the media library
@ -237,26 +215,16 @@ namespace MediaBrowser.Controller.Entities
return RefreshMetadata(CancellationToken.None, forceSave: true, forceRefresh: true); return RefreshMetadata(CancellationToken.None, forceSave: true, forceRefresh: true);
} }
/// <summary>
/// The _configuration directory path
/// </summary>
private string _configurationDirectoryPath;
/// <summary> /// <summary>
/// Gets the path to the user's configuration directory /// Gets the path to the user's configuration directory
/// </summary> /// </summary>
/// <value>The configuration directory path.</value> /// <value>The configuration directory path.</value>
[IgnoreDataMember]
private string ConfigurationDirectoryPath private string ConfigurationDirectoryPath
{ {
get get
{ {
if (_configurationDirectoryPath == null) return GetConfigurationDirectoryPath(Name);
{
_configurationDirectoryPath = GetConfigurationDirectoryPath(Name);
Directory.CreateDirectory(_configurationDirectoryPath);
}
return _configurationDirectoryPath;
} }
} }
@ -281,6 +249,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets the path to the user's configuration file /// Gets the path to the user's configuration file
/// </summary> /// </summary>
/// <value>The configuration file path.</value> /// <value>The configuration file path.</value>
[IgnoreDataMember]
public string ConfigurationFilePath public string ConfigurationFilePath
{ {
get get
@ -294,7 +263,9 @@ namespace MediaBrowser.Controller.Entities
/// </summary> /// </summary>
public void SaveConfiguration(IXmlSerializer serializer) public void SaveConfiguration(IXmlSerializer serializer)
{ {
serializer.SerializeToFile(Configuration, ConfigurationFilePath); var xmlPath = ConfigurationFilePath;
Directory.CreateDirectory(System.IO.Path.GetDirectoryName(xmlPath));
serializer.SerializeToFile(Configuration, xmlPath);
} }
/// <summary> /// <summary>

View File

@ -2,10 +2,7 @@
<MonoDevelop.Ide.Workspace ActiveConfiguration="Release Mono" /> <MonoDevelop.Ide.Workspace ActiveConfiguration="Release Mono" />
<MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.Server.Mono\app.config"> <MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.Server.Mono\app.config">
<Files> <Files>
<File FileName="MediaBrowser.Server.Mono\app.config" Line="15" Column="3" /> <File FileName="MediaBrowser.Server.Mono\app.config" Line="1" Column="39" />
<File FileName="MediaBrowser.Server.Mono\FFMpeg\FFMpegDownloadInfo.cs" Line="1" Column="1" />
<File FileName="MediaBrowser.Server.Mono\Program.cs" Line="1" Column="1" />
<File FileName="MediaBrowser.Server.Implementations\Library\UserManager.cs" Line="1" Column="1" />
</Files> </Files>
</MonoDevelop.Ide.Workbench> </MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints> <MonoDevelop.Ide.DebuggingService.Breakpoints>

View File

@ -377,7 +377,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (!string.IsNullOrEmpty(genres)) if (!string.IsNullOrEmpty(genres))
{ {
video.Genres = genres.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries) video.Genres = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Where(i => !string.IsNullOrWhiteSpace(i)) .Where(i => !string.IsNullOrWhiteSpace(i))
.Select(i => i.Trim()) .Select(i => i.Trim())
.ToList(); .ToList();

View File

@ -8,7 +8,6 @@
</nlog> </nlog>
<appSettings> <appSettings>
<add key="DebugProgramDataPath" value="ProgramData-Server" /> <add key="DebugProgramDataPath" value="ProgramData-Server" />
<add key="ReleaseProgramDataPath" value="" /> <add key="ReleaseProgramDataPath" value="ProgramData-Server" />
<add key="ProgramDataFolderName" value="ProgramData-Server" />
</appSettings> </appSettings>
</configuration> </configuration>

View File

@ -11,8 +11,7 @@
</nlog> </nlog>
<appSettings> <appSettings>
<add key="DebugProgramDataPath" value="..\..\..\..\ProgramData-Server" /> <add key="DebugProgramDataPath" value="..\..\..\..\ProgramData-Server" />
<add key="ReleaseProgramDataPath" value="%ApplicationData%" /> <add key="ReleaseProgramDataPath" value="%ApplicationData%\MediaBrowser-Server" />
<add key="ProgramDataFolderName" value="MediaBrowser-Server" />
<add key="ClientSettingsProvider.ServiceUri" value="" /> <add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings> </appSettings>
<startup useLegacyV2RuntimeActivationPolicy="true"> <startup useLegacyV2RuntimeActivationPolicy="true">

View File

@ -590,7 +590,8 @@ namespace MediaBrowser.ServerApplication
{ {
return Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly) return Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly)
.Select(LoadAssembly) .Select(LoadAssembly)
.Where(a => a != null); .Where(a => a != null)
.ToList();
} }
catch (DirectoryNotFoundException) catch (DirectoryNotFoundException)
{ {

View File

@ -94,9 +94,6 @@
<Content Include="dashboard-ui\css\images\clients\xbmc.png"> <Content Include="dashboard-ui\css\images\clients\xbmc.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\editor.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\icons\audiocd.png"> <Content Include="dashboard-ui\css\images\icons\audiocd.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -193,9 +190,6 @@
<Content Include="dashboard-ui\css\images\editor\missingtrailer.png"> <Content Include="dashboard-ui\css\images\editor\missingtrailer.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\remote.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\metadataeditor.css"> <Content Include="dashboard-ui\css\metadataeditor.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -208,9 +202,6 @@
<Content Include="dashboard-ui\css\detailtable.css"> <Content Include="dashboard-ui\css\detailtable.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\bgflip.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\clients\chrome.png"> <Content Include="dashboard-ui\css\images\clients\chrome.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -289,9 +280,6 @@
<Content Include="dashboard-ui\css\images\rotten.png"> <Content Include="dashboard-ui\css\images\rotten.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\css\images\searchbutton.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\currentuserdefaultblack.png"> <Content Include="dashboard-ui\css\images\currentuserdefaultblack.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -1486,11 +1474,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\css\images\toolswhite.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="dashboard-ui\css\images\rightarrow.png"> <Content Include="dashboard-ui\css\images\rightarrow.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -1573,11 +1556,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\css\images\bg.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="dashboard-ui\plugincatalog.html"> <Content Include="dashboard-ui\plugincatalog.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -1586,21 +1564,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\css\images\leftarrowblack.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\css\images\leftarrowwhite.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\css\images\toolsblack.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="dashboard-ui\scheduledtasks.html"> <Content Include="dashboard-ui\scheduledtasks.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -1765,11 +1728,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="dashboard-ui\css\images\home.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="dashboard-ui\css\images\notifications\done.png"> <Content Include="dashboard-ui\css\images\notifications\done.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>