93 Commits

Author SHA1 Message Date
Gary Sharp e2c07f019c v2.5 release 2025-09-28 11:24:29 +10:00
Gary Sharp 7603cac01a feature: scheduled flag removal 2025-09-19 12:18:45 +10:00
Gary Sharp 356762c811 feature: enrol devices bound to another domain 2025-09-18 18:27:29 +10:00
Gary Sharp deaac0f073 bug fixes 2025-09-11 15:57:16 +10:00
Gary Sharp de10f92c02 minor bug fixes 2025-09-10 15:23:06 +10:00
Gary Sharp 3e514fdf9a feature: device profiles - set assigned user for logon 2025-09-07 12:48:10 +10:00
Gary Sharp 36c24542e1 update: minor changes to document template bulk generation 2025-09-07 12:06:23 +10:00
Gary Sharp ca7193a8fc feature: device document template bulk generation 2025-08-17 18:56:56 +10:00
Gary Sharp 676ff82e4b qol: user device assignment helper methods for expressions 2025-08-13 16:15:53 +10:00
Gary Sharp 53fdea5325 update dependencies: jQuery, jQuery UI, jQuery Validate, jQuery Validate Unobtrusive, SignalR 2025-08-09 19:00:29 +10:00
Gary Sharp 0c0a7bf297 use fetch over $.getJSON 2025-08-09 18:43:44 +10:00
Gary Sharp 57aeaa3eaa remove disconnected dialogs 2025-08-09 16:17:10 +10:00
Gary Sharp d291ad464f qol: online upload: remove dialog when attachment received 2025-08-01 11:40:02 +10:00
Gary Sharp be7ee4cae8 feature: flag permissions
feature: flag permissions
2025-07-31 19:03:33 +10:00
Gary Sharp 7deead494b security: use more antiforgery tokens 2025-07-31 16:18:32 +10:00
Gary Sharp fd43d85778 qol: simplify and Tuple.Create() 2025-07-20 15:58:42 +10:00
Gary Sharp 4c27b0ff3c qol: use type keywords and more interpolated strings 2025-07-20 15:44:44 +10:00
Gary Sharp 58546ed16d qol: simplify default 2025-07-20 15:31:35 +10:00
Gary Sharp 9656c15c4b qol: simplify calls 2025-07-20 15:20:22 +10:00
Gary Sharp 1add4ee0f5 qol: inline variable declaration 2025-07-20 15:12:33 +10:00
Gary Sharp 5792771ea1 qol: formatting 2025-07-20 13:47:56 +10:00
Gary Sharp 49da389c2c qol: unnecessary usings 2025-07-20 12:00:57 +10:00
Gary Sharp 7faebe56a8 qol: interpolated strings 2025-07-20 11:59:28 +10:00
Gary Sharp 4e518d6684 qol: remove this 2025-07-20 11:39:42 +10:00
Gary Sharp b4e54c9edf qol: simplify accessors 2025-07-20 11:24:04 +10:00
Gary Sharp 3aeb9374a9 feature: job export supports individual user details 2025-07-17 13:09:10 +10:00
Gary Sharp 0905a02aea #172 attempt reconnect if signalR disconnects 2025-07-17 12:44:06 +10:00
Gary Sharp f8fd1a58a3 #145 add comments for devices 2025-07-17 11:40:50 +10:00
Gary Sharp 2184c9e22e add comments for users [#145] 2025-07-12 19:55:58 +10:00
Gary Sharp 42e9045d5e bug fixed: users with Remove Own Attachment permission had to refresh before they could remove 2025-07-12 19:51:54 +10:00
Gary Sharp 092c6249ee refactor job logs/comments [#145] 2025-07-12 16:48:27 +10:00
Gary Sharp b56e82d5c4 resolves #151: BYOD sub type added to User - Management jobs 2025-07-11 13:25:45 +10:00
Gary Sharp 54a578f4a1 feature: custom device models 2025-07-11 12:55:50 +10:00
Gary Sharp 3f1fa3d7de Resolves #173: Feature Request: Filter box for device/user flag assignment 2025-07-05 17:01:19 +10:00
Gary Sharp caa0bedc93 Update #9: by default, hide decommissioned devices from search 2025-07-05 14:14:07 +10:00
Gary Sharp 6e99b4503b feature: device model/profile decommissioning 2025-07-05 13:55:44 +10:00
Gary Sharp 583552ffdd feature: batch device decommissioning 2025-07-03 19:13:52 +10:00
Gary Sharp 4660425ccc qol: quick search input to have fixed width 2025-07-03 12:53:47 +10:00
Gary Sharp 8b8b26116e feature: specify device profile/batch during pending enrolment 2025-06-27 14:51:03 +10:00
Gary Sharp 57ae665070 bug: remove stray braces from the Device Batch and Profile views 2025-06-18 13:18:57 +10:00
Gary Sharp f06a37ebb4 bug: remove stray brace from device model view 2025-06-18 13:09:31 +10:00
Gary Sharp ee273ffe03 bug: show correct error message if Online Upload session fails 2025-06-18 13:03:47 +10:00
Gary Sharp 0672bdb7c0 qol: avoid license/activation confusion by renaming license Activate button to Apply 2025-06-18 13:03:20 +10:00
Gary Sharp 662e1ed231 feature: Upload Online Attachments front end 2025-06-15 18:01:01 +10:00
Gary Sharp cc1f224456 feature: Upload Online Attachments 2025-06-15 17:56:13 +10:00
Gary Sharp 6e2c36d4ae bug: enforce device details scope 2025-06-15 17:51:35 +10:00
Gary Sharp bccbb20b84 bug fix #171 device batch attachments not working 2025-03-14 16:40:55 +11:00
Gary Sharp fd3eb80648 bug fix: online services authentication token not expiring 2025-03-10 14:35:57 +11:00
Gary Sharp 9a171a8417 bug fix #168 device export: batch filtering inverted 2025-03-04 17:34:51 +11:00
Gary Sharp eb1ffae212 bug fix: export user details without User.ShowDetails claim 2025-02-27 13:54:43 +11:00
Gary Sharp d31c2db43b regression fix: device page header overflow 2025-02-27 13:17:04 +11:00
Gary Sharp 62a5da7513 regression fix: quick search 2025-02-27 13:16:37 +11:00
Gary Sharp eb3ed7f819 regression fix: ajax icons not appearing 2025-02-26 17:59:08 +11:00
Gary Sharp a9687b5f25 feature: user details are individually exported; shared export field renderer 2025-02-26 13:23:24 +11:00
Gary Sharp 539503133a qol: fix System.Net.Http dependencies 2025-02-26 13:16:29 +11:00
Gary Sharp d2b5e7ab6a exporting: remember last options for documents/user flags/device flags 2025-02-26 13:06:34 +11:00
Gary Sharp 04430bba50 bug fix #162 document template id closure not updated on subsequent invoke 2025-02-17 18:08:22 +11:00
Gary Sharp 162ca20046 fix: enrollment > enrolment 2025-02-16 17:13:55 +11:00
Gary Sharp 786d4809b5 feature: document instance exporting
resolves #154
2025-02-14 16:05:23 +11:00
Gary Sharp d3cef11796 feature: exports api refactoring 2025-02-14 13:07:30 +11:00
Gary Sharp 2c215e4856 feature: saved exports; include jobs and flags 2025-02-13 18:20:47 +11:00
Gary Sharp eec8ba438c feature: saved exports view/edit/trigger 2025-02-12 18:36:30 +11:00
Gary Sharp 59dc0b9d5a regression bug: csv export was failing 2025-02-12 15:39:18 +11:00
Gary Sharp ac24055365 feature: saved exports
initial - not feature complete
2025-02-09 17:14:04 +11:00
Gary Sharp 2fce645066 refactor: simplify export metadata construction 2025-02-07 16:12:19 +11:00
Gary Sharp 67f1c2a5d1 refactor: make exporting consistent 2025-02-06 19:14:36 +11:00
Gary Sharp f946f3250c feature: collect MDM Hardware Data (Autopilot hash) during device enrolment
resolves #160
2025-02-05 17:38:57 +11:00
Gary Sharp 0853bcee50 feature: initial comments template
completes #150
2025-01-24 17:28:27 +11:00
Gary Sharp 408e1c4c14 qol: make Online Services Connect more reliable 2025-01-23 15:14:30 +11:00
Gary Sharp dee54bb6d7 feature: choose which noticeboard components to display with the link builder
also restyle noticeboard using flex
2025-01-22 17:58:45 +11:00
Gary Sharp 50603210b0 update expression browser route 2025-01-19 21:44:50 +11:00
Gary Sharp b640e51874 feature: add clipboard link to various identifiers (resolves #148) 2025-01-18 13:33:55 +11:00
Gary Sharp 7a336e699a request: device profile OUs should be sorted alphabetically 2025-01-17 13:05:06 +11:00
Gary Sharp a3e1e1d030 feature: update expression browser and add plugin expression extensions 2025-01-16 12:36:01 +11:00
Gary Sharp 963970feeb update list of shipped binaries for plugins 2025-01-15 15:36:44 +11:00
Gary Sharp 296f7a13fd feature: online services push notifications 2025-01-01 19:23:18 +11:00
Gary Sharp 4006bdbcc6 bug: AD ignore foreign security principals 2024-12-30 14:25:08 +11:00
Gary Sharp 26bac92e5a qol: online services authentication expiration offset 2024-12-30 14:24:28 +11:00
Gary Sharp b6dfaa3445 feature: online activation 2024-12-28 08:12:31 +11:00
Gary Sharp 39ba206831 qol: attachments newest to oldest and adjustments so attachments are shown 2024-12-18 20:09:10 +11:00
Gary Sharp 7550e0e45d qol: wait for attachment thumbnail generation and show additional file type-specific icons 2024-12-18 19:37:15 +11:00
Gary Sharp 9f10eeeb70 qol: make attachment comments optional 2024-12-18 18:40:23 +11:00
Gary Sharp 77acf0bfdb bug fix #104 hardware mac addresses not saving on MacOSX enrol 2024-12-15 18:00:40 +11:00
Gary Sharp f0dfe45cd4 bug fix #153 save job log message when bulk generating document templates 2024-12-15 17:42:32 +11:00
Gary Sharp fb6432a5c8 feature: add email address to organisation address (resolves #156) 2024-12-15 17:08:49 +11:00
Gary Sharp b15917254f clean up: remove unused namespaces 2024-12-14 16:55:37 +11:00
Gary Sharp 8abe31f430 qol: use unified exporting for logs 2024-12-14 16:49:31 +11:00
Gary Sharp a6b9cd1af2 feature: job exporting (resolves #155) 2024-12-12 16:02:12 +11:00
Gary Sharp 90c709c4c1 feature: #158 adds job preference option to include all attachments on lodgment 2024-12-11 17:01:42 +11:00
Gary Sharp 25e3a8e1f1 feature: add select all/none attachments when submitting waranty/repair/insurance job 2024-12-11 15:15:22 +11:00
Gary Sharp 343f20980d qol: impove plugin installation/update api 2024-12-11 15:13:26 +11:00
Gary Sharp f36871abe2 feature: dont disable a computer account if a duplicate, commissioned device exists 2024-12-11 15:11:33 +11:00
Gary Sharp cb354cd13e skip disabling computer account during decommissioning if another active device with the same name exists 2024-10-10 16:17:38 +11:00
989 changed files with 111139 additions and 77035 deletions
@@ -17,13 +17,12 @@ namespace Disco.BI.Extensions
{
public static class DocumentTemplateExtensions
{
private static Tuple<Dictionary<string, Expression>, List<DocumentField>> CreateExpressions(DocumentTemplate dt, DiscoDataContext database)
public static Tuple<Dictionary<string, Expression>, List<DocumentField>> CreateExpressions(string templateFileName, DiscoDataContext database)
{
Dictionary<string, Expression> expressions = new Dictionary<string, Expression>();
List<DocumentField> fields = new List<DocumentField>();
string templateFilename = dt.RepositoryFilename(database);
PdfReader pdfReader = new PdfReader(templateFilename);
PdfReader pdfReader = new PdfReader(templateFileName);
int pdfFieldOrdinal = 0;
foreach (string pdfFieldKey in pdfReader.AcroFields.Fields.Keys)
{
@@ -61,54 +60,60 @@ namespace Disco.BI.Extensions
return Tuple.Create(expressions, fields);
}
public static Dictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
private static Tuple<Dictionary<string, Expression>, List<DocumentField>> CreateExpressions(DocumentTemplate dt, DiscoDataContext database)
{
return ExpressionCache.GetOrCreateExpressions(dt, () => CreateExpressions(dt, Database));
string templateFileName = dt.RepositoryFilename(database);
return CreateExpressions(templateFileName, database);
}
public static List<DocumentField> PdfFieldsFromCache(this DocumentTemplate dt, DiscoDataContext Database)
public static Dictionary<string, Expression> PdfExpressionsFromCache(this DocumentTemplate dt, DiscoDataContext database)
{
return ExpressionCache.GetOrCreateFields(dt, () => CreateExpressions(dt, Database));
return ExpressionCache.GetOrCreateExpressions(dt, () => CreateExpressions(dt, database));
}
public static List<Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext Database)
public static List<DocumentField> PdfFieldsFromCache(this DocumentTemplate dt, DiscoDataContext database)
{
return dt.PdfExpressionsFromCache(Database).Values.OrderBy(e => e.Ordinal).ToList();
return ExpressionCache.GetOrCreateFields(dt, () => CreateExpressions(dt, database));
}
public static Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
public static List<Expression> ExtractPdfExpressions(this DocumentTemplate dt, DiscoDataContext database)
{
return dt.PdfExpressionsFromCache(database).Values.OrderBy(e => e.Ordinal).ToList();
}
public static Stream GeneratePdf(this DocumentTemplate dt, DiscoDataContext database, IAttachmentTarget target, User creatorUser, DateTime timeStamp, DocumentState state, bool flattenFields = false)
{
bool generateExpression = !string.IsNullOrEmpty(dt.OnGenerateExpression);
string generateExpressionResult = null;
if (generateExpression)
generateExpressionResult = dt.EvaluateOnGenerateExpression(Target, Database, CreatorUser, TimeStamp, State);
generateExpressionResult = dt.EvaluateOnGenerateExpression(target, database, creatorUser, timeStamp, state);
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, Database, Target, CreatorUser, TimeStamp, State, FlattenFields);
var pdfStream = Interop.Pdf.PdfGenerator.GenerateFromTemplate(dt, database, target, creatorUser, timeStamp, state, flattenFields);
if (generateExpression)
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser, generateExpressionResult);
DocumentsLog.LogDocumentGenerated(dt, target, creatorUser, generateExpressionResult);
else
DocumentsLog.LogDocumentGenerated(dt, Target, CreatorUser);
DocumentsLog.LogDocumentGenerated(dt, target, creatorUser);
return pdfStream;
}
public static Stream GeneratePdfPackage(this DocumentTemplatePackage package, DiscoDataContext Database, IAttachmentTarget Target, User CreatorUser, DateTime TimeStamp, DocumentState State)
public static Stream GeneratePdfPackage(this DocumentTemplatePackage package, DiscoDataContext database, IAttachmentTarget target, User creatorUser, DateTime timeStamp, DocumentState state)
{
return Interop.Pdf.PdfGenerator.GenerateFromPackage(package, Database, Target, CreatorUser, TimeStamp, State);
return Interop.Pdf.PdfGenerator.GenerateFromPackage(package, database, target, creatorUser, timeStamp, state);
}
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds)
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext database, User creatorUser, DateTime timestamp, bool? insertBlankPages, List<string> dataObjectsIds)
{
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjectsIds);
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, database, creatorUser, timestamp, insertBlankPages, dataObjectsIds);
}
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects)
public static Stream GeneratePdfPackageBulk(this DocumentTemplatePackage package, DiscoDataContext database, User creatorUser, DateTime timestamp, bool? insertBlankPages, List<IAttachmentTarget> dataObjects)
{
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
return Interop.Pdf.PdfGenerator.GenerateBulkFromPackage(package, database, creatorUser, timestamp, insertBlankPages, dataObjects);
}
public static List<bool> PdfPageHasAttachmentId(this DocumentTemplate dt, DiscoDataContext Database)
public static List<bool> PdfPageHasAttachmentId(this DocumentTemplate dt, DiscoDataContext database)
{
string templateFilename = dt.RepositoryFilename(Database);
string templateFilename = dt.RepositoryFilename(database);
if (!File.Exists(templateFilename))
throw new FileNotFoundException("PDF template not found", templateFilename);
@@ -127,30 +132,20 @@ namespace Disco.BI.Extensions
public static void Delete(this DocumentTemplate dt, DiscoDataContext Database)
{
// Find & Rename all references
foreach (DeviceAttachment a in Database.DeviceAttachments.Where(a => a.DocumentTemplateId == dt.Id))
void updateAttachment(IAttachment a)
{
a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments);
if (a.Comments.Length > 500)
a.Comments = a.Comments.Substring(0, 500);
var comments = $"{dt.Description} - {a.Comments}";
if (comments.Length > 500)
comments = comments.Substring(0, 500);
a.Comments = comments;
a.DocumentTemplateId = null;
a.DocumentTemplate = null;
}
foreach (JobAttachment a in Database.JobAttachments.Where(a => a.DocumentTemplateId == dt.Id))
{
a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments);
if (a.Comments.Length > 500)
a.Comments = a.Comments.Substring(0, 500);
a.DocumentTemplateId = null;
a.DocumentTemplate = null;
}
foreach (var a in Database.DeviceAttachments.Where(a => a.DocumentTemplateId == dt.Id))
updateAttachment(a);
foreach (var a in Database.JobAttachments.Where(a => a.DocumentTemplateId == dt.Id))
updateAttachment(a);
foreach (UserAttachment a in Database.UserAttachments.Where(a => a.DocumentTemplateId == dt.Id))
{
a.Comments = string.Format("{0} - {1}", dt.Description, a.Comments);
if (a.Comments.Length > 500)
a.Comments = a.Comments.Substring(0, 500);
a.DocumentTemplateId = null;
a.DocumentTemplate = null;
}
updateAttachment(a);
// Remove Linked Group
ActiveDirectory.Context.ManagedGroups.Remove(DocumentTemplateDevicesManagedGroup.GetKey(dt));
@@ -161,8 +156,8 @@ namespace Disco.BI.Extensions
// Delete Template
string templateRepositoryFilename = dt.RepositoryFilename(Database);
if (System.IO.File.Exists(templateRepositoryFilename))
System.IO.File.Delete(templateRepositoryFilename);
if (File.Exists(templateRepositoryFilename))
File.Delete(templateRepositoryFilename);
// Remove from Cache
dt.FilterExpressionInvalidateCache();
+47 -48
View File
@@ -21,16 +21,16 @@ namespace Disco.BI.Interop.Pdf
{
public static class PdfGenerator
{
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects)
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext database, User creatorUser, DateTime timestamp, bool? insertBlankPages, List<IAttachmentTarget> dataObjects)
{
if (DataObjects.Count > 0)
if (dataObjects.Count > 0)
{
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Count);
List<Stream> generatedPdfs = new List<Stream>(dataObjects.Count);
using (var state = DocumentState.DefaultState())
{
foreach (var d in DataObjects)
foreach (var d in dataObjects)
{
generatedPdfs.Add(package.GeneratePdfPackage(Database, d, CreatorUser, Timestamp, state));
generatedPdfs.Add(package.GeneratePdfPackage(database, d, creatorUser, timestamp, state));
state.SequenceNumber++;
state.FlushScopeCache();
}
@@ -41,7 +41,7 @@ namespace Disco.BI.Interop.Pdf
}
else
{
Stream bulkPdf = Utilities.JoinPdfs(package.InsertBlankPages || InsertBlankPages, generatedPdfs);
Stream bulkPdf = Utilities.JoinPdfs(insertBlankPages.GetValueOrDefault(package.InsertBlankPages), generatedPdfs);
foreach (Stream singlePdf in generatedPdfs)
singlePdf.Dispose();
return bulkPdf;
@@ -50,25 +50,25 @@ namespace Disco.BI.Interop.Pdf
return null;
}
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds)
public static Stream GenerateBulkFromPackage(DocumentTemplatePackage package, DiscoDataContext database, User creatorUser, DateTime timestamp, bool? insertBlankPages, List<string> dataObjectsIds)
{
List<IAttachmentTarget> DataObjects;
switch (package.Scope)
{
case AttachmentTypes.Device:
DataObjects = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).ToList<IAttachmentTarget>();
DataObjects = database.Devices.Where(d => dataObjectsIds.Contains(d.SerialNumber)).ToList<IAttachmentTarget>();
break;
case AttachmentTypes.Job:
int[] intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToArray();
DataObjects = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToList<IAttachmentTarget>();
int[] intDataObjectsIds = dataObjectsIds.Select(i => int.Parse(i)).ToArray();
DataObjects = database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).ToList<IAttachmentTarget>();
break;
case AttachmentTypes.User:
DataObjects = new List<IAttachmentTarget>(DataObjectsIds.Count);
for (int idIndex = 0; idIndex < DataObjectsIds.Count; idIndex++)
DataObjects = new List<IAttachmentTarget>(dataObjectsIds.Count);
for (int idIndex = 0; idIndex < dataObjectsIds.Count; idIndex++)
{
string dataObjectId = DataObjectsIds[idIndex];
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), Database, true);
string dataObjectId = dataObjectsIds[idIndex];
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(dataObjectId), database, true);
if (user == null)
throw new Exception($"Unknown Username specified: {dataObjectId}");
DataObjects.Add(user);
@@ -78,12 +78,12 @@ namespace Disco.BI.Interop.Pdf
throw new InvalidOperationException("Invalid DocumentType Scope");
}
return GenerateBulkFromPackage(package, Database, CreatorUser, Timestamp, InsertBlankPages, DataObjects);
return GenerateBulkFromPackage(package, database, creatorUser, timestamp, insertBlankPages, DataObjects);
}
public static Stream GenerateFromPackage(DocumentTemplatePackage package, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime Timestamp, DocumentState State)
public static Stream GenerateFromPackage(DocumentTemplatePackage package, DiscoDataContext database, IAttachmentTarget data, User creatorUser, DateTime timestamp, DocumentState state)
{
var templates = package.GetDocumentTemplates(Database);
var templates = package.GetDocumentTemplates(database);
if (templates.Count == 0)
return null;
@@ -92,21 +92,21 @@ namespace Disco.BI.Interop.Pdf
string generateExpressionResult = null;
if (generateExpression)
generateExpressionResult = package.EvaluateOnGenerateExpression(Data, Database, CreatorUser, Timestamp, State);
generateExpressionResult = package.EvaluateOnGenerateExpression(data, database, creatorUser, timestamp, state);
List<Stream> generatedPdfs = new List<Stream>(templates.Count);
foreach (var template in templates)
{
generatedPdfs.Add(template.GeneratePdf(Database, Data, CreatorUser, Timestamp, State, true));
generatedPdfs.Add(template.GeneratePdf(database, data, creatorUser, timestamp, state, true));
State.SequenceNumber++;
State.FlushScopeCache();
state.SequenceNumber++;
state.FlushScopeCache();
}
if (generateExpression)
DocumentsLog.LogDocumentPackageGenerated(package, Data, CreatorUser, generateExpressionResult);
DocumentsLog.LogDocumentPackageGenerated(package, data, creatorUser, generateExpressionResult);
else
DocumentsLog.LogDocumentPackageGenerated(package, Data, CreatorUser);
DocumentsLog.LogDocumentPackageGenerated(package, data, creatorUser);
if (generatedPdfs.Count == 1)
{
@@ -120,20 +120,20 @@ namespace Disco.BI.Interop.Pdf
return bulkPdf;
}
}
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<IAttachmentTarget> DataObjects, IScheduledTaskStatus taskStatus)
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext database, User creatorUser, DateTime timestamp, bool insertBlankPages, List<IAttachmentTarget> dataObjects, IScheduledTaskStatus taskStatus)
{
if (DataObjects.Count > 0)
if (dataObjects.Count > 0)
{
List<Stream> generatedPdfs = new List<Stream>(DataObjects.Count);
var progressPerDoc = 80d / DataObjects.Count;
List<Stream> generatedPdfs = new List<Stream>(dataObjects.Count);
var progressPerDoc = 80d / dataObjects.Count;
var progressDoc = 10d;
using (var state = DocumentState.DefaultState())
{
taskStatus.UpdateStatus(10, "Rendering", "Starting");
foreach (var d in DataObjects)
foreach (var d in dataObjects)
{
taskStatus.UpdateStatus(progressDoc += progressPerDoc, $"Rendering {d.AttachmentReferenceId}");
generatedPdfs.Add(dt.GeneratePdf(Database, d, CreatorUser, Timestamp, state, true));
generatedPdfs.Add(dt.GeneratePdf(database, d, creatorUser, timestamp, state, true));
state.SequenceNumber++;
state.FlushScopeCache();
}
@@ -145,7 +145,7 @@ namespace Disco.BI.Interop.Pdf
else
{
taskStatus.UpdateStatus(90, "Merging", "Merging documents");
Stream bulkPdf = Utilities.JoinPdfs(InsertBlankPages, generatedPdfs);
Stream bulkPdf = Utilities.JoinPdfs(insertBlankPages, generatedPdfs);
foreach (Stream singlePdf in generatedPdfs)
singlePdf.Dispose();
return bulkPdf;
@@ -154,28 +154,28 @@ namespace Disco.BI.Interop.Pdf
return null;
}
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext Database, User CreatorUser, DateTime Timestamp, bool InsertBlankPages, List<string> DataObjectsIds, IScheduledTaskStatus taskStatus)
public static Stream GenerateBulkFromTemplate(DocumentTemplate dt, DiscoDataContext database, User creatorUser, DateTime timestamp, bool insertBlankPages, List<string> dataObjectsIds, IScheduledTaskStatus taskStatus)
{
Dictionary<string, IAttachmentTarget> dataObjectLookup;
List<string> dataObjectIds = DataObjectsIds;
List<string> dataObjectIds = dataObjectsIds;
taskStatus.UpdateStatus(0, "Resolving targets", "Resolving render targets");
switch (dt.Scope)
{
case DocumentTemplate.DocumentTemplateScopes.Device:
dataObjectLookup = Database.Devices.Where(d => DataObjectsIds.Contains(d.SerialNumber)).AsEnumerable().Cast<IAttachmentTarget>().ToDictionary(i => i.AttachmentReferenceId, StringComparer.OrdinalIgnoreCase);
dataObjectLookup = database.Devices.Where(d => dataObjectsIds.Contains(d.SerialNumber)).AsEnumerable().Cast<IAttachmentTarget>().ToDictionary(i => i.AttachmentReferenceId, StringComparer.OrdinalIgnoreCase);
break;
case DocumentTemplate.DocumentTemplateScopes.Job:
var intDataObjectsIds = DataObjectsIds.Select(i => int.Parse(i)).ToList();
dataObjectLookup = Database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).AsEnumerable().Cast<IAttachmentTarget>().ToDictionary(i => i.AttachmentReferenceId, StringComparer.OrdinalIgnoreCase);
var intDataObjectsIds = dataObjectsIds.Select(i => int.Parse(i)).ToList();
dataObjectLookup = database.Jobs.Where(j => intDataObjectsIds.Contains(j.Id)).AsEnumerable().Cast<IAttachmentTarget>().ToDictionary(i => i.AttachmentReferenceId, StringComparer.OrdinalIgnoreCase);
break;
case DocumentTemplate.DocumentTemplateScopes.User:
dataObjectLookup = new Dictionary<string, IAttachmentTarget>(DataObjectsIds.Count, StringComparer.OrdinalIgnoreCase);
dataObjectIds = new List<string>(DataObjectsIds.Count);
foreach (var userId in DataObjectsIds)
dataObjectLookup = new Dictionary<string, IAttachmentTarget>(dataObjectsIds.Count, StringComparer.OrdinalIgnoreCase);
dataObjectIds = new List<string>(dataObjectsIds.Count);
foreach (var userId in dataObjectsIds)
{
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(userId), Database, true);
var user = UserService.GetUser(ActiveDirectory.ParseDomainAccountId(userId), database, true);
if (user == null)
{
dataObjectIds.Add(userId);
@@ -190,7 +190,7 @@ namespace Disco.BI.Interop.Pdf
}
// recreate list to honor the sort-order provided in DataObjectsIds
var dataObjects = new List<IAttachmentTarget>(DataObjectsIds.Count);
var dataObjects = new List<IAttachmentTarget>(dataObjectsIds.Count);
var missingIds = new List<string>();
foreach (var id in dataObjectIds)
{
@@ -204,10 +204,10 @@ namespace Disco.BI.Interop.Pdf
throw new Exception($"Unknown id specified: {string.Join("; ", missingIds)}");
}
return GenerateBulkFromTemplate(dt, Database, CreatorUser, Timestamp, InsertBlankPages, dataObjects, taskStatus);
return GenerateBulkFromTemplate(dt, database, creatorUser, timestamp, insertBlankPages, dataObjects, taskStatus);
}
public static Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime TimeStamp, DocumentState State, bool FlattenFields = false)
public static Stream GenerateFromTemplate(DocumentTemplate dt, DiscoDataContext Database, IAttachmentTarget Data, User CreatorUser, DateTime TimeStamp, DocumentState State, bool flattenFields = false)
{
// Validate Data
switch (dt.Scope)
@@ -232,7 +232,7 @@ namespace Disco.BI.Interop.Pdf
// Override FlattenFields if Document Template instructs.
if (dt.FlattenForm)
FlattenFields = true;
flattenFields = true;
var expressionCache = dt.PdfExpressionsFromCache(Database);
@@ -242,7 +242,7 @@ namespace Disco.BI.Interop.Pdf
MemoryStream pdfGeneratedStream = new MemoryStream();
PdfStamper pdfStamper = new PdfStamper(pdfReader, pdfGeneratedStream);
pdfStamper.FormFlattening = FlattenFields;
pdfStamper.FormFlattening = flattenFields;
pdfStamper.Writer.CloseStream = false;
IDictionary expressionVariables = Expression.StandardVariables(dt, Database, CreatorUser, TimeStamp, State, Data);
@@ -253,7 +253,7 @@ namespace Disco.BI.Interop.Pdf
{
AcroFields.Item fields = pdfStamper.AcroFields.Fields[pdfFieldKey];
string fieldValue = dt.CreateUniqueIdentifier(Database, Data, CreatorUser, TimeStamp, 0).ToJson();
if (FlattenFields)
if (flattenFields)
pdfStamper.AcroFields.SetField(pdfFieldKey, string.Empty);
else
pdfStamper.AcroFields.SetField(pdfFieldKey, fieldValue);
@@ -296,8 +296,7 @@ namespace Disco.BI.Interop.Pdf
}
else
{
Expression fieldExpression = null;
if (expressionCache.TryGetValue(pdfFieldKey, out fieldExpression))
if (expressionCache.TryGetValue(pdfFieldKey, out var fieldExpression))
{
if (fieldExpression.IsDynamic)
{
@@ -397,7 +396,7 @@ namespace Disco.BI.Interop.Pdf
TechUserId = CreatorUser.UserId,
Timestamp = DateTime.Now
};
jl.Comments = string.Format("# Document Generated\r\n**{0}** [{1}]", dt.Description, dt.Id);
jl.Comments = $"# Document Generated\r\n**{dt.Description}** [{dt.Id}]";
Database.JobLogs.Add(jl);
}
+1 -1
View File
@@ -17,7 +17,7 @@ namespace Disco.BI.Interop.Pdf
public static Stream JoinPdfs(bool InsertBlankPages, List<Stream> Pdfs)
{
if (Pdfs.Count == 0)
throw new System.ArgumentNullException(nameof(Pdfs));
throw new ArgumentNullException(nameof(Pdfs));
// Only One PDF - Possible Reference Bug v's Memory/Speed (Returning Param Memory Stream)
if (Pdfs.Count == 1)
-2
View File
@@ -53,7 +53,6 @@
<Reference Include="System.DirectoryServices" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions, Version=2.2.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll</HintPath>
<Private>True</Private>
@@ -62,7 +61,6 @@
<HintPath>..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web" />
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.4.24270.0000")]
[assembly: AssemblyVersion("2.5.25262.0000")]
[assembly: AssemblyFileVersion("2.5.25262.0000")]
+30 -22
View File
@@ -1,56 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<system.serviceModel>
<bindings/>
<client/>
<bindings />
<client />
</system.serviceModel>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True"/>
<parameter value="Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
<assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
<assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0"/>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.1.1.3" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
+5 -8
View File
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using Disco.Client.Extensions;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using Disco.Client.Extensions;
using Newtonsoft.Json;
namespace Disco.Client
{
@@ -88,7 +85,7 @@ namespace Disco.Client
string reportJson = JsonConvert.SerializeObject(report);
string reportResponse;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(ServicePathTemplate);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(ServicePathTemplate);
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
request.ContentType = "application/json";
request.Method = WebRequestMethods.Http.Post;
@@ -108,7 +105,7 @@ namespace Disco.Client
}
}
System.Diagnostics.Debug.WriteLine("Error Report Logged to Server; Response: {0}", reportResponse);
Debug.WriteLine($"Error Report Logged to Server; Response: {reportResponse}");
}
#endregion
@@ -8,13 +8,13 @@ namespace Disco.Client.Extensions
{
public static class ClientServicesExtensions
{
//#if DEBUG
// public const string ServicePathAuthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Authenticated/{0}";
// public const string ServicePathUnauthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Unauthenticated/{0}";
//#else
//#if DEBUG
// public const string ServicePathAuthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Authenticated/{0}";
// public const string ServicePathUnauthenticatedTemplate = "http://WS-GSHARP:57252/Services/Client/Unauthenticated/{0}";
//#else
public const string ServicePathAuthenticatedTemplate = "http://DISCO:9292/Services/Client/Authenticated/{0}";
public const string ServicePathUnauthenticatedTemplate = "http://DISCO:9292/Services/Client/Unauthenticated/{0}";
//#endif
//#endif
public static ResponseType Post<ResponseType>(this ServiceBase<ResponseType> Service, bool Authenticated)
{
@@ -26,7 +26,7 @@ namespace Disco.Client.Extensions
else
serviceUrl = string.Format(ServicePathUnauthenticatedTemplate, Service.Feature);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUrl);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceUrl);
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
request.ContentType = "application/json";
request.Method = WebRequestMethods.Http.Post;
+5 -2
View File
@@ -104,7 +104,7 @@ namespace Disco.Client.Extensions
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
{
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DomainName, RegistryValueKind.String);
regWinlogon.SetValue("DefaultUserName", String.Empty, RegistryValueKind.String);
regWinlogon.SetValue("DefaultUserName", string.Empty, RegistryValueKind.String);
}
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
{
@@ -133,8 +133,11 @@ namespace Disco.Client.Extensions
Presentation.UpdateStatus("Enrolling Device", $"Configuring the device owner:\r\n{enrolResponse.AssignedUserDescription} ({enrolResponse.AssignedUserDomain}\\{enrolResponse.AssignedUserUsername})", true, -1, 3000);
if (enrolResponse.AssignedUserIsLocalAdmin)
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.AssignedUserSID, enrolResponse.AssignedUserUsername, enrolResponse.AssignedUserDomain);
LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.AssignedUserSID, enrolResponse.AssignedUserUsername, enrolResponse.AssignedUserDomain);
}
if (enrolResponse.SetAssignedUserForLogon && !string.IsNullOrEmpty(enrolResponse.AssignedUserDomain) && !string.IsNullOrEmpty(enrolResponse.AssignedUserUsername))
{
// Make Windows think this user was the last to logon
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
{
+1 -5
View File
@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Disco.Models.ClientServices;
using System.Text;
using System.Threading.Tasks;
using Disco.Models.ClientServices;
namespace Disco.Client.Extensions
{
+1 -2
View File
@@ -105,8 +105,7 @@ namespace Disco.Client.Interop
{
foreach (var thumbprint in RemoveThumbprints)
{
List<X509Certificate2> certificates;
if (existingThumbprints.TryGetValue(thumbprint, out certificates) && !addedThumbprints.Contains(thumbprint))
if (existingThumbprints.TryGetValue(thumbprint, out var certificates) && !addedThumbprints.Contains(thumbprint))
{
foreach (var certificate in certificates)
{
+14 -2
View File
@@ -46,6 +46,7 @@ namespace Disco.Client.Interop
audit.ApplyPhysicalMemoryInformation();
audit.ApplyDiskDriveInformation();
audit.ApplyBatteryInformation();
audit.ApplyMobileDeviceManagementInformation();
audit.NetworkAdapters = Network.GetNetworkAdapters();
@@ -538,8 +539,7 @@ namespace Disco.Client.Interop
// if serial number is absent attempt using UUID if valid
if (string.IsNullOrWhiteSpace(deviceHardware.SerialNumber))
{
Guid uuidGuid;
if (Guid.TryParse(deviceHardware.UUID, out uuidGuid) && uuidGuid != Guid.Empty)
if (Guid.TryParse(deviceHardware.UUID, out var uuidGuid) && uuidGuid != Guid.Empty)
{
deviceHardware.SerialNumber = $"UUID{uuidGuid:N}";
}
@@ -560,6 +560,18 @@ namespace Disco.Client.Interop
}
}
private static void ApplyMobileDeviceManagementInformation(this DeviceHardware deviceHardware)
{
try
{
using (var wmiObject = new ManagementObject(@"\\.\ROOT\CIMV2\mdm\dmmap:MDM_DevDetail_Ext01.InstanceID=""Ext"",ParentID=""./DevDetail"""))
{
deviceHardware.MdmHardwareData = (string)wmiObject.GetPropertyValue("DeviceHardwareData");
}
}
catch (Exception) { }
}
private static string Description(this PCSystemTypes type)
{
switch (type)
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Client.Interop.Native
namespace Disco.Client.Interop.Native
{
public enum NetworkConnectionStatuses : ushort
{
@@ -10,7 +10,7 @@ namespace Disco.Client.Interop.Native
/// The number of wireless profile entries in the ProfileInfo member.
/// </summary>
public uint dwNumberOfItems;
/// <summary>
/// The index of the current item. The index of the first item is 0. The dwIndex member must be less than the dwNumberOfItems member.
/// This member is not used by the wireless service. Applications can use this member when processing individual profiles in the
+1 -1
View File
@@ -21,7 +21,7 @@ namespace Disco.Client.Interop
return adapters;
}
private static List<NetworkAdapter> GetWmiNetworkAdapters()
{
try
+9 -23
View File
@@ -17,16 +17,13 @@ namespace Disco.Client.Interop
{
try
{
IntPtr wlanHandle;
uint wlanServiceVersion;
if (WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle) == WlanApi.ERROR_SUCCESS)
if (WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out var wlanServiceVersion, out var wlanHandle) == WlanApi.ERROR_SUCCESS)
{
try
{
IntPtr wlanInterfacesPtr;
if (WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr) == WlanApi.ERROR_SUCCESS)
if (WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out var wlanInterfacesPtr) == WlanApi.ERROR_SUCCESS)
{
try
{
@@ -69,12 +66,10 @@ namespace Disco.Client.Interop
{
try
{
IntPtr wlanHandle;
uint wlanServiceVersion;
uint interopResult;
// Connect to wireless service
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle);
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out var wlanServiceVersion, out var wlanHandle);
if (interopResult == WlanApi.ERROR_SERVICE_NOT_ACTIVE)
{
// Indicates the Wlan service has not been started on the client
@@ -109,10 +104,9 @@ namespace Disco.Client.Interop
private static List<WirelessProfile> GetWirelessProfiles(IntPtr wlanHandle)
{
uint interopResult;
IntPtr wlanInterfacesPtr;
// Enumerate wireless interfaces
interopResult = WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out wlanInterfacesPtr);
interopResult = WlanApi.WlanEnumInterfaces(wlanHandle, IntPtr.Zero, out var wlanInterfacesPtr);
if (interopResult != WlanApi.ERROR_SUCCESS)
{
throw new Exception($"Unable to list interfaces with the local wireless service. WlanEnumInterfaces returned: {interopResult}");
@@ -124,9 +118,8 @@ namespace Disco.Client.Interop
foreach (var wlanInterface in wlanInterfaces.InterfaceInfo)
{
IntPtr wlanProfilesPtr;
// Enumerate wireless profiles for interface
interopResult = WlanApi.WlanGetProfileList(wlanHandle, wlanInterface.InterfaceGuid, IntPtr.Zero, out wlanProfilesPtr);
interopResult = WlanApi.WlanGetProfileList(wlanHandle, wlanInterface.InterfaceGuid, IntPtr.Zero, out var wlanProfilesPtr);
if (interopResult != WlanApi.ERROR_SUCCESS)
{
throw new Exception($"Unable to list wireless profiles for the {wlanInterface.InterfaceGuid} interface with the local wireless service. WlanGetProfileList returned: {interopResult}");
@@ -165,12 +158,10 @@ namespace Disco.Client.Interop
try
{
IntPtr wlanHandle;
uint wlanServiceVersion;
uint interopResult;
// Connect to wireless service
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out wlanServiceVersion, out wlanHandle);
interopResult = WlanApi.WlanOpenHandle(WlanApi.WLAN_API_VERSION_2_0, IntPtr.Zero, out var wlanServiceVersion, out var wlanHandle);
if (interopResult == WlanApi.ERROR_SERVICE_NOT_ACTIVE)
{
// Indicates the Wlan service has not been started on the client
@@ -243,9 +234,8 @@ namespace Disco.Client.Interop
}
else
{
uint pdwReasonCode;
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nAdding Wireless Profile '{addProfile.Name}' on '{adapter.NetConnectionID}'", true, -1, 1000);
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, addProfile.ProfileXml, null, true, IntPtr.Zero, out pdwReasonCode);
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, addProfile.ProfileXml, null, true, IntPtr.Zero, out var pdwReasonCode);
if (interopResult != WlanApi.ERROR_SUCCESS)
{
@@ -285,11 +275,8 @@ namespace Disco.Client.Interop
else
{
// Load profile
IntPtr pstrProfileXml;
uint pdwFlags;
IntPtr pdwGrantAccess;
interopResult = WlanApi.WlanGetProfile(wlanHandle, adapter.ConnectionIdentifier, profileName, IntPtr.Zero, out pstrProfileXml, out pdwFlags, out pdwGrantAccess);
interopResult = WlanApi.WlanGetProfile(wlanHandle, adapter.ConnectionIdentifier, profileName, IntPtr.Zero, out var pstrProfileXml, out var pdwFlags, out var pdwGrantAccess);
if (interopResult == WlanApi.ERROR_SUCCESS)
{
@@ -312,10 +299,9 @@ namespace Disco.Client.Interop
if (!XNode.DeepEquals(originalProfileXml, transformedProfileXml))
{
// Set Profile
uint pdwReasonCode;
Presentation.UpdateStatus("Enrolling Device", $"Configuring Wireless Profiles\r\nModifying Wireless Profile '{profileName}' on '{adapter.NetConnectionID}'", true, -1, 1000);
transformProfileXml = transformedProfileXml.ToString(SaveOptions.None);
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, transformProfileXml, null, true, IntPtr.Zero, out pdwReasonCode);
interopResult = WlanApi.WlanSetProfile(wlanHandle, adapter.ConnectionIdentifier, 0, transformProfileXml, null, true, IntPtr.Zero, out var pdwReasonCode);
if (interopResult != WlanApi.ERROR_SUCCESS)
{
+6 -8
View File
@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Disco.Client.Extensions;
using Disco.Client.Interop;
using System;
using System.Reflection;
using System.Text;
using System.Threading;
using Disco.Client.Extensions;
using Disco.Client.Interop;
namespace Disco.Client
{
@@ -22,13 +20,13 @@ namespace Disco.Client
}
public static void UpdateStatus(string SubHeading, string Message, bool ShowProgress, int Progress, int TryDelay)
{
Presentation.UpdateStatus(SubHeading, Message, ShowProgress, Progress);
UpdateStatus(SubHeading, Message, ShowProgress, Progress);
if (TryDelay > 0)
Presentation.TryDelay(TryDelay);
}
public static void UpdateStatus(string SubHeading, string Message, bool ShowProgress, int Progress)
{
Console.WriteLine("#{0},{1},{2},{3}", SubHeading.EscapeMessage(), Message.EscapeMessage(), ShowProgress.ToString(), Progress.ToString());
Console.WriteLine($"#{SubHeading.EscapeMessage()},{Message.EscapeMessage()},{ShowProgress.ToString()},{Progress.ToString()}");
}
public static void TryDelay(int Milliseconds)
{
@@ -92,7 +90,7 @@ namespace Disco.Client
public static void RegisterBootstrapperPostActions(ShutdownActions ShutdownAction, bool Uninstall)
{
Console.WriteLine("!{0},{1}", Enum.GetName(typeof(ShutdownActions), ShutdownAction), Uninstall ? "UninstallBootstrapper" : "DontUninstallBootstrapper");
Console.WriteLine($"!{Enum.GetName(typeof(ShutdownActions), ShutdownAction)},{(Uninstall ? "UninstallBootstrapper" : "DontUninstallBootstrapper")}");
}
public enum ShutdownActions
{
+11 -14
View File
@@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using Disco.Client.Extensions;
using Disco.Models.ClientServices;
using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Disco.Models.ClientServices;
using Disco.Client.Extensions;
namespace Disco.Client
{
@@ -38,14 +35,14 @@ namespace Disco.Client
Presentation.WriteBanner();
// WhoAmI Phase
keepProcessing = Program.WhoAmI();
keepProcessing = WhoAmI();
// Enrol Phase
if (keepProcessing)
keepProcessing = Program.Enrol();
keepProcessing = Enrol();
// End conversation with Bootstrapper
Presentation.WriteFooter(Program.RebootRequired, Program.AllowUninstall, !keepProcessing);
Presentation.WriteFooter(RebootRequired, AllowUninstall, !keepProcessing);
}
public static void SetupEnvironment()
@@ -122,7 +119,7 @@ namespace Disco.Client
EnrolResponse response = null;
// Build Request
Presentation.UpdateStatus("Enrolling Device", "Building enrollment request and preparing to send data to the server.", true, -1);
Presentation.UpdateStatus("Enrolling Device", "Building enrolment request and preparing to send data to the server.", true, -1);
request = new Enrol();
request.Build();
@@ -130,11 +127,11 @@ namespace Disco.Client
do
{
// Send Request
Presentation.UpdateStatus("Enrolling Device", "Sending the enrollment request to the server.", true, -1);
response = request.Post(Program.IsAuthenticated);
Presentation.UpdateStatus("Enrolling Device", "Sending the enrolment request to the server.", true, -1);
response = request.Post(IsAuthenticated);
// Process Response
Presentation.UpdateStatus("Enrolling Device", "Processing the enrollment response from the server.", true, -1);
Presentation.UpdateStatus("Enrolling Device", "Processing the enrolment response from the server.", true, -1);
response.Process();
if (response.IsPending)
@@ -147,7 +144,7 @@ namespace Disco.Client
var secondsConsumed = (DateTimeOffset.Now - startTime).TotalSeconds;
var progress = (int)((secondsConsumed / totalSeconds) * 100);
Presentation.UpdateStatus($"Pending Device Enrollment Approval: {response.PendingIdentifier}", $"Waiting for enrollment session '{response.PendingIdentifier}' to be approved.{Environment.NewLine}Reason: {response.PendingReason}", true, progress);
Presentation.UpdateStatus($"Pending Device Enrolment Approval: {response.PendingIdentifier}", $"Waiting for enrolment session '{response.PendingIdentifier}' to be approved.{Environment.NewLine}Reason: {response.PendingReason}", true, progress);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
}
else
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.4.24270.0000")]
[assembly: AssemblyVersion("2.5.25262.0000")]
[assembly: AssemblyFileVersion("2.5.25262.0000")]
+23 -23
View File
@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Net;
using System.IO;
using System.Diagnostics;
namespace Disco.ClientBootstrapper
{
@@ -20,25 +20,25 @@ namespace Disco.ClientBootstrapper
private StringBuilder errorMessage;
private Process clientProcess;
//#if DEBUG
// public const string DiscoServerName = "WS-GSHARP";
// public const int DiscoServerPort = 57252;
//#else
//#if DEBUG
// public const string DiscoServerName = "WS-GSHARP";
// public const int DiscoServerPort = 57252;
//#else
public const string DiscoServerName = "DISCO";
public const int DiscoServerPort = 9292;
//#endif
//#endif
public BootstrapperLoop(IStatus StatusUI, LoopCompleteCallback Callback)
{
this.statusUI = StatusUI;
this.mLoopCompleteCallback = Callback;
this.errorMessage = new StringBuilder();
statusUI = StatusUI;
mLoopCompleteCallback = Callback;
errorMessage = new StringBuilder();
}
public void Start()
{
this.LoopThread = new Thread(new ThreadStart(loopHost));
this.LoopThread.Start();
LoopThread = new Thread(new ThreadStart(loopHost));
LoopThread.Start();
}
private void loopHost()
@@ -128,14 +128,14 @@ namespace Disco.ClientBootstrapper
break;
}
}
}
}
if (!Interop.NetworkInterop.PingDiscoIct(DiscoServerName))
{
// Client Failed
if (this.mLoopCompleteCallback != null)
if (mLoopCompleteCallback != null)
{
this.mLoopCompleteCallback.BeginInvoke(null, null);
mLoopCompleteCallback.BeginInvoke(null, null);
}
return;
}
@@ -197,15 +197,15 @@ namespace Disco.ClientBootstrapper
Interop.CertificateInterop.RemoveTempCerts();
// Pause if Error
if (this.errorMessage.Length > 0)
if (errorMessage.Length > 0)
{
Program.SleepThread(10000, true);
}
// End Of Loop
if (this.mLoopCompleteCallback != null)
if (mLoopCompleteCallback != null)
{
this.mLoopCompleteCallback.BeginInvoke(null, null);
mLoopCompleteCallback.BeginInvoke(null, null);
}
}
@@ -217,11 +217,11 @@ namespace Disco.ClientBootstrapper
{
if (na.IsWireless)
{
info.AppendLine(string.Format("{0}: {1}", na.NetConnectionID, na.WirelessConnectionStatusMeaning(na.WirelessConnectionStatus)));
info.AppendLine($"{na.NetConnectionID}: {na.WirelessConnectionStatusMeaning(na.WirelessConnectionStatus)}");
}
else
{
info.AppendLine(string.Format("{0}: {1}", na.NetConnectionID, na.ConnectionStatusMeaning(na.ConnectionStatus)));
info.AppendLine($"{na.NetConnectionID}: {na.ConnectionStatusMeaning(na.ConnectionStatus)}");
}
}
statusUI.UpdateStatus(null, null, info.ToString());
@@ -232,7 +232,7 @@ namespace Disco.ClientBootstrapper
{
if (!string.IsNullOrWhiteSpace(e.Data))
{
System.Diagnostics.Debug.WriteLine(string.Format("OUTPUT: {0}", e.Data));
Debug.WriteLine($"OUTPUT: {e.Data}");
var data = e.Data.Substring(1).Split(new char[] { ',' });
switch (e.Data[0])
{
+4 -10
View File
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Disco.ClientBootstrapper
@@ -12,7 +6,7 @@ namespace Disco.ClientBootstrapper
public partial class FormStatus : Form, IStatus
{
private delegate void dUpdateStatus(string Heading, string SubHeading, string Message, Nullable<bool> ShowProgress, Nullable<int> Progress);
private delegate void dUpdateStatus(string Heading, string SubHeading, string Message, bool? ShowProgress, int? Progress);
private dUpdateStatus mUpdateStatus;
public FormStatus()
@@ -20,7 +14,7 @@ namespace Disco.ClientBootstrapper
InitializeComponent();
var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
this.labelVersion.Text = string.Format("v{0}", version.ToString(3));
this.labelVersion.Text = $"v{version.ToString(3)}";
this.FormClosed += new FormClosedEventHandler(FormStatus_FormClosed);
@@ -34,7 +28,7 @@ namespace Disco.ClientBootstrapper
Program.ExitApplication();
}
public void UpdateStatus(string Heading, string SubHeading, string Message, Nullable<bool> ShowProgress = null, Nullable<int> Progress = null)
public void UpdateStatus(string Heading, string SubHeading, string Message, bool? ShowProgress = null, int? Progress = null)
{
try
{
@@ -42,7 +36,7 @@ namespace Disco.ClientBootstrapper
}
catch (Exception) { }
}
private void UpdateStatusDo(string Heading, string SubHeading, string Message, Nullable<bool> ShowProgress, Nullable<int> Progress)
private void UpdateStatusDo(string Heading, string SubHeading, string Message, bool? ShowProgress, int? Progress)
{
if (Heading != null)
if (this.labelHeading.Text != Heading)
+2 -7
View File
@@ -1,12 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.ClientBootstrapper
namespace Disco.ClientBootstrapper
{
interface IStatus
{
void UpdateStatus(string Heading, string SubHeading, string Message, Nullable<bool> ShowProgress = null, Nullable<int> Progress = null);
void UpdateStatus(string Heading, string SubHeading, string Message, bool? ShowProgress = null, int? Progress = null);
}
}
+6 -6
View File
@@ -22,9 +22,9 @@ namespace Disco.ClientBootstrapper
public void Start(CompleteCallback Callback)
{
this.mCompleteCallback = Callback;
this.LoopThread = new Thread(new ThreadStart(loopHost));
this.LoopThread.Start();
mCompleteCallback = Callback;
LoopThread = new Thread(new ThreadStart(loopHost));
LoopThread.Start();
}
private void loopHost()
{
@@ -33,10 +33,10 @@ namespace Disco.ClientBootstrapper
//Program.Status.UpdateStatus(null, null, "Testing UI");
//Program.SleepThread(5000, false);
Interop.InstallInterop.Install(this.InstallLocation, this.WimImageId, this.TempPath);
if (this.mCompleteCallback != null)
Interop.InstallInterop.Install(InstallLocation, WimImageId, TempPath);
if (mCompleteCallback != null)
{
this.mCompleteCallback.BeginInvoke(null, null);
mCompleteCallback.BeginInvoke(null, null);
}
}
catch (Exception ex)
@@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using System.IO;
namespace Disco.ClientBootstrapper.Interop
{
@@ -42,7 +41,7 @@ namespace Disco.ClientBootstrapper.Interop
{
if (Path.GetFileNameWithoutExtension(certFile).ToLower().Contains("temp"))
_tempCerts.Add(cert.SerialNumber);
Program.Status.UpdateStatus(null, null, string.Format("Added Root Certificate: {0}", cert.ShortSubjectName()));
Program.Status.UpdateStatus(null, null, $"Added Root Certificate: {cert.ShortSubjectName()}");
Program.SleepThread(500, false);
}
}
@@ -67,7 +66,7 @@ namespace Disco.ClientBootstrapper.Interop
{
if (Path.GetFileNameWithoutExtension(certFile).ToLower().Contains("temp"))
_tempCerts.Add(cert.SerialNumber);
Program.Status.UpdateStatus(null, null, string.Format("Added Intermediate Certificate: {0}", cert.ShortSubjectName()));
Program.Status.UpdateStatus(null, null, $"Added Intermediate Certificate: {cert.ShortSubjectName()}");
Program.SleepThread(500, false);
}
}
@@ -92,7 +91,7 @@ namespace Disco.ClientBootstrapper.Interop
{
if (Path.GetFileNameWithoutExtension(certFile).ToLower().Contains("temp"))
_tempCerts.Add(cert.SerialNumber);
Program.Status.UpdateStatus(null, null, string.Format("Added Host Certificate: {0}", cert.ShortSubjectName()));
Program.Status.UpdateStatus(null, null, $"Added Host Certificate: {cert.ShortSubjectName()}");
Program.SleepThread(500, false);
}
}
@@ -44,7 +44,7 @@ namespace Disco.ClientBootstrapper.Interop
}
catch (Exception ex)
{
throw new IOException(string.Format("Unable to delete folder: ", InstallLocation), ex);
throw new IOException($"Unable to delete folder: {InstallLocation}", ex);
}
}
if (!Directory.Exists(InstallLocation))
@@ -66,7 +66,7 @@ namespace Disco.ClientBootstrapper.Interop
foreach (var file in Directory.EnumerateFiles(SourceLocation))
{
var fileName = Path.GetFileName(file);
// Only Copy Certain Files
// Copy Wireless Certificates
@@ -79,7 +79,7 @@ namespace Disco.ClientBootstrapper.Interop
if (fileName.StartsWith("WLAN_Profile_", StringComparison.OrdinalIgnoreCase) &&
fileName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
File.Copy(file, Path.Combine(InstallLocation, fileName));
}
#endregion
@@ -105,7 +105,7 @@ namespace Disco.ClientBootstrapper.Interop
{
using (var scriptsIniStreamWriter = new StreamWriter(scriptsIniStream, Encoding.Unicode))
{
scriptsIniStreamWriter.Write(string.Format("[Startup]{0}0CmdLine={1}{0}0Parameters=/AllowUninstall", Environment.NewLine, BootstrapperCmdLinePath));
scriptsIniStreamWriter.Write($"[Startup]{Environment.NewLine}0CmdLine={BootstrapperCmdLinePath}{Environment.NewLine}0Parameters=/AllowUninstall");
scriptsIniStreamWriter.Flush();
}
}
@@ -193,18 +193,18 @@ namespace Disco.ClientBootstrapper.Interop
if (InstallLocation.EndsWith(".wim", StringComparison.OrdinalIgnoreCase))
{
// Offline File System (WIM)
Program.Status.UpdateStatus("Installing Bootstrapper (Offline)", "Installing", string.Format("Install Location: {0}", InstallLocation));
Program.Status.UpdateStatus("Installing Bootstrapper (Offline)", "Installing", $"Install Location: {InstallLocation}");
Program.SleepThread(1000, false);
// Mount WIM
int wimImageIndex = 0;
using (var wim = new Interop.WIMInterop.WindowsImageContainer(InstallLocation, WIMInterop.WindowsImageContainer.CreateFileMode.OpenExisting, WIMInterop.WindowsImageContainer.CreateFileAccess.Write))
using (var wim = new WIMInterop.WindowsImageContainer(InstallLocation, WIMInterop.WindowsImageContainer.CreateFileMode.OpenExisting, WIMInterop.WindowsImageContainer.CreateFileAccess.Write))
{
if (WimImageId == null)
WimImageId = "1";
if (!int.TryParse(WimImageId, out wimImageIndex))
{
Program.Status.UpdateStatus(null, "Analysing WIM", string.Format("Looking for Image Name: {0}", WimImageId));
Program.Status.UpdateStatus(null, "Analysing WIM", $"Looking for Image Name: {WimImageId}");
Program.SleepThread(500, false);
for (int i = 0; i < wim.ImageCount; i++)
{
@@ -215,7 +215,7 @@ namespace Disco.ClientBootstrapper.Interop
if (wimImageInfoName != null && wimImageInfoName.InnerText.Equals(WimImageId, StringComparison.OrdinalIgnoreCase))
{
wimImageIndex = i + 1;
Program.Status.UpdateStatus(null, "Analysing WIM", string.Format("Found Image Id '{0}' at Index {1}", WimImageId, wimImageIndex));
Program.Status.UpdateStatus(null, "Analysing WIM", $"Found Image Id '{WimImageId}' at Index {wimImageIndex}");
Program.SleepThread(500, false);
break;
}
@@ -224,7 +224,7 @@ namespace Disco.ClientBootstrapper.Interop
}
if (wimImageIndex == 0)
{
Program.Status.UpdateStatus(null, "Error", string.Format("Unable to load WIM Image Id: {0}", WimImageId));
Program.Status.UpdateStatus(null, "Error", $"Unable to load WIM Image Id: {WimImageId}");
Program.SleepThread(5000, false);
return;
}
@@ -241,22 +241,22 @@ namespace Disco.ClientBootstrapper.Interop
Directory.CreateDirectory(wimTempMountPath);
bool wimCommitChanges = true;
Interop.WIMInterop.WindowsImageContainer.NativeMethods.MessageCallback m_MessageCallback = null;
WIMInterop.WindowsImageContainer.NativeMethods.MessageCallback m_MessageCallback = null;
try
{
// Mount WIM
Program.Status.UpdateStatus(null, "Mounting WIM", string.Format("Mounting WIM Image to '{0}'", wimMountPath));
Program.Status.UpdateStatus(null, "Mounting WIM", $"Mounting WIM Image to '{wimMountPath}'");
Program.SleepThread(500, false);
m_MessageCallback = new Interop.WIMInterop.WindowsImageContainer.NativeMethods.MessageCallback(WimImageEventMessagePump);
Interop.WIMInterop.WindowsImageContainer.NativeMethods.RegisterCallback(m_MessageCallback);
m_MessageCallback = new WIMInterop.WindowsImageContainer.NativeMethods.MessageCallback(WimImageEventMessagePump);
WIMInterop.WindowsImageContainer.NativeMethods.RegisterCallback(m_MessageCallback);
Interop.WIMInterop.WindowsImageContainer.NativeMethods.MountImage(wimMountPath, InstallLocation, wimImageIndex, wimTempMountPath);
WIMInterop.WindowsImageContainer.NativeMethods.MountImage(wimMountPath, InstallLocation, wimImageIndex, wimTempMountPath);
// Load Local Machine Registry
var wimHivePath = Path.Combine(wimMountPath, "Windows\\System32\\config\\SOFTWARE");
Program.Status.UpdateStatus(null, "Mounting Offline Registry Hive", string.Format("Mounting Offline Registry Hive at '{0}'", wimHivePath));
Program.Status.UpdateStatus(null, "Mounting Offline Registry Hive", $"Mounting Offline Registry Hive at '{wimHivePath}'");
Program.SleepThread(500, false);
using (var wimReg = new Interop.RegistryInterop(RegistryInterop.RegistryHives.HKEY_LOCAL_MACHINE, "DiscoClientBootstrapperWimHive", wimHivePath))
using (var wimReg = new RegistryInterop(RegistryInterop.RegistryHives.HKEY_LOCAL_MACHINE, "DiscoClientBootstrapperWimHive", wimHivePath))
{
using (RegistryKey rootRegistryLocation = Registry.LocalMachine.OpenSubKey("DiscoClientBootstrapperWimHive", true))
{
@@ -268,7 +268,7 @@ namespace Disco.ClientBootstrapper.Interop
}
// Unload Local Machine Registry
Program.Status.UpdateStatus(null, "Unmounting Offline Registry Hive", string.Format("Unmounting Offline Registry Hive at '{0}'", wimHivePath));
Program.Status.UpdateStatus(null, "Unmounting Offline Registry Hive", $"Unmounting Offline Registry Hive at '{wimHivePath}'");
Program.SleepThread(500, false);
wimReg.Unload();
}
@@ -281,13 +281,13 @@ namespace Disco.ClientBootstrapper.Interop
finally
{
// Unmount WIM
Program.Status.UpdateStatus(null, "Unmounting WIM", string.Format("Unmounting WIM Image at '{0}'", wimMountPath));
Program.Status.UpdateStatus(null, "Unmounting WIM", $"Unmounting WIM Image at '{wimMountPath}'");
Program.SleepThread(500, false);
Interop.WIMInterop.WindowsImageContainer.NativeMethods.DismountImage(wimMountPath, InstallLocation, wimImageIndex, wimCommitChanges);
WIMInterop.WindowsImageContainer.NativeMethods.DismountImage(wimMountPath, InstallLocation, wimImageIndex, wimCommitChanges);
if (m_MessageCallback != null)
{
Interop.WIMInterop.WindowsImageContainer.NativeMethods.UnregisterMessageCallback(m_MessageCallback);
WIMInterop.WindowsImageContainer.NativeMethods.UnregisterMessageCallback(m_MessageCallback);
m_MessageCallback = null;
}
@@ -300,7 +300,7 @@ namespace Disco.ClientBootstrapper.Interop
else
{
// Online File System
Program.Status.UpdateStatus("Installing Bootstrapper (Online)", "Installing", string.Format("Install Location: {0}", InstallLocation), true, -1);
Program.Status.UpdateStatus("Installing Bootstrapper (Online)", "Installing", $"Install Location: {InstallLocation}", true, -1);
Program.SleepThread(1000, false);
string rootFileSystemLocation = Path.GetPathRoot(InstallLocation);
RegistryKey rootRegistryLocation = Registry.LocalMachine.OpenSubKey("SOFTWARE", true);
@@ -321,16 +321,16 @@ namespace Disco.ClientBootstrapper.Interop
IntPtr UserData
)
{
uint status = (uint)Interop.WIMInterop.WindowsImageContainer.NativeMethods.WIMMessage.WIM_MSG_SUCCESS;
Interop.WIMInterop.DefaultImageEventArgs eventArgs = new Interop.WIMInterop.DefaultImageEventArgs(wParam, lParam, UserData);
uint status = (uint)WIMInterop.WindowsImageContainer.NativeMethods.WIMMessage.WIM_MSG_SUCCESS;
WIMInterop.DefaultImageEventArgs eventArgs = new WIMInterop.DefaultImageEventArgs(wParam, lParam, UserData);
//System.Diagnostics.Debug.WriteLine(MessageId);
switch ((Interop.WIMInterop.WindowsImageContainer.ImageEventMessage)MessageId)
switch ((WIMInterop.WindowsImageContainer.ImageEventMessage)MessageId)
{
case Interop.WIMInterop.WindowsImageContainer.ImageEventMessage.Progress:
case Interop.WIMInterop.WindowsImageContainer.ImageEventMessage.MountCleanupProgress:
case WIMInterop.WindowsImageContainer.ImageEventMessage.Progress:
case WIMInterop.WindowsImageContainer.ImageEventMessage.MountCleanupProgress:
var timeRemainingMil = eventArgs.LeftParameter.ToInt32();
string timeRemainingMessage;
if (timeRemainingMil > 0)
@@ -339,8 +339,8 @@ namespace Disco.ClientBootstrapper.Interop
timeRemainingMessage = "Calculating, please wait...";
var progress = eventArgs.WideParameter.ToInt32();
Program.Status.UpdateStatus(null, null, string.Format("Time remaining: {0}", timeRemainingMessage), true, progress);
Program.Status.UpdateStatus(null, null, $"Time remaining: {timeRemainingMessage}", true, progress);
break;
default:
break;
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;
@@ -17,8 +14,8 @@ namespace Disco.ClientBootstrapper.Interop
public string Name { get; set; }
public string NetConnectionID { get; set; }
public string MACAddress { get; set; }
public UInt64 Speed { get; set; }
public UInt16 LastConnectionStatus { get; set; }
public ulong Speed { get; set; }
public ushort LastConnectionStatus { get; set; }
public bool IsWireless { get; set; }
public string WirelessInterfaceDescription { get; set; }
public int LastWirelessConnectionStatus { get; set; }
@@ -30,51 +27,51 @@ namespace Disco.ClientBootstrapper.Interop
private void UpdateFromWmi(ManagementObject wmiObject)
{
this.WmiPath = (string)wmiObject.GetPropertyValue("__PATH");
this.Index = (UInt32)wmiObject.GetPropertyValue("Index");
this.Guid = Guid.Parse((string)wmiObject.GetPropertyValue("GUID"));
this.MACAddress = (string)wmiObject.GetPropertyValue("MACAddress");
this.Name = (string)wmiObject.GetPropertyValue("Name");
this.NetConnectionID = (string)wmiObject.GetPropertyValue("NetConnectionID");
this.Speed = (UInt64)wmiObject.GetPropertyValue("Speed");
var connectionStatus = ConnectionStatus;
this.IsWireless = true;
WmiPath = (string)wmiObject.GetPropertyValue("__PATH");
Index = (uint)wmiObject.GetPropertyValue("Index");
Guid = Guid.Parse((string)wmiObject.GetPropertyValue("GUID"));
MACAddress = (string)wmiObject.GetPropertyValue("MACAddress");
Name = (string)wmiObject.GetPropertyValue("Name");
NetConnectionID = (string)wmiObject.GetPropertyValue("NetConnectionID");
Speed = (ulong)wmiObject.GetPropertyValue("Speed");
_ = ConnectionStatus;
IsWireless = true;
try
{
var wirelessConnectionStatus = WirelessConnectionStatus;
}
catch (Exception) {
this.IsWireless = false;
};
catch (Exception)
{
IsWireless = false;
}
}
public int WirelessConnectionStatus
{
get {
if (this.IsWireless)
get
{
if (IsWireless)
{
IntPtr handle = IntPtr.Zero;
uint negotiatedVersion;
try
{
if (NetworkInterop.WlanOpenHandle(1, IntPtr.Zero, out negotiatedVersion, ref handle) != 0)
if (NetworkInterop.WlanOpenHandle(1, IntPtr.Zero, out var negotiatedVersion, ref handle) != 0)
throw new NotSupportedException("This network adapter does not support Wireless");
IntPtr ptr = new IntPtr();
uint dataSize;
var interfaceGuid = this.Guid;
var interfaceGuid = Guid;
if (NetworkInterop.WlanQueryInterface(handle, ref interfaceGuid, NetworkInterop.WLAN_INTF_OPCODE.wlan_intf_opcode_interface_state, IntPtr.Zero, out dataSize, ref ptr, IntPtr.Zero) != 0)
if (NetworkInterop.WlanQueryInterface(handle, ref interfaceGuid, NetworkInterop.WLAN_INTF_OPCODE.wlan_intf_opcode_interface_state, IntPtr.Zero, out var dataSize, ref ptr, IntPtr.Zero) != 0)
throw new NotSupportedException("This network adapter does not support Wireless");
this.LastWirelessConnectionStatus = Marshal.ReadInt32(ptr);
LastWirelessConnectionStatus = Marshal.ReadInt32(ptr);
NetworkInterop.WlanFreeMemory(ptr);
return this.LastWirelessConnectionStatus;
return LastWirelessConnectionStatus;
}
finally
{
@@ -114,46 +111,46 @@ namespace Disco.ClientBootstrapper.Interop
}
}
public UInt16 ConnectionStatus
public ushort ConnectionStatus
{
get
{
using (var wmiObject = new ManagementObject(this.WmiPath))
using (var wmiObject = new ManagementObject(WmiPath))
{
this.LastConnectionStatus = (UInt16)wmiObject.GetPropertyValue("NetConnectionStatus");
LastConnectionStatus = (ushort)wmiObject.GetPropertyValue("NetConnectionStatus");
}
return this.LastConnectionStatus;
return LastConnectionStatus;
}
}
public string ConnectionStatusMeaning(UInt16 status)
public string ConnectionStatusMeaning(ushort status)
{
switch (status)
{
case (UInt16)0:
case (ushort)0:
return "Disconnected";
case (UInt16)1:
case (ushort)1:
return "Connecting";
case (UInt16)2:
case (ushort)2:
return "Connected";
case (UInt16)3:
case (ushort)3:
return "Disconnecting";
case (UInt16)4:
case (ushort)4:
return "Hardware not present";
case (UInt16)5:
case (ushort)5:
return "Hardware disabled";
case (UInt16)6:
case (ushort)6:
return "Hardware malfunction";
case (UInt16)7:
case (ushort)7:
return "Media disconnected";
case (UInt16)8:
case (ushort)8:
return "Authenticating";
case (UInt16)9:
case (ushort)9:
return "Authentication succeeded";
case (UInt16)10:
case (ushort)10:
return "Authentication failed";
case (UInt16)11:
case (ushort)11:
return "Invalid address";
case (UInt16)12:
case (ushort)12:
return "Credentials required";
default:
return "Unknown";
@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.NetworkInformation;
using System.Management;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Xml;
@@ -197,11 +196,10 @@ namespace Disco.ClientBootstrapper.Interop
{
IntPtr wlanHandle = IntPtr.Zero;
uint negotiatedVersion;
try
{
if (WlanOpenHandle(1, IntPtr.Zero, out negotiatedVersion, ref wlanHandle) != 0)
if (WlanOpenHandle(1, IntPtr.Zero, out var negotiatedVersion, ref wlanHandle) != 0)
throw new NotSupportedException("This device does not support Wireless");
// Add Profile to Each Wireless Adapter
@@ -212,12 +210,12 @@ namespace Disco.ClientBootstrapper.Interop
{
if (inlineWirelessProfile.AddProfile(wlanHandle, na.Guid))
{
Program.Status.UpdateStatus(null, null, string.Format("Added Wireless Profile: {0}", inlineWirelessProfile.ProfileName));
Program.Status.UpdateStatus(null, null, $"Added Wireless Profile: {inlineWirelessProfile.ProfileName}");
Program.SleepThread(500, false);
}
else
{
Program.Status.UpdateStatus(null, null, string.Format("Unable to add Wireless Profile: {0}", inlineWirelessProfile.ProfileName));
Program.Status.UpdateStatus(null, null, $"Unable to add Wireless Profile: {inlineWirelessProfile.ProfileName}");
Program.SleepThread(5000, false);
}
}
@@ -226,7 +224,7 @@ namespace Disco.ClientBootstrapper.Interop
finally
{
if (wlanHandle != IntPtr.Zero)
NetworkInterop.WlanCloseHandle(wlanHandle, IntPtr.Zero);
WlanCloseHandle(wlanHandle, IntPtr.Zero);
}
}
@@ -240,10 +238,9 @@ namespace Disco.ClientBootstrapper.Interop
public bool AddProfile(IntPtr WlanHandle, Guid interfaceGuid)
{
var pInterfaceGuid = interfaceGuid;
var pProfileXml = this.ProfileXml;
var pProfileXml = ProfileXml;
uint pFlag = 0;
uint failReason;
return (WlanSetProfile(WlanHandle, ref pInterfaceGuid, pFlag, pProfileXml, null, true, IntPtr.Zero, out failReason) == 0);
return WlanSetProfile(WlanHandle, ref pInterfaceGuid, pFlag, pProfileXml, null, true, IntPtr.Zero, out _) == 0;
}
}
@@ -280,7 +277,7 @@ namespace Disco.ClientBootstrapper.Interop
WlanGetProfileList(WlanHandle, ref pInterfaceGuid, new IntPtr(), ref ppProfileList);
WLAN_PROFILE_INFO_LIST wlanProfileInfoList = new WLAN_PROFILE_INFO_LIST(ppProfileList);
NetworkInterop.WlanFreeMemory(ppProfileList);
WlanFreeMemory(ppProfileList);
return wlanProfileInfoList;
}
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Disco.ClientBootstrapper.Interop
@@ -33,7 +30,7 @@ namespace Disco.ClientBootstrapper.Interop
private static extern int LookupPrivilegeValue(string lpsystemname, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
private static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES Newstate, int bufferlength, int PreivousState, int Returnlength);
private static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs, [MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES Newstate, int bufferlength, int PreivousState, int Returnlength);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int RegLoadKey(uint hKey, string lpSubKey, string lpFile);
@@ -61,16 +58,15 @@ namespace Disco.ClientBootstrapper.Interop
public RegistryInterop(RegistryHives hive, string subKey, string filePath)
{
int token = 0;
int retval = 0;
TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
TOKEN_PRIVILEGES TP2 = new TOKEN_PRIVILEGES();
LUID RestoreLuid = new LUID();
LUID BackupLuid = new LUID();
retval = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token);
retval = LookupPrivilegeValue(null, SE_RESTORE_NAME, ref RestoreLuid);
retval = LookupPrivilegeValue(null, SE_BACKUP_NAME, ref BackupLuid);
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token);
LookupPrivilegeValue(null, SE_RESTORE_NAME, ref RestoreLuid);
LookupPrivilegeValue(null, SE_BACKUP_NAME, ref BackupLuid);
TP.PrivilegeCount = 1;
TP.Attributes = SE_PRIVILEGE_ENABLED;
TP.Luid = RestoreLuid;
@@ -78,25 +74,25 @@ namespace Disco.ClientBootstrapper.Interop
TP2.Attributes = SE_PRIVILEGE_ENABLED;
TP2.Luid = BackupLuid;
retval = AdjustTokenPrivileges(token, 0, ref TP, 1024, 0, 0);
retval = AdjustTokenPrivileges(token, 0, ref TP2, 1024, 0, 0);
AdjustTokenPrivileges(token, 0, ref TP, 1024, 0, 0);
AdjustTokenPrivileges(token, 0, ref TP2, 1024, 0, 0);
uint regHive = (uint)hive;
this.Hive = hive;
this.SubKey = subKey;
Hive = hive;
SubKey = subKey;
RegLoadKey(regHive, subKey, filePath);
this.IsUnloaded = false;
IsUnloaded = false;
}
public void Unload()
{
if (!IsUnloaded)
{
uint regHive = (uint)this.Hive;
string subKey = this.SubKey;
uint regHive = (uint)Hive;
string subKey = SubKey;
RegUnLoadKey(regHive, subKey);
this.IsUnloaded = true;
IsUnloaded = true;
}
}
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;
namespace Disco.ClientBootstrapper.Interop
@@ -43,21 +39,20 @@ namespace Disco.ClientBootstrapper.Interop
// End Removed 2012-11-23 G#
// Added 2012-11-23 G# - Migrate to Win32 PInvoke Shutdown
bool result;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
result = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
result = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
result = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
result = ExitWindowsEx(flag, 0);
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
ExitWindowsEx(flag, 0);
// End Added 2012-11-23 G#
}
+44 -65
View File
@@ -1,10 +1,8 @@
using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
namespace Disco.ClientBootstrapper.Interop.WIMInterop
{
@@ -140,8 +138,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
CreateFileAccessPrivate fileAccess = GetMappedFileAccess(access);
if (fileAccess == CreateFileAccessPrivate.Read && (!File.Exists(imageFilePath) || (CreateFileMode.OpenExisting != mode)))
{
throw new System.UnauthorizedAccessException(string.Format(CultureInfo.CurrentCulture,
"Read access can be specified only with OpenExisting mode or OpenAlways mode when the .wim file does not exist."));
throw new UnauthorizedAccessException("Read access can be specified only with OpenExisting mode or OpenAlways mode when the .wim file does not exist.");
}
//
@@ -152,9 +149,9 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
m_ImageContainerHandle = NativeMethods.CreateFile(imageFilePath, (uint)fileAccess, (uint)mode);
m_WindowsImageFilePath = imageFilePath;
}
catch (System.DllNotFoundException ex)
catch (DllNotFoundException ex)
{
throw new System.DllNotFoundException(string.Format(CultureInfo.CurrentCulture,
throw new DllNotFoundException(string.Format(
"Unable to load WIM libraries. Make sure the correct DLLs are present (Wimgapi.dll and Xmlrw.dll)."), ex.InnerException);
}
@@ -164,7 +161,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//Set the temporary path so that we can write to an image. This
//cannot be %TEMP% as it does not exist on Windows PE
//
string tempDirectory = System.Environment.GetEnvironmentVariable("systemdrive");
string tempDirectory = Environment.GetEnvironmentVariable("systemdrive");
NativeMethods.SetTemporaryPath(m_ImageContainerHandle, tempDirectory);
}
@@ -173,8 +170,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to open the .wim file {0}.", imageFilePath));
throw new InvalidOperationException($"Unable to open the .wim file {imageFilePath}.");
}
//
@@ -481,7 +477,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//
//Never commit changes when destroying this object.
//
this.DismountImage(false);
DismountImage(false);
}
GC.KeepAlive(this);
}
@@ -576,12 +572,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//1. Leading 0xFEFF
//2. Be in <IMAGE></IMAGE>
//
string formattedXml = String.Format(CultureInfo.InvariantCulture,
"{0}{1}{2}{3}",
UNICODE_FILE_MARKER,
"<IMAGE>",
imageInformation,
"</IMAGE>");
string formattedXml = $"{UNICODE_FILE_MARKER}{"<IMAGE>"}{imageInformation}{"</IMAGE>"}";
NativeMethods.SetImageInformation(m_ImageHandle, formattedXml);
GC.KeepAlive(this);
@@ -597,7 +588,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//Mount the image
//
m_MountedPath = pathToMountTo;
NativeMethods.MountImage(pathToMountTo, m_ParentWindowsImageFilePath, m_Index, System.IO.Path.GetTempPath());
NativeMethods.MountImage(pathToMountTo, m_ParentWindowsImageFilePath, m_Index, Path.GetTempPath());
m_Mounted = true;
}
@@ -650,7 +641,8 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
///Private null constructor
///</summary>
private
NativeMethods() { }
NativeMethods()
{ }
[DllImport("Wimgapi.dll", ExactSpelling = true,
EntryPoint = "WIMCreateFile",
@@ -684,16 +676,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
IntPtr windowsImageHandle = IntPtr.Zero;
int rc = -1;
windowsImageHandle = NativeMethods.WimCreateFile(imageFile, access, mode, 0, 0, out creationResult);
windowsImageHandle = WimCreateFile(imageFile, access, mode, 0, 0, out _);
rc = Marshal.GetLastWin32Error();
if (windowsImageHandle == IntPtr.Zero)
{
//
//Everything failed; throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to open/create .wim file {0}. Error = {1}",
imageFile, rc));
throw new InvalidOperationException($"Unable to open/create .wim file {imageFile}. Error = {rc}");
}
return windowsImageHandle;
@@ -721,15 +711,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
void
CloseHandle(IntPtr handle)
{
bool status = NativeMethods.WimCloseHandle(handle);
bool status = WimCloseHandle(handle);
int rc = Marshal.GetLastWin32Error();
if (status == false)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to close image handle. Error = {0}", rc));
throw new InvalidOperationException($"Unable to close image handle. Error = {rc}");
}
}
@@ -757,14 +746,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
void
SetTemporaryPath(IntPtr handle, string temporaryPath)
{
bool status = NativeMethods.WimSetTemporaryPath(handle, temporaryPath);
bool status = WimSetTemporaryPath(handle, temporaryPath);
int rc = Marshal.GetLastWin32Error();
if (status == false)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Unable to set temporary path. Error = {0}", rc));
throw new InvalidOperationException($"Unable to set temporary path. Error = {rc}");
}
}
@@ -794,14 +783,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
{
//Load the image data based on the .wim handle
//
IntPtr hWim = NativeMethods.WimLoadImage(handle, (uint)imageIndex);
IntPtr hWim = WimLoadImage(handle, (uint)imageIndex);
int rc = Marshal.GetLastWin32Error();
if (hWim == IntPtr.Zero)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Unable to load image. Error = {0}", rc));
throw new InvalidOperationException($"Unable to load image. Error = {rc}");
}
return hWim;
@@ -832,15 +821,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
IntPtr
CaptureImage(IntPtr handle, string path)
{
IntPtr hImage = NativeMethods.WimCaptureImage(handle, path, 0);
IntPtr hImage = WimCaptureImage(handle, path, 0);
int rc = Marshal.GetLastWin32Error();
if (hImage == IntPtr.Zero)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Failed to capture image from {0}. Error = {1}", path, rc));
throw new InvalidOperationException($"Failed to capture image from {path}. Error = {rc}");
}
return hImage;
}
@@ -873,14 +861,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
int
GetImageCount(IntPtr windowsImageHandle)
{
int count = NativeMethods.WimGetImageCount(windowsImageHandle);
int count = WimGetImageCount(windowsImageHandle);
int rc = Marshal.GetLastWin32Error();
if (count == -1)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Unable to get image count. Error = {0}", rc));
throw new InvalidOperationException($"Unable to get image count. Error = {rc}");
}
return count;
@@ -971,28 +959,25 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
try
{
status = NativeMethods.WimMountImage(mountPath,
status = WimMountImage(mountPath,
windowsImageFileName,
(uint)imageIndex,
temporaryPath);
rc = Marshal.GetLastWin32Error();
}
catch (System.StackOverflowException)
catch (StackOverflowException)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to mount image {0} to {1}.", windowsImageFileName, mountPath));
throw new InvalidOperationException($"Unable to mount image {windowsImageFileName} to {mountPath}.");
}
if (status == false)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to mount image {0} to {1}. Error = {2}",
windowsImageFileName, mountPath, rc));
throw new InvalidOperationException($"Unable to mount image {windowsImageFileName} to {mountPath}. Error = {rc}");
}
}
@@ -1022,15 +1007,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//
//Call WimApplyImage always with the Index flag for performance reasons.
//
bool status = NativeMethods.WimApplyImage(imageHandle, applicationPath, NativeMethods.WIM_FLAG_INDEX);
bool status = WimApplyImage(imageHandle, applicationPath, WIM_FLAG_INDEX);
int rc = Marshal.GetLastWin32Error();
if (status == false)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to apply image to {0}. Error = {1}", applicationPath, rc));
throw new InvalidOperationException($"Unable to apply image to {applicationPath}. Error = {rc}");
}
}
@@ -1062,7 +1046,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
IntPtr info = IntPtr.Zero, sizeOfInfo = IntPtr.Zero;
bool status;
status = NativeMethods.WimGetImageInformation(handle, out info, out sizeOfInfo);
status = WimGetImageInformation(handle, out info, out _);
int rc = Marshal.GetLastWin32Error();
if (status == false)
@@ -1070,8 +1054,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to get image information. Error = {0}", rc));
throw new InvalidOperationException($"Unable to get image information. Error = {rc}");
}
string s = Marshal.PtrToStringUni(info);
@@ -1112,15 +1095,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
IntPtr xmlBuffer = Marshal.AllocHGlobal(byteBufferSize);
Marshal.Copy(byteBuffer, 0, xmlBuffer, byteBufferSize);
bool status = NativeMethods.WimSetImageInformation(handle, xmlBuffer, (uint)byteBufferSize);
bool status = WimSetImageInformation(handle, xmlBuffer, (uint)byteBufferSize);
int rc = Marshal.GetLastWin32Error();
if (status == false)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to set image information. Error = {0}", rc));
throw new InvalidOperationException($"Unable to set image information. Error = {rc}");
}
}
@@ -1153,16 +1135,15 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
try
{
status = NativeMethods.WimUnmountImage(mountPath, wimdowsImageFileName, (uint)imageIndex, commitChanges);
status = WimUnmountImage(mountPath, wimdowsImageFileName, (uint)imageIndex, commitChanges);
rc = Marshal.GetLastWin32Error();
}
catch (System.StackOverflowException ex)
catch (StackOverflowException ex)
{
//
//Throw an exception
//
throw new System.StackOverflowException(string.Format(CultureInfo.CurrentCulture,
"Unable to unmount image {0} from {1}.", wimdowsImageFileName, mountPath),
throw new StackOverflowException($"Unable to unmount image {wimdowsImageFileName} from {mountPath}.",
ex.InnerException);
}
if (status == false)
@@ -1170,9 +1151,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
"Unable to unmount image {0} from {1}. Error = {2}",
wimdowsImageFileName, mountPath, rc));
throw new InvalidOperationException($"Unable to unmount image {wimdowsImageFileName} from {mountPath}. Error = {rc}");
}
}
@@ -1221,14 +1200,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
void
RegisterCallback(MessageCallback callback)
{
uint callbackZeroBasedIndex = NativeMethods.WimRegisterMessageCallback(IntPtr.Zero, callback, IntPtr.Zero);
WimRegisterMessageCallback(IntPtr.Zero, callback, IntPtr.Zero);
int rc = Marshal.GetLastWin32Error();
if (rc != 0)
{
//
//Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Unable to register message callback."));
throw new InvalidOperationException("Unable to register message callback.");
}
}
@@ -1253,14 +1232,14 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
void
UnregisterMessageCallback(MessageCallback registeredCallback)
{
bool status = NativeMethods.WimUnregisterMessageCallback(IntPtr.Zero, registeredCallback);
int rc = Marshal.GetLastWin32Error();
bool status = WimUnregisterMessageCallback(IntPtr.Zero, registeredCallback);
_ = Marshal.GetLastWin32Error();
if (status != true)
{
//
// Throw an exception
//
throw new System.InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Unable to unregister message callback."));
throw new InvalidOperationException("Unable to unregister message callback.");
}
}
@@ -1358,13 +1337,13 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
fileAccess = CreateFileAccessPrivate.Write;
break;
default:
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "No file access level specified."));
throw new ArgumentException("No file access level specified.");
}
return fileAccess;
}
//[CLSCompliant(false)]
[FlagsAttribute]
[Flags]
private
enum
CreateFileAccessPrivate : uint
@@ -1436,7 +1415,7 @@ namespace Disco.ClientBootstrapper.Interop.WIMInterop
///Abort.
///</summary>
Abort = NativeMethods.WIMMessage.WIM_MSG_ABORT_IMAGE,
MountCleanupProgress = NativeMethods.WIMMessage.WIM_MSG_MOUNT_CLEANUP_PROGRESS
}
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.ClientBootstrapper
namespace Disco.ClientBootstrapper
{
class NullStatus : IStatus
{
+17 -18
View File
@@ -86,15 +86,15 @@ namespace Disco.ClientBootstrapper
{
try
{
string AppErrorPath = string.Format("{0}{1}", System.Reflection.Assembly.GetExecutingAssembly().Location, ".errors.txt");
string AppErrorPath = $"{System.Reflection.Assembly.GetExecutingAssembly().Location}.errors.txt";
System.Text.StringBuilder ErrorMessage = new System.Text.StringBuilder();
ErrorMessage.AppendLine();
ErrorMessage.AppendLine(DateTime.Now.ToLongDateString());
ErrorMessage.AppendLine(DateTime.Now.ToLongTimeString());
ErrorMessage.AppendLine(string.Format("Type: {0}", ex.GetType().FullName));
ErrorMessage.AppendLine(string.Format("Message: {0}", ex.Message));
ErrorMessage.AppendLine(string.Format("Source: {0}", ex.Source));
ErrorMessage.AppendLine(string.Format("Stack: {0}", ex.StackTrace));
ErrorMessage.AppendLine($"Type: {ex.GetType().FullName}");
ErrorMessage.AppendLine($"Message: {ex.Message}");
ErrorMessage.AppendLine($"Source: {ex.Source}");
ErrorMessage.AppendLine($"Stack: {ex.StackTrace}");
System.IO.File.AppendAllText(AppErrorPath, ErrorMessage.ToString());
}
catch (Exception) { }
@@ -118,18 +118,17 @@ namespace Disco.ClientBootstrapper
SleepThread(4000, true);
Interop.ShutdownInterop.Shutdown();
}
else if (PostBootstrapperActions.Contains("Reboot"))
{
Status.UpdateStatus("System Preparation (Bootstrapper)", "Rebooting; Finished...", string.Empty, false, 0);
SleepThread(4000, true);
Interop.ShutdownInterop.Reboot();
}
else
if (PostBootstrapperActions.Contains("Reboot"))
{
Status.UpdateStatus("System Preparation (Bootstrapper)", "Rebooting; Finished...", string.Empty, false, 0);
SleepThread(4000, true);
Interop.ShutdownInterop.Reboot();
}
else
{
Status.UpdateStatus("System Preparation (Bootstrapper)", "Starting System; Finished...", string.Empty, false, 0);
SleepThread(2000, true);
}
{
Status.UpdateStatus("System Preparation (Bootstrapper)", "Starting System; Finished...", string.Empty, false, 0);
SleepThread(2000, true);
}
}
else
{
@@ -154,11 +153,11 @@ namespace Disco.ClientBootstrapper
{
if (BootstrapperLoop.LoopThread != null)
{
if (BootstrapperLoop.LoopThread.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
if (BootstrapperLoop.LoopThread.ThreadState == ThreadState.WaitSleepJoin)
{
BootstrapperLoop.LoopThread.Interrupt();
}
if (BootstrapperLoop.LoopThread.ThreadState == System.Threading.ThreadState.Running)
if (BootstrapperLoop.LoopThread.ThreadState == ThreadState.Running)
{
BootstrapperLoop.LoopThread.Abort();
}
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.4.24270.0000")]
[assembly: AssemblyVersion("2.5.25262.0000")]
[assembly: AssemblyFileVersion("2.5.25262.0000")]
+13 -13
View File
@@ -28,17 +28,17 @@ namespace Disco.Data.Configuration
{
get
{
return ConfigurationCache.GetScopeKeys(Database, this.Scope);
return ConfigurationCache.GetScopeKeys(Database, Scope);
}
}
private void SetValue<T>(string Key, T Value)
{
ConfigurationCache.Helpers<T>.SetValue(Database, this.Scope, Key, Value);
ConfigurationCache.Helpers<T>.SetValue(Database, Scope, Key, Value);
}
private T GetValue<T>(string Key, T Default)
{
return ConfigurationCache.Helpers<T>.GetValue(Database, this.Scope, Key, Default);
return ConfigurationCache.Helpers<T>.GetValue(Database, Scope, Key, Default);
}
protected void Set<T>(T Value, [CallerMemberName] string Key = null)
@@ -46,7 +46,7 @@ namespace Disco.Data.Configuration
if (Key == null)
throw new ArgumentNullException("Key");
this.SetValue(Key, Value);
SetValue(Key, Value);
}
protected T Get<T>(T Default, [CallerMemberName] string Key = null)
@@ -54,17 +54,17 @@ namespace Disco.Data.Configuration
if (Key == null)
throw new ArgumentNullException("Key");
return this.GetValue(Key, Default);
return GetValue(Key, Default);
}
protected void SetObsfucated(string Value, [CallerMemberName] string Key = null)
{
this.Set(Value.Obsfucate(), Key);
Set(Value.Obsfucate(), Key);
}
protected string GetDeobsfucated(string Default, [CallerMemberName] string Key = null)
{
var obsfucatedValue = this.Get<string>(null, Key);
var obsfucatedValue = Get<string>(null, Key);
if (obsfucatedValue == null)
return Default;
@@ -74,35 +74,35 @@ namespace Disco.Data.Configuration
protected void RemoveScope()
{
ConfigurationCache.RemoveScope(Database, this.Scope);
ConfigurationCache.RemoveScope(Database, Scope);
}
protected void RemoveItem(string Key)
{
ConfigurationCache.RemoveScopeKey(Database, this.Scope, Key);
ConfigurationCache.RemoveScopeKey(Database, Scope, Key);
}
[Obsolete("Types are automatically serialized/deserialized if required, use Set<T>(T Value) instead.")]
protected void SetAsJson<T>(T Value, [CallerMemberName] string Key = null)
{
this.Set(Value, Key);
Set(Value, Key);
}
[Obsolete("Types are automatically serialized/deserialized if required, use Get<T>(T Default) instead.")]
protected T GetFromJson<T>(T Default, [CallerMemberName] string Key = null)
{
return this.Get(Default, Key);
return Get(Default, Key);
}
[Obsolete("Types are automatically serialized/deserialized if required, use Set<T>(T Value) instead.")]
protected void SetAsEnum<T>(T Value, [CallerMemberName] string Key = null)
{
this.Set(Value, Key);
Set(Value, Key);
}
[Obsolete("Types are automatically serialized/deserialized if required, use Set<T>(T Value) instead.")]
protected T GetFromEnum<T>(T Default, [CallerMemberName] string Key = null)
{
return this.Get(Default, Key);
return Get(Default, Key);
}
}
}
+72 -40
View File
@@ -22,11 +22,11 @@ namespace Disco.Data.Configuration
private static ConfigurationCacheType Cache(DiscoDataContext Database)
{
if (ConfigurationCache.cacheStore == null)
if (cacheStore == null)
{
lock (configChangeLock)
{
if (ConfigurationCache.cacheStore == null)
if (cacheStore == null)
{
if (Database == null)
throw new InvalidOperationException("The Configuration must be loaded at least once before a Cache-Only Configuration Context is used");
@@ -46,18 +46,16 @@ namespace Disco.Data.Configuration
}
}
return ConfigurationCache.cacheStore;
return cacheStore;
}
private static ConfigurationCacheItemType CacheGetItem(DiscoDataContext Database, string Scope, string Key)
{
var cache = Cache(Database);
ConfigurationCacheScopeType scopeCache;
if (cache.TryGetValue(Scope, out scopeCache))
if (cache.TryGetValue(Scope, out var scopeCache))
{
ConfigurationCacheItemType item = default(ConfigurationCacheItemType);
if (scopeCache.TryGetValue(Key, out item))
if (scopeCache.TryGetValue(Key, out var item))
return item;
}
@@ -93,8 +91,7 @@ namespace Disco.Data.Configuration
Database.ConfigurationItems.Add(configItem);
// Add Item to Cache
ConfigurationCacheScopeType scopeCache;
if (!cacheStore.TryGetValue(Scope, out scopeCache))
if (!cacheStore.TryGetValue(Scope, out var scopeCache))
{
scopeCache = new ConfigurationCacheScopeType();
cacheStore.TryAdd(Scope, scopeCache);
@@ -134,10 +131,9 @@ namespace Disco.Data.Configuration
Database.ConfigurationItems.Remove(configItem);
// Remove item from Cache
ConfigurationCacheScopeType scopeCache;
if (cacheStore.TryGetValue(Scope, out scopeCache))
if (cacheStore.TryGetValue(Scope, out var scopeCache))
{
scopeCache.TryRemove(Key, out item);
scopeCache.TryRemove(Key, out _);
}
return null;
@@ -148,8 +144,7 @@ namespace Disco.Data.Configuration
configItem.Value = Value;
// Update Cache
ConfigurationCacheScopeType scopeCache;
if (cacheStore.TryGetValue(Scope, out scopeCache))
if (cacheStore.TryGetValue(Scope, out var scopeCache))
{
scopeCache.TryRemove(Key, out item);
item = new ConfigurationCacheItemType(configItem, ObjectValue);
@@ -165,10 +160,9 @@ namespace Disco.Data.Configuration
}
private static ConfigurationCacheItemType SetItemTypeValue(ConfigurationCacheItemType ExistingItem, object Value)
{
var cache = ConfigurationCache.cacheStore;
var cache = cacheStore;
ConfigurationCacheScopeType scopeCache;
if (cache.TryGetValue(ExistingItem.Item1.Scope, out scopeCache))
if (cache.TryGetValue(ExistingItem.Item1.Scope, out var scopeCache))
{
ConfigurationCacheItemType newItem = new ConfigurationCacheItemType(ExistingItem.Item1, Value);
scopeCache.TryUpdate(ExistingItem.Item1.Key, newItem, ExistingItem);
@@ -183,18 +177,18 @@ namespace Disco.Data.Configuration
#region Helpers
private static bool IsConvertableFromString(Type t)
{
if (t == typeof(Boolean) ||
t == typeof(Char) ||
t == typeof(SByte) ||
t == typeof(Byte) ||
t == typeof(Int16) || t == typeof(UInt16) ||
t == typeof(Int32) || t == typeof(UInt32) ||
t == typeof(Int64) || t == typeof(UInt64) ||
t == typeof(Single) ||
t == typeof(Double) ||
t == typeof(Decimal) ||
if (t == typeof(bool) ||
t == typeof(char) ||
t == typeof(sbyte) ||
t == typeof(byte) ||
t == typeof(short) || t == typeof(ushort) ||
t == typeof(int) || t == typeof(uint) ||
t == typeof(long) || t == typeof(ulong) ||
t == typeof(float) ||
t == typeof(double) ||
t == typeof(decimal) ||
t == typeof(DateTime) ||
t == typeof(String))
t == typeof(string))
return true;
else
return false;
@@ -242,9 +236,34 @@ namespace Disco.Data.Configuration
}
else if (itemType.BaseType != null && itemType.BaseType == typeof(Enum))
{
// Enum
// enum
itemValue = Enum.Parse(typeof(T), item.Item1.Value);
}
else if (itemType.IsGenericType &&
itemType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
IsConvertableFromString(Nullable.GetUnderlyingType(itemType)))
{
// nullable
itemValue = (T)Convert.ChangeType(item.Item1.Value, Nullable.GetUnderlyingType(itemType));
}
else if (itemType == typeof(Guid))
{
// guid
itemValue = new Guid(item.Item1.Value);
}
else if (itemType == typeof(Guid?))
{
// guid
if (string.IsNullOrEmpty(item.Item1.Value))
itemValue = null;
else
itemValue = new Guid(item.Item1.Value);
}
else if (itemType == typeof(byte[]))
{
// byte[]
itemValue = Convert.FromBase64String(item.Item1.Value);
}
else
{
// JSON Deserialize
@@ -263,13 +282,13 @@ namespace Disco.Data.Configuration
Type valueType = typeof(T);
string stringValue;
if (comparer.Equals(Value, default(T)))
if (comparer.Equals(Value, default))
{
stringValue = null;
}
else if (valueType == typeof(object))
{
throw new ArgumentException(string.Format("Cannot serialize the configuration item [{0}].[{1}] which defines a type of [System.Object]", Scope, Key), "Value");
throw new ArgumentException($"Cannot serialize the configuration item [{Scope}].[{Key}] which has the type [System.Object]", "Value");
}
else if (IsConvertableFromString(valueType))
{
@@ -278,9 +297,25 @@ namespace Disco.Data.Configuration
}
else if (valueType.BaseType != null && valueType.BaseType == typeof(Enum))
{
// Enum
// enum
stringValue = Value.ToString();
}
else if (valueType.IsGenericType &&
valueType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
IsConvertableFromString(Nullable.GetUnderlyingType(valueType)))
{
// nullable
stringValue = Value.ToString();
}
else if (valueType == typeof(Guid) || valueType == typeof(Guid?))
{
stringValue = Value.ToString();
}
else if (Value is byte[] valueBytes)
{
// byte[]
stringValue = Convert.ToBase64String(valueBytes);
}
else
{
// JSON Serialize
@@ -290,7 +325,7 @@ namespace Disco.Data.Configuration
CacheSetItem(Database, Scope, Key, stringValue, Value);
}
}
#endregion
#region Cache Helpers
@@ -299,8 +334,7 @@ namespace Disco.Data.Configuration
{
var cache = Cache(Database);
ConfigurationCacheScopeType scopeCache;
if (cache.TryGetValue(Scope, out scopeCache))
if (cache.TryGetValue(Scope, out var scopeCache))
{
return scopeCache.Keys.ToList();
}
@@ -324,8 +358,7 @@ namespace Disco.Data.Configuration
// Remove item from Cache
if (cacheStore != null)
{
ConfigurationCacheScopeType scopeCache;
cacheStore.TryRemove(Scope, out scopeCache);
cacheStore.TryRemove(Scope, out var scopeCache);
}
}
}
@@ -365,10 +398,9 @@ namespace Disco.Data.Configuration
// Remove item from Cache
if (cacheItem != null)
{
ConfigurationCacheScopeType scopeCache;
if (cacheStore.TryGetValue(Scope, out scopeCache))
if (cacheStore.TryGetValue(Scope, out var scopeCache))
{
scopeCache.TryRemove(Key, out cacheItem);
scopeCache.TryRemove(Key, out _);
}
}
}
@@ -35,7 +35,8 @@ namespace Disco.Data.Configuration.Modules
public bool? SearchAllServers
{
get {
get
{
var value = Get<bool?>(null);
/// migrate <see cref="SearchAllForestServers"/>
@@ -0,0 +1,18 @@
using Disco.Data.Repository;
using Disco.Models.Services.Devices.DeviceFlag;
namespace Disco.Data.Configuration.Modules
{
public class DeviceFlagsConfiguration : ConfigurationBase
{
public DeviceFlagsConfiguration(DiscoDataContext database) : base(database) { }
public override string Scope { get; } = "DeviceFlags";
public DeviceFlagExportOptions LastExportOptions
{
get => Get(DeviceFlagExportOptions.DefaultOptions());
set => Set(value);
}
}
}
@@ -7,13 +7,13 @@ namespace Disco.Data.Configuration.Modules
{
public DeviceProfilesConfiguration(DiscoDataContext Database) : base(Database) { }
public override string Scope { get { return "DeviceProfiles"; } }
public override string Scope { get; } = "DeviceProfiles";
public int DefaultDeviceProfileId
{
get
{
var v = this.Get(1);
var v = Get(1);
if (v > 0)
return v;
else
@@ -24,21 +24,21 @@ namespace Disco.Data.Configuration.Modules
if (value < 1)
throw new ArgumentOutOfRangeException("value", "Expected >= 1");
this.Set(value);
Set(value);
}
}
public int DefaultAddDeviceOfflineDeviceProfileId
{
get
{
return this.Get(0);
return Get(0);
}
set
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "Expected >= 0");
this.Set(value);
Set(value);
}
}
@@ -1,5 +1,5 @@
using Disco.Data.Repository;
using Disco.Models.Services.Devices.Exporting;
using Disco.Models.Services.Devices;
namespace Disco.Data.Configuration.Modules
{
@@ -7,12 +7,12 @@ namespace Disco.Data.Configuration.Modules
{
public DevicesConfiguration(DiscoDataContext Database) : base(Database) { }
public override string Scope { get { return "Devices"; } }
public override string Scope { get; } = "Devices";
public DeviceExportOptions LastExportOptions
{
get { return this.Get<DeviceExportOptions>(DeviceExportOptions.DefaultOptions()); }
set { this.Set(value); }
get => Get(DeviceExportOptions.DefaultOptions());
set => Set(value);
}
}
}
@@ -8,12 +8,18 @@ namespace Disco.Data.Configuration.Modules
{
public DocumentsConfiguration(DiscoDataContext Database) : base(Database) { }
public override string Scope { get { return "Documents"; } }
public override string Scope { get; } = "Documents";
public List<DocumentTemplatePackage> Packages
{
get { return Get<List<DocumentTemplatePackage>>(null); }
set { Set(value); }
}
public DocumentExportOptions LastExportOptions
{
get => Get(DocumentExportOptions.DefaultOptions());
set => Set(value);
}
}
}
@@ -1,5 +1,5 @@
using Disco.Data.Repository;
using Disco.Models.Services.Job;
using Disco.Models.Services.Jobs;
using System;
using System.Collections.Generic;
@@ -9,18 +9,27 @@ namespace Disco.Data.Configuration.Modules
{
public JobPreferencesConfiguration(DiscoDataContext Database) : base(Database) { }
public override string Scope { get { return "JobPreferences"; } }
public override string Scope { get; } = "JobPreferences";
/// <summary>
/// Initial comments template for new jobs
/// </summary>
public string InitialCommentsTemplate
{
get => Get<string>(null);
set => Set(value);
}
/// <summary>
/// Number of days a job is open before it is considered 'Long Running'
/// </summary>
public int LongRunningJobDaysThreshold
{
get { return Get<int>(7); }
get => Get(7);
set
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "The Long Running Job Days Threshold cannot be less than zero");
throw new ArgumentOutOfRangeException(nameof(value), "The Long Running Job Days Threshold cannot be less than zero");
Set(value);
}
@@ -31,27 +40,33 @@ namespace Disco.Data.Configuration.Modules
/// </summary>
public int StaleJobMinutesThreshold
{
get { return Get<int>(60 * 24 * 2); } // Default to 48 Hours (2 days)
get => Get(60 * 24 * 2); // Default to 48 Hours (2 days)
set
{
if (value < 0)
throw new ArgumentOutOfRangeException("value", "The Stale Job Minutes Threshold cannot be less than zero");
throw new ArgumentOutOfRangeException(nameof(value), "The Stale Job Minutes Threshold cannot be less than zero");
Set(value);
}
}
public bool LodgmentIncludeAllAttachmentsByDefault
{
get => Get(false);
set => Set(value);
}
/// <summary>
/// Theme used in noticeboards by default.
/// <see cref="Disco.Services.Extensions.UIHelpers.NoticeboardThemes"/>
/// </summary>
public string DefaultNoticeboardTheme
{
get { return Get("default"); }
get => Get("default");
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException("DefaultNoticeboardTheme");
throw new ArgumentNullException(nameof(DefaultNoticeboardTheme));
Set(value);
}
@@ -59,32 +74,48 @@ namespace Disco.Data.Configuration.Modules
public LocationModes LocationMode
{
get { return Get(LocationModes.Unrestricted); }
set { Set(value); }
get => Get(LocationModes.Unrestricted);
set => Set(value);
}
public List<string> LocationList
{
get { return Get(new List<string>()); }
set { Set(value); }
get => Get(new List<string>());
set => Set(value);
}
public string OnCreateExpression
{
get { return Get<string>(null); }
set { Set(value); }
get => Get<string>(null);
set => Set(value);
}
public string OnDeviceReadyForReturnExpression
{
get { return Get<string>(null); }
set { Set(value); }
get => Get<string>(null);
set => Set(value);
}
public string OnCloseExpression
{
get { return Get<string>(null); }
set { Set(value); }
get => Get<string>(null);
set => Set(value);
}
public JobExportOptions LastExportOptions
{
get => Get(JobExportOptions.DefaultOptions());
set
{
Set(value);
LastExportDate = DateTime.Now;
}
}
public DateTime? LastExportDate
{
get => Get<DateTime?>(null);
set => Set(value);
}
}
}
@@ -1,6 +1,5 @@
using Disco.Data.Repository;
using Disco.Models.BI.Config;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
@@ -8,11 +7,9 @@ namespace Disco.Data.Configuration.Modules
{
public class OrganisationAddressesConfiguration : ConfigurationBase
{
private const string scope = "OrganisationAddresses";
public OrganisationAddressesConfiguration(DiscoDataContext Database) : base(Database) { }
public override string Scope { get { return scope; } }
public override string Scope { get; } = "OrganisationAddresses";
public OrganisationAddress GetAddress(int Id)
{
@@ -58,19 +55,5 @@ namespace Disco.Data.Configuration.Modules
}
}
internal static void MigrateDatabase(DiscoDataContext Database)
{
// Migrate all organisation addresses to JSON
if (Database.ConfigurationItems.Count(i => i.Scope == scope && !i.Value.StartsWith("{")) > 0)
{
var items = Database.ConfigurationItems.Where(i => i.Scope == scope && !i.Value.StartsWith("{")).ToList();
items.ForEach(i =>
{
i.Value = JsonConvert.SerializeObject(OrganisationAddress.FromConfigurationEntry(int.Parse(i.Key), i.Value));
});
Database.SaveChanges();
}
}
}
}
@@ -0,0 +1,18 @@
using Disco.Data.Repository;
using Disco.Models.Services.Users.UserFlags;
namespace Disco.Data.Configuration.Modules
{
public class UserFlagsConfiguration : ConfigurationBase
{
public UserFlagsConfiguration(DiscoDataContext database) : base(database) { }
public override string Scope { get; } = "UserFlags";
public UserFlagExportOptions LastExportOptions
{
get => Get(UserFlagExportOptions.DefaultOptions());
set => Set(value);
}
}
}
+68 -93
View File
@@ -1,6 +1,8 @@
using Disco.Data.Repository;
using Disco.Models.Services.Exporting;
using Disco.Models.Services.Interop.DiscoServices;
using System;
using System.Collections.Generic;
using System.IO;
namespace Disco.Data.Configuration
@@ -18,6 +20,8 @@ namespace Disco.Data.Configuration
moduleActiveDirectoryConfiguration = new Lazy<Modules.ActiveDirectoryConfiguration>(() => new Modules.ActiveDirectoryConfiguration(Database));
moduleDevicesConfiguration = new Lazy<Modules.DevicesConfiguration>(() => new Modules.DevicesConfiguration(Database));
moduleDocumentsConfiguration = new Lazy<Modules.DocumentsConfiguration>(() => new Modules.DocumentsConfiguration(Database));
moduleUserFlagsConfiguration = new Lazy<Modules.UserFlagsConfiguration>(() => new Modules.UserFlagsConfiguration(Database));
moduleDeviceFlagsConfiguration = new Lazy<Modules.DeviceFlagsConfiguration>(() => new Modules.DeviceFlagsConfiguration(Database));
}
#region Configuration Modules
@@ -29,61 +33,22 @@ namespace Disco.Data.Configuration
private Lazy<Modules.ActiveDirectoryConfiguration> moduleActiveDirectoryConfiguration;
private Lazy<Modules.DevicesConfiguration> moduleDevicesConfiguration;
private Lazy<Modules.DocumentsConfiguration> moduleDocumentsConfiguration;
private Lazy<Modules.UserFlagsConfiguration> moduleUserFlagsConfiguration;
private Lazy<Modules.DeviceFlagsConfiguration> moduleDeviceFlagsConfiguration;
public Modules.BootstrapperConfiguration Bootstrapper
{
get
{
return moduleBootstrapperConfiguration.Value;
}
}
public Modules.DeviceProfilesConfiguration DeviceProfiles
{
get
{
return moduleDeviceProfilesConfiguration.Value;
}
}
public Modules.OrganisationAddressesConfiguration OrganisationAddresses
{
get
{
return moduleOrganisationAddressesConfiguration.Value;
}
}
public Modules.JobPreferencesConfiguration JobPreferences
{
get
{
return moduleJobPreferencesConfiguration.Value;
}
}
public Modules.ActiveDirectoryConfiguration ActiveDirectory
{
get
{
return moduleActiveDirectoryConfiguration.Value;
}
}
public Modules.DevicesConfiguration Devices
{
get
{
return moduleDevicesConfiguration.Value;
}
}
public Modules.DocumentsConfiguration Documents
{
get
{
return moduleDocumentsConfiguration.Value;
}
}
public Modules.BootstrapperConfiguration Bootstrapper => moduleBootstrapperConfiguration.Value;
public Modules.DeviceProfilesConfiguration DeviceProfiles => moduleDeviceProfilesConfiguration.Value;
public Modules.OrganisationAddressesConfiguration OrganisationAddresses => moduleOrganisationAddressesConfiguration.Value;
public Modules.JobPreferencesConfiguration JobPreferences => moduleJobPreferencesConfiguration.Value;
public Modules.ActiveDirectoryConfiguration ActiveDirectory => moduleActiveDirectoryConfiguration.Value;
public Modules.DevicesConfiguration Devices => moduleDevicesConfiguration.Value;
public Modules.DocumentsConfiguration Documents => moduleDocumentsConfiguration.Value;
public Modules.UserFlagsConfiguration UserFlags => moduleUserFlagsConfiguration.Value;
public Modules.DeviceFlagsConfiguration DeviceFlags => moduleDeviceFlagsConfiguration.Value;
#endregion
public override string Scope { get { return "System"; } }
public override string Scope { get; } = "System";
public string DataStoreLocation
{
@@ -93,26 +58,27 @@ namespace Disco.Data.Configuration
if (result == null)
{
var appDataPath = System.Web.HttpContext.Current.Server.MapPath("~/App_Data");
if (appDataPath.EndsWith("\\"))
return appDataPath;
else
return string.Concat(appDataPath, '\\');
if (!appDataPath.EndsWith(@"\"))
appDataPath += @"\";
return appDataPath;
}
else
return result;
}
set
{
if (value == null)
throw new ArgumentNullException("value");
if (!System.IO.Directory.Exists(value))
throw new System.IO.DirectoryNotFoundException(string.Format("DataStoreLocation: '{0}' could not be found", value));
string storePath;
if (value.EndsWith("\\"))
storePath = value;
else
storePath = string.Concat(value, '\\');
Set(storePath);
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException(nameof(value));
if (!Directory.Exists(value))
throw new DirectoryNotFoundException($"DataStoreLocation: '{value}' could not be found");
if (!value.EndsWith(@"\"))
value += @"\";
Set(value);
}
}
@@ -129,30 +95,10 @@ namespace Disco.Data.Configuration
}
#region Plugin Locations
public string PluginsLocation
{
get
{
return System.IO.Path.Combine(DataStoreLocation, @"Plugins\");
}
}
public string PluginStorageLocation
{
get
{
return System.IO.Path.Combine(DataStoreLocation, @"PluginStorage\");
}
}
public string PluginPackagesLocation
{
get
{
return System.IO.Path.Combine(DataStoreLocation, @"PluginPackages\");
}
}
public string PluginUserPhotosLocation
=> Path.Combine(DataStoreLocation, @"PluginUserPhotos\");
public string PluginsLocation => Path.Combine(DataStoreLocation, @"Plugins\");
public string PluginStorageLocation => Path.Combine(DataStoreLocation, @"PluginStorage\");
public string PluginPackagesLocation => Path.Combine(DataStoreLocation, @"PluginPackages\");
public string PluginUserPhotosLocation => Path.Combine(DataStoreLocation, @"PluginUserPhotos\");
public DateTime PluginDetailsCacheExpiration
{
@@ -167,7 +113,7 @@ namespace Disco.Data.Configuration
{
get
{
return System.IO.Path.Combine(DataStoreLocation, "OrganisationLogo.png");
return Path.Combine(DataStoreLocation, "OrganisationLogo.png");
}
}
public string OrganisationLogoHash
@@ -189,15 +135,15 @@ namespace Disco.Data.Configuration
if (File.Exists(path))
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
else
return new MemoryStream(Disco.Data.Properties.Resources.EmptyLogo);
return new MemoryStream(Properties.Resources.EmptyLogo);
}
set
{
string organisationLogoPath = OrganisationLogoPath;
if (value == null)
{
if (System.IO.File.Exists(organisationLogoPath))
System.IO.File.Delete(organisationLogoPath);
if (File.Exists(organisationLogoPath))
File.Delete(organisationLogoPath);
}
else
{
@@ -319,6 +265,29 @@ namespace Disco.Data.Configuration
#endregion
#region UpdateCheck
public bool IsActivated => ActivationId.HasValue;
public DateTime? ActivatedOn
{
get => Get((DateTime?)null);
set => Set(value);
}
public string ActivatedBy
{
get => Get((string)null);
set => Set(value);
}
public Guid? ActivationId
{
get => Get((Guid?)null);
set => Set(value);
}
public byte[] ActivationKey
{
get => Get((byte[])null);
set => Set(value);
}
public bool IsLicensed
{
get => LicenseKey != null && LicenseExpiresOn != null && LicenseExpiresOn > DateTime.UtcNow && LicenseError == null;
@@ -379,5 +348,11 @@ namespace Disco.Data.Configuration
}
#endregion
public List<SavedExport> SavedExports
{
get => Get(new List<SavedExport>());
set => Set(value);
}
}
}
+44
View File
@@ -77,6 +77,8 @@
<Compile Include="Configuration\ConfigurationCache.cs" />
<Compile Include="Configuration\Modules\ActiveDirectoryConfiguration.cs" />
<Compile Include="Configuration\Modules\DevicesConfiguration.cs" />
<Compile Include="Configuration\Modules\DeviceFlagsConfiguration.cs" />
<Compile Include="Configuration\Modules\UserFlagsConfiguration.cs" />
<Compile Include="Configuration\Modules\DocumentsConfiguration.cs" />
<Compile Include="Configuration\Modules\JobPreferencesConfiguration.cs" />
<Compile Include="Configuration\SystemConfiguration.cs" />
@@ -183,6 +185,30 @@
<Compile Include="Migrations\202403030134280_DBv24.Designer.cs">
<DependentUpon>202403030134280_DBv24.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\202412180604170_DBv25.cs" />
<Compile Include="Migrations\202412180604170_DBv25.Designer.cs">
<DependentUpon>202412180604170_DBv25.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\202503140520548_DBv26.cs" />
<Compile Include="Migrations\202503140520548_DBv26.Designer.cs">
<DependentUpon>202503140520548_DBv26.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\202507110430252_DBv27.cs" />
<Compile Include="Migrations\202507110430252_DBv27.Designer.cs">
<DependentUpon>202507110430252_DBv27.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\202507170522576_DBv28.cs" />
<Compile Include="Migrations\202507170522576_DBv28.Designer.cs">
<DependentUpon>202507170522576_DBv28.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\202509070209304_DBv29.cs" />
<Compile Include="Migrations\202509070209304_DBv29.Designer.cs">
<DependentUpon>202509070209304_DBv29.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\202509180416385_DBv30.cs" />
<Compile Include="Migrations\202509180416385_DBv30.Designer.cs">
<DependentUpon>202509180416385_DBv30.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\Configuration.cs" />
<Compile Include="Migrations\DiscoDataMigrator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -270,6 +296,24 @@
<EmbeddedResource Include="Migrations\202403030134280_DBv24.resx">
<DependentUpon>202403030134280_DBv24.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202412180604170_DBv25.resx">
<DependentUpon>202412180604170_DBv25.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202503140520548_DBv26.resx">
<DependentUpon>202503140520548_DBv26.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202507110430252_DBv27.resx">
<DependentUpon>202507110430252_DBv27.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202507170522576_DBv28.resx">
<DependentUpon>202507170522576_DBv28.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202509070209304_DBv29.resx">
<DependentUpon>202509070209304_DBv29.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Migrations\202509180416385_DBv30.resx">
<DependentUpon>202509180416385_DBv30.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv25 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv25));
string IMigrationMetadata.Id
{
get { return "202412180604170_DBv25"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,26 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv25 : DbMigration
{
public override void Up()
{
AlterColumn("dbo.UserAttachments", "Comments", c => c.String(maxLength: 500));
AlterColumn("dbo.JobAttachments", "Comments", c => c.String(maxLength: 500));
AlterColumn("dbo.DeviceAttachments", "Comments", c => c.String(maxLength: 500));
Sql("DELETE [dbo].[Configuration] WHERE [Scope]='System' AND [Key] IN ('ActivatedOn', 'ActivationId', 'LicenseExpiresOn')");
Sql("DELETE [dbo].[Configuration] WHERE [Scope]='DocFill' AND [Key] IN ('LicenseExpiresOn')");
Sql("DELETE [dbo].[Configuration] WHERE [Scope]='JobPreferences' AND [Key] IN ('LastExportDate')");
}
public override void Down()
{
AlterColumn("dbo.DeviceAttachments", "Comments", c => c.String(nullable: false, maxLength: 500));
AlterColumn("dbo.JobAttachments", "Comments", c => c.String(nullable: false, maxLength: 500));
AlterColumn("dbo.UserAttachments", "Comments", c => c.String(nullable: false, maxLength: 500));
}
}
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv26 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv26));
string IMigrationMetadata.Id
{
get { return "202503140520548_DBv26"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,18 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv26 : DbMigration
{
public override void Up()
{
AlterColumn("dbo.DeviceBatchAttachments", "Comments", c => c.String(maxLength: 500));
}
public override void Down()
{
AlterColumn("dbo.DeviceBatchAttachments", "Comments", c => c.String(nullable: false, maxLength: 500));
}
}
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv27 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv27));
string IMigrationMetadata.Id
{
get { return "202507110430252_DBv27"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,58 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv27 : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.UserComments",
c => new
{
Id = c.Int(nullable: false, identity: true),
UserId = c.String(maxLength: 50),
TechUserId = c.String(nullable: false, maxLength: 50),
Timestamp = c.DateTime(nullable: false),
Comments = c.String(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Users", t => t.TechUserId)
.ForeignKey("dbo.Users", t => t.UserId)
.Index(t => t.TechUserId)
.Index(t => t.UserId);
CreateTable(
"dbo.DeviceComments",
c => new
{
Id = c.Int(nullable: false, identity: true),
DeviceSerialNumber = c.String(maxLength: 60),
TechUserId = c.String(nullable: false, maxLength: 50),
Timestamp = c.DateTime(nullable: false),
Comments = c.String(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Users", t => t.TechUserId)
.ForeignKey("dbo.Devices", t => t.DeviceSerialNumber)
.Index(t => t.TechUserId)
.Index(t => t.DeviceSerialNumber);
}
public override void Down()
{
DropIndex("dbo.DeviceComments", new[] { "DeviceSerialNumber" });
DropIndex("dbo.DeviceComments", new[] { "TechUserId" });
DropIndex("dbo.UserComments", new[] { "UserId" });
DropIndex("dbo.UserComments", new[] { "TechUserId" });
DropForeignKey("dbo.DeviceComments", "DeviceSerialNumber", "dbo.Devices");
DropForeignKey("dbo.DeviceComments", "TechUserId", "dbo.Users");
DropForeignKey("dbo.UserComments", "UserId", "dbo.Users");
DropForeignKey("dbo.UserComments", "TechUserId", "dbo.Users");
DropTable("dbo.DeviceComments");
DropTable("dbo.UserComments");
}
}
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv28 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv28));
string IMigrationMetadata.Id
{
get { return "202507170522576_DBv28"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,40 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv28 : DbMigration
{
public override void Up()
{
AddColumn("dbo.UserFlagAssignments", "RemoveDate", c => c.DateTime());
AddColumn("dbo.UserFlagAssignments", "RemoveUserId", c => c.String(maxLength: 50));
AddColumn("dbo.UserFlags", "Permissions", c => c.String());
AddColumn("dbo.UserFlags", "DefaultRemoveDays", c => c.Int());
AddColumn("dbo.DeviceFlagAssignments", "RemoveDate", c => c.DateTime());
AddColumn("dbo.DeviceFlagAssignments", "RemoveUserId", c => c.String(maxLength: 50));
AddColumn("dbo.DeviceFlags", "Permissions", c => c.String());
AddColumn("dbo.DeviceFlags", "DefaultRemoveDays", c => c.Int());
AddForeignKey("dbo.UserFlagAssignments", "RemoveUserId", "dbo.Users", "Id");
AddForeignKey("dbo.DeviceFlagAssignments", "RemoveUserId", "dbo.Users", "Id");
CreateIndex("dbo.UserFlagAssignments", "RemoveUserId");
CreateIndex("dbo.DeviceFlagAssignments", "RemoveUserId");
}
public override void Down()
{
DropIndex("dbo.DeviceFlagAssignments", new[] { "RemoveUserId" });
DropIndex("dbo.UserFlagAssignments", new[] { "RemoveUserId" });
DropForeignKey("dbo.DeviceFlagAssignments", "RemoveUserId", "dbo.Users");
DropForeignKey("dbo.UserFlagAssignments", "RemoveUserId", "dbo.Users");
DropColumn("dbo.DeviceFlags", "DefaultRemoveDays");
DropColumn("dbo.DeviceFlags", "Permissions");
DropColumn("dbo.DeviceFlagAssignments", "RemoveUserId");
DropColumn("dbo.DeviceFlagAssignments", "RemoveDate");
DropColumn("dbo.UserFlags", "DefaultRemoveDays");
DropColumn("dbo.UserFlags", "Permissions");
DropColumn("dbo.UserFlagAssignments", "RemoveUserId");
DropColumn("dbo.UserFlagAssignments", "RemoveDate");
}
}
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv29 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv29));
string IMigrationMetadata.Id
{
get { return "202509070209304_DBv29"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,18 @@
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
public partial class DBv29 : DbMigration
{
public override void Up()
{
AddColumn("dbo.DeviceProfiles", "SetAssignedUserForLogon", c => c.Boolean(nullable: false));
Sql("UPDATE dbo.DeviceProfiles SET SetAssignedUserForLogon = 1");
}
public override void Down()
{
DropColumn("dbo.DeviceProfiles", "SetAssignedUserForLogon");
}
}
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv30 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv30));
string IMigrationMetadata.Id
{
get { return "202509180416385_DBv30"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,17 @@
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
public partial class DBv30 : DbMigration
{
public override void Up()
{
AddColumn("dbo.DeviceProfiles", "ProvisionFromOtherDomain", c => c.Boolean(nullable: false, defaultValue: false));
}
public override void Down()
{
DropColumn("dbo.DeviceProfiles", "ProvisionFromOtherDomain");
}
}
}
File diff suppressed because one or more lines are too long
-3
View File
@@ -1,9 +1,6 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using Disco.Data.Repository;
internal sealed class Configuration : DbMigrationsConfiguration<DiscoDataContext>
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using Disco.Data.Repository;
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.4.24270.0000")]
[assembly: AssemblyVersion("2.5.25262.0000")]
[assembly: AssemblyFileVersion("2.5.25262.0000")]
+4 -2
View File
@@ -11,7 +11,7 @@ namespace Disco.Data.Repository
public DiscoDataContext()
{
this._Configuration = new Lazy<Configuration.SystemConfiguration>(() => new Configuration.SystemConfiguration(this));
_Configuration = new Lazy<Configuration.SystemConfiguration>(() => new Configuration.SystemConfiguration(this));
}
public virtual DbSet<ConfigurationItem> ConfigurationItems { get; set; }
@@ -19,6 +19,7 @@ namespace Disco.Data.Repository
public virtual DbSet<DocumentTemplate> DocumentTemplates { get; set; }
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<UserComment> UserComments { get; set; }
public virtual DbSet<UserDetail> UserDetails { get; set; }
public virtual DbSet<UserAttachment> UserAttachments { get; set; }
public virtual DbSet<UserFlag> UserFlags { get; set; }
@@ -28,6 +29,7 @@ namespace Disco.Data.Repository
public virtual DbSet<DeviceUserAssignment> DeviceUserAssignments { get; set; }
public virtual DbSet<Device> Devices { get; set; }
public virtual DbSet<DeviceComment> DeviceComments { get; set; }
public virtual DbSet<DeviceDetail> DeviceDetails { get; set; }
public virtual DbSet<DeviceModel> DeviceModels { get; set; }
public virtual DbSet<DeviceProfile> DeviceProfiles { get; set; }
@@ -58,7 +60,7 @@ namespace Disco.Data.Repository
{
get
{
return this._Configuration.Value;
return _Configuration.Value;
}
}
+16 -18
View File
@@ -20,8 +20,6 @@ namespace Disco.Data.Repository
Database.SaveChanges();
// Migration Maintenance
Database.MigrateConfiguration();
Database.MigratePreDomainObjects();
}
@@ -60,7 +58,7 @@ namespace Disco.Data.Repository
{
if (Database.DeviceModels.Count() == 0)
{
Database.DeviceModels.Add(new DeviceModel { Manufacturer = "Unknown", Model = "Unknown", Description = "Unknown Device Model" });
Database.DeviceModels.Add(new DeviceModel { Manufacturer = "Unknown", Model = "Unknown", Description = "Unknown Device Model", ModelType = "Unknown" });
}
UpdateDeviceModelConfiguration(Database);
// Removed: 2013-01-14 G#
@@ -210,6 +208,15 @@ namespace Disco.Data.Repository
#endregion
// End
// 2025-07-11
#region "User Management - BYOD" Added
if (Database.JobSubTypes.Count(jst => jst.JobTypeId == JobType.JobTypeIds.UMgmt && jst.Id == JobSubType.UserManagementJobSubTypes.BYOD) == 0)
{
Database.JobSubTypes.Add(new JobSubType { Id = JobSubType.UserManagementJobSubTypes.BYOD, JobTypeId = JobType.JobTypeIds.UMgmt, Description = JobSubType.UserManagementJobSubTypes.BYOD });
}
#endregion
// End
// 2012-05-29 - Audits
#region "Audit" Added
if (Database.JobSubTypes.Count(jst => jst.JobTypeId == JobType.JobTypeIds.HMisc && jst.Id == "Audit") == 0)
@@ -257,8 +264,7 @@ namespace Disco.Data.Repository
foreach (var configurationItem in configurationItems)
{
int profileId = int.Parse(configurationItem.Scope.Substring(configurationItem.Scope.IndexOf(":") + 1));
DeviceProfile dp;
if (deviceProfiles.TryGetValue(profileId, out dp))
if (deviceProfiles.TryGetValue(profileId, out var dp))
{
switch (configurationItem.Key)
{
@@ -266,7 +272,7 @@ namespace Disco.Data.Repository
dp.ComputerNameTemplate = configurationItem.Value;
break;
case "DistributionType":
dp.DistributionType = (DeviceProfile.DistributionTypes)(int.Parse(configurationItem.Value));
dp.DistributionType = (DeviceProfile.DistributionTypes)int.Parse(configurationItem.Value);
break;
case "OrganisationalUnit":
dp.OrganisationalUnit = configurationItem.Value;
@@ -289,7 +295,7 @@ namespace Disco.Data.Repository
private static void UpdateDeviceModelDuplicates(this DiscoDataContext Database)
{
var deviceModels = Database.DeviceModels.ToList();
var duplicateModels = deviceModels.GroupBy(g => string.Format("{0}|{1}", g.Manufacturer, g.Model)).Where(g => g.Count() > 1);
var duplicateModels = deviceModels.GroupBy(g => $"{g.Manufacturer}|{g.Model}").Where(g => g.Count() > 1);
foreach (var duplicateModel in duplicateModels)
{
var primaryModel = duplicateModel.OrderBy(dm => dm.Id).First();
@@ -303,23 +309,15 @@ namespace Disco.Data.Repository
if (!redundantModel.Description.EndsWith("** REDUNDANT **"))
{
if (redundantModel.Description.Length > 484)
redundantModel.Description = string.Format("{0} ** REDUNDANT **", redundantModel.Description.Substring(0, 484));
redundantModel.Description = $"{redundantModel.Description.Substring(0, 484)} ** REDUNDANT **";
else
redundantModel.Description = string.Format("{0} ** REDUNDANT **", redundantModel.Description);
redundantModel.Description = $"{redundantModel.Description} ** REDUNDANT **";
}
}
}
}
// End Added: 2013-02-07 G#
public static void MigrateConfiguration(this DiscoDataContext Database)
{
// Organisation Addresses - Force all to JSON serializing
Configuration.Modules.OrganisationAddressesConfiguration.MigrateDatabase(Database);
Database.SaveChanges();
}
#region Migrate Users SQL
private const string MigratePreDomainUsers_Sql = @"INSERT INTO [Users] SELECT @IdNew, u.DisplayName, u.Surname, u.GivenName, u.PhoneNumber, u.EmailAddress FROM [Users] u WHERE [Id]=@IdExisting;
@@ -426,7 +424,7 @@ DELETE [Users] WHERE [Id]=@IdExisting;";
var dataStoreLocation = Database.ConfigurationItems.Where(ci => ci.Scope == "System" && ci.Key == "DataStoreLocation").Select(ci => ci.Value).FirstOrDefault();
if (!string.IsNullOrWhiteSpace(dataStoreLocation) && System.IO.Directory.Exists(dataStoreLocation))
{
string filePrefix = string.Format("{0}_", netBiosName);
string filePrefix = $"{netBiosName}_";
var userAttachmentsDirectory = System.IO.Path.Combine(dataStoreLocation, "UserAttachments");
if (System.IO.Directory.Exists(userAttachmentsDirectory))
@@ -1,12 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity.Infrastructure;
using Microsoft.Win32;
using Microsoft.Win32;
using System;
using System.Data.Common;
using System.Data.Entity.Infrastructure;
using System.Security;
using System.Security.Permissions;
namespace Disco.Data.Repository
{
@@ -52,18 +48,18 @@ namespace Disco.Data.Repository
}
catch (UnauthorizedAccessException ex)
{
throw new SecurityException(string.Format("Unable to write to the Registry Location: HKML\\{0}[DatabaseConnectionString]", DiscoRegistryKey), ex);
throw new SecurityException($"Unable to write to the Registry Location: HKML\\{DiscoRegistryKey}[DatabaseConnectionString]", ex);
}
}
}
public DiscoDatabaseConnectionFactory(IDbConnectionFactory Default)
{
this.DefaultConnectionFactory = Default;
this.SqlCeConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
DefaultConnectionFactory = Default;
SqlCeConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
}
public System.Data.Common.DbConnection CreateConnection(string nameOrConnectionString)
public DbConnection CreateConnection(string nameOrConnectionString)
{
if (nameOrConnectionString == "Disco.Data.Repository.DiscoDataContext")
{
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reactive;
using System.Reactive.Subjects;
using System.Data.Entity.Infrastructure;
using Disco.Models.Repository;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using Disco.Models.Repository;
using System.Linq;
using System.Reactive.Subjects;
namespace Disco.Data.Repository.Monitor
{
@@ -52,9 +49,8 @@ namespace Disco.Data.Repository.Monitor
private static Type EntityTypeFromProxy(Type EntityProxyType)
{
Type EntityType;
if (entityProxyTypeCache.TryGetValue(EntityProxyType, out EntityType))
if (entityProxyTypeCache.TryGetValue(EntityProxyType, out var EntityType))
return EntityType;
EntityType = EntityProxyType;
@@ -113,7 +109,7 @@ namespace Disco.Data.Repository.Monitor
eventType = RepositoryMonitorEventType.Unchanged;
break;
default:
throw new NotSupportedException(string.Format("Database Entry State not supported: {0}", entryState.State.ToString()));
throw new NotSupportedException($"Database Entry State not supported: {entryState.State.ToString()}");
}
entityType = EntityTypeFromProxy(entryState.Entity.GetType());
@@ -3,9 +3,6 @@ using System;
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Data.Repository.Monitor
{
@@ -55,7 +52,8 @@ namespace Disco.Data.Repository.Monitor
return (T)dbEntityState.CurrentValues[PropertyName];
}
public void ExecuteAfterCommit(Action<RepositoryMonitorEvent> action){
public void ExecuteAfterCommit(Action<RepositoryMonitorEvent> action)
{
if (afterCommit)
{
// Execute Immediately
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Data.Repository.Monitor
namespace Disco.Data.Repository.Monitor
{
public enum RepositoryMonitorEventType
{
+3 -49
View File
@@ -1,12 +1,9 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Text;
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.BI.Config
{
public class OrganisationAddress
{
public int? Id { get; set; }
[Required]
public string Name { get; set; }
@@ -23,54 +20,11 @@ namespace Disco.Models.BI.Config
[Required]
public string ShortName { get; set; }
// Added 2012-12-11 G#
// http://discoict.com.au/forum/support/2012/12/address-details.aspx
public string PhoneNumber { get; set; }
public string FaxNumber { get; set; }
// End Added 2012-12-11 G#
public string ToConfigurationEntry()
{
StringBuilder entryBuilder = new StringBuilder();
entryBuilder.AppendLine(Name.Trim());
entryBuilder.AppendLine(Address.Trim());
entryBuilder.AppendLine(Suburb.Trim());
entryBuilder.AppendLine(Postcode.Trim());
entryBuilder.AppendLine(State.Trim());
entryBuilder.AppendLine(Country.Trim());
if (!string.IsNullOrEmpty(ShortName))
{
entryBuilder.AppendLine(ShortName.Trim());
}
return entryBuilder.ToString();
}
public static OrganisationAddress FromConfigurationEntry(int Id, string Entry)
{
string[] entryLines = Entry.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
if (entryLines.Length >= 6)
{
return new OrganisationAddress()
{
Id = Id,
Name = entryLines[0].Trim(),
Address = entryLines[1].Trim(),
Suburb = entryLines[2].Trim(),
Postcode = entryLines[3].Trim(),
State = entryLines[4].Trim(),
Country = entryLines[5].Trim(),
ShortName = (entryLines.Length > 6 ? entryLines[6].Trim() : string.Empty)
};
}
throw new ArgumentException("Invalid Configuration Address Entry", "entry");
}
public string EmailAddress { get; set; }
public override string ToString()
{
return string.Format("{0} ({1})", this.Name, this.ShortName);
}
=> $"{Name} ({ShortName})";
}
}
@@ -1,4 +1,5 @@
using Disco.Models.ClientServices.EnrolmentInformation;
using Newtonsoft.Json;
using System;
namespace Disco.Models.ClientServices
@@ -10,12 +11,18 @@ namespace Disco.Models.ClientServices
public string DomainName { get; set; }
public string ComputerName { get; set; }
[JsonIgnore]
public int? DeviceProfileId { get; set; }
[JsonIgnore]
public int? DeviceBatchId { get; set; }
public string AssignedUserDomain { get; set; }
public string AssignedUserUsername { get; set; }
public string AssignedUserSID { get; set; }
public string AssignedUserDescription { get; set; }
public bool AssignedUserIsLocalAdmin { get; set; }
public bool SetAssignedUserForLogon { get; set; }
public string OfflineDomainJoinManifest { get; set; }
@@ -3,7 +3,7 @@
public class ComputerSystem
{
public string ChassisSKUNumber { get; set; }
public short? CurrentTimeZone { get; set;}
public short? CurrentTimeZone { get; set; }
public string Description { get; set; }
public string[] OEMStringArray { get; set; }
public string PCSystemType { get; set; }
@@ -11,6 +11,8 @@ namespace Disco.Models.ClientServices.EnrolmentInformation
public string Model { get; set; }
public string ModelType { get; set; }
public string MdmHardwareData { get; set; }
public List<Bios> Bios { get; set; }
public List<BaseBoard> BasebBoard { get; set; }
public List<ComputerSystem> ComputerSystem { get; set; }
@@ -19,7 +19,7 @@ namespace Disco.Models.ClientServices.EnrolmentInformation
public string WlanStatus { get; set; }
public bool NetEnabled { get; set; }
public bool IPEnabled { get; set; }
public List<string> IPAddresses { get; set; }
}
}
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
namespace Disco.Models.ClientServices.EnrolmentInformation
{
+2 -7
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Models.ClientServices
namespace Disco.Models.ClientServices
{
public class MacEnrol : ServiceBase<MacEnrolResponse>
{
@@ -16,7 +11,7 @@ namespace Disco.Models.ClientServices
public string DeviceUUID { get; set; }
public string DeviceComputerName { get; set; }
public string DeviceManufacturer { get; set; }
public string DeviceModel { get; set; }
public string DeviceModelType { get; set; }
@@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Models.ClientServices
namespace Disco.Models.ClientServices
{
public class MacEnrolResponse
{
public string DeviceComputerName { get; set; }
public string DeviceAssignedUserDomain { get; set; }
public string DeviceAssignedUserName { get; set; }
public string DeviceAssignedUserSID { get; set; }
@@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Models.ClientServices
namespace Disco.Models.ClientServices
{
public class MacSecureEnrolResponse
{
public string DeviceComputerName { get; set; }
public string DeviceAssignedUserDomain { get; set; }
public string DeviceAssignedUserName { get; set; }
public string DeviceAssignedUserSID { get; set; }
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Models.ClientServices
namespace Disco.Models.ClientServices
{
public abstract class ServiceBase<ResponseType>
{
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Models.ClientServices
namespace Disco.Models.ClientServices
{
public class WhoAmI : ServiceBase<WhoAmIResponse>
{
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Disco.Models.ClientServices
namespace Disco.Models.ClientServices
{
public class WhoAmIResponse
{
+33 -5
View File
@@ -41,6 +41,9 @@
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@@ -49,13 +52,24 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BI\Config\OrganisationAddress.cs" />
<Compile Include="Exporting\ExportFieldMetadata.cs" />
<Compile Include="Exporting\ExportMetadataField.cs" />
<Compile Include="Exporting\ExportFormat.cs" />
<Compile Include="Exporting\ExportMetadata.cs" />
<Compile Include="Exporting\IExportRecord.cs" />
<Compile Include="Repository\Device\Flag\DeviceFlag.cs" />
<Compile Include="Repository\Device\Flag\DeviceFlagAssignment.cs" />
<Compile Include="Repository\Device\DeviceComment.cs" />
<Compile Include="Repository\FlagType.cs" />
<Compile Include="Repository\User\UserComment.cs" />
<Compile Include="Repository\FlagPermission.cs" />
<Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportOptions.cs" />
<Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportRecord.cs" />
<Compile Include="Services\Documents\DocumentExportOptions.cs" />
<Compile Include="Services\Documents\DocumentExportRecord.cs" />
<Compile Include="Services\Exporting\ExportOptionField.cs" />
<Compile Include="Services\Exporting\ExportOptionGroup.cs" />
<Compile Include="Services\Exporting\SavedExport.cs" />
<Compile Include="Services\Exporting\SavedExportSchedule.cs" />
<Compile Include="Services\Expressions\Extensions\ImageExpressionFormat.cs" />
<Compile Include="ClientServices\EnrolmentInformation\BaseBoard.cs" />
<Compile Include="ClientServices\EnrolmentInformation\Battery.cs" />
@@ -80,6 +94,11 @@
<Compile Include="Services\Documents\DocumentTemplatePackage.cs" />
<Compile Include="Services\Documents\OnImportUserFlagRule.cs" />
<Compile Include="Exporting\IExportOptions.cs" />
<Compile Include="Services\Interop\DiscoServices\Activation\CallbackModel.cs" />
<Compile Include="Services\Interop\DiscoServices\Activation\ChallengeModel.cs" />
<Compile Include="Services\Interop\DiscoServices\IConnectNotification.cs" />
<Compile Include="Services\Jobs\JobExportOptions.cs" />
<Compile Include="Services\Jobs\JobExportRecord.cs" />
<Compile Include="Services\Jobs\LocationModes.cs" />
<Compile Include="ClientServices\EnrolmentInformation\Certificate.cs" />
<Compile Include="ClientServices\Register.cs" />
@@ -132,10 +151,10 @@
<Compile Include="Repository\User\UserAttachment.cs" />
<Compile Include="Repository\User\UserDetail.cs" />
<Compile Include="Repository\User\AuthorizationRole.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportRecord.cs" />
<Compile Include="Services\Devices\DeviceExportRecord.cs" />
<Compile Include="Exporting\ExportResult.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportTypes.cs" />
<Compile Include="Services\Devices\Exporting\DeviceExportOptions.cs" />
<Compile Include="Services\Devices\DeviceExportTypes.cs" />
<Compile Include="Services\Devices\DeviceExportOptions.cs" />
<Compile Include="Services\Devices\Importing\DeviceImportFieldTypes.cs" />
<Compile Include="Services\Devices\Importing\IDeviceImportRecord.cs" />
<Compile Include="Services\Devices\Importing\IDeviceImportContext.cs" />
@@ -154,6 +173,7 @@
<Compile Include="Services\Jobs\JobLists\JobTableStatusQueueItemModel.cs" />
<Compile Include="Services\Jobs\JobQueues\IJobQueueToken.cs" />
<Compile Include="Services\Jobs\Noticeboards\IHeldDeviceItem.cs" />
<Compile Include="Services\Logging\LogExportOptions.cs" />
<Compile Include="Services\Messaging\Email.cs" />
<Compile Include="Services\Messaging\EmailAttachment.cs" />
<Compile Include="Services\Users\Contact\UserContact.cs" />
@@ -178,6 +198,7 @@
<Compile Include="UI\Config\DeviceModel\ConfigDeviceModelIndexModelItem.cs" />
<Compile Include="UI\Config\DeviceModel\ConfigDeviceModelComponentsModel.cs" />
<Compile Include="UI\Config\DeviceModel\ConfigDeviceModelShowModel.cs" />
<Compile Include="UI\Config\DeviceModel\ConfigDeviceModelCreateModel.cs" />
<Compile Include="UI\Config\DeviceProfile\ConfigDeviceProfileCreateModel.cs" />
<Compile Include="UI\Config\DeviceProfile\ConfigDeviceProfileDefaultsModel.cs" />
<Compile Include="UI\Config\DeviceProfile\ConfigDeviceProfileIndexModel.cs" />
@@ -186,7 +207,12 @@
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateBulkGenerate.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateCreatePackageModel.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateCreateModel.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateExpressionBrowserModel.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateExportModel.cs" />
<Compile Include="UI\Config\Export\ConfigExportShowModel.cs" />
<Compile Include="UI\Config\Export\ConfigExportEditModel.cs" />
<Compile Include="UI\Config\Export\ConfigExportIndexModel.cs" />
<Compile Include="UI\Config\Export\ConfigExportCreateModel.cs" />
<Compile Include="UI\Config\Expressions\ConfigExpressionsBrowserModel.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateImportStatusModel.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateIndexModel.cs" />
<Compile Include="UI\Config\DocumentTemplate\ConfigDocumentTemplateShowPackageModel.cs" />
@@ -217,11 +243,13 @@
<Compile Include="UI\Device\DeviceImportReviewModel.cs" />
<Compile Include="UI\Device\DeviceIndexModel.cs" />
<Compile Include="UI\Device\DeviceShowModel.cs" />
<Compile Include="UI\Job\JobExportModel.cs" />
<Compile Include="UI\Job\JobCreateModel.cs" />
<Compile Include="UI\Job\JobIndexModel.cs" />
<Compile Include="UI\Job\JobListModel.cs" />
<Compile Include="UI\Job\JobShowModel.cs" />
<Compile Include="UI\Search\SearchQueryModel.cs" />
<Compile Include="UI\Shared\SharedExportFieldsModel.cs" />
<Compile Include="UI\User\UserIndexModel.cs" />
<Compile Include="UI\User\UserShowModel.cs" />
</ItemGroup>
@@ -1,27 +0,0 @@
using System;
namespace Disco.Models.Exporting
{
public class ExportFieldMetadata<T> where T : IExportRecord
{
public string Name { get; set; }
public string ColumnName { get; set; }
public Type ValueType { get; set; }
public Func<T, object> Accessor { get; set; }
public Func<object, string> CsvEncoder { get; set; }
public ExportFieldMetadata(string name, Type valueType, Func<T, object> accessor, Func<object, string> csvEncoder)
{
Name = name;
ValueType = valueType;
Accessor = accessor;
CsvEncoder = csvEncoder;
}
public ExportFieldMetadata(string name, string columnName, Type valueType, Func<T, object> accessor, Func<object, string> csvEncoder)
: this(name, valueType, accessor, csvEncoder)
{
ColumnName = columnName;
}
}
}
+19
View File
@@ -0,0 +1,19 @@
using Disco.Models.Services.Exporting;
using System.Collections.Generic;
namespace Disco.Models.Exporting
{
public class ExportMetadata<O, R>
: List<ExportMetadataField<R>>
where O : IExportOptions
where R : IExportRecord
{
public List<string> IgnoreGroupNames { get; } = new List<string>();
public O Options { get; set; }
public ExportMetadata(O options)
{
Options = options;
}
}
}
@@ -0,0 +1,20 @@
using System;
namespace Disco.Models.Exporting
{
public class ExportMetadataField<T> where T : IExportRecord
{
public string ColumnName { get; }
public Type ValueType { get; }
public Func<T, object> Accessor { get; }
public Func<object, string> CsvEncoder { get; }
public ExportMetadataField(string columnName, Type valueType, Func<T, object> accessor, Func<object, string> csvEncoder)
{
ColumnName = columnName;
ValueType = valueType;
Accessor = accessor;
CsvEncoder = csvEncoder;
}
}
}
+2 -4
View File
@@ -4,9 +4,7 @@ namespace Disco.Models.Services.Exporting
{
public interface IExportOptions
{
ExportFormat Format { get; }
string FilenamePrefix { get; }
string ExcelWorksheetName { get; }
string ExcelTableName { get; }
int Version { get; set; }
ExportFormat Format { get; set; }
}
}
+2 -2
View File
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.4.24270.0000")]
[assembly: AssemblyFileVersion("2.4.24270.0000")]
[assembly: AssemblyVersion("2.5.25262.0000")]
[assembly: AssemblyFileVersion("2.5.25262.0000")]
+1 -5
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository
+5 -19
View File
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -49,31 +47,19 @@ namespace Disco.Models.Repository
public virtual IList<DeviceAttachment> DeviceAttachments { get; set; }
public virtual IList<DeviceCertificate> DeviceCertificates { get; set; }
[InverseProperty("DeviceSerialNumber")]
[InverseProperty(nameof(Job.Device))]
public virtual IList<Job> Jobs { get; set; }
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
/// <summary>
/// A list of the current device assignments, ordered by the most recent assignment date.
/// </summary>
[NotMapped]
public IList<DeviceUserAssignment> CurrentDeviceUserAssignments
{
get
{
return DeviceUserAssignments?
.Where(dua => dua.UnassignedDate is null)
.OrderByDescending(dua => dua.AssignedDate)
.ToList();
}
}
[InverseProperty(nameof(DeviceComment.Device))]
public virtual IList<DeviceComment> DeviceComments { get; set; }
public override string ToString()
{
if (DeviceModel != null)
return string.Format("{0} - {1}", this.DeviceModel, this.SerialNumber);
return $"{DeviceModel} - {SerialNumber}";
else
return this.SerialNumber;
return SerialNumber;
}
[NotMapped]
@@ -16,7 +16,7 @@ namespace Disco.Models.Repository
[Required, StringLength(500)]
public string MimeType { get; set; }
public DateTime Timestamp { get; set; }
[Required, StringLength(500)]
[StringLength(500)]
public string Comments { get; set; }
public string DocumentTemplateId { get; set; }
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -55,11 +53,11 @@ namespace Disco.Models.Repository
public override string ToString()
{
if (string.IsNullOrWhiteSpace(this.Name))
if (string.IsNullOrWhiteSpace(Name))
{
return string.Format("{0}: {1}", this.Id, this.PurchaseDate.ToLongDateString());
return $"{Id}: {PurchaseDate.ToLongDateString()}";
}
return this.Name;
return Name;
}
}
}
@@ -16,7 +16,7 @@ namespace Disco.Models.Repository
[Required, StringLength(500)]
public string MimeType { get; set; }
public DateTime Timestamp { get; set; }
[Required, StringLength(500)]
[StringLength(500)]
public string Comments { get; set; }
[NotMapped]
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -0,0 +1,25 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository
{
public class DeviceComment
{
[Key]
public int Id { get; set; }
public string DeviceSerialNumber { get; set; }
[Required]
public string TechUserId { get; set; }
public DateTime Timestamp { get; set; }
[Required]
public string Comments { get; set; }
[ForeignKey(nameof(DeviceSerialNumber))]
public Device Device { get; set; }
[ForeignKey(nameof(TechUserId))]
public User TechUser { get; set; }
}
}
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -15,10 +12,10 @@ namespace Disco.Models.Repository
[StringLength(100)]
public string Description { get; set; }
public decimal Cost { get; set; }
[ForeignKey("DeviceModelId")]
public virtual DeviceModel DeviceModel { get; set; }
public virtual IList<JobSubType> JobSubTypes { get; set; }
}
}
@@ -20,16 +20,17 @@ namespace Disco.Models.Repository
public const string HardwareKeyBaseBoard = "BaseBoard";
public const string HardwareKeyComputerSystem = "ComputerSystem";
public const string HardwareKeyBatteries = "Batteries";
public const string HardwareKeyMdmHardwareData = "MdmHardwareData";
[Column(Order = 0), Key]
public string DeviceSerialNumber { get; set; }
[Key, StringLength(100), Column(Order = 2)]
public string Key { get; set; }
[Column(Order = 1), StringLength(100), Key]
public string Scope { get; set; }
public string Value { get; set; }
[ForeignKey("DeviceSerialNumber")]
+8 -10
View File
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
namespace Disco.Models.Repository
{
public class DeviceModel
{
public static readonly string CustomModelType = "Custom";
[Key]
public int Id { get; set; }
[StringLength(500)]
@@ -19,11 +19,6 @@ namespace Disco.Models.Repository
public string Model { get; set; }
[StringLength(40)]
public string ModelType { get; set; }
// Remove Reliance On!
// Removed: 2013-01-14 G#
//[Obsolete("Image to be removed from the Database")]
//public byte[] Image { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true, DataFormatString = "{0:yyyy/MM/dd}", HtmlEncode = false)]
public DateTime? DefaultPurchaseDate { get; set; }
@@ -42,11 +37,14 @@ namespace Disco.Models.Repository
public override string ToString()
{
if (string.IsNullOrWhiteSpace(this.Description))
if (string.IsNullOrWhiteSpace(Description))
{
return string.Format("{0} {1}", this.Manufacturer, this.Model);
return $"{Manufacturer} {Model}";
}
return this.Description;
return Description;
}
public bool IsCustomModel()
=> CustomModelType.Equals(ModelType, StringComparison.Ordinal);
}
}

Some files were not shown because too many files have changed in this diff Show More