Files
C4IT-F4SD-Collector/F4SD-Cockpit-ServerCore/Common/C4IT.FASD.Communication.Citrix.cs
Meik ccc48c521a Prepare Data History Provider 2.7 integration update
- modularize Citrix and agent integrations and add remote desktop endpoints
- extend ticket overview, ticket links, token validation, and staged relation handling
- update configuration, licensing, project, signing, and publish artifacts
2026-07-20 09:31:52 +02:00

1022 lines
37 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using C4IT.HTTP;
using C4IT.Logging;
using Newtonsoft.Json.Linq;
using static C4IT.Logging.cLogManager;
namespace C4IT.FASD.Communication.Citrix
{
public class cCitrixApiResultList : List<cCitrixApiResultBase>
{
public string NextResultUrl { get; private set; } = null;
public bool retryForbidden { get; private set; } = false;
public cCitrixApiResultList(bool retryForbidden)
{
this.retryForbidden = retryForbidden;
}
public bool hasRemaining
{
get
{
return !string.IsNullOrEmpty(NextResultUrl);
}
}
public void AddResult(dynamic Result)
{
try
{
NextResultUrl = null;
if (Result.TryGetValue("@odata.nextLink", out JToken JT))
{
var JO = (JValue)JT;
NextResultUrl = Result["@odata.nextLink"];
}
if (Result.TryGetValue("value", out JToken JT2))
{
foreach (dynamic Entry in Result.value)
try
{
var val = new cCitrixApiResultBase(Entry);
this.Add(val);
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
}
}
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
}
}
}
public class cCitrixApiResultBase
{
public string ID { get; private set; } = null;
public string ODataId { get; private set; } = null;
public string DisplayName { get; private set; } = null;
public string Context { get; private set; } = null;
public dynamic Result { get; private set; } = null;
public cCitrixApiResultBase(dynamic Result, string namePropery = null)
{
this.Result = Result;
try { ID = Result.Id; } catch { }
;
try
{
if (namePropery == null)
namePropery = "displayName";
if (Result.TryGetValue(namePropery, out JToken JT1))
{
var _ty = JT1.GetType().ToString();
if (JT1 is JValue _jVal)
DisplayName = _jVal.Value?.ToString();
}
else if (Result.TryGetValue("name", out JToken JT2))
DisplayName = Result.name;
}
catch { }
try { Context = Result["@odata.context"]; } catch { }
ODataId = GetStringFromDynamic(Result, "@odata.id");
if (string.IsNullOrEmpty(ODataId))
ODataId = @"https://api.cloud.com/" + ID;
}
public cCitrixApiResultBase(cCitrixApiResultBase Result)
{
if (Result == null)
return;
this.Result = Result.Result;
ID = Result.ID;
ODataId = Result.ODataId;
DisplayName = Result.DisplayName;
Context = Result.Context;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetStringFromDynamic(dynamic O, string ProperyName)
{
try
{
return (string)O[ProperyName];
}
catch { }
return null;
}
}
public class cCitrixCustomerInfo
{
public string Id { get; set; }
public string Name { get; set; } = string.Empty;
public cCitrixSiteInfo PrimarySite { get; set; }
public Dictionary<Guid, cCitrixSiteInfo> Sites { get; private set; } = new Dictionary<Guid, cCitrixSiteInfo>();
}
public class cCitrixSiteInfo
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public bool? IsValid { get; set; } = null;
public bool IsPrimarySite { get; set; } = false;
}
public class cCitrixCommunicationSystem
{
public const string constCitrixCloudMonitorUrl = "monitorodata/";
public const string constCitrixOnPremMonitorUrl = "Citrix/Monitor/OData/v4/Data/";
public cCitrixCommunicationMonitor Monitor { get; private set; }
public cCitrixCommunicationCvad CVAD { get; private set; }
public bool IsCloud { get; private set; }
public string Name { get; private set; } = string.Empty;
public cCitrixCommunicationSystem(cCitrixCommunicationCloudBase CitrixCloud, string Name)
{
IsCloud = true;
this.Name = Name;
this.Monitor = new cCitrixCommunicationMonitor(CitrixCloud);
this.CVAD = new cCitrixCommunicationCvad(CitrixCloud);
}
public cCitrixCommunicationSystem(cCitrixCommunicationOnPremCvad Cvad, cCitrixCommunicationOnPremMonitor Monitor, string Name)
{
IsCloud = false;
this.Name = Name;
this.Monitor = new cCitrixCommunicationMonitor(Monitor);
this.CVAD = new cCitrixCommunicationCvad(Cvad);
}
public async Task<cCitrixCustomerInfo> ScanCustomerInfosAsync(CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _retVal = new cCitrixCustomerInfo();
var CustomerInfo = await CVAD.GetCustomerInfoAsync(token);
if (token.IsCancellationRequested)
return null;
if (CustomerInfo == null)
return _retVal;
_retVal.Id = CustomerInfo.Id;
_retVal.Name = CustomerInfo.Name;
cCitrixSiteInfo PrimarySite = null;
int maxConsitency = 0;
int countC0 = 0;
int countC1 = 0;
int countC2 = 0;
foreach (var site in CustomerInfo.Sites.Values)
{
var _newSite = new cCitrixSiteInfo()
{
Name = site.Name,
Id = site.Id,
IsValid = false
};
// validate the site consitency
var _resultConsitency = await CheckSiteConsitencyAsync(site.Id.ToString("D"), token);
if (token.IsCancellationRequested)
return null;
switch (_resultConsitency)
{
case 0: _newSite.IsValid = null; countC0++; break;
case 1: _newSite.IsValid = true; countC1++; break;
case 2: _newSite.IsValid = true; countC2++; break;
}
if (maxConsitency < _resultConsitency)
PrimarySite = _newSite;
maxConsitency = Math.Max(maxConsitency, _resultConsitency);
_retVal.Sites.Add(_newSite.Id, _newSite);
}
if (PrimarySite != null)
{
if (countC2 == 1)
PrimarySite.IsPrimarySite = true;
else if (countC1 == 1 && countC2 == 0)
PrimarySite.IsPrimarySite = true;
}
if (PrimarySite?.IsPrimarySite == true)
_retVal.PrimarySite = PrimarySite;
return _retVal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public async Task<int> CheckSiteConsitencyAsync(string SiteId, CancellationToken token)
{
// check if the machines queried from the monitor component could be found in the cvad component
// return values:
// 2: all machines could be found
// 1: al least one machine could be found
// 0: no machines in monitor component
// -1: none of the machines could be found
// -2: internal error occured
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
var _lastSiteId = CVAD.CitrixInfo.SiteId;
try
{
CVAD.CitrixInfo.SiteId = SiteId;
// get the machine list from cvad
var _machinesCvad = await CVAD.GetMachineNamesAsync(token);
if (token.IsCancellationRequested)
return -2;
// get the machine list from monitor
var _machinesMonitor = await Monitor.GetMachineNamesAsync(token);
if (token.IsCancellationRequested)
return -2;
if (_machinesMonitor == null || _machinesMonitor.Count == 0)
return 0;
var atLeastOne = false;
var all = true;
foreach ( var machineName in _machinesMonitor )
{
if (_machinesCvad.Contains(machineName))
atLeastOne = true;
else
all = false;
}
if (atLeastOne && all)
return 2;
if (atLeastOne)
return 1;
return -1;
}
catch (Exception E)
{
LogException(E);
}
finally
{
CVAD.CitrixInfo.SiteId = _lastSiteId;
if (CM != null) LogMethodEnd(CM);
}
return -2;
}
}
public interface iCitrixCvadInfo
{
string CustomerId { get; }
string SiteId { get; set; }
}
public class cCitrixCommunicationCloudBase : cHttpApiBase, iCitrixCvadInfo
{
public const int constMaxPageSize = 1000;
private string InstanceId = null;
public cCitrixCommunicationCloudBase(string baseUrlCloud) : base("Citrix customer tenant", $"{baseUrlCloud}/cctrustoauth2/{{Tenant}}/tokens/clients", "Citrix API", baseUrlCloud)
{
MaxConcurrentRequests = 1;
KnownAutoRetryErrors.Add((HttpStatusCode)429);
autoRetryCount = 50;
autoRetryDelay = 200;
autoRetryOnKnownErrors = true;
}
private protected override List<KeyValuePair<string, string>> GetRequestHeaders(cOAuthLogonInfo privLogonInfo)
{
return new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("Authorization", $"CwsAuth Bearer={AccessToken}"),
new KeyValuePair<string, string>("Citrix-CustomerId", privLogonInfo.Tenant),
new KeyValuePair<string, string>("Citrix-InstanceId", InstanceId)
};
}
public string CustomerId { get {
return this.privLogonInfo?.Tenant;
} }
public string SiteId
{
get { return InstanceId; }
set { InstanceId = value; }
}
}
public class cCitrixCommunicationOnPremCvad : cHttpApiBase, iCitrixCvadInfo
{
private const string constLogonUrl = "manage/Tokens";
private string privCustomerId = null;
private string InstanceId = null;
public cCitrixCommunicationOnPremCvad(string baseUrl) : base("Citrix on-prem system", baseUrl, "Citrix API", baseUrl + "/cvad/")
{
// MaxConcurrentRequests = 1;
//KnownAutoRetryErrors.Add((HttpStatusCode)429);
//autoRetryCount = 50;
//autoRetryDelay = 200;
//autoRetryOnKnownErrors = true;
}
public string CustomerId { get { return privCustomerId; } }
public string SiteId
{
get { return InstanceId; }
set { InstanceId = value; }
}
private protected override async Task<cCredentialLoginInfo> privLogonWithCredentialsAsync(NetworkCredential credentials)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _usr = credentials.UserName;
if (!string.IsNullOrEmpty(credentials.Domain))
_usr = $"{credentials.Domain}\\{_usr}";
var _auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{_usr}:{credentials.Password}"));
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", _auth);
httpClient.BaseAddress = new Uri(RequestBaseUrl);
var _result = await httpClient.PostAsync(constLogonUrl, null);
if (_result != null)
{
var content = await _result.Content.ReadAsStringAsync();
if (_result.IsSuccessStatusCode)
{
var JO = JObject.Parse(content);
var token = JO["Token"]?.ToString();
var CustomerId = JO["CustomerId"]?.ToString();
var strExpires = JO["ExpiresAt"]?.ToString();
if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(CustomerId) || string.IsNullOrEmpty(strExpires))
{
LastErrorMessage = $"CVAD Logon failed because no valid token information could be found in the logon result.";
return new cCredentialLoginInfo();
}
if (!DateTime.TryParse(strExpires, out var expires))
{
LastErrorMessage = $"CVAD Logon failed because no valid expiration information could be found in the logon result.";
return new cCredentialLoginInfo();
}
expires = DateTime.SpecifyKind(expires, DateTimeKind.Utc);
var _now = DateTime.UtcNow;
var _expieresInteral = expires - _now;
var _delta = _expieresInteral.TotalSeconds * RelogonFactor;
var expires2 = _now + TimeSpan.FromSeconds(_delta);
this.privCustomerId = CustomerId;
return new cCredentialLoginInfo() { IsValid = true, Token = token, TokenExpiresIn = expires2 };
}
else
{
LastErrorMessage = $"CVAD Logon failed with status code {(int)_result.StatusCode}: {_result.ReasonPhrase}";
}
}
else
LastErrorMessage = $"CVAD Logon failed due to unknown reason.";
}
}
catch (Exception E)
{
LastErrorMessage = $"CVAD Logon failed with exception: {E.Message}";
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return new cCredentialLoginInfo();
}
private protected override List<KeyValuePair<string, string>> GetRequestHeaders(cOAuthLogonInfo privLogonInfo)
{
var _retVal = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("Authorization", $"CwsAuth Bearer={AccessToken}")
};
if (privCustomerId != null)
_retVal.Add(new KeyValuePair<string, string>("Citrix-CustomerId", privCustomerId));
if (InstanceId != null)
_retVal.Add(new KeyValuePair<string, string>("Citrix-InstanceId", InstanceId));
return _retVal;
}
}
public class cCitrixCommunicationOnPremMonitor : cHttpApiBase
{
private const string constLogonUrl = "Users?$top=1&$select=Id";
public cCitrixCommunicationOnPremMonitor(string baseUrl) : base("Citrix on-prem system", baseUrl, "Citrix API", baseUrl + string.Format("/Citrix/Monitor/OData/v4/Data/"))
{
}
private protected override async Task<cCredentialLoginInfo> privLogonWithCredentialsAsync(NetworkCredential credentials)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{credentials.Domain}\\{credentials.UserName}:{credentials.Password}"));
using (var _handler = new HttpClientHandler())
{
_handler.Credentials = credentials;
_handler.PreAuthenticate = true;
using (var httpClient = new HttpClient(_handler))
{
httpClient.BaseAddress = new Uri(RequestBaseUrl);
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var _result = await httpClient.GetAsync(constLogonUrl);
if (_result != null)
{
var content = await _result.Content.ReadAsStringAsync();
if (_result.IsSuccessStatusCode)
return new cCredentialLoginInfo() { IsValid = true, Token = null, TokenExpiresIn = DateTime.MaxValue, useAlwaysCredentials = true };
else
LastErrorMessage = $"Monitor Logon failed with status code {(int)_result.StatusCode}: {_result.ReasonPhrase}";
}
else
LastErrorMessage = $"Monitor Logon failed due to unknown reason.";
}
}
}
catch (Exception E)
{
LastErrorMessage = $"Monitor Logon failed with exception: {E.Message}";
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return new cCredentialLoginInfo();
}
private protected override List<KeyValuePair<string, string>> GetRequestHeaders(cOAuthLogonInfo privLogonInfo)
{
var _retVal = new List<KeyValuePair<string, string>>();
{
new KeyValuePair<string, string>("Accept", "application/json");
}
;
return _retVal;
}
}
public class cCitrixCommunicationBase
{
private cHttpApiBase HttpApi;
public Uri baseUri { get; private set; }
public string LastErrorMessage { get { return HttpApi.LastErrorMessage; } }
public cCitrixCommunicationBase(cHttpApiBase HttpApi, string baseUrl)
{
this.HttpApi = HttpApi;
this.baseUri = new Uri(new Uri(HttpApi.RequestBaseUrl), baseUrl);
}
public async Task<cCitrixApiResultBase> RequestAsync(string Request, eHttpMethod httpMethod, object JsonData, string nameProperty = null, bool retryForbidden = false, bool noAutoRelogon = false, CancellationToken token = default)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var uriRequest = new Uri(baseUri, Request);
var data = await HttpApi.privRequestAsync(uriRequest.OriginalString, httpMethod, JsonData, retryForbidden, noAutoRelogon: noAutoRelogon, token: token);
if (data == null)
return null;
if (data is bool isValid)
{
if (isValid)
return new cCitrixApiResultBase(null);
else
return null;
}
var RetVal = new cCitrixApiResultBase(data, nameProperty);
return RetVal;
}
catch (Exception E)
{
cLogManager.LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public async Task<cCitrixApiResultList> RequestListAsync(string Request, bool loadPaged, bool retryForbidden, CancellationToken token = default)
{
try
{
var uriRequest = new Uri(baseUri, Request);
var res = await HttpApi.privRequestAsync(uriRequest.OriginalString, autoRetry: retryForbidden, token: token);
if (res != null)
{
var RetVal = new cCitrixApiResultList(retryForbidden);
RetVal.AddResult(res);
if (!RetVal.hasRemaining || loadPaged)
return RetVal;
while (RetVal.hasRemaining)
{
if (!await RequestNextAsync(RetVal))
return RetVal;
}
return RetVal;
}
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
}
return null;
}
public async Task<bool> RequestNextAsync(cCitrixApiResultList List, CancellationToken token = default)
{
try
{
var res = await HttpApi.privRequestAsync(List.NextResultUrl, autoRetry: List.retryForbidden, token: token);
if (res != null)
{
List.AddResult(res);
return true;
}
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
}
return false;
}
}
public class cCitrixCommunicationCvad
{
public const string constCitrixCvadUrl = "cvad/";
public const string constCitrixApiMe = "manage/Me";
public const string constCitrixApiMachineNames = "manage/Machines?fields=DnsName";
public const string constCitrixApiSessions = "manage/Sessions?fields=Id,Uid,State,StartTime";
public cCitrixCommunicationBase Request { get; private set; }
public iCitrixCvadInfo CitrixInfo { get; private set; }
public cCitrixCommunicationCvad(cCitrixCommunicationCloudBase CitrixCloud)
{
this.Request = new cCitrixCommunicationBase(CitrixCloud, constCitrixCvadUrl);
this.CitrixInfo = CitrixCloud as iCitrixCvadInfo;
}
public cCitrixCommunicationCvad(cCitrixCommunicationOnPremCvad OnPremCvad)
{
this.Request = new cCitrixCommunicationBase(OnPremCvad, null);
this.CitrixInfo = OnPremCvad as iCitrixCvadInfo;
}
public string GetServer()
{
return Request?.baseUri?.Host;
}
public async Task<cCitrixCustomerInfo> GetCustomerInfoAsync(CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _resultMe = await Request.RequestAsync(constCitrixApiMe, eHttpMethod.get, null);
if (Token.IsCancellationRequested)
return null;
if (_resultMe?.Result == null)
return null;
var _obj = _resultMe.Result.Customers;
var _customers = _obj as IEnumerable<dynamic>;
if (_customers == null)
return null;
cCitrixCustomerInfo _retVal = null;
foreach (var _customer in _customers) {
var id = _customer.Id;
if (id != CitrixInfo?.CustomerId)
continue;
_retVal = new cCitrixCustomerInfo()
{
Id = _customer.Id,
Name = _customer?.Name
};
_obj = _customer.Sites;
var _sites = _obj as IEnumerable<dynamic>;
if (_sites != null)
foreach (var _site in _sites)
{
try
{
if (Guid.TryParse(_site.Id.ToString(), out Guid _id))
{
var siteInfo = new cCitrixSiteInfo()
{
Id = _id,
Name = _site.Name
};
_retVal.Sites[_id] = siteInfo;
}
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
}
}
}
return _retVal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public async Task<List<string>> GetMachineNamesAsync(CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _result = await Request.RequestAsync(constCitrixApiMachineNames, eHttpMethod.get, null, token: token);
if (_result?.Result == null)
return null;
var _items = _result.Result?.Items as IEnumerable<dynamic>;
if (_items == null)
return null;
var _retVal = new List<string>();
foreach ( var item in _items )
{
try
{
var _dnsName = item.DnsName?.ToString()?.ToLowerInvariant();
if (!string.IsNullOrEmpty( _dnsName ))
_retVal.Add( _dnsName );
}
catch (Exception E)
{
LogException(E);
}
}
return _retVal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
public class SessionInfo
{
public string Id { get; set; }
public string Uid { get; set; }
public string State { get; set; }
public DateTime? StartTime { get; set; }
}
public async Task<List<SessionInfo>> GetSessionsAsync()
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
var _result = await Request.RequestAsync(constCitrixApiSessions, eHttpMethod.get, null);
if (_result?.Result == null)
return null;
var _items = _result.Result?.Items as IEnumerable<dynamic>;
if (_items == null)
return null;
var _retVal = new List<SessionInfo>();
foreach (var item in _items)
{
try
{
var _sessionInfo = new SessionInfo()
{
Id = item.Id?.ToString(),
Uid = item.Uid?.ToString(),
State = item.State?.ToString(),
StartTime = item.StartTime != null ? (DateTime?)item.StartTime : null
};
_retVal.Add(_sessionInfo);
}
catch (Exception E)
{
LogException(E);
}
}
return _retVal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return null;
}
}
public class cCitrixCommunicationMonitor
{
public const string constCitrixCloudUrl = "monitorodata/";
public const string constCitrixMachineNames = "Machines/?$select=DnsName&$filter=DesktopGroupId+ne+null+and+Name+ne+null";
public const string constCitrixUserList = "Users?$select=Id,Sid,Upn,Domain&$filter=Domain ne ''";
public const string constCitrixMachineList = "Machines?$select=Id,Sid,DnsName&$filter=DesktopGroupId ne null and Name ne null";
public const string constCitrixSessionListDetailed = "Sessions?$select=SessionKey,StartDate,EndDate,ConnectionState, UserId, MachineId&$expand=Machine($select=Id,DnsName,Name)&$filter=EndDate eq null or EndDate gt {0}";
public int MaxPageSize { get; set; } = 100;
public cCitrixCommunicationBase Request { get; private set; }
public cCitrixCommunicationMonitor(cCitrixCommunicationCloudBase CitrixCloud)
{
this.Request = new cCitrixCommunicationBase(CitrixCloud, constCitrixCloudUrl);
}
public cCitrixCommunicationMonitor(cCitrixCommunicationOnPremMonitor OnPremMonitor)
{
this.Request = new cCitrixCommunicationBase(OnPremMonitor, null);
}
private string getFormattedDateTime(int DayOffset = 0)
{
var _dateTime = DateTime.UtcNow.AddDays(DayOffset);
var _strDateTime = _dateTime.ToString("yyyy-MM-ddTHH:mm:ssZ");
return _strDateTime;
}
private string getFormattedGuid(Guid id)
{
return id.ToString("D");
}
public async Task<List<string>> GetMachineNamesAsync(CancellationToken token)
{
var _processor = new ScanEntryStringListProcessor("DnsName", true);
var _count = await RequestListAsync(constCitrixMachineList, _processor.ProcessScannedItemAsync, token: token);
return _processor.Result;
}
public delegate Task<bool> ProcessScanEntryDelegate(dynamic ScanEntry, CancellationToken token);
public abstract class ScanEntryProcessor
{
public abstract Task<bool> ProcessScannedItemAsync(dynamic _node, CancellationToken token);
}
public class ScanEntryCountProcessor : ScanEntryProcessor
{
private string nameProperty = null;
public ScanEntryCountProcessor(string nameProperty)
{
this.nameProperty = nameProperty;
}
public async override Task<bool> ProcessScannedItemAsync(dynamic _node, CancellationToken token)
{
try
{
string _prop = cCitrixApiResultBase.GetStringFromDynamic(_node, nameProperty);
if (!string.IsNullOrEmpty(_prop))
return true;
}
catch (Exception E)
{
LogException(E);
}
return false;
}
}
public class ScanEntryStringListProcessor : ScanEntryProcessor
{
private string nameProperty = null;
private bool toLowercase = false;
public List<string> Result = new List<string>();
public ScanEntryStringListProcessor(string nameProperty, bool toLowercase = false)
{
this.nameProperty = nameProperty;
this.toLowercase = toLowercase;
}
public async override Task<bool> ProcessScannedItemAsync(dynamic _node, CancellationToken token)
{
try
{
string _prop = cCitrixApiResultBase.GetStringFromDynamic(_node, nameProperty);
if (!string.IsNullOrEmpty(_prop))
{
if (toLowercase)
_prop = _prop.ToLowerInvariant();
Result.Add(_prop);
return true;
}
}
catch (Exception E)
{
LogException(E);
}
return false;
}
}
private async Task<int> RequestListAsync(string Url, ProcessScanEntryDelegate ProcessScanEntry, CancellationToken token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
int countTotal = 0;
int skipping = 0;
int lastCount = 0;
do
{
lastCount = 0;
var _url = Url + $"&$top={MaxPageSize}&$skip={skipping}";
var _result = await Request.RequestAsync(_url, eHttpMethod.get, null, token: token);
if (_result == null || _result.Result == null)
return -1;
var _items = _result.Result?.value as IEnumerable<dynamic>;
if (_items == null)
return -1;
foreach (var item in _items)
{
try
{
var _item = item as dynamic;
var _ok = await ProcessScanEntry(_item, token);
if (token.IsCancellationRequested)
return 0;
if (_ok)
{
lastCount++;
countTotal++;
}
}
catch (Exception E)
{
LogException(E);
}
}
skipping += lastCount;
} while (lastCount >= MaxPageSize);
return countTotal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
return -1;
}
public async Task<int> ScanUsersAsync(ScanEntryProcessor _processor, CancellationToken token)
{
return await RequestListAsync(constCitrixUserList, _processor.ProcessScannedItemAsync, token);
}
public async Task<int> ScanMachinesAsync(ScanEntryProcessor _processor, CancellationToken token)
{
return await RequestListAsync(constCitrixMachineList, _processor.ProcessScannedItemAsync, token);
}
public async Task<int> ScanSessionsAsync(ScanEntryProcessor _processor, int DayOffset, CancellationToken token)
{
var _url = string.Format(constCitrixSessionListDetailed, getFormattedDateTime(DayOffset));
return await RequestListAsync(_url, _processor.ProcessScannedItemAsync, token);
}
}
}