Winify

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 29  →  ?path2? @ 30
/trunk/Winify/Utilities/Miscellaneous.cs
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
@@ -14,31 +15,21 @@
{
#region Public Methods
 
public static TimeSpan GetIdleTime()
public static bool LaunchOnBootSet(bool enable)
{
var lastInPut = new Natives.LASTINPUTINFO();
lastInPut.cbSize = (uint)Marshal.SizeOf(lastInPut);
Natives.GetLastInputInfo(ref lastInPut);
using var key = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
 
return TimeSpan.FromMilliseconds((uint)Environment.TickCount - lastInPut.dwTime);
}
if (key == null) return false;
 
public static bool LaunchOnBootSet(bool enable)
{
using (var key = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
switch (enable)
{
if (key == null) return false;
 
switch (enable)
{
case true:
key.SetValue(Constants.AssemblyName, Assembly.GetEntryAssembly().Location);
break;
default:
key.DeleteValue(Constants.AssemblyName, false);
break;
}
case true:
key.SetValue(Constants.AssemblyName, Assembly.GetEntryAssembly().Location);
break;
default:
key.DeleteValue(Constants.AssemblyName, false);
break;
}
 
return true;
@@ -46,11 +37,10 @@
 
public static bool LaunchOnBootGet()
{
using (var key = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
return key?.GetValue(Constants.AssemblyName) != null;
}
using var key = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
 
return key?.GetValue(Constants.AssemblyName) != null;
}
 
/// <summary>
@@ -59,30 +49,26 @@
/// <param name="control">the control to enable double buffering for</param>
/// <returns>true on success</returns>
/// <remarks>Do not enable double buffering on RDP: https://devblogs.microsoft.com/oldnewthing/20060103-12/?p=32793</remarks>
public static bool SetDoubleBuffered(this Control control)
public static void SetDoubleBuffered(this Control control)
{
if (SystemInformation.TerminalServerSession) return false;
 
var dgvType = control.GetType();
var pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
if (pi == null) return false;
 
pi.SetValue(control, true, null);
 
return true;
// Double buffering can make DGV slow in remote desktop
if (!SystemInformation.TerminalServerSession)
{
var dgvType = control.GetType();
var pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(control, true, null);
}
}
 
public static async Task<Icon> CreateIconFromResource(string resource)
{
var iconBytes = await LoadResource(resource);
using (var iconMemoryStream = new MemoryStream(iconBytes))
{
var bitmap = (Bitmap)Image.FromStream(iconMemoryStream);
var bitmapIntPtr = bitmap.GetHicon();
var icon = Icon.FromHandle(bitmapIntPtr);
return icon;
}
using var iconMemoryStream = new MemoryStream(iconBytes);
var bitmap = (Bitmap)Image.FromStream(iconMemoryStream);
var bitmapIntPtr = bitmap.GetHicon();
var icon = Icon.FromHandle(bitmapIntPtr);
return icon;
}
 
public static async Task<byte[]> LoadResource(string resource)
@@ -89,18 +75,17 @@
{
var assembly = Assembly.GetExecutingAssembly();
 
using (var manifestResourceStream = assembly.GetManifestResourceStream(resource))
{
if (manifestResourceStream == null) return null;
using var manifestResourceStream = assembly.GetManifestResourceStream(resource);
 
var memoryStream = new MemoryStream();
if (manifestResourceStream == null) return null;
 
await manifestResourceStream.CopyToAsync(memoryStream);
var memoryStream = new MemoryStream();
 
memoryStream.Position = 0L;
await manifestResourceStream.CopyToAsync(memoryStream);
 
return memoryStream.ToArray();
}
memoryStream.Position = 0L;
 
return memoryStream.ToArray();
}
 
public static void InvokeIfRequired<T>(this T control, Action<T> action) where T : Control
@@ -114,36 +99,40 @@
action(control);
}
 
public static T MapValueToRange<T>(this T value, T xMin, T xMax, T yMin, T yMax)
where T : struct, IComparable<T>, IConvertible
/// <summary>
/// Attempts to access a file within <see cref="timeout" /> milliseconds by retrying to access the file every
/// <see cref="retry" /> milliseconds.
/// </summary>
/// <param name="path">the path to the file</param>
/// <param name="mode">the file mode used to access the file</param>
/// <param name="access">the file access to use</param>
/// <param name="share">the file share to use</param>
/// <param name="cancellationToken">a cancellation token</param>
/// <param name="retry">the amount of milliseconds to retry between accesses to the file</param>
/// <param name="timeout">the amount of time in milliseconds to attempt and access the file</param>
/// <returns>a file stream if the file could be accessed within the allotted time</returns>
public static async Task<FileStream> GetFileStream(string path, FileMode mode, FileAccess access,
FileShare share, CancellationToken cancellationToken,
int retry = 1000, int timeout = 60000)
{
return (dynamic)yMin +
((dynamic)yMax - (dynamic)yMin) * ((dynamic)value - (dynamic)xMin) /
((dynamic)xMax - (dynamic)xMin);
}
var time = Stopwatch.StartNew();
 
public static IEnumerable<TU> SequenceSubtract<TU, TV>(this IEnumerable<TU> a,
IEnumerable<TV> b,
Func<TU, TV, bool> cmp)
{
var eb = new List<TV>(b);
 
using (var ea = a.GetEnumerator())
while (time.ElapsedMilliseconds < timeout && !cancellationToken.IsCancellationRequested)
{
while (ea.MoveNext())
try
{
if (ea.Current == null) continue;
return new FileStream(path, mode, access, share);
}
catch (IOException e)
{
// access error
if (e.HResult != -2147024864) throw;
}
 
foreach (var ib in eb)
{
if (cmp.Invoke(ea.Current, ib)) continue;
await Task.Delay(retry, cancellationToken);
}
 
yield return ea.Current;
 
break;
}
}
}
throw new TimeoutException($"Failed to get a access to {path} within {timeout}ms.");
}
 
/// <summary>
/trunk/Winify/Utilities/ScheduledContinuation.cs
@@ -0,0 +1,105 @@
using System;
using System.Threading;
using System.Threading.Tasks;
 
namespace Winify.Utilities
{
public class ScheduledContinuation : IDisposable
{
#region Constructors, Destructors and Finalizers
 
public void Dispose()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
}
}
 
#endregion
 
#region Private Delegates, Events, Enums, Properties, Indexers and Fields
 
private CancellationTokenSource _cancellationTokenSource;
 
private Task _task;
 
#endregion
 
#region Public Methods
 
public void Schedule(TimeSpan delay, Action execute, CancellationToken cancellationToken)
{
try
{
if (_task != null)
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
_task = null;
}
}
catch
{
// Ignore errors.
}
finally
{
_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
}
 
_task = Task.Delay(delay, _cancellationTokenSource.Token)
.ContinueWith(task =>
{
try
{
execute.Invoke();
}
catch (Exception exception) when (exception is ObjectDisposedException ||
exception is OperationCanceledException)
{
}
}, _cancellationTokenSource.Token);
}
 
public void Schedule(int delay, Action execute, CancellationToken cancellationToken)
{
try
{
if (_task != null)
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
_task = null;
}
}
catch
{
// Ignore errors.
}
finally
{
_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
}
 
_task = Task.Delay(delay, _cancellationTokenSource.Token)
.ContinueWith(task =>
{
try
{
execute.Invoke();
}
catch (Exception exception) when (exception is ObjectDisposedException ||
exception is OperationCanceledException)
{
}
}, _cancellationTokenSource.Token);
}
 
#endregion
}
}
/trunk/Winify/Utilities/Serialization/Serialization.cs
@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Horizon.Utilities.Serialization;
 
namespace Winify.Utilities.Serialization
{
public static class Serialization
{
#region Public Methods
 
public static async Task<SerializationState> Deserialize<T>(string file, string targetNamespace,
string schemeUri,
CancellationToken cancellationToken)
{
var xmlSerializer = new XmlSerializer(typeof(T));
 
var validationEventArgs = new List<ValidationEventArgs>();
 
void XmlReaderSettingsValidationEventHandler(object sender, ValidationEventArgs e)
{
validationEventArgs.Add(e);
}
 
T servers;
 
var settings = new XmlReaderSettings();
 
try
{
settings.Async = true;
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationType = ValidationType.Schema;
 
settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation |
XmlSchemaValidationFlags.ReportValidationWarnings |
XmlSchemaValidationFlags.ProcessIdentityConstraints;
 
settings.Schemas = new XmlSchemaSet();
 
settings.ValidationEventHandler += XmlReaderSettingsValidationEventHandler;
 
settings.Schemas.Add(targetNamespace, schemeUri);
 
using var fileStream =
await Miscellaneous.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read,
cancellationToken);
 
using var xmlReader = XmlReader.Create(fileStream,
settings);
 
var stringBuilder = new StringBuilder();
 
using (var stringWriter = new StringWriter(stringBuilder))
{
while (await xmlReader.ReadAsync())
await stringWriter.WriteAsync(await xmlReader.ReadOuterXmlAsync());
}
 
using var stringReader = new StringReader(stringBuilder.ToString());
 
servers =
(T)xmlSerializer
.Deserialize(stringReader);
}
catch (Exception exception)
{
return new SerializationFailure(exception, validationEventArgs);
}
finally
{
settings.ValidationEventHandler -=
XmlReaderSettingsValidationEventHandler;
}
 
return new SerializationSuccess<T>(servers, validationEventArgs);
}
 
public static async Task<SerializationState> Serialize<T>(T servers, string file, string name, string subset,
CancellationToken cancellationToken)
{
var xmlSerializer = new XmlSerializer(typeof(T));
 
try
{
using var memoryStream = new MemoryStream();
using var xmlWriter =
XmlWriter.Create(memoryStream,
new XmlWriterSettings
{
Async = true,
Indent = true,
IndentChars = " ",
OmitXmlDeclaration = false
});
await xmlWriter.WriteDocTypeAsync(name,
null,
null,
subset);
 
xmlSerializer.Serialize(xmlWriter, servers);
 
using var fileStream =
await Miscellaneous.GetFileStream(file, FileMode.Create, FileAccess.Write, FileShare.Write,
cancellationToken);
 
memoryStream.Position = 0L;
 
await memoryStream.CopyToAsync(fileStream);
}
catch (Exception exception)
{
return new SerializationFailure(exception);
}
 
return new SerializationSuccess<T>();
}
 
#endregion
}
}
/trunk/Winify/Utilities/Serialization/SerializationFailure.cs
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Xml.Schema;
using Horizon.Utilities.Serialization;
 
namespace Winify.Utilities.Serialization
{
public class SerializationFailure : SerializationState
{
#region Public Enums, Properties and Fields
 
public Exception Exception { get; set; }
 
public List<ValidationEventArgs> ValidationEventArgs { get; }
 
#endregion
 
#region Constructors, Destructors and Finalizers
 
public SerializationFailure(Exception exception)
{
Exception = exception;
}
 
public SerializationFailure(Exception exception, List<ValidationEventArgs> validationEventArgs) :
this(exception)
{
ValidationEventArgs = validationEventArgs;
}
 
#endregion
}
}
/trunk/Winify/Utilities/Serialization/SerializationState.cs
@@ -0,0 +1,6 @@
namespace Horizon.Utilities.Serialization
{
public class SerializationState
{
}
}
/trunk/Winify/Utilities/Serialization/SerializationSuccess.cs
@@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Xml.Schema;
using Horizon.Utilities.Serialization;
 
namespace Winify.Utilities.Serialization
{
public class SerializationSuccess<T> : SerializationState
{
#region Public Enums, Properties and Fields
 
public T Result { get; }
 
public List<ValidationEventArgs> ValidationEventArgs { get; }
 
#endregion
 
#region Constructors, Destructors and Finalizers
 
public SerializationSuccess()
{
}
 
public SerializationSuccess(T result) : this()
{
Result = result;
}
 
public SerializationSuccess(T result,
List<ValidationEventArgs> validationEventArgs) : this(result)
{
ValidationEventArgs = validationEventArgs;
}
 
#endregion
}
}