mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
dd8939b395
Combined DisplayMagicianShared logging into the main log file to simplify log reporting for the future. Also started adding info and debug statements to the program to make the debug level log work well for troubleshooting. This is going to take a LONG time to complete, but will be worth it in the end.
1039 lines
48 KiB
C#
1039 lines
48 KiB
C#
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing.IconLib;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using WindowsDisplayAPI.DisplayConfig;
|
|
using NvAPIWrapper.Mosaic;
|
|
using NvAPIWrapper.Native.Mosaic;
|
|
using WindowsDisplayAPI;
|
|
using System.Diagnostics;
|
|
using System.Text.RegularExpressions;
|
|
using NvAPIWrapper.Native.GPU;
|
|
|
|
namespace DisplayMagicianShared
|
|
{
|
|
|
|
public static class ProfileRepository
|
|
{
|
|
#region Class Variables
|
|
// Common items to the class
|
|
private static List<ProfileItem> _allProfiles = new List<ProfileItem>();
|
|
private static bool _profilesLoaded = false;
|
|
public static Version _version = new Version(1, 0, 0);
|
|
private static ProfileItem _currentProfile;
|
|
|
|
// Other constants that are useful
|
|
public static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician");
|
|
public static string AppIconPath = System.IO.Path.Combine(AppDataPath, $"Icons");
|
|
public static string AppDisplayMagicianIconFilename = System.IO.Path.Combine(AppIconPath, @"DisplayMagician.ico");
|
|
private static readonly string AppProfileStoragePath = System.IO.Path.Combine(AppDataPath, $"Profiles");
|
|
private static readonly string _profileStorageJsonFileName = System.IO.Path.Combine(AppProfileStoragePath, $"DisplayProfiles_{_version.ToString(2)}.json");
|
|
|
|
|
|
#endregion
|
|
|
|
#region Class Constructors
|
|
static ProfileRepository()
|
|
{
|
|
|
|
// Initialise the the NVIDIA NvAPIWrapper
|
|
try
|
|
{
|
|
SharedLogger.logger.Debug($"ProfileRepository/ProfileRepository: Initialising the NvAPIWrapper.NVIDIA library.");
|
|
NvAPIWrapper.NVIDIA.Initialize();
|
|
|
|
SharedLogger.logger.Debug($"ProfileRepository/ProfileRepository: Creating the Profiles storage folder {AppProfileStoragePath}.");
|
|
// Create the Profile Storage Path if it doesn't exist so that it's avilable for all the program
|
|
if (!Directory.Exists(AppProfileStoragePath))
|
|
{
|
|
Directory.CreateDirectory(AppProfileStoragePath);
|
|
}
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/ProfileRepository: DisplayMagician doesn't have permissions to create the Profiles storage folder {AppProfileStoragePath}.");
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/ProfileRepository: DisplayMagician can't create the Profiles storage folder {AppProfileStoragePath} due to an invalid argument.");
|
|
}
|
|
catch (PathTooLongException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/ProfileRepository: DisplayMagician can't create the Profiles storage folder {AppProfileStoragePath} as the path is too long.");
|
|
}
|
|
catch (DirectoryNotFoundException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/ProfileRepository: DisplayMagician can't create the Profiles storage folder {AppProfileStoragePath} as the parent folder isn't there.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Warn(ex, $"ProfileRepository/ProfileRepository: Initialising NVIDIA NvAPIWrapper caused an exception.");
|
|
}
|
|
// Load the Profiles from storage
|
|
LoadProfiles();
|
|
}
|
|
#endregion
|
|
|
|
#region Class Properties
|
|
public static List<ProfileItem> AllProfiles
|
|
{
|
|
get
|
|
{
|
|
if (!_profilesLoaded)
|
|
// Load the Profiles from storage if they need to be
|
|
LoadProfiles();
|
|
return _allProfiles;
|
|
}
|
|
}
|
|
|
|
public static ProfileItem CurrentProfile
|
|
{
|
|
get
|
|
{
|
|
if (_currentProfile == null)
|
|
UpdateActiveProfile();
|
|
return _currentProfile;
|
|
}
|
|
set
|
|
{
|
|
if (value is ProfileItem)
|
|
{
|
|
_currentProfile = value;
|
|
// And if we have the _originalBitmap we can also save the Bitmap overlay, but only if the ProfileToUse is set
|
|
//if (_originalBitmap is Bitmap)
|
|
// _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap, 256, 256);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static int ProfileCount
|
|
{
|
|
get
|
|
{
|
|
if (!_profilesLoaded)
|
|
// Load the Profiles from storage if they need to be
|
|
LoadProfiles();
|
|
|
|
|
|
return _allProfiles.Count;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Class Methods
|
|
public static bool AddProfile(ProfileItem profile)
|
|
{
|
|
if (!(profile is ProfileItem))
|
|
return false;
|
|
|
|
// Doublecheck if it already exists
|
|
// Because then we just update the one that already exists
|
|
if (!ContainsProfile(profile))
|
|
{
|
|
// Add the Profile to the list of Profiles
|
|
_allProfiles.Add(profile);
|
|
|
|
// Generate the Profile Icon ready to be used
|
|
SaveProfileIconToCache(profile);
|
|
|
|
profile.PreSave();
|
|
|
|
// Save the Profiles JSON as it's different
|
|
SaveProfiles();
|
|
}
|
|
|
|
//Doublecheck it's been added
|
|
if (ContainsProfile(profile))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
public static bool RemoveProfile(ProfileItem Profile)
|
|
{
|
|
if (!(Profile is ProfileItem))
|
|
return false;
|
|
|
|
// Remove the Profile Icons from the Cache
|
|
List<ProfileItem> ProfilesToRemove = _allProfiles.FindAll(item => item.UUID.Equals(Profile.UUID));
|
|
foreach (ProfileItem ProfileToRemove in ProfilesToRemove)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(ProfileToRemove.SavedProfileIconCacheFilename);
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile: DisplayMagician doesn't have permissions to delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename}.");
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} due to an invalid argument.");
|
|
}
|
|
catch (PathTooLongException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} as the path is too long.");
|
|
}
|
|
catch (DirectoryNotFoundException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} as the parent folder isn't there.");
|
|
}
|
|
|
|
}
|
|
|
|
// Remove the Profile from the list.
|
|
int numRemoved = _allProfiles.RemoveAll(item => item.UUID.Equals(Profile.UUID));
|
|
|
|
if (numRemoved == 1)
|
|
{
|
|
SaveProfiles();
|
|
return true;
|
|
}
|
|
else if (numRemoved == 0)
|
|
return false;
|
|
else
|
|
throw new ProfileRepositoryException();
|
|
}
|
|
|
|
|
|
public static bool RemoveProfile(string ProfileName)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(ProfileName))
|
|
return false;
|
|
|
|
// Remove the Profile Icons from the Cache
|
|
List<ProfileItem> ProfilesToRemove = _allProfiles.FindAll(item => item.Name.Equals(ProfileName));
|
|
foreach (ProfileItem ProfileToRemove in ProfilesToRemove)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(ProfileToRemove.SavedProfileIconCacheFilename);
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile2: DisplayMagician doesn't have permissions to delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename}.");
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile2: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} due to an invalid argument.");
|
|
}
|
|
catch (PathTooLongException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile2: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} as the path is too long.");
|
|
}
|
|
catch (DirectoryNotFoundException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile2: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} as the parent folder isn't there.");
|
|
}
|
|
}
|
|
|
|
// Remove the Profile from the list.
|
|
int numRemoved = _allProfiles.RemoveAll(item => item.Name.Equals(ProfileName));
|
|
|
|
if (numRemoved == 1)
|
|
{
|
|
SaveProfiles();
|
|
return true;
|
|
}
|
|
else if (numRemoved == 0)
|
|
return false;
|
|
else
|
|
throw new ProfileRepositoryException();
|
|
|
|
}
|
|
|
|
public static bool RemoveProfile(uint ProfileId)
|
|
{
|
|
if (ProfileId == 0)
|
|
return false;
|
|
|
|
// Remove the Profile Icons from the Cache
|
|
List<ProfileItem> ProfilesToRemove = _allProfiles.FindAll(item => item.UUID.Equals(ProfileId));
|
|
foreach (ProfileItem ProfileToRemove in ProfilesToRemove)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(ProfileToRemove.SavedProfileIconCacheFilename);
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile3: DisplayMagician doesn't have permissions to delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename}.");
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile3: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} due to an invalid argument.");
|
|
}
|
|
catch (PathTooLongException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile3: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} as the path is too long.");
|
|
}
|
|
catch (DirectoryNotFoundException ex)
|
|
{
|
|
SharedLogger.logger.Error(ex, $"ProfileRepository/RemoveProfile3: DisplayMagician can't delete the cached Profile Icon {ProfileToRemove.SavedProfileIconCacheFilename} as the parent folder isn't there.");
|
|
}
|
|
}
|
|
|
|
// Remove the Profile from the list.
|
|
int numRemoved = _allProfiles.RemoveAll(item => item.UUID.Equals(ProfileId));
|
|
|
|
if (numRemoved == 1)
|
|
{
|
|
SaveProfiles();
|
|
return true;
|
|
}
|
|
else if (numRemoved == 0)
|
|
return false;
|
|
else
|
|
throw new ProfileRepositoryException();
|
|
}
|
|
|
|
|
|
public static bool ContainsProfile(ProfileItem Profile)
|
|
{
|
|
if (!(Profile is ProfileItem))
|
|
return false;
|
|
|
|
foreach (ProfileItem testProfile in _allProfiles)
|
|
{
|
|
if (testProfile.UUID.Equals(Profile.UUID))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static bool ContainsProfile(string ProfileNameOrId)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(ProfileNameOrId))
|
|
return false;
|
|
|
|
if (ProfileItem.IsValidUUID(ProfileNameOrId))
|
|
foreach (ProfileItem testProfile in _allProfiles)
|
|
{
|
|
if (testProfile.UUID.Equals(ProfileNameOrId))
|
|
return true;
|
|
}
|
|
else
|
|
foreach (ProfileItem testProfile in _allProfiles)
|
|
{
|
|
if (testProfile.Name.Equals(ProfileNameOrId))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
public static bool ContainsCurrentProfile()
|
|
{
|
|
if (!(_currentProfile is ProfileItem))
|
|
return false;
|
|
|
|
foreach (ProfileItem testProfile in _allProfiles)
|
|
{
|
|
if (testProfile.Paths.SequenceEqual(_currentProfile.Paths))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static ProfileItem GetProfile(string ProfileNameOrId)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(ProfileNameOrId))
|
|
return null;
|
|
|
|
if (ProfileItem.IsValidUUID(ProfileNameOrId))
|
|
foreach (ProfileItem testProfile in _allProfiles)
|
|
{
|
|
if (testProfile.UUID.Equals(ProfileNameOrId))
|
|
return testProfile;
|
|
}
|
|
else
|
|
foreach (ProfileItem testProfile in _allProfiles)
|
|
{
|
|
if (testProfile.Name.Equals(ProfileNameOrId))
|
|
return testProfile;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static bool RenameProfile(ProfileItem profile, string renamedName)
|
|
{
|
|
if (!(profile is ProfileItem))
|
|
return false;
|
|
|
|
if (!IsValidFilename(renamedName))
|
|
return false;
|
|
|
|
profile.Name = GetValidFilename(renamedName);
|
|
|
|
// If it's been added to the list of AllProfiles
|
|
// then we also need to reproduce the Icons
|
|
if (ContainsProfile(profile))
|
|
{
|
|
// Save the Profiles JSON as it's different now
|
|
SaveProfiles();
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
public static void UpdateActiveProfile()
|
|
{
|
|
|
|
ProfileItem activeProfile = new ProfileItem
|
|
{
|
|
Name = "Current Display Profile",
|
|
Paths = PathInfo.GetActivePaths().Select(info => new DisplayMagicianShared.Topology.Path(info)).ToArray()
|
|
};
|
|
|
|
activeProfile.ProfileIcon = new ProfileIcon(activeProfile);
|
|
activeProfile.ProfileBitmap = activeProfile.ProfileIcon.ToBitmap(256, 256);
|
|
|
|
if (_profilesLoaded && _allProfiles.Count > 0)
|
|
{
|
|
foreach (ProfileItem loadedProfile in ProfileRepository.AllProfiles)
|
|
{
|
|
if (activeProfile.Paths.SequenceEqual(loadedProfile.Paths))
|
|
{
|
|
_currentProfile = loadedProfile;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
_currentProfile = activeProfile;
|
|
|
|
}
|
|
|
|
|
|
public static ProfileItem GetActiveProfile()
|
|
{
|
|
//UpdateActiveProfile();
|
|
|
|
if (!(_currentProfile is ProfileItem))
|
|
return null;
|
|
return _currentProfile;
|
|
}
|
|
|
|
public static bool IsActiveProfile(ProfileItem profile)
|
|
{
|
|
//UpdateActiveProfile();
|
|
|
|
if (!(_currentProfile is ProfileItem))
|
|
return false;
|
|
|
|
if (!(profile is ProfileItem))
|
|
return false;
|
|
|
|
if (profile.Paths.SequenceEqual(_currentProfile.Paths))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
private static bool LoadProfiles()
|
|
{
|
|
|
|
if (File.Exists(_profileStorageJsonFileName))
|
|
{
|
|
var json = File.ReadAllText(_profileStorageJsonFileName, Encoding.Unicode);
|
|
|
|
if (!string.IsNullOrWhiteSpace(json))
|
|
{
|
|
//List<ProfileItem> profiles = new List<ProfileItem>();
|
|
try
|
|
{
|
|
_allProfiles = JsonConvert.DeserializeObject<List<ProfileItem>>(json, new JsonSerializerSettings
|
|
{
|
|
MissingMemberHandling = MissingMemberHandling.Ignore,
|
|
NullValueHandling = NullValueHandling.Ignore,
|
|
DefaultValueHandling = DefaultValueHandling.Include,
|
|
TypeNameHandling = TypeNameHandling.Auto,
|
|
ObjectCreationHandling = ObjectCreationHandling.Replace
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// ignored
|
|
Console.WriteLine($"ProfileRepository/LoadProfiles exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
|
Console.WriteLine($"Unable to load Profiles from JSON file {_profileStorageJsonFileName}: " + ex.Message);
|
|
}
|
|
|
|
ProfileItem myCurrentProfile = new ProfileItem
|
|
{
|
|
Name = "Current Display Profile",
|
|
Paths = PathInfo.GetActivePaths().Select(info => new DisplayMagicianShared.Topology.Path(info)).ToArray()
|
|
};
|
|
|
|
_currentProfile = myCurrentProfile;
|
|
|
|
// Lookup all the Profile Names in the Saved Profiles
|
|
foreach (ProfileItem loadedProfile in _allProfiles)
|
|
{
|
|
// Save a profile Icon to the profile
|
|
/* loadedProfile.ProfileIcon = new ProfileIcon(loadedProfile);
|
|
loadedProfile.ProfileBitmap = loadedProfile.ProfileIcon.ToBitmap(256, 256);
|
|
*/
|
|
if (ProfileRepository.IsActiveProfile(loadedProfile))
|
|
_currentProfile = loadedProfile;
|
|
|
|
}
|
|
|
|
// Sort the profiles alphabetically
|
|
_allProfiles.Sort();
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If we get here, then we don't have any profiles saved!
|
|
// So we gotta start from scratch
|
|
// Create a new profile based on our current display settings
|
|
ProfileItem myCurrentProfile = new ProfileItem
|
|
{
|
|
Name = "Current Display Profile",
|
|
Paths = PathInfo.GetActivePaths().Select(info => new DisplayMagicianShared.Topology.Path(info)).ToArray()
|
|
};
|
|
|
|
_currentProfile = myCurrentProfile;
|
|
|
|
// Save a profile Icon to the profile
|
|
_currentProfile.ProfileIcon = new ProfileIcon(_currentProfile);
|
|
_currentProfile.ProfileBitmap = _currentProfile.ProfileIcon.ToBitmap(256, 256);
|
|
}
|
|
_profilesLoaded = true;
|
|
return true;
|
|
}
|
|
|
|
public static bool SaveProfiles()
|
|
{
|
|
|
|
if (!Directory.Exists(AppProfileStoragePath))
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(AppProfileStoragePath);
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/SaveProfiles: DisplayMagician doesn't have permissions to create the Profiles storage folder {AppProfileStoragePath}.");
|
|
}
|
|
catch (ArgumentException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/SaveProfiles: DisplayMagician can't create the Profiles storage folder {AppProfileStoragePath} due to an invalid argument.");
|
|
}
|
|
catch (PathTooLongException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/SaveProfiles: DisplayMagician can't create the Profiles storage folder {AppProfileStoragePath} as the path is too long.");
|
|
}
|
|
catch (DirectoryNotFoundException ex)
|
|
{
|
|
SharedLogger.logger.Fatal(ex, $"ProfileRepository/SaveProfiles: DisplayMagician can't create the Profiles storage folder {AppProfileStoragePath} as the parent folder isn't there.");
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
var json = JsonConvert.SerializeObject(_allProfiles, Formatting.Indented, new JsonSerializerSettings
|
|
{
|
|
NullValueHandling = NullValueHandling.Include,
|
|
DefaultValueHandling = DefaultValueHandling.Populate,
|
|
TypeNameHandling = TypeNameHandling.Auto
|
|
|
|
});
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(json))
|
|
{
|
|
File.WriteAllText(_profileStorageJsonFileName, json, Encoding.Unicode);
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"ProfileRepository/SaveProfiles exception 2: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
|
Console.WriteLine($"Unable to save Profile JSON file {_profileStorageJsonFileName}: " + ex.Message);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static void SaveProfileIconToCache(ProfileItem profile)
|
|
{
|
|
|
|
// Work out the name of the Profile we'll save.
|
|
profile.SavedProfileIconCacheFilename = System.IO.Path.Combine(AppProfileStoragePath, string.Concat(@"profile-", profile.UUID, @".ico"));
|
|
|
|
MultiIcon ProfileIcon;
|
|
try
|
|
{
|
|
ProfileIcon = profile.ProfileIcon.ToIcon();
|
|
ProfileIcon.Save(profile.SavedProfileIconCacheFilename, MultiIconFormat.ICO);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"ProfileRepository/SaveProfileIconToCache exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
|
// If we fail to create an icon based on the Profile, then we use the standard DisplayMagician profile one.
|
|
// Which is created on program startup.
|
|
File.Copy(AppDisplayMagicianIconFilename, profile.SavedProfileIconCacheFilename);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static List<string> GenerateProfileDisplayIdentifiers()
|
|
{
|
|
List<string> displayIdentifiers = new List<string>();
|
|
|
|
// If the Video Card is an NVidia, then we should generate specific NVidia displayIdentifiers
|
|
bool isNvidia = false;
|
|
NvAPIWrapper.GPU.PhysicalGPU[] myPhysicalGPUs = null;
|
|
try
|
|
{
|
|
myPhysicalGPUs = NvAPIWrapper.GPU.PhysicalGPU.GetPhysicalGPUs();
|
|
isNvidia = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Debug(ex, "ProfileRepository/GenerateProfileDisplayIdentifiers: Attemped to get GetPhysicalCPUs through NvAPIWrapper library but got exception.");
|
|
}
|
|
|
|
if (isNvidia && myPhysicalGPUs != null && myPhysicalGPUs.Length > 0)
|
|
{
|
|
SharedLogger.logger.Debug("ProfileRepository/GenerateProfileDisplayIdentifiers: Was able to GetPhysicalCPUs through NvAPIWrapper library.");
|
|
|
|
foreach (NvAPIWrapper.GPU.PhysicalGPU myPhysicalGPU in myPhysicalGPUs)
|
|
{
|
|
// get a list of all physical outputs attached to the GPUs
|
|
NvAPIWrapper.GPU.GPUOutput[] myGPUOutputs = myPhysicalGPU.ActiveOutputs;
|
|
foreach (NvAPIWrapper.GPU.GPUOutput aGPUOutput in myGPUOutputs)
|
|
{
|
|
// Figure out the displaydevice attached to the output
|
|
NvAPIWrapper.Display.DisplayDevice aConnectedDisplayDevice = myPhysicalGPU.GetDisplayDeviceByOutput(aGPUOutput);
|
|
|
|
// Create an array of all the important display info we need to record
|
|
string[] displayInfo = {
|
|
"NVIDIA",
|
|
myPhysicalGPU.CorrespondingLogicalGPU.ToString(),
|
|
myPhysicalGPU.ToString(),
|
|
myPhysicalGPU.ArchitectInformation.ShortName.ToString(),
|
|
myPhysicalGPU.ArchitectInformation.Revision.ToString(),
|
|
myPhysicalGPU.Board.ToString(),
|
|
myPhysicalGPU.Foundry.ToString(),
|
|
myPhysicalGPU.GPUId.ToString(),
|
|
myPhysicalGPU.GPUType.ToString(),
|
|
//aGPUOutput.OutputId.ToString(),
|
|
aConnectedDisplayDevice.ConnectionType.ToString(),
|
|
aConnectedDisplayDevice.DisplayId.ToString()
|
|
};
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfo);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
}
|
|
|
|
}
|
|
}
|
|
// else videocard is not NVIdia so we just use the WindowsAPI access method
|
|
// Note: This won't support any special AMD EyeFinity profiles unfortunately.....
|
|
// TODO: Add the detection and generation of the device ids using an AMD library
|
|
// so that we can match valid AMD Eyefinity profiles with valid AMD standard profiles.
|
|
else
|
|
{
|
|
|
|
// Then go through the adapters we have running using the WindowsDisplayAPI
|
|
List<Display> attachedDisplayDevices = Display.GetDisplays().ToList();
|
|
|
|
foreach (Display attachedDisplay in attachedDisplayDevices)
|
|
{
|
|
DisplayAdapter displayAdapter = attachedDisplay.Adapter;
|
|
PathDisplayAdapter pathDisplayAdapter = displayAdapter.ToPathDisplayAdapter();
|
|
PathDisplaySource pathDisplaySource = attachedDisplay.ToPathDisplaySource();
|
|
PathDisplayTarget pathDisplayTarget = attachedDisplay.ToPathDisplayTarget();
|
|
|
|
Debug.WriteLine($"ADDN : {attachedDisplay.DeviceName}");
|
|
Debug.WriteLine($"ADDFN : {attachedDisplay.DisplayFullName}");
|
|
Debug.WriteLine($"ADDIN : {attachedDisplay.DisplayName}");
|
|
Debug.WriteLine($"ADDIN : {attachedDisplay.IsAvailable}");
|
|
Debug.WriteLine($"ADDIGP : {attachedDisplay.IsGDIPrimary}");
|
|
Debug.WriteLine($"ADDIV : {attachedDisplay.IsValid}");
|
|
Debug.WriteLine($"ADCSCD : {attachedDisplay.CurrentSetting.ColorDepth}");
|
|
Debug.WriteLine($"ADCSF : {attachedDisplay.CurrentSetting.Frequency}");
|
|
Debug.WriteLine($"ADCSIE : {attachedDisplay.CurrentSetting.IsEnable}");
|
|
Debug.WriteLine($"ADCSII : {attachedDisplay.CurrentSetting.IsInterlaced}");
|
|
Debug.WriteLine($"ADCSO : {attachedDisplay.CurrentSetting.Orientation}");
|
|
Debug.WriteLine($"ADCSOSM : {attachedDisplay.CurrentSetting.OutputScalingMode}");
|
|
Debug.WriteLine($"ADCSP : {attachedDisplay.CurrentSetting.Position}");
|
|
Debug.WriteLine($"ADCSR : {attachedDisplay.CurrentSetting.Resolution}");
|
|
Debug.WriteLine($"DP : {displayAdapter.DevicePath}");
|
|
Debug.WriteLine($"DK : {displayAdapter.DeviceKey}");
|
|
Debug.WriteLine($"DN : {displayAdapter.DeviceName}");
|
|
Debug.WriteLine($"DK : {displayAdapter.DeviceKey}");
|
|
Debug.WriteLine($"AI : {pathDisplayAdapter.AdapterId}");
|
|
Debug.WriteLine($"AIDP : {pathDisplayAdapter.DevicePath}");
|
|
Debug.WriteLine($"AIII : {pathDisplayAdapter.IsInvalid}");
|
|
Debug.WriteLine($"DDA : {displayAdapter.DeviceName}");
|
|
Debug.WriteLine($"PDSA : {pathDisplaySource.Adapter}");
|
|
Debug.WriteLine($"PDSCDS : {pathDisplaySource.CurrentDPIScale}");
|
|
Debug.WriteLine($"PDSDN : {pathDisplaySource.DisplayName}");
|
|
Debug.WriteLine($"PDSMDS : {pathDisplaySource.MaximumDPIScale}");
|
|
Debug.WriteLine($"PDSRDS : {pathDisplaySource.RecommendedDPIScale}");
|
|
Debug.WriteLine($"PDSSI : {pathDisplaySource.SourceId}");
|
|
Debug.WriteLine($"PDTA : {pathDisplayTarget.Adapter}");
|
|
Debug.WriteLine($"PDTCI : {pathDisplayTarget.ConnectorInstance}");
|
|
Debug.WriteLine($"PDTDP : {pathDisplayTarget.DevicePath}");
|
|
Debug.WriteLine($"PDTEMC : {pathDisplayTarget.EDIDManufactureCode}");
|
|
Debug.WriteLine($"PDTEMI : {pathDisplayTarget.EDIDManufactureId}");
|
|
Debug.WriteLine($"PDTEPC : {pathDisplayTarget.EDIDProductCode}");
|
|
Debug.WriteLine($"PDTFN : {pathDisplayTarget.FriendlyName}");
|
|
Debug.WriteLine($"PDTIA : {pathDisplayTarget.IsAvailable}");
|
|
Debug.WriteLine($"PDTPR : {pathDisplayTarget.PreferredResolution}");
|
|
Debug.WriteLine($"PDTPSM : {pathDisplayTarget.PreferredSignalMode}");
|
|
Debug.WriteLine($"PDTTI : {pathDisplayTarget.TargetId}");
|
|
Debug.WriteLine($"PDTVRS : {pathDisplayTarget.VirtualResolutionSupport}");
|
|
|
|
// Create an array of all the important display info we need to record
|
|
string[] displayInfo = {
|
|
"WINAPI",
|
|
displayAdapter.DeviceName.ToString(),
|
|
pathDisplayAdapter.AdapterId.ToString(),
|
|
pathDisplayTarget.ConnectorInstance.ToString(),
|
|
pathDisplayTarget.FriendlyName,
|
|
pathDisplayTarget.EDIDManufactureCode.ToString(),
|
|
pathDisplayTarget.EDIDManufactureId.ToString(),
|
|
pathDisplayTarget.EDIDProductCode.ToString(),
|
|
pathDisplayTarget.TargetId.ToString(),
|
|
};
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfo);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return displayIdentifiers;
|
|
}
|
|
|
|
public static List<string> GenerateAllAvailableDisplayIdentifiers()
|
|
{
|
|
List<string> displayIdentifiers = new List<string>();
|
|
|
|
// If the Video Card is an NVidia, then we should generate specific NVidia displayIdentifiers
|
|
bool isNvidia = false;
|
|
NvAPIWrapper.GPU.PhysicalGPU[] myPhysicalGPUs = null;
|
|
try
|
|
{
|
|
myPhysicalGPUs = NvAPIWrapper.GPU.PhysicalGPU.GetPhysicalGPUs();
|
|
isNvidia = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SharedLogger.logger.Debug(ex, "ProfileRepository/GenerateAllAvailableDisplayIdentifiers: Attemped to get GetPhysicalCPUs through NvAPIWrapper library but got exception.");
|
|
}
|
|
|
|
if (isNvidia && myPhysicalGPUs != null && myPhysicalGPUs.Length > 0)
|
|
{
|
|
|
|
foreach (NvAPIWrapper.GPU.PhysicalGPU myPhysicalGPU in myPhysicalGPUs)
|
|
{
|
|
// get a list of all physical outputs attached to the GPUs
|
|
NvAPIWrapper.Display.DisplayDevice[] allDisplayDevices = myPhysicalGPU.GetConnectedDisplayDevices(ConnectedIdsFlag.None);
|
|
foreach (NvAPIWrapper.Display.DisplayDevice aDisplayDevice in allDisplayDevices)
|
|
{
|
|
|
|
if (aDisplayDevice.IsAvailable== true)
|
|
{
|
|
// Create an array of all the important display info we need to record
|
|
string[] displayInfo = {
|
|
"NVIDIA",
|
|
myPhysicalGPU.CorrespondingLogicalGPU.ToString(),
|
|
myPhysicalGPU.ToString(),
|
|
myPhysicalGPU.ArchitectInformation.ShortName.ToString(),
|
|
myPhysicalGPU.ArchitectInformation.Revision.ToString(),
|
|
myPhysicalGPU.Board.ToString(),
|
|
myPhysicalGPU.Foundry.ToString(),
|
|
myPhysicalGPU.GPUId.ToString(),
|
|
myPhysicalGPU.GPUType.ToString(),
|
|
//aDisplayDevice.Output.OutputId.ToString(),
|
|
aDisplayDevice.ConnectionType.ToString(),
|
|
aDisplayDevice.DisplayId.ToString(),
|
|
};
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfo);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// else videocard is not NVIdia so we just use the WindowsAPI access method
|
|
// Note: This won't support any special AMD EyeFinity profiles unfortunately.....
|
|
// TODO: Add the detection and generation of the device ids using an AMD library
|
|
// so that we can match valid AMD Eyefinity profiles with valid AMD standard profiles.
|
|
else
|
|
{
|
|
|
|
// Then go through the adapters we have running using the WindowsDisplayAPI
|
|
List<Display> attachedDisplayDevices = Display.GetDisplays().ToList();
|
|
List<UnAttachedDisplay> unattachedDisplayDevices = UnAttachedDisplay.GetUnAttachedDisplays().ToList();
|
|
|
|
foreach (Display attachedDisplay in attachedDisplayDevices)
|
|
{
|
|
DisplayAdapter displayAdapter = attachedDisplay.Adapter;
|
|
PathDisplayAdapter pathDisplayAdapter = displayAdapter.ToPathDisplayAdapter();
|
|
PathDisplaySource pathDisplaySource = attachedDisplay.ToPathDisplaySource();
|
|
PathDisplayTarget pathDisplayTarget = attachedDisplay.ToPathDisplayTarget();
|
|
|
|
Debug.WriteLine($"ADDN : {attachedDisplay.DeviceName}");
|
|
Debug.WriteLine($"ADDFN : {attachedDisplay.DisplayFullName}");
|
|
Debug.WriteLine($"ADDIN : {attachedDisplay.DisplayName}");
|
|
Debug.WriteLine($"ADDIN : {attachedDisplay.IsAvailable}");
|
|
Debug.WriteLine($"ADDIGP : {attachedDisplay.IsGDIPrimary}");
|
|
Debug.WriteLine($"ADDIV : {attachedDisplay.IsValid}");
|
|
Debug.WriteLine($"ADCSCD : {attachedDisplay.CurrentSetting.ColorDepth}");
|
|
Debug.WriteLine($"ADCSF : {attachedDisplay.CurrentSetting.Frequency}");
|
|
Debug.WriteLine($"ADCSIE : {attachedDisplay.CurrentSetting.IsEnable}");
|
|
Debug.WriteLine($"ADCSII : {attachedDisplay.CurrentSetting.IsInterlaced}");
|
|
Debug.WriteLine($"ADCSO : {attachedDisplay.CurrentSetting.Orientation}");
|
|
Debug.WriteLine($"ADCSOSM : {attachedDisplay.CurrentSetting.OutputScalingMode}");
|
|
Debug.WriteLine($"ADCSP : {attachedDisplay.CurrentSetting.Position}");
|
|
Debug.WriteLine($"ADCSR : {attachedDisplay.CurrentSetting.Resolution}");
|
|
Debug.WriteLine($"DP : {displayAdapter.DevicePath}");
|
|
Debug.WriteLine($"DK : {displayAdapter.DeviceKey}");
|
|
Debug.WriteLine($"DN : {displayAdapter.DeviceName}");
|
|
Debug.WriteLine($"DK : {displayAdapter.DeviceKey}");
|
|
Debug.WriteLine($"AI : {pathDisplayAdapter.AdapterId}");
|
|
Debug.WriteLine($"AIDP : {pathDisplayAdapter.DevicePath}");
|
|
Debug.WriteLine($"AIII : {pathDisplayAdapter.IsInvalid}");
|
|
Debug.WriteLine($"DDA : {displayAdapter.DeviceName}");
|
|
Debug.WriteLine($"PDSA : {pathDisplaySource.Adapter}");
|
|
Debug.WriteLine($"PDSCDS : {pathDisplaySource.CurrentDPIScale}");
|
|
Debug.WriteLine($"PDSDN : {pathDisplaySource.DisplayName}");
|
|
Debug.WriteLine($"PDSMDS : {pathDisplaySource.MaximumDPIScale}");
|
|
Debug.WriteLine($"PDSRDS : {pathDisplaySource.RecommendedDPIScale}");
|
|
Debug.WriteLine($"PDSSI : {pathDisplaySource.SourceId}");
|
|
Debug.WriteLine($"PDTA : {pathDisplayTarget.Adapter}");
|
|
Debug.WriteLine($"PDTCI : {pathDisplayTarget.ConnectorInstance}");
|
|
Debug.WriteLine($"PDTDP : {pathDisplayTarget.DevicePath}");
|
|
Debug.WriteLine($"PDTEMC : {pathDisplayTarget.EDIDManufactureCode}");
|
|
Debug.WriteLine($"PDTEMI : {pathDisplayTarget.EDIDManufactureId}");
|
|
Debug.WriteLine($"PDTEPC : {pathDisplayTarget.EDIDProductCode}");
|
|
Debug.WriteLine($"PDTFN : {pathDisplayTarget.FriendlyName}");
|
|
Debug.WriteLine($"PDTIA : {pathDisplayTarget.IsAvailable}");
|
|
Debug.WriteLine($"PDTPR : {pathDisplayTarget.PreferredResolution}");
|
|
Debug.WriteLine($"PDTPSM : {pathDisplayTarget.PreferredSignalMode}");
|
|
Debug.WriteLine($"PDTTI : {pathDisplayTarget.TargetId}");
|
|
Debug.WriteLine($"PDTVRS : {pathDisplayTarget.VirtualResolutionSupport}");
|
|
|
|
// Create an array of all the important display info we need to record
|
|
string[] displayInfo = {
|
|
"WINAPI",
|
|
displayAdapter.DeviceName.ToString(),
|
|
pathDisplayAdapter.AdapterId.ToString(),
|
|
pathDisplayTarget.ConnectorInstance.ToString(),
|
|
pathDisplayTarget.FriendlyName,
|
|
pathDisplayTarget.EDIDManufactureCode.ToString(),
|
|
pathDisplayTarget.EDIDManufactureId.ToString(),
|
|
pathDisplayTarget.EDIDProductCode.ToString(),
|
|
pathDisplayTarget.TargetId.ToString(),
|
|
};
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfo);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
|
|
}
|
|
|
|
foreach (UnAttachedDisplay unattachedDisplay in unattachedDisplayDevices)
|
|
{
|
|
DisplayAdapter displayAdapter = unattachedDisplay.Adapter;
|
|
PathDisplayAdapter pathDisplayAdapter = displayAdapter.ToPathDisplayAdapter();
|
|
PathDisplaySource pathDisplaySource = unattachedDisplay.ToPathDisplaySource();
|
|
PathDisplayTarget pathDisplayTarget = unattachedDisplay.ToPathDisplayTarget();
|
|
|
|
Debug.WriteLine($"ADDN : {unattachedDisplay.DeviceName}");
|
|
Debug.WriteLine($"ADDFN : {unattachedDisplay.DisplayFullName}");
|
|
Debug.WriteLine($"ADDIN : {unattachedDisplay.DisplayName}");
|
|
Debug.WriteLine($"ADDIN : {unattachedDisplay.IsAvailable}");
|
|
Debug.WriteLine($"ADDIV : {unattachedDisplay.IsValid}");
|
|
Debug.WriteLine($"DP : {displayAdapter.DevicePath}");
|
|
Debug.WriteLine($"DK : {displayAdapter.DeviceKey}");
|
|
Debug.WriteLine($"DN : {displayAdapter.DeviceName}");
|
|
Debug.WriteLine($"DK : {displayAdapter.DeviceKey}");
|
|
Debug.WriteLine($"AI : {pathDisplayAdapter.AdapterId}");
|
|
Debug.WriteLine($"AIDP : {pathDisplayAdapter.DevicePath}");
|
|
Debug.WriteLine($"AIII : {pathDisplayAdapter.IsInvalid}");
|
|
Debug.WriteLine($"PDSA : {pathDisplaySource.Adapter}");
|
|
Debug.WriteLine($"PDSCDS : {pathDisplaySource.CurrentDPIScale}");
|
|
Debug.WriteLine($"PDSDN : {pathDisplaySource.DisplayName}");
|
|
Debug.WriteLine($"PDSMDS : {pathDisplaySource.MaximumDPIScale}");
|
|
Debug.WriteLine($"PDSRDS : {pathDisplaySource.RecommendedDPIScale}");
|
|
Debug.WriteLine($"PDSSI : {pathDisplaySource.SourceId}");
|
|
Debug.WriteLine($"PDTA : {pathDisplayTarget.Adapter}");
|
|
Debug.WriteLine($"PDTCI : {pathDisplayTarget.ConnectorInstance}");
|
|
Debug.WriteLine($"PDTDP : {pathDisplayTarget.DevicePath}");
|
|
Debug.WriteLine($"PDTEMC : {pathDisplayTarget.EDIDManufactureCode}");
|
|
Debug.WriteLine($"PDTEMI : {pathDisplayTarget.EDIDManufactureId}");
|
|
Debug.WriteLine($"PDTEPC : {pathDisplayTarget.EDIDProductCode}");
|
|
Debug.WriteLine($"PDTFN : {pathDisplayTarget.FriendlyName}");
|
|
Debug.WriteLine($"PDTIA : {pathDisplayTarget.IsAvailable}");
|
|
Debug.WriteLine($"PDTPR : {pathDisplayTarget.PreferredResolution}");
|
|
Debug.WriteLine($"PDTPSM : {pathDisplayTarget.PreferredSignalMode}");
|
|
Debug.WriteLine($"PDTTI : {pathDisplayTarget.TargetId}");
|
|
Debug.WriteLine($"PDTVRS : {pathDisplayTarget.VirtualResolutionSupport}");
|
|
|
|
// Create an array of all the important display info we need to record
|
|
string[] displayInfo = {
|
|
"WINAPI",
|
|
displayAdapter.DeviceName.ToString(),
|
|
pathDisplayAdapter.AdapterId.ToString(),
|
|
pathDisplayTarget.ConnectorInstance.ToString(),
|
|
pathDisplayTarget.FriendlyName,
|
|
pathDisplayTarget.EDIDManufactureCode.ToString(),
|
|
pathDisplayTarget.EDIDManufactureId.ToString(),
|
|
pathDisplayTarget.EDIDProductCode.ToString(),
|
|
pathDisplayTarget.TargetId.ToString(),
|
|
};
|
|
|
|
// Create a display identifier out of it
|
|
string displayIdentifier = String.Join("|", displayInfo);
|
|
// Add it to the list of display identifiers so we can return it
|
|
displayIdentifiers.Add(displayIdentifier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return displayIdentifiers;
|
|
}
|
|
|
|
public static bool ApplyNVIDIAGridTopology(ProfileItem profile)
|
|
{
|
|
Debug.Print("ProfileRepository.ApplyTopology()");
|
|
|
|
if (!(profile is ProfileItem))
|
|
return false;
|
|
|
|
try
|
|
{
|
|
var surroundTopologies =
|
|
profile.Paths.SelectMany(paths => paths.TargetDisplays)
|
|
.Select(target => target.SurroundTopology)
|
|
.Where(topology => topology != null)
|
|
.Select(topology => topology.ToGridTopology())
|
|
.ToArray();
|
|
|
|
if (surroundTopologies.Length == 0)
|
|
{
|
|
// The profile we're changing to does not use NVIDIA Surround
|
|
// So we need to set the Grid Topologies to individual screens
|
|
// in preparation for the PathInfo step later
|
|
var currentTopologies = GridTopology.GetGridTopologies();
|
|
|
|
if (currentTopologies.Any(topology => topology.Rows * topology.Columns > 1))
|
|
{
|
|
surroundTopologies =
|
|
GridTopology.GetGridTopologies()
|
|
.SelectMany(topology => topology.Displays)
|
|
.Select(displays => new GridTopology(1, 1, new[] { displays }))
|
|
.ToArray();
|
|
|
|
GridTopology.SetGridTopologies(surroundTopologies, SetDisplayTopologyFlag.MaximizePerformance);
|
|
}
|
|
} else if (surroundTopologies.Length > 0)
|
|
{
|
|
// This profile is an NVIDIA Surround profile
|
|
GridTopology.SetGridTopologies(surroundTopologies, SetDisplayTopologyFlag.MaximizePerformance);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"ProfileRepository/ApplyTopology exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static bool ApplyWindowsDisplayPathInfo(ProfileItem profile)
|
|
{
|
|
Debug.Print("ProfileRepository.ApplyPathInfo()");
|
|
if (!(profile is ProfileItem))
|
|
return false;
|
|
|
|
try
|
|
{
|
|
var pathInfos = profile.Paths.Select(paths => paths.ToPathInfo()).Where(info => info != null).ToArray();
|
|
PathInfo.ApplyPathInfos(pathInfos, true, true, true);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"ProfileRepository/ApplyPathInfo exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
public static bool IsValidFilename(string testName)
|
|
{
|
|
string strTheseAreInvalidFileNameChars = new string(System.IO.Path.GetInvalidFileNameChars());
|
|
Regex regInvalidFileName = new Regex("[" + Regex.Escape(strTheseAreInvalidFileNameChars) + "]");
|
|
|
|
if (regInvalidFileName.IsMatch(testName)) { return false; };
|
|
|
|
return true;
|
|
}
|
|
|
|
public static string GetValidFilename(string uncheckedFilename)
|
|
{
|
|
string invalid = new string(System.IO.Path.GetInvalidFileNameChars()) + new string(System.IO.Path.GetInvalidPathChars());
|
|
foreach (char c in invalid)
|
|
{
|
|
uncheckedFilename = uncheckedFilename.Replace(c.ToString(), "");
|
|
}
|
|
return uncheckedFilename;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
|
|
[global::System.Serializable]
|
|
public class ProfileRepositoryException : Exception
|
|
{
|
|
public ProfileRepositoryException() { }
|
|
public ProfileRepositoryException(string message) : base(message) { }
|
|
public ProfileRepositoryException(string message, Exception inner) : base(message, inner) { }
|
|
protected ProfileRepositoryException(
|
|
System.Runtime.Serialization.SerializationInfo info,
|
|
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
|
}
|
|
|
|
|
|
}
|
|
|