Modifica YAML:

- messo doxygen al posto di docfx
- update doc classe appCheck
This commit is contained in:
Samuele Locatelli
2025-11-28 09:27:43 +01:00
parent db589e9716
commit bbbb7a6f85
7 changed files with 355 additions and 47 deletions
+1
View File
@@ -16,6 +16,7 @@ EgwProxy/EgwProxy.dll
# Doxygen generated docs
docs/*
doxygen/*
# Build results
[Dd]ebug/
+10 -10
View File
@@ -17,11 +17,11 @@ variables:
.DocReplica: &DocReplica
- |
net use X: /delete
net use X: $env:NET_SHARE_X /u:$env:NET_USER_X $XDRIVE_PASSWD
ROBOCOPY docfx X:\$env:APP_NAME /MIR /XF .git* /XD .git
net use A: /delete
net use A: $env:NET_SHARE_X /u:$env:NET_USER_X $XDRIVE_PASSWD
ROBOCOPY doxygen A:\$env:APP_NAME /MIR /XF .git* /XD .git
SLEEP 2
net use X: /delete
net use A: /delete
# helper x fix pacchetti nuget da repo locale nexus.steamware.net
.nuget-fix: &nuget-fix
@@ -191,7 +191,7 @@ variables:
stages:
- build
- release
- docfx
- doxygen
# --------------------------------
# BUILD
@@ -239,10 +239,10 @@ IOB-MAN:release:
- *SendToVersionsLog
# --------------------------------
# DocFx
# doxygen
# --------------------------------
IOB-MAN:docfx:
stage: docfx
IOB-MAN:doxygen:
stage: doxygen
needs: ["IOB-MAN:build"]
tags:
- win
@@ -257,6 +257,6 @@ IOB-MAN:docfx:
- *nuget-fix
- '& "$env:NUGET_PATH" restore "$env:APP_NAME.sln" -verbosity quiet'
script:
- docfx $env:APP_NAME/docfx.json
- mv $env:APP_NAME/_site "docfx"
- doxygen Doxyfile
# - mv $env:APP_NAME/_site "doxygen"
- *DocReplica
+1 -1
View File
@@ -3,7 +3,7 @@
#---------------------------------------------------------------------------
PROJECT_NAME = "IOB-MAN"
OUTPUT_DIRECTORY = docs
OUTPUT_DIRECTORY = doxygen
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
EXTRACT_ALL = YES
@@ -1,3 +1,17 @@
/// <summary>
/// Component responsible for monitoring and managing IOB (Industrial Operation Block) services.
///
/// This Blazor component displays real-time status of running processes, provides UI controls
/// for starting/stopping services, and manages auto-restart logic based on configuration and thresholds.
///
/// Key Features:
/// - Displays live status of IOB services (running, stopped, ratio, color-coded indicators).
/// - Enables user to open process folders (config, logs, target paths).
/// - Supports dynamic filtering by IOB type.
/// - Implements auto-restart logic triggered when service health degrades.
/// - Integrates with external services (AppControlService, FluxLogManService) via DI.
/// - Handles UI state updates via parameterized events and background scanning.
/// </summary>
using IOB_MAN.Core;
using IOB_MAN.Core.Services;
using Microsoft.AspNetCore.Components;
@@ -13,6 +27,12 @@ namespace IOB_MAN.Components.Compo
{
#region Public Methods
/// <summary>
/// Cleans up event subscriptions and resources when the component is disposed.
///
/// Specifically:
/// - Unsubscribes from ACService.StatusUpdated event.
/// </summary>
public void Dispose()
{
ACService.EA_StatusUpdated -= ACService_EA_StatusUpdated;
@@ -22,17 +42,37 @@ namespace IOB_MAN.Components.Compo
#region Protected Fields
/// <summary>
/// Selected IOB type filter (e.g., "PLC", "SCADA", "HMI").
/// Used to filter displayed records in the UI.
/// </summary>
protected string iobTypeSel = "";
/// <summary>
/// List of page sizes available for record pagination (e.g., 5, 10, 20 records per page).
/// Used in UI for user-controlled pagination.
/// </summary>
protected List<int> PageSizeDispl = new List<int>() { 5, 10, 15, 20, 25, 50 };
#endregion Protected Fields
#region Protected Properties
/// <summary>
/// Injected service for managing external applications and service states.
/// Responsible for opening, closing, and monitoring IOB processes.
/// </summary>
[Inject]
protected AppControlService ACService { get; set; } = null!;
/// <summary>
/// Gets or sets whether auto-restart is enabled.
///
/// Behavior:
/// - When enabled, triggers automatic restart of closed services.
/// - When disabled, delays restart until a configurable threshold (VetoAutoCheck) is reached.
/// - On change, updates service state and forces UI reload.
/// </summary>
protected bool AutoRestart
{
get => ACService.AutoRestartEnabled;
@@ -41,7 +81,6 @@ namespace IOB_MAN.Components.Compo
if (ACService.AutoRestartEnabled != value)
{
ACService.AutoRestartEnabled = value;
// eseguo check/riavvio...
if (value)
{
ACService.DoReopenClosed();
@@ -57,11 +96,23 @@ namespace IOB_MAN.Components.Compo
}
}
/// <summary>
/// CSS style for context menu (positioned absolutely at mouse coordinates).
/// Dynamically set based on user right-click position.
/// </summary>
protected string contextMenuStyle
{
get => $"position: absolute; top: {menuYpx}; left: {menuXpx}; z-index:999;";
}
/// <summary>
/// CSS class for process startup status indicator.
///
/// Color logic:
/// - If fewer than configured processes are started ? "text-info"
/// - If <50% of processes are running ? "text-danger"
/// - If 50% to 100% running ? "text-warning"
/// </summary>
protected string cssCheckProc
{
get
@@ -87,6 +138,14 @@ namespace IOB_MAN.Components.Compo
}
}
/// <summary>
/// CSS class for "active processes" status.
///
/// Color logic:
/// - If <50% of started processes are running ? "bg-danger"
/// - If 50% to 100% running ? "bg-warning"
/// - Otherwise ? "bg-success"
/// </summary>
protected string cssProcAttivi
{
get
@@ -105,6 +164,14 @@ namespace IOB_MAN.Components.Compo
}
}
/// <summary>
/// CSS class for "started processes" status.
///
/// Color logic:
/// - If <50% of configured processes are started ? "bg-danger"
/// - If 50% to 100% started ? "bg-warning"
/// - Otherwise ? "bg-success"
/// </summary>
protected string cssProcAvviati
{
get
@@ -123,14 +190,26 @@ namespace IOB_MAN.Components.Compo
}
}
/// <summary>
/// Current list of IOB types (e.g., PLC, SCADA) available in the system.
/// Retrieved from ACService.
/// </summary>
protected List<string> CurrIobType
{
get => ACService.CurrIobType;
}
/// <summary>
/// Injected service for managing flux log data and opening log views.
/// Used to open specific log files or view logs for a selected IOB.
/// </summary>
[Inject]
protected FluxLogManService FLMService { get; set; } = null!;
/// <summary>
/// Selected IOB type (user-filtered value).
/// Updates UI when changed and triggers a reload.
/// </summary>
protected string IobTypeSel
{
get => iobTypeSel;
@@ -144,11 +223,16 @@ namespace IOB_MAN.Components.Compo
}
}
/// <summary>
/// Injected JS runtime for interacting with browser APIs (e.g., confirm dialogs).
/// Used for user confirmation before reboot or restart actions.
/// </summary>
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
/// <summary>
/// Livello Log impostato
/// Current logging level (e.g., Debug, Info, Warning).
/// Controls verbosity of logs in the application.
/// </summary>
protected LogLevelIob LogLevel
{
@@ -156,29 +240,52 @@ namespace IOB_MAN.Components.Compo
set => ACService.LogLevel = value;
}
/// <summary>
/// Navigation manager for routing to pages (e.g., About, Settings).
/// </summary>
[Inject]
protected NavigationManager NavMan { get; set; } = null!;
/// <summary>
/// Total number of configured IOB processes.
/// Used to calculate startup and running ratios.
/// </summary>
protected int NumProcConfig
{
get => ACService.NumProcConfig;
}
/// <summary>
/// Number of IOB processes currently running.
/// Used in status indicators and health checks.
/// </summary>
protected int NumProcRunning
{
get => ACService.NumProcRunning;
}
/// <summary>
/// Number of IOB processes that have been started (not necessarily running).
/// Used in status indicators and auto-restart logic.
/// </summary>
protected int NumProcStarted
{
get => ACService.NumProcStarted;
}
/// <summary>
/// Total number of configured IOB types.
/// Used for type-based filtering and UI display.
/// </summary>
protected int NumTypeConfig
{
get => ACService.NumTypeConfig;
}
/// <summary>
/// Round-trip time (in ms) for communication between components and services.
/// Used to measure responsiveness and performance.
/// </summary>
protected double RoundTrip
{
get => ACService.RoundTrip;
@@ -188,25 +295,54 @@ namespace IOB_MAN.Components.Compo
#region Protected Methods
/// <summary>
/// Returns CSS class based on whether a specific IOB is running.
///
/// Style:
/// - If not running ? "bg-danger bg-opacity-25"
/// - Otherwise ? empty (default background)
/// </summary>
/// <param name="currRec">The IOB record to evaluate.</param>
/// <returns>Appropriate CSS class string.</returns>
protected string CssClassIob(IobAdapt currRec)
{
string css = !currRec.isRunning ? "bg-danger bg-opacity-25" : "";
return css;
}
/// <summary>
/// Delays a restart request by setting a countdown timer in the UI.
///
/// Used when auto-restart is disabled to prevent immediate restarts.
/// </summary>
protected void DelayRestart()
{
ACService.DelayRestart(false);
}
/// <summary>
/// Closes all child IOB processes and refreshes the UI.
///
/// Actions:
/// - Stops all running services.
/// - Triggers a full scan to update state.
/// - Optionally resets the list of services.
/// </summary>
protected async Task DoCloseAll()
{
// chiude tutto
CloseAllChild(false);
await ACService.DoScan();
//ForceReload();
// ForceReload(); // Optional: can be removed if UI refresh is handled elsewhere
}
/// <summary>
/// Closes a specific child IOB process.
///
/// Action:
/// - Sends a close command to the service.
/// - Hides the right-click menu.
/// </summary>
/// <param name="currRec">The IOB record to close.</param>
protected void DoCloseChild(IobAdapt currRec)
{
ACService.DoCloseChild(currRec);
@@ -214,9 +350,13 @@ namespace IOB_MAN.Components.Compo
}
/// <summary>
/// Nasconde gli IOB
/// Minimizes all IOB process windows to the system tray.
///
/// Behavior:
/// - Iterates over all CurrRecords.
/// - For each process, retrieves its MainWindowHandle and minimizes it.
/// - Logs any errors (e.g., process already closed).
/// </summary>
/// <returns></returns>
protected void DoHideAll()
{
foreach (var item in CurrRecords)
@@ -224,23 +364,29 @@ namespace IOB_MAN.Components.Compo
try
{
Process p = Process.GetProcessById(item.pID);
// cerco e chiudo quelli che mi interessano...
var windowsHandle = p.MainWindowHandle;
ShowWindowAsync(windowsHandle, CoreEnum.SW_SHOWMINIMIZED);
}
catch (Exception exc)
{
// errore era già chiuso..
Log.Error($"Errore in HIDE windows:{Environment.NewLine}{exc}");
}
}
}
/// <summary>
/// Reboots all IOB processes and optionally reloads configuration.
///
/// Actions:
/// - Closes all services.
/// - If 'reloadConf' is true, re-scans configuration and reloads it.
/// - Reopens all services.
/// - Triggers a final scan to update UI.
/// </summary>
/// <param name="reloadConf">If true, re-reads configuration after restart.</param>
protected async Task DoRestartAll(bool reloadConf)
{
// chiude tutto
CloseAllChild(true);
// se richiesto rilettura conf riesegue anche quello...
if (reloadConf)
{
await ACService.DoScan();
@@ -251,7 +397,12 @@ namespace IOB_MAN.Components.Compo
}
/// <summary>
/// Mostra in primo piano tutte le finestre IOB
/// Restores all IOB process windows to full screen.
///
/// Behavior:
/// - Iterates over all CurrRecords.
/// - For each process, retrieves its MainWindowHandle and restores it.
/// - Logs any errors (e.g., process already closed).
/// </summary>
protected void DoShowAll()
{
@@ -260,43 +411,62 @@ namespace IOB_MAN.Components.Compo
try
{
Process p = Process.GetProcessById(item.pID);
// cerco e chiudo quelli che mi interessano...
var windowsHandle = p.MainWindowHandle;
ShowWindowAsync(windowsHandle, CoreEnum.SW_SHOWNORMAL);
}
catch (Exception exc)
{
// errore era già chiuso..
Log.Error($"Errore in SHOW windows:{Environment.NewLine}{exc}");
}
}
}
/// <summary>
/// Mostra in primo piano tutte le finestre IOB
/// Restores a specific IOB process window.
///
/// Action:
/// - Finds the process by ID and restores it to normal view.
/// </summary>
/// <param name="item">The IOB record to restore.</param>
protected void DoShowChild(IobAdapt item)
{
try
{
Process p = Process.GetProcessById(item.pID);
// cerco e chiudo quelli che mi interessano...
var windowsHandle = p.MainWindowHandle;
ShowWindowAsync(windowsHandle, CoreEnum.SW_SHOWNORMAL);
}
catch (Exception exc)
{
// errore era già chiuso..
Log.Error($"Errore in SHOW windows:{Environment.NewLine}{exc}");
}
}
/// <summary>
/// Starts a specific IOB process.
///
/// Action:
/// - Sends a command to ACService to open and start the selected IOB.
/// - Hides the right-click menu.
/// </summary>
/// <param name="currRec">The IOB record to start.</param>
protected void DoStartChild(IobAdapt currRec)
{
ACService.DoOpenChildSel(currRec);
dxMenuVisible = false;
}
/// <summary>
/// Forces a full scan of all IOB services and updates UI state.
///
/// Actions:
/// - Sets isLoading to true.
/// - Clears current records.
/// - Calls DoScan() to refresh service list.
/// - Updates filtered list based on current filters (e.g., IOB type).
/// - Applies pagination.
/// - Sets isLoading to false and triggers UI update.
/// </summary>
protected async Task ForceCheck()
{
isLoading = true;
@@ -305,17 +475,37 @@ namespace IOB_MAN.Components.Compo
isLoading = false;
}
/// <summary>
/// Initializes the component.
///
/// Action:
/// - Subscribes to ACService.StatusUpdated event to update UI on status changes.
/// </summary>
protected override void OnInitialized()
{
ACService.EA_StatusUpdated += ACService_EA_StatusUpdated;
}
/// <summary>
/// Called when parameters change (e.g., user selects a new IOB type).
///
/// Actions:
/// - Triggers a full scan of services.
/// - Updates the UI with filtered records.
/// </summary>
protected override async Task OnParametersSetAsync()
{
await ACService.DoScan();
ForceReload();
}
/// <summary>
/// Updates the number of records per page (e.g., from 10 to 20).
///
/// Behavior:
/// - Updates the page count and triggers a reload to refresh the UI.
/// </summary>
/// <param name="newNum">New number of records per page.</param>
protected void SetNumRec(int newNum)
{
numRecord = newNum;
@@ -323,6 +513,13 @@ namespace IOB_MAN.Components.Compo
ForceReload();
}
/// <summary>
/// Updates the current page (e.g., page 2, 3, etc.).
///
/// Behavior:
/// - Updates the page number and triggers a reload to refresh the UI.
/// </summary>
/// <param name="newNum">New page number.</param>
protected void SetPage(int newNum)
{
currPage = newNum;
@@ -334,58 +531,116 @@ namespace IOB_MAN.Components.Compo
#region Private Fields
/// <summary>
/// Classe logger
/// Logger instance for structured logging within this component.
/// </summary>
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Timestamp of last UI render to prevent rapid re-renders.
/// Prevents excessive updates when data changes quickly.
/// </summary>
private DateTime _lastRender = DateTime.MinValue;
/// <summary>
/// Auto-restart countdown (in seconds) displayed in UI.
/// Shows time remaining before auto-restart is triggered.
/// </summary>
private string countAutoRestart = "";
/// <summary>
/// Flag indicating whether the right-click menu is visible.
/// Used for UI state management.
/// </summary>
private bool dxMenuVisible = false;
/// <summary>
/// Flag controlling whether task killing is allowed (e.g., for safety).
/// </summary>
private bool enableKillTask = true;
/// <summary>
/// X-coordinate for context menu positioning (in pixels).
/// Set dynamically on right-click.
/// </summary>
private string menuXpx = "0px";
/// <summary>
/// Y-coordinate for context menu positioning (in pixels).
/// Set dynamically on right-click.
/// </summary>
private string menuYpx = "0px";
/// <summary>
/// Currently selected IOB record (used for actions like opening folders).
/// </summary>
private IobAdapt? selIOB = null;
#endregion Private Fields
#region Private Properties
/// <summary>
/// Current computer name (e.g., "DESKTOP-ABC123").
/// </summary>
private string ComputerName
{
get => Environment.MachineName;
}
/// <summary>
/// Css e abilitazione chiusura (solo se c'è qualcosa da chiudere)
/// CSS class for "Close All" button.
///
/// Behavior:
/// - Enabled only if at least one service is currently running.
/// - Disabled otherwise (grayed out).
/// </summary>
private string cssBtnCloseAll
{
get => NumProcStarted > 0 ? "" : "disabled opacity-50";
}
/// <summary>
/// Current page number (1-indexed).
/// </summary>
private int currPage { get; set; } = 1;
/// <summary>
/// Current list of IOB service records (e.g., PLC, HMI).
/// Retrieved from ACService and used for UI display.
/// </summary>
private List<IobAdapt> CurrRecords
{
get => ACService.ListIobAdapters;
}
/// <summary>
/// User domain (e.g., "DOMAIN\\username").
/// </summary>
private string DomainName
{
get => Environment.UserDomainName;
}
/// <summary>
/// Indicates whether the UI is loading (used for spinner or placeholder state).
/// </summary>
private bool isLoading { get; set; } = false;
/// <summary>
/// Paginated list of records currently displayed in the UI.
/// Filtered and paginated based on IOB type and page size.
/// </summary>
private List<IobAdapt>? ListRecords { get; set; } = null;
/// <summary>
/// Number of records per page (e.g., 10, 20).
/// </summary>
private int numRecord { get; set; } = 10;
/// <summary>
/// Target path for a selected IOB (e.g., C:\IOB\PLC\001).
/// Built dynamically from CodIOB and ACService.
/// </summary>
private string selIobTgtPath
{
get
@@ -395,8 +650,14 @@ namespace IOB_MAN.Components.Compo
}
}
/// <summary>
/// Total number of records (used for pagination and UI display).
/// </summary>
private int totalCount { get; set; } = 0;
/// <summary>
/// Current user name (e.g., "JohnDoe").
/// </summary>
private string UserName
{
get => Environment.UserName;
@@ -406,17 +667,29 @@ namespace IOB_MAN.Components.Compo
#region Private Methods
/// <summary>
/// Windows API: Shows a window with a specified style (e.g., minimized, normal).
/// Used to minimize or restore IOB process windows.
/// </summary>
/// <param name="hWnd">Handle to the window.</param>
/// <param name="nCmdShow">Style (e.g., SW_SHOWMINIMIZED, SW_SHOWNORMAL).</param>
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
/// <summary>
/// Handles status updates from ACService.
///
/// Logic:
/// - If auto-restart is disabled, shows countdown until auto-restart is triggered.
/// - When countdown reaches zero, enables auto-restart.
/// - Forces UI reload to reflect new state.
/// </summary>
private void ACService_EA_StatusUpdated()
{
// verifico gestione atuorestart...
if (!AutoRestart)
{
var remSec = (int)ACService.VetoAutoCheck.Subtract(DateTime.Now).TotalSeconds;
countAutoRestart = remSec > 0 ? $"{remSec:N0}" : "!!!";
// se va a zero... abilito riavvio!
if (remSec <= 0)
{
AutoRestart = true;
@@ -426,9 +699,12 @@ namespace IOB_MAN.Components.Compo
}
/// <summary>
/// Chiude tutti i child
/// Closes all child IOB processes.
///
/// Parameters:
/// - doReset: if true, resets the internal list of services.
/// </summary>
/// <param name="doReset">resetta elenco</param>
/// <param name="doReset">Whether to reset the service list after closing.</param>
private void CloseAllChild(bool doReset)
{
enableKillTask = false;
@@ -436,19 +712,35 @@ namespace IOB_MAN.Components.Compo
enableKillTask = true;
}
/// <summary>
/// Triggers a reboot request with user confirmation.
///
/// Behavior:
/// - Uses JSRuntime to show a confirmation dialog.
/// - If confirmed, raises a reboot request to ACService.
/// </summary>
/// <param name="args">Mouse event arguments (used for context menu).</param>
private async Task ForceReboot(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Sicuro di voler riavviare il programma?"))
return;
// richiesta riavvio
ACService.RaiseRebootReq();
}
/// <summary>
/// Forces a UI reload with current filters and pagination.
///
/// Behavior:
/// - Skips if too soon (less than 1 second since last render).
/// - Updates filtered list based on IOB type.
/// - Applies pagination.
/// - Updates UI state and triggers re-render.
/// </summary>
private void ForceReload()
{
if ((DateTime.Now - _lastRender).TotalSeconds < 1)
return; // skip if too soon
return;
_lastRender = DateTime.Now;
isLoading = true;
@@ -457,7 +749,6 @@ namespace IOB_MAN.Components.Compo
filtered = filtered.Where(x => x.TgtName == IobTypeSel).ToList();
totalCount = filtered.Count();
// paginazione!
ListRecords = filtered
.OrderBy(x => x.CodIOB)
.Skip(numRecord * (currPage - 1))
@@ -467,51 +758,71 @@ namespace IOB_MAN.Components.Compo
_ = InvokeAsync(StateHasChanged);
}
/// <summary>
/// Opens the target folder of the selected IOB (e.g., for configuration).
/// </summary>
private void IobFolderOpenApp()
{
if (selIOB != null)
Process.Start("explorer.exe", selIobTgtPath);
// chiudo e resetto selezione
selIOB = null;
dxMenuVisible = false;
}
/// <summary>
/// Opens the configuration folder of the selected IOB.
/// </summary>
private void IobFolderOpenConf()
{
if (selIOB != null)
Process.Start("explorer.exe", Path.Combine(selIobTgtPath, "DATA", "CONF"));
// chiudo e resetto selezione
selIOB = null;
dxMenuVisible = false;
}
/// <summary>
/// Opens the logs folder of the selected IOB.
/// </summary>
private void IobFolderOpenLog()
{
if (selIOB != null)
Process.Start("explorer.exe", Path.Combine(selIobTgtPath, "logs", selIOB.CodIOB));
// chiudo e resetto selezione
selIOB = null;
dxMenuVisible = false;
}
/// <summary>
/// Navigates to the "About" page.
/// </summary>
private void NavAbout()
{
NavMan.NavigateTo("About");
}
/// <summary>
/// Opens a FluxLog view for the selected IOB.
/// </summary>
private void OpenFLForm()
{
if (selIOB != null)
FLMService.RequestLoadFLogData(selIOB.CodIOB);
// chiudo e resetto selezione
selIOB = null;
dxMenuVisible = false;
}
/// <summary>
/// Handles right-click event on an IOB record.
///
/// Behavior:
/// - Sets selected IOB.
/// - Shows context menu at mouse position.
/// </summary>
/// <param name="e">Mouse event arguments.</param>
/// <param name="currRec">The IOB record being right-clicked.</param>
private void RightClick(Microsoft.AspNetCore.Components.Web.MouseEventArgs e, IobAdapt currRec)
{
selIOB = currRec;
@@ -525,4 +836,4 @@ namespace IOB_MAN.Components.Compo
#endregion Private Methods
}
}
}
-4
View File
@@ -9,7 +9,3 @@
<a class="text-light" href="https://www.egalware.com/" target="_blank"><img class="img-fluid" width="12" src="images/LogoEgw.png" /> Egalware </a>
</div>
</div>
@@ -1,4 +1,4 @@
namespace GPW.CORE.ADM.Components.Layout
namespace IOB_MAN.Components.Layout
{
public partial class MainLayout
{
+1 -1
View File
@@ -8,7 +8,7 @@
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Version>4.0.2511.2808</Version>
<Version>4.0.2511.2809</Version>
<Configurations>Debug;Release;Remote_DEBUG</Configurations>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>