first commit

This commit is contained in:
2026-02-09 10:55:45 -07:00
commit 7cca957e1a
77 changed files with 44415 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

371
.gitignore vendored Normal file
View File

@@ -0,0 +1,371 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
publish_final/
appSettings.json
*.bak
*.zip
dist/
publish/
Instalador/setup

24
App.config Normal file
View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="EFCDesk.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<EFCDesk.Properties.Settings>
<setting name="IdUsuario" serializeAs="String">
<value />
</setting>
<setting name="urlEFC" serializeAs="String">
<value />
</setting>
<setting name="ExpWinsaai" serializeAs="String">
<value>0</value>
</setting>
<setting name="ExpLogistico" serializeAs="String">
<value>0</value>
</setting>
</EFCDesk.Properties.Settings>
</userSettings>
</configuration>

466
Classes/ApiClient.cs Normal file
View File

@@ -0,0 +1,466 @@
using EFCDesk.Entidades;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public class ApiException : Exception
{
public int StatusCode { get; }
public ApiException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
}
public class ApiClient : IDisposable
{
private readonly HttpClient _httpClient;
private readonly int _maxRetries;
private readonly TimeSpan _retryDelay;
private string? _currentToken;
private string? _currentRefreshToken;
private readonly object _tokenLock = new object();
public ApiClient(TimeSpan? timeout = null, int maxRetries = 3, TimeSpan? retryDelay = null)
{
_httpClient = new HttpClient();
if (timeout.HasValue)
_httpClient.Timeout = timeout.Value;
else
_httpClient.Timeout = TimeSpan.FromSeconds(30);
_maxRetries = maxRetries >= 0 ? maxRetries : 3;
_retryDelay = retryDelay ?? TimeSpan.FromSeconds(2);
}
//private void SetAuthorization(string token)
//{
// if (string.IsNullOrWhiteSpace(token))
// throw new ArgumentException("El token no puede estar vacío.", nameof(token));
// _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token);
//}
public string EndpointLoginToken()
{
return @"/api/v1/token/";
}
public string EndpointRefreshToken()
{
return @"/api/v1/token/refresh/";
}
private void SetAuthorizationBearer(string token, string refresh_token)
{
if (string.IsNullOrWhiteSpace(token))
throw new ArgumentException("El token no puede estar vacío.", nameof(token));
if (string.IsNullOrWhiteSpace(refresh_token))
throw new ArgumentException("El refresh token no puede estar vacío.", nameof(refresh_token));
lock (_tokenLock)
{
_currentToken = token;
_currentRefreshToken = refresh_token;
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
}
private async Task<bool> TryRefreshTokenAsync()
{
try
{
Globales.configJson = ConfiguracionJSON.LoadFromJson();
// Obtener el refresh token actual guardado
string? savedToken = Globales.refresToken;
if (string.IsNullOrEmpty(savedToken))
return false;
// Usar el endpoint de refresh token
string dominio = Globales.configJson.DominioExp ?? "";
if (string.IsNullOrEmpty(dominio))
return false;
string refreshUrl = dominio + EndpointRefreshToken();
// Crear solicitud de refresh con el token actual
var refreshData = new { refresh = savedToken };
var jsonContent = JsonSerializer.Serialize(refreshData);
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
// Limpiar headers para esta solicitud
_httpClient.DefaultRequestHeaders.Authorization = null;
var response = await _httpClient.PostAsync(refreshUrl, content);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
if (IsJson(responseContent) && HasJsonData(responseContent))
{
using var doc = JsonDocument.Parse(responseContent);
var root = doc.RootElement;
// Buscar nuevo token en la respuesta (ajustar según tu API)
string newToken = "";
if (root.TryGetProperty("access", out var accessProp))
{
newToken = accessProp.GetString() ?? "";
}
else if (root.TryGetProperty("token", out var tokenProp))
{
newToken = tokenProp.GetString() ?? "";
}
// Buscar nuevo refresh token en la respuesta (ajustar según tu API)
string newRefreshToken = "";
if (root.TryGetProperty("refresh", out var refreshProp))
{
newRefreshToken = refreshProp.GetString() ?? "";
}
else if (root.TryGetProperty("refresh_token", out var refreshtokenProp))
{
newRefreshToken = refreshtokenProp.GetString() ?? "";
}
if (!string.IsNullOrEmpty(newToken) && !string.IsNullOrEmpty(newRefreshToken))
{
// Guardar nuevo token
Globales.accesToken = newToken;
// Guardar nuevo refresh token
Globales.refresToken = newRefreshToken;
// Actualizar headers
SetAuthorizationBearer(newToken, newRefreshToken);
return true;
}
}
}
return false;
}
catch (Exception ex)
{
Globales.logger.LogError("Error al intentar refresh token", ex);
return false;
}
finally
{
// Restaurar el token actual si el refresh falló
if (!string.IsNullOrEmpty(_currentToken) && !string.IsNullOrEmpty(_currentRefreshToken))
{
SetAuthorizationBearer(_currentToken, _currentRefreshToken);
}
}
}
private async Task EnsureTokenAsync()
{
// Si ya tenemos token en memoria, usarlo
if (!string.IsNullOrEmpty(_currentToken) && !string.IsNullOrEmpty(_currentRefreshToken))
{
SetAuthorizationBearer(_currentToken, _currentRefreshToken);
return;
}
// Intentar obtener token guardado
string? savedToken = Globales.accesToken;
string? savedRefreshToken = Globales.refresToken;
if (!string.IsNullOrEmpty(savedToken) && !string.IsNullOrEmpty(savedRefreshToken))
{
SetAuthorizationBearer(savedToken, savedRefreshToken);
return;
}
throw new InvalidOperationException("No hay token disponible. Inicie sesión primero.");
}
private async Task<string> SendWithRetriesAsync(Func<Task<HttpResponseMessage>> sendFunc, bool requireAuth = true)
{
int attempts = 0;
while (true)
{
attempts++;
try
{
// Asegurar que tenemos token antes de enviar (solo si requiere auth)
if (requireAuth)
await EnsureTokenAsync();
var response = await sendFunc();
if (!response.IsSuccessStatusCode)
{
// Si es 401 Unauthorized y requiere auth, intentar refresh token
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized && requireAuth)
{
bool refreshed = await TryRefreshTokenAsync();
if (refreshed)
{
// Reintentar con nuevo token
response = await sendFunc();
if (response.IsSuccessStatusCode)
return await response.Content.ReadAsStringAsync();
}
}
string errorContent = await response.Content.ReadAsStringAsync();
// throw new ApiException($"Error {response.StatusCode}: {errorContent}", (int)response.StatusCode);
return errorContent;
}
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException) when (attempts <= _maxRetries)
{
// Timeout: reintentar
await Task.Delay(_retryDelay);
}
catch (HttpRequestException) when (attempts <= _maxRetries)
{
// Error red: reintentar
await Task.Delay(_retryDelay);
}
catch (TaskCanceledException)
{
return CrearJsonError(408, "Tiempo de espera agotado");
}
catch (HttpRequestException ex)
{
return CrearJsonError(503, $"Error de red: {ex.Message}");
}
catch (Exception ex)
{
return CrearJsonError(500, $"Error inesperado: {ex.Message}");
}
}
}
public async Task<string> GetAsync(string url)
{
return await SendWithRetriesAsync(() => _httpClient.GetAsync(url));
}
public async Task<string> PostJsonAsync(string url, string jsonContent)
{
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, content));
}
public async Task<string> PutJsonAsync(string url, string jsonContent)
{
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
return await SendWithRetriesAsync(() => _httpClient.PutAsync(url, content));
}
public async Task<string> DeleteAsync(string url)
{
return await SendWithRetriesAsync(() => _httpClient.DeleteAsync(url));
}
// Método para enviar archivo y JSON juntos en multipart/form-data
public async Task<string> PostMultipartAsync(string url, string filePath, object jsonData, string fileFieldName = "archivo", string jsonFieldName = "data")
{
if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
throw new ArgumentException("El archivo no existe o la ruta es inválida.", nameof(filePath));
using var form = new MultipartFormDataContent();
// Archivo
var fileStream = File.OpenRead(filePath);
var fileContent = new StreamContent(fileStream);
form.Add(fileContent, fileFieldName, Path.GetFileName(filePath));
// JSON
var jsonString = JsonSerializer.Serialize(jsonData);
var jsonContent = new StringContent(jsonString, System.Text.Encoding.UTF8, "application/json");
form.Add(jsonContent, jsonFieldName);
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
}
public async Task<string> PostMultipartAsync(string url, string filePath, string organizacion, string pedimento,
string documentType,
string fuente,
string fileFieldName = "archivo"
)
{
if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
throw new ArgumentException("El archivo no existe o la ruta es inválida.", nameof(filePath));
using var form = new MultipartFormDataContent();
// Archivo
var fileStream = File.OpenRead(filePath);
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
form.Add(fileContent, fileFieldName, Path.GetFileName(filePath));
// Campos de texto
form.Add(new StringContent(organizacion), "organizacion");
form.Add(new StringContent(pedimento), "pedimento");
form.Add(new StringContent(documentType), "document_type");
form.Add(new StringContent(fuente), "fuente");
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
}
//public async Task<string> PostMultipartZipAsync(string url, string token, byte[] zipBytes, string zipFileName, string fileFieldName = "archivos")
//{
// if (zipBytes == null || zipBytes.Length == 0)
// throw new ArgumentException("El ZIP está vacío o no es válido.", nameof(zipBytes));
// SetAuthorization(token);
// using var form = new MultipartFormDataContent();
// // Convertimos el byte[] a contenido del archivo
// var fileContent = new ByteArrayContent(zipBytes);
// fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/zip");
// // Nombre del archivo en el multipart
// form.Add(fileContent, fileFieldName, zipFileName);
// // Campos de texto
// //form.Add(new StringContent(pedimento), "pedimento");
// return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
//}
public async Task<string> PostMultipartZipAsync(string url, string filePath, string zipFileName, Dictionary<string, string> metadatos, string fileFieldName = "archivos")
{
if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath))
throw new ArgumentException("El archivo no existe o la ruta es inválida.", nameof(filePath));
using var form = new MultipartFormDataContent();
// Archivo
var fileStream = File.OpenRead(filePath);
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
form.Add(fileContent, fileFieldName, Path.GetFileName(filePath));
if (metadatos != null)
{
foreach (var kvp in metadatos)
{
form.Add(new StringContent(kvp.Value), kvp.Key);
}
}
// Campos de texto
//form.Add(new StringContent(organizacion), "organizacion");
//form.Add(new StringContent(pedimento), "pedimento");
//form.Add(new StringContent(documentType), "document_type");
//form.Add(new StringContent(fuente), "fuente");
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, form));
}
// Método existente que acepta string JSON
public async Task<string> PostJsonWithoutAuthAsync(string url, string jsonContent)
{
using var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
return await SendWithRetriesAsync(() => _httpClient.PostAsync(url, content), requireAuth: false);
}
// Nueva sobrecarga que acepta cualquier objeto
public async Task<string> PostJsonWithoutAuthAsync(string url, object data)
{
var jsonContent = JsonSerializer.Serialize(data);
return await PostJsonWithoutAuthAsync(url, jsonContent);
}
public bool IsJson(string response)
{
if (string.IsNullOrWhiteSpace(response)) return false;
try
{
using var doc = JsonDocument.Parse(response);
return true;
}
catch (JsonException)
{
return false;
}
}
public bool HasJsonData(string response)
{
if (string.IsNullOrWhiteSpace(response)) return false;
try
{
using var doc = JsonDocument.Parse(response);
var root = doc.RootElement;
if (root.ValueKind == JsonValueKind.Object)
{
return root.EnumerateObject().Any();
}
else if (root.ValueKind == JsonValueKind.Array)
{
return root.GetArrayLength() > 0;
}
else
{
return false;
}
}
catch (JsonException)
{
return false;
}
}
// Método para deserializar el JSON a un objeto genérico
public T? TryParseJson<T>(string response) where T : class
{
if (string.IsNullOrWhiteSpace(response)) return null;
try
{
return JsonSerializer.Deserialize<T>(response);
}
catch (JsonException ex)
{
Globales.logger.LogError($"Error al deserializar JSON: {ex.Message}");
return null;
}
}
private static string CrearJsonError(int status, string message)
{
return $$"""
{
"success": false,
"status": {{status}},
"message": "{{message.Replace("\"", "\\\"")}}"
}
""";
}
public void Dispose()
{
_httpClient.Dispose();
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
internal class ArchivosProcesados
{
public int IdArchivo { get; set; }
public string NombreArchivo { get; set; }
public string RutaArchivo { get; set; }
public string Estado { get; set; }
public DateTime FechaProcesado { get; set; }
public string FolderExpedinete { get; set; }
public string ArchivoZip { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;
// using System.Deployment.Application;
using System.Reflection;
namespace EFCDesk.Classes
{
public static class AutoStartHelper
{
private const string AppName = "EFC-DESK";
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public static class AutoUpdateAppHelper
{
public static void CheckForUpdatesManually()
{
Version? installedVersion = Assembly.GetExecutingAssembly().GetName().Version;
Version latestVersion = GetLatestVersionFromConfigFile();
if (installedVersion != null && latestVersion > installedVersion)
{
MessageBox.Show($"Hay una nueva versión disponible ({latestVersion}). " +
"Por favor, instálela desde su medio de almacenamiento.");
}
}
private static Version GetLatestVersionFromConfigFile()
{
// Leer de un archivo de configuración incluido en el USB/CD
string versionFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "latest_version.txt");
if (File.Exists(versionFile))
{
return new Version(File.ReadAllText(versionFile));
}
return Assembly.GetExecutingAssembly().GetName().Version ?? new Version(1, 0, 0, 0);
}
public static void LogInstallation()
{
string logPath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData),
"EFCDeskv2", "install_log.txt");
File.AppendAllText(logPath,
$"Instalado: {DateTime.Now} | Versión: {Assembly.GetExecutingAssembly().GetName().Version}\n");
}
}
}

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public class ConfiguracionExpediente
{
public bool IniciarExpedienteWindows { get; set; }
public string? FolderParaGenerarExpediente { get; set; }
public bool DepurarExpediente { get; set; }
public string? FolderParaDepurarExpediente { get; set; }
public bool UsarEstructuraPedimentosWinsaai { get; set; }
public bool UsarExpedienteLogistico { get; set; }
public string ServidorFTP { get; set; }
public string UsuarioFTP { get; set; }
public string PasswordFTP { get; set; }
public bool ModoPasivoFTP { get; set; }
public int PuertoFTP { get; set; }
public ConfiguracionExpediente() {
ServidorFTP = "efc.aduanasoft.com";
UsuarioFTP = "expElec";
PasswordFTP = "8lackSta8";
ModoPasivoFTP = true;
PuertoFTP = 20;
}
// Método para guardar la configuración en la base de datos
public void GuardarEnBaseDeDatos(SQLiteHelper sqliteHelper)
{
try
{
using (var connection = sqliteHelper.GetConnection())
{
connection.Open();
string insertOrUpdateQuery = @"
INSERT OR REPLACE INTO Configuracion (
Id, IniciarExpedienteWindows, FolderParaGenerarExpediente, DepurarExpediente,
FolderParaDepurarExpediente, UsarEstructuraPedimentosWinsaai, UsarExpedienteLogistico, ServidorFTP, UsuarioFTP, PasswordFTP, PuertoFTP , ModoPasivoFTP
) VALUES (
1, @IniciarExpedienteWindows, @FolderParaGenerarExpediente, @DepurarExpediente,
@FolderParaDepurarExpediente, @UsarEstructuraPedimentosWinsaai, @UsarExpedienteLogistico, @ServidorFTP, @UsuarioFTP, @PasswordFTP, @PuertoFTP, @ModoPasivoFTP
);";
using (var command = new SQLiteCommand(insertOrUpdateQuery, connection))
{
command.Parameters.AddWithValue("@IniciarExpedienteWindows", IniciarExpedienteWindows ? 1 : 0);
command.Parameters.AddWithValue("@FolderParaGenerarExpediente", FolderParaGenerarExpediente ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@DepurarExpediente", DepurarExpediente ? 1 : 0);
command.Parameters.AddWithValue("@FolderParaDepurarExpediente", FolderParaDepurarExpediente ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@UsarEstructuraPedimentosWinsaai", UsarEstructuraPedimentosWinsaai ? 1 : 0);
command.Parameters.AddWithValue("@UsarExpedienteLogistico", UsarExpedienteLogistico ? 1 : 0);
command.Parameters.AddWithValue("@ServidorFTP", ServidorFTP ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@UsuarioFTP", UsuarioFTP ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@PasswordFTP", PasswordFTP ?? (object)DBNull.Value);
command.Parameters.AddWithValue("@PuertoFTP", PuertoFTP == 0 ? (object)DBNull.Value : PuertoFTP);
command.Parameters.AddWithValue("@ModoPasivoFTP", ModoPasivoFTP ? 1 : 0);
command.ExecuteNonQuery();
}
}
} catch(Exception ex) {
MessageBox.Show(ex.Message);
}
}
// Método para obtener la configuración desde la base de datos
public static ConfiguracionExpediente ObtenerDesdeBaseDeDatos(SQLiteHelper sqliteHelper)
{
using (var connection = sqliteHelper.GetConnection())
{
connection.Open();
string selectQuery = "SELECT * FROM Configuracion WHERE Id = 1;";
using (var command = new SQLiteCommand(selectQuery, connection))
{
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
return new ConfiguracionExpediente
{
IniciarExpedienteWindows = reader.GetInt32(reader.GetOrdinal("IniciarExpedienteWindows")) == 1,
FolderParaGenerarExpediente = reader["FolderParaGenerarExpediente"] as string,
DepurarExpediente = reader.IsDBNull(reader.GetOrdinal("DepurarExpediente")) ? false : (reader.GetInt32(reader.GetOrdinal("DepurarExpediente")) == 1),
FolderParaDepurarExpediente = reader["FolderParaDepurarExpediente"] as string,
UsarEstructuraPedimentosWinsaai = reader.IsDBNull(reader.GetOrdinal("UsarEstructuraPedimentosWinsaai")) ? false : (reader.GetInt32(reader.GetOrdinal("UsarEstructuraPedimentosWinsaai")) == 1),
UsarExpedienteLogistico = reader.IsDBNull(reader.GetOrdinal("UsarExpedienteLogistico")) ? false : (reader.GetInt32(reader.GetOrdinal("UsarExpedienteLogistico")) == 1),
ServidorFTP = reader["ServidorFTP"] as string,
UsuarioFTP = reader["UsuarioFTP"] as string,
PasswordFTP = reader["PasswordFTP"] as string,
ModoPasivoFTP = reader.IsDBNull(reader.GetOrdinal("ModoPasivoFTP")) ? false : (reader.GetInt32(reader.GetOrdinal("ModoPasivoFTP")) == 1),
PuertoFTP = reader.IsDBNull(reader.GetOrdinal("PuertoFTP")) ? 21 : reader.GetInt32(reader.GetOrdinal("PuertoFTP"))
};
}
}
}
}
// Si no hay registro, devolver una nueva instancia con valores predeterminados
return new ConfiguracionExpediente();
}
}
}

View File

@@ -0,0 +1,225 @@
using EFCDesk.Utils;
using Microsoft.VisualBasic.ApplicationServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Xml;
namespace EFCDesk.Classes
{
public class ConfiguracionJSON
{
private string? _passwordExpEncriptado;
public string? UsuarioExp { get; set; }
[JsonIgnore]
public string? PasswordExp
{
get
{
if (string.IsNullOrEmpty(_passwordExpEncriptado))
return null;
string pwd = Util.Desencriptar(_passwordExpEncriptado);
// Si no se pudo desencriptar → config corrupta
if (string.IsNullOrEmpty(pwd))
{
LimpiarCredenciales();
return null;
}
return pwd;
}
set
{
if (string.IsNullOrWhiteSpace(value))
{
_passwordExpEncriptado = null;
}
else
{
_passwordExpEncriptado = Util.Encriptar(value);
}
}
}
public string? DominioExp { get; set; }
public bool ProxyNingunoGenerico { get; set; }
public string? ServidorProxyGenerico { get; set; }
public int? PuertoProxyGenerico { get; set; }
public string? UsuarioProxyGenerico { get; set; }
public string? PasswordProxyGenerico { get; set; }
public bool AuthProxyGenerico { get; set; }
public bool ProxyFTPNinguno { get; set; }
public string? ServidorProxyFTP { get; set; }
public int? PuertoProxyFTP { get; set; }
public string? UsuarioProxyFTP { get; set; }
public string? PasswordProxyFTP { get; set; }
public bool AuthProxyFTP { get; set; }
public int idUsuarioExp { get; set; }
public string? FolderExpediente { get; set; }
public string MacAddress { get; set; }
public int ExpWinsaai { get; set; }
public int ExpLogistico { get; set; }
[JsonPropertyName("PasswordExp")]
public string? PasswordExpEncriptado
{
get => _passwordExpEncriptado;
set => _passwordExpEncriptado = value;
}
public ConfiguracionJSON() {
MacAddress = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)
.Select(nic => nic.GetPhysicalAddress().ToString())
.FirstOrDefault();
DominioExp = "";
}
// Método para cargar la configuración desde un archivo JSON
public static ConfiguracionJSON LoadFromJson()
{
string pathConfigJson = AppDomain.CurrentDomain.BaseDirectory+"appSettings.json";
if (!File.Exists(pathConfigJson))
{
var defaultConfig = new ConfiguracionJSON();
string json = JsonSerializer.Serialize(defaultConfig, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(pathConfigJson, json);
}
string contenidoJson = File.ReadAllText(pathConfigJson);
return JsonSerializer.Deserialize<ConfiguracionJSON>(contenidoJson) ?? new ConfiguracionJSON();
}
public void SaveToJson()
{
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appSettings.json");
string json = JsonSerializer.Serialize(this, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(path, json);
}
// Limpieza automática
public void LimpiarCredenciales()
{
UsuarioExp = null;
PasswordExpEncriptado = null;
SaveToJson();
}
public string[] Login()
{
string [] result = new string[2];
result[0] = "0";
result[1] = "Error de conexion";
try
{
string cadena = UsuarioExp + "|" + PasswordExp;
dynamic root = Consulta(DominioExp+"/api/auth/" + cadena);
if (root is XmlElement)
{
XmlNodeList nodes = root.SelectNodes("/xml/item");
foreach (XmlNode node in nodes)
{
result[0] = node["login"].InnerText;
result[1] = node["mensaje"].InnerText;
}
if (result[0] != "0")
{
string path = FolderExpediente;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
return result;
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return result;
}
public dynamic Consulta(string url)
{
WebClient wc = new WebClient();
if (ProxyNingunoGenerico)
{
dynamic wp = Proxy();
if (wp is WebProxy)
{
wc.Proxy = wp;
}
else
{
return wp;
}
}
else
{
IWebProxy proxy = WebRequest.GetSystemWebProxy();
proxy.Credentials = CredentialCache.DefaultCredentials;
wc.Proxy = proxy;
}
try
{
MemoryStream ms = new MemoryStream(wc.DownloadData(url));
XmlTextReader rdr = new XmlTextReader(ms);
XmlDocument doc1 = new XmlDocument();
doc1.Load(rdr);
XmlElement root = doc1.DocumentElement;
return root;
}
catch (Exception e)
{
string sNombreClase = MethodBase.GetCurrentMethod()?.DeclaringType?.Name;
string currentMethod = MethodBase.GetCurrentMethod().Name;
//MyClass.LogErrores(e, sNombreClase, currentMethod);
return e;
}
}
public dynamic Proxy()
{
try
{
WebProxy myproxy = new WebProxy(ServidorProxyGenerico + ":" + PuertoProxyGenerico, true);
myproxy.BypassProxyOnLocal = false;
if (AuthProxyGenerico)
{
NetworkCredential credential = new NetworkCredential(UsuarioProxyGenerico, PasswordProxyGenerico);
myproxy.Credentials = credential;
}
return myproxy;
}
catch (Exception e)
{
string sNombreClase = MethodBase.GetCurrentMethod()?.DeclaringType?.Name;
string currentMethod = MethodBase.GetCurrentMethod().Name;
//MyClass.LogErrores(e, sNombreClase, currentMethod);
return e;
}
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public class DatosActualizadosEventArgs : EventArgs
{
public string CarpetaRaiz
{
get;
}
public DatosActualizadosEventArgs(string carpetaRaiz)
{
CarpetaRaiz = carpetaRaiz;
}
}
}

50
Classes/ErrorLog.cs Normal file
View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
internal class ErrorLog
{
public int Id { get; set; }
public string LineaError { get; set; }
public string Error { get; set; }
public string Comentarios { get; set; }
public string Fecha { get; set; }
public List<ErrorLog> GetRegistrosErrorLog(SQLiteHelper sqliteHelper)
{
var lista = new List<ErrorLog>();
using (var connection = sqliteHelper.GetConnection())
{
connection.Open();
string query = "SELECT Id, LineaError, Error, Comentario, Fecha FROM ErrorLog;";
using (var command = new SQLiteCommand(query, connection))
{
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
lista.Add(new ErrorLog
{
Id = reader.GetInt32(0),
LineaError = reader.IsDBNull(1) ? "" : reader.GetString(1),
Error = reader.IsDBNull(2) ? "" : reader.GetString(2),
Comentarios = reader.IsDBNull(3) ? "" : reader.GetString(3),
Fecha = reader.IsDBNull(4) ? "" : reader.GetString(4)
});
}
}
}
}
return lista;
}
}
}

62
Classes/FileUtil.cs Normal file
View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
namespace EFCDesk.Classes
{
public static class FileUtil
{
public static bool IsFileReady(string path)
{
try
{
using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
return stream.Length >= 0; // si abre sin excepción, está listo
}
catch
{
return false;
}
}
public static bool WaitAllFilesReady(IEnumerable<string> files, int perFileTimeoutSeconds)
{
var deadline = DateTime.UtcNow.AddSeconds(perFileTimeoutSeconds);
var pendientes = new HashSet<string>(files);
while (pendientes.Count > 0 && DateTime.UtcNow < deadline)
{
var listos = new List<string>();
foreach (var f in pendientes)
{
if (File.Exists(f) && IsFileReady(f))
listos.Add(f);
}
foreach (var ok in listos)
pendientes.Remove(ok);
if (pendientes.Count == 0) return true;
Thread.Sleep(500);
}
return pendientes.Count == 0;
}
public static string? TryGetSHA1(string path)
{
try
{
using var fs = File.OpenRead(path);
using var sha1 = SHA1.Create();
var hash = sha1.ComputeHash(fs);
return BitConverter.ToString(hash).Replace("-", "");
}
catch
{
return null;
}
}
}
}

34
Classes/General.cs Normal file
View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace EFCDesk.Classes
{
public class General
{
public static string CodificarBase64(string cadena)
{
string resultado = cadena;
string[] arrayLetras = { "J", "G", "V", "S" };
int limite = arrayLetras.Length;
Random random = new Random();
int num = random.Next(0, limite);
for (var i = 0; i <= num; i++)
{
resultado = Base64Encode(resultado);
}
resultado = resultado + "+" + arrayLetras[num];
resultado = Base64Encode(resultado);
return resultado;
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
}
}

364
Classes/Helpers.cs Normal file
View File

@@ -0,0 +1,364 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
namespace EFCDesk.Classes
{
public static class Helpers
{
// Lista de extensiones permitidas
private static readonly HashSet<string> ExtensionesPermitidas = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".jpg",
".jpeg",
".png",
".gif",
".bmp",
".pdf",
".txt",
".csv"
};
// Lista de extensiones prohibidas (opcional, para mayor seguridad)
private static readonly HashSet<string> ExtensionesProhibidas = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".exe",
".bat",
".cmd",
".msi",
".sh",
".js",
".vbs",
".ps1",
".jar",
".com",
".msp",
".scr",
".docm",
".xlsm",
".pptm"
};
public static bool ValidarArchivo(string rutaArchivo)
{
string extension = Path.GetExtension(rutaArchivo);
// Revisar primero si está en la lista prohibida
if (ExtensionesProhibidas.Contains(extension))
{
return false;
}
//// Solo permitir si está en la lista de permitidas
//return ExtensionesPermitidas.Contains(extension);
return true;
}
/// <summary>
/// Obtiene el tamaño de un archivo en bytes.
/// </summary>
/// <param name="rutaArchivo">Ruta completa del archivo.</param>
/// <returns>Tamaño en bytes, o -1 si el archivo no existe.</returns>
public static long ObtenerTamanoEnBytes(string rutaArchivo)
{
if (!File.Exists(rutaArchivo))
return -1;
FileInfo info = new FileInfo(rutaArchivo);
return info.Length;
}
/// <summary>
/// Obtiene el tamaño de un archivo en formato legible (KB, MB, GB).
/// </summary>
/// <param name="rutaArchivo">Ruta completa del archivo.</param>
/// <returns>Cadena con el tamaño formateado, o mensaje de error.</returns>
public static string ObtenerTamanoFormateado(string rutaArchivo)
{
if (!File.Exists(rutaArchivo))
return "El archivo no existe";
long bytes = new FileInfo(rutaArchivo).Length;
string[] sufijos = { "B", "KB", "MB", "GB", "TB" };
int indice = 0;
double tamaño = bytes;
while (tamaño >= 1024 && indice < sufijos.Length - 1)
{
tamaño /= 1024;
indice++;
}
return $"{tamaño:0.##} {sufijos[indice]}";
}
/// <summary>
/// Obtiene la url del endpoint para obtener el pedimento.
/// </summary>
/// <returns>Cadena del endpoint.</returns>
public static string ObtenerEndpointPedimentos()
{
return @"/api/v1/customs/pedimentos/?pedimento_app=";
}
/// <summary>
/// Obtiene la url del endpoint para obtener el documento.
/// </summary>
/// <returns>Cadena del endpoint.</returns>
public static string ObtenerEndpointDocumentos()
{
return @"/api/v1/record/documents/";
}
public static string CrearEndpointpedimentoDesk()
{
return @"/api/v1/customs/pedimentos/bulk-create-pedimento_desk/";
}
/// <summary>
/// Espera hasta que todos los archivos dentro de la carpeta estén libres (no en uso)
/// </summary>
public static bool EsperarArchivosListos(string carpetaRaiz, int timeoutSegundos = 30)
{
var archivos = Directory.GetFiles(carpetaRaiz, "*.*", SearchOption.AllDirectories);
var inicio = DateTime.Now;
while ((DateTime.Now - inicio).TotalSeconds < timeoutSegundos)
{
bool todosListos = true;
foreach (var archivo in archivos)
{
try
{
using (FileStream stream = new FileStream(archivo, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
// Archivo disponible
}
}
catch (IOException)
{
todosListos = false;
break;
}
}
if (todosListos)
return true;
Thread.Sleep(500);
}
return false;
}
/// <summary>
/// Obtiene la carpeta raíz según aplicaWinsaii
/// </summary>
public static (string RutaRaiz, string NombreRaiz) ObtenerCarpetaRaiz(string ruta)
{
SQLiteHelper sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
ConfiguracionExpediente config = ConfiguracionExpediente.ObtenerDesdeBaseDeDatos(sqliteHelper);
bool aplicaWinsaii = config.UsarEstructuraPedimentosWinsaai;
string? carpetaActual = EsCarpeta(ruta) ? ruta : Path.GetDirectoryName(ruta);
string carpetaBase = Path.GetFullPath(config.FolderParaGenerarExpediente);
carpetaActual = Path.GetFullPath(carpetaActual);
string[] segmentosBase = carpetaBase.Trim(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar);
string[] segmentosActual = carpetaActual.Trim(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar);
int nivelDeseado = aplicaWinsaii ? segmentosBase.Length + 2 : segmentosBase.Length + 1;
if (segmentosActual.Length > nivelDeseado)
segmentosActual = segmentosActual.Take(nivelDeseado).ToArray();
string carpetaRaiz = string.Join(Path.DirectorySeparatorChar.ToString(), segmentosActual);
if (!Path.IsPathRooted(carpetaRaiz))
carpetaRaiz = Path.DirectorySeparatorChar + carpetaRaiz;
string nombreRaiz = Path.GetFileName(carpetaRaiz);
return (carpetaRaiz, nombreRaiz);
}
public static bool EsCarpeta(string ruta)
{
return Directory.Exists(ruta);
}
public static string DominioExpedienteElectronico()
{
string efc = Properties.Settings.Default.urlEFC as string;
return efc;
}
public static bool EsValidaNomeclaturaCarpeta(string pathCarpeta)
{
var nombre = Path.GetFileName(pathCarpeta);
string pattern = @"^\d{2}-\d{4}-\d{7}$|^\d{2}-\d{2}-\d{4}-\d{7}$";
bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombre, pattern);
if (!esValido)
{
return false;
}
return true;
}
public static bool EsValidaNomeclaturaSAAIM3(string pathArchivo)
{
var nombre = Path.GetFileName(pathArchivo);
string pattern = @"^[m|M]\d{7}\.\d{3}$";
bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombre, pattern);
if (!esValido)
{
return false;
}
return true;
}
public static bool EsArchivoXMl(string rutaArchivo)
{
try
{
string extension = Path.GetExtension(rutaArchivo);
if (!extension.Equals(".xml", StringComparison.OrdinalIgnoreCase))
return false;
XDocument xdoc = XDocument.Load(rutaArchivo);
}
catch (XmlException exception)
{
Globales.logger.LogError("Helpers - EsArchivoXML", exception);
return false;
}
catch (Exception ex)
{
Globales.logger.LogError("Helpers - EsArchivoXML", ex);
return false;
}
return true;
}
public static byte[] CrearZipEnMemoria(string nombreArchivo, byte[] contenido)
{
try
{
using (var memoryStream = new MemoryStream())
{
using (var zip = new System.IO.Compression.ZipArchive(memoryStream, System.IO.Compression.ZipArchiveMode.Create, leaveOpen: true))
{
// Aquí puedes agregar archivos al archivo ZIP si es necesario
var entry = zip.CreateEntry(nombreArchivo);
using (var entryStream = entry.Open())
{
entryStream.Write(contenido, 0, contenido.Length);
}
}
return memoryStream.ToArray();
}
}
catch (Exception ex)
{
// Manejo de la excepción (puedes registrar el error o lanzar una excepción personalizada)
Globales.logger.LogError("Helpers", ex);
return Array.Empty<byte>();
}
}
public static string CalcularHashMD5(string rutaArchivo)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(rutaArchivo))
{
var hashBytes = md5.ComputeHash(stream);
StringBuilder sb = new StringBuilder();
foreach (var b in hashBytes)
{
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
}
/// <summary>
/// Crea un ZIP de un solo archivo en una carpeta temporal única.
/// </summary>
/// <param name="rutaArchivo">Archivo a comprimir.</param>
/// <param name="nombreArchivoZip">Nombre del ZIP que se generará.</param>
/// <param name="autoLimpiar">Si es true, borra la carpeta temporal automáticamente después de crear el ZIP.</param>
/// <returns>Ruta completa del ZIP generado.</returns>
public static string CrearZipArchivoEnTemp(string rutaArchivo, string nombreArchivoZip, bool autoLimpiar = false)
{
// Obtiene la ruta raíz de la carpeta temporal del sistema
string tempRoot = Path.Combine(Path.GetTempPath(), "temp-efc-desk");
//string tempRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),"tempEFCDesk");
// Crea una subcarpeta temporal única
string tempFolder = Path.Combine(tempRoot, Guid.NewGuid().ToString().ToLower().Replace("-","").Substring(0,8));
Directory.CreateDirectory(tempFolder);
// Ruta completa del archivo ZIP dentro de la carpeta temporal
string zipPath = Path.Combine(tempFolder, nombreArchivoZip);
try
{
// Verifica que el archivo exista
if (!File.Exists(rutaArchivo))
{
throw new FileNotFoundException($"El archivo no existe: {rutaArchivo}");
}
// Crea el ZIP y agrega el archivo
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
{
zip.CreateEntryFromFile(rutaArchivo, Path.GetFileName(rutaArchivo));
}
return zipPath;
}
catch (Exception ex)
{
Globales.logger.LogError("Helpers - CrearZipArchivoEnTemp", ex);
return "";
}
finally
{
if (autoLimpiar)
{
try
{
// Espera un momento para asegurarse de que el ZIP no esté bloqueado
System.Threading.Thread.Sleep(3000);
// Borra toda la carpeta temporal
if (Directory.Exists(tempFolder))
{
Directory.Delete(tempFolder, true);
}
}
catch (Exception ex)
{
Globales.logger.LogError("Helpers - No se pudo limpiar la carpeta temporal", ex);
}
}
}
}
}
}

139
Classes/JsonHelper.cs Normal file
View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
namespace EFCDesk.Classes
{
public static class JsonHelper
{
//public static bool TryGetProperty(JsonElement element, string propertyName, out JsonElement value)
//{
// if (element.ValueKind == JsonValueKind.Object &&
// element.TryGetProperty(propertyName, out value))
// {
// return true;
// }
// value = default;
// return false;
//}
//public static string? GetString(JsonElement element, string propertyName)
//{
// return TryGetProperty(element, propertyName, out var value) && value.ValueKind == JsonValueKind.String
// ? value.GetString()
// : null;
//}
//public static bool? GetBool(JsonElement element, string propertyName)
//{
// return TryGetProperty(element, propertyName, out var value) && value.ValueKind == JsonValueKind.True || value.ValueKind == JsonValueKind.False
// ? value.GetBoolean()
// : null;
//}
//public static int? GetInt(JsonElement element, string propertyName)
//{
// return TryGetProperty(element, propertyName, out var value) && value.ValueKind == JsonValueKind.Number
// ? value.GetInt32()
// : null;
//}
//public static JsonElement? GetArray(JsonElement element, string propertyName)
//{
// return TryGetProperty(element, propertyName, out var value) && value.ValueKind == JsonValueKind.Array
// ? value
// : null;
//}
//public static JsonElement? GetObject(JsonElement element, string propertyName)
//{
// return TryGetProperty(element, propertyName, out var value) && value.ValueKind == JsonValueKind.Object
// ? value
// : null;
//}
// ----------------------------
// PUBLIC METHODS
// ----------------------------
public static Dictionary<string, object?>? ToDictionary(JsonElement element)
{
if (element.ValueKind != JsonValueKind.Object)
return null;
var dict = new Dictionary<string, object?>();
foreach (var prop in element.EnumerateObject())
{
dict[prop.Name] = ConvertElement(prop.Value);
}
return dict;
}
public static List<object?>? ToList(JsonElement element)
{
if (element.ValueKind != JsonValueKind.Array)
return null;
var list = new List<object?>();
foreach (var item in element.EnumerateArray())
{
list.Add(ConvertElement(item));
}
return list;
}
public static object? Get(JsonElement element, string key)
{
return element.TryGetProperty(key, out var value)
? ConvertElement(value)
: null;
}
// ----------------------------
// INTERNAL CONVERTER
// ----------------------------
private static object? ConvertElement(JsonElement element)
{
return element.ValueKind switch
{
JsonValueKind.String => element.GetString(),
JsonValueKind.Number => element.TryGetInt64(out long l) ? l : element.GetDouble(),
JsonValueKind.True => true,
JsonValueKind.False => false,
JsonValueKind.Object => ToDictionary(element),
JsonValueKind.Array => ToList(element),
JsonValueKind.Null => null,
JsonValueKind.Undefined => null,
_ => element.ToString()
};
}
public static bool TryParse(string json, out JsonElement root)
{
root = default;
if (string.IsNullOrWhiteSpace(json))
return false;
try
{
var doc = JsonDocument.Parse(json);
root = doc.RootElement.Clone(); // Clonamos para que no se deseche
return true;
}
catch
{
return false;
}
}
}
}

990
Classes/MonitorCarpetas.cs Normal file
View File

@@ -0,0 +1,990 @@
using EFCDesk.Entidades;
using Microsoft.VisualBasic.Devices;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Runtime.InteropServices.JavaScript.JSType;
using EFCDesk.Parsers;
namespace EFCDesk.Classes
{
public sealed class MonitorCarpetas : IDisposable
{
private readonly string _carpetaBase;
private readonly bool _aplicaWinsaii;
private readonly SQLiteHelper _repo;
private FileSystemWatcher? _watcher;
//private readonly ConcurrentStack<string> _pilaCarpetas = new ConcurrentStack<string>(); // LIFO
private readonly ConcurrentQueue<string> _colaCarpetas = new ConcurrentQueue<string>(); // FIFO
private readonly SemaphoreSlim _semaforo;
private readonly SemaphoreSlim _dbSemaforo; // Limitar acceso a BD
private readonly HashSet<string> _enProceso = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly object _lockProceso = new object();
// Parámetros de robustez
private readonly int _maxConcurrent = 2;
private readonly int _perFileTimeoutSeconds = 30;
private readonly int _maxReintentos = 10; // reintentos de 1 minuto
private readonly TimeSpan _reintentoDelay = TimeSpan.FromMinutes(1);
private string ApiPostDocuments = Helpers.ObtenerEndpointDocumentos();
private string ApiGetPedimento = Helpers.ObtenerEndpointPedimentos();
private string ApiGetPedimentoDesk = Helpers.CrearEndpointpedimentoDesk();
private ProcessLogger logger = new ProcessLogger();
private string DominioEFC = Helpers.DominioExpedienteElectronico();
private bool _MonitoreoTimer = false;
// Evento para notificar a la UI
//public event EventHandler? DatosActualizados;
// Evento con argumentos personalizados para notificar a la UI
public event EventHandler<DatosActualizadosEventArgs>? DatosActualizados;
public MonitorCarpetas(string carpetaBase, int? maxConcurrent = null, int? perFileTimeoutSeconds = null, int? maxReintentos = null)
{
_carpetaBase = Path.GetFullPath(carpetaBase);
_repo = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
ConfiguracionExpediente config = ConfiguracionExpediente.ObtenerDesdeBaseDeDatos(_repo);
_aplicaWinsaii = config.UsarEstructuraPedimentosWinsaai;
if (maxConcurrent.HasValue) _maxConcurrent = Math.Max(1, maxConcurrent.Value);
if (perFileTimeoutSeconds.HasValue) _perFileTimeoutSeconds = Math.Max(5, perFileTimeoutSeconds.Value);
if (maxReintentos.HasValue) _maxReintentos = Math.Max(1, maxReintentos.Value);
_semaforo = new SemaphoreSlim(_maxConcurrent);
_dbSemaforo = new SemaphoreSlim(1); // Solo un hilo a la vez en BD
}
public void Iniciar()
{
// 1) Watcher
_watcher = new FileSystemWatcher(_carpetaBase)
{
IncludeSubdirectories = true,
NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.DirectoryName,
};
_watcher.Created += OnFsEvent;
_watcher.Renamed += OnFsRenamed;
_watcher.Changed += OnFsEvent; // por si hay carreras mientras se crea la carpeta
_watcher.EnableRaisingEvents = true;
//// 2) Recuperar pendientes
//var pendientes = _repo.ObtenerPendientes();
//foreach (var (ruta, nombre, _) in pendientes)
// EncolarSiNoEsta(ruta);
//// 3) Disparar procesamiento inicial
//_ = ProcesarPilaAsync();
}
private async void OnFsEvent(object? sender, FileSystemEventArgs e)
{
// Sólo nos interesan carpetas (pero el evento puede ser de archivo: ignorar)
var asDir = e.FullPath;
if (!Directory.Exists(asDir))
{
// Si es archivo, su carpeta raíz puede estar lista: intentamos derivar
asDir = Path.GetDirectoryName(e.FullPath) ?? e.FullPath;
if (string.IsNullOrWhiteSpace(asDir) || !Directory.Exists(asDir)) return;
}
var raiz = ObtenerCarpetaRaiz(asDir);
if (raiz == null) return;
var nombre = Path.GetFileName(raiz);
var tipo = _aplicaWinsaii ? "Nieto" : "Hijo";
//string pattern = @"^\d{2}-\d{2}-\d{4}-\d{7}$";
//bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombre, pattern);
//if (esValido)
//{
// _repo.UpsertCarpeta(raiz, nombre, tipo, "Nuevo");
// EncolarSiNoEsta(raiz);
//}
bool esValido = Helpers.EsValidaNomeclaturaCarpeta(nombre);
if (esValido)
{
await _dbSemaforo.WaitAsync();
try
{
_repo.UpsertCarpeta(raiz, nombre, tipo, "Nuevo");
}
finally
{
_dbSemaforo.Release();
}
EncolarSiNoEsta(raiz);
}
// Solo debe ejecutarse cuando el Timer no este activo
if (_MonitoreoTimer == true) return;
_ = ProcesarPilaAsync();
}
private void OnFsRenamed(object? sender, RenamedEventArgs e)
{
OnFsEvent(sender, new FileSystemEventArgs(WatcherChangeTypes.Created, Path.GetDirectoryName(e.FullPath) ?? e.FullPath, Path.GetFileName(e.FullPath)));
}
private void EncolarSiNoEsta(string carpetaRaiz)
{
carpetaRaiz = Path.GetFullPath(carpetaRaiz);
lock (_lockProceso)
{
if (_enProceso.Contains(carpetaRaiz)) return;
_enProceso.Add(carpetaRaiz);
}
//_pilaCarpetas.Push(carpetaRaiz); // LIFO
_colaCarpetas.Enqueue(carpetaRaiz); // FIFO
//Dispara el evento para avisar al FormMain
OnDatosActualizados(carpetaRaiz);
}
// Devuelve la carpeta raíz (hijo o nieto) dado un path dentro de _carpetaBase
private string? ObtenerCarpetaRaiz(string ruta)
{
string full = Path.GetFullPath(ruta);
if (!full.StartsWith(_carpetaBase, StringComparison.OrdinalIgnoreCase)) return null;
var relativa = full.Substring(_carpetaBase.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var partes = relativa.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
if (partes.Length == 0) return null;
// hijo = primer segmento; nieto = primer y segundo segmento
if (_aplicaWinsaii)
{
if (partes.Length < 2) return null;
return Path.Combine(_carpetaBase, partes[0], partes[1]);
}
else
{
return Path.Combine(_carpetaBase, partes[0]);
}
}
private async Task ProcesarPilaAsync()
{
//while (_pilaCarpetas.TryPop(out var carpetaRaiz))
//{
// await _semaforo.WaitAsync();
// _ = Task.Run(async () =>
// {
// try
// {
// await ProcesarCarpetaRaizAsync(carpetaRaiz);
// }
// catch (Exception ex)
// {
// Console.WriteLine($"[ERR] {carpetaRaiz}: {ex.Message}");
// }
// finally
// {
// lock (_lockProceso) _enProceso.Remove(carpetaRaiz);
// _semaforo.Release();
// }
// });
//}
while (_colaCarpetas.TryDequeue(out var carpetaRaiz))
{
await _semaforo.WaitAsync();
_ = Task.Run(async () =>
{
try
{
await ProcesarCarpetaRaizAsync(carpetaRaiz);
}
catch (Exception ex)
{
Console.WriteLine($"[ERR] {carpetaRaiz}: {ex.Message}");
}
finally
{
lock (_lockProceso) _enProceso.Remove(carpetaRaiz);
_semaforo.Release();
}
});
//Dispara el evento para avisar al FormMain
OnDatosActualizados(carpetaRaiz);
}
}
//private async Task ProcesarCarpetaRaizAsync(string carpetaRaiz)
//{
// if (!Directory.Exists(carpetaRaiz))
// {
// Console.WriteLine($"[SKIP] No existe: {carpetaRaiz}");
// return;
// }
// Console.WriteLine($"➡️ Procesando raíz: {carpetaRaiz}");
// var nombreRaiz = Path.GetFileName(carpetaRaiz);
// var archivos = Directory.GetFiles(carpetaRaiz, "*.*", SearchOption.AllDirectories)
// .Where(f => !EsTemporal(f))
// .ToArray();
// if (archivos.Length == 0)
// {
// Console.WriteLine($"[INFO] Sin archivos en {carpetaRaiz}");
// _repo.MarcarCarpetaProcesada(carpetaRaiz);
// return;
// }
// // Reintentos para archivos en uso
// int intento = 0;
// while (intento <= _maxReintentos)
// {
// var pendientes = archivos.Where(f => File.Exists(f) && !FileUtil.IsFileReady(f)).ToArray();
// if (pendientes.Length == 0) break;
// if (intento == _maxReintentos)
// {
// Console.WriteLine($"[WARN] Archivos bloqueados tras {_maxReintentos} intentos. Se omite: {carpetaRaiz}");
// return;
// }
// Console.WriteLine($"[WAIT] {pendientes.Length} archivos bloqueados en {carpetaRaiz}. Reintento {intento + 1}/{_maxReintentos} en {_reintentoDelay.TotalMinutes} min.");
// await Task.Delay(_reintentoDelay);
// intento++;
// }
// // Filtrar archivos ya procesados (persistente en SQLite)
// var archivosAProcesar = new List<string>(archivos.Length);
// foreach (var f in archivos)
// {
// if (_repo.EstaArchivoProcesado(f)) continue;
// archivosAProcesar.Add(f);
// }
// if (archivosAProcesar.Count == 0)
// {
// Console.WriteLine($"[INFO] Todos los archivos ya fueron procesados en {carpetaRaiz}");
// _repo.MarcarCarpetaProcesada(carpetaRaiz);
// return;
// }
// // Crear ZIP aplanado
// var rutaZip = Path.Combine(Path.GetDirectoryName(carpetaRaiz)!, $"{nombreRaiz}.zip");
// if (File.Exists(rutaZip)) File.Delete(rutaZip);
// using (var zip = ZipFile.Open(rutaZip, ZipArchiveMode.Create))
// {
// foreach (var archivo in archivosAProcesar)
// {
// var nombreArchivo = Path.GetFileName(archivo);
// // Seguridad adicional: esperar per-file si justo se bloquea
// if (!FileUtil.WaitAllFilesReady(new[] { archivo }, _perFileTimeoutSeconds))
// {
// Console.WriteLine($"[SKIP] Bloqueado: {archivo}");
// continue;
// }
// // Registrar como procesado antes de subir, para evitar duplicados si se cae después
// var sha1 = FileUtil.TryGetSHA1(archivo); // opcional, puede ser null
// _repo.RegistrarArchivoProcesado(archivo, nombreArchivo, carpetaRaiz, $"{nombreRaiz}.zip", sha1);
// // Agregar al zip aplanado (sin directorios)
// zip.CreateEntryFromFile(archivo, nombreArchivo, CompressionLevel.Optimal);
// Console.WriteLine($" + {nombreArchivo}");
// }
// }
// Console.WriteLine($"ZIP creado: {rutaZip}");
// // 🔌 HOOK: Subir a FTP
// try
// {
// SubirArchivoFTP(rutaZip);
// }
// catch (Exception ex)
// {
// Console.WriteLine($"[FTP ERR] {ex.Message}");
// // según tu estrategia, podrías marcar la carpeta como pendiente otra vez
// // y retornar aquí para reintentar más tarde.
// }
// // 🔌 HOOK: Registrar en API
// try
// {
// RegistrarArchivoEnAPI(rutaZip);
// }
// catch (Exception ex)
// {
// Console.WriteLine($"[API ERR] {ex.Message}");
// }
// try
// {
// File.Delete(rutaZip);
// Console.WriteLine($"🧹 ZIP eliminado: {rutaZip}");
// }
// catch (Exception ex)
// {
// Console.WriteLine($"[ZIP DEL ERR] {ex.Message}");
// }
// _repo.MarcarCarpetaProcesada(carpetaRaiz);
// Console.WriteLine($"✅ Completado: {carpetaRaiz}");
//}
private async Task ProcesarCarpetaRaizAsync(string carpetaRaiz)
{
if (!Directory.Exists(carpetaRaiz))
{
_repo.MarcarCarpetaProcesada(carpetaRaiz, "No existe");
Console.WriteLine($"[SKIP] No existe: {carpetaRaiz}");
return;
}
Console.WriteLine($"Procesando raíz: {carpetaRaiz}");
var nombreRaiz = Path.GetFileName(carpetaRaiz);
var archivos = Directory.GetFiles(carpetaRaiz, "*.*", SearchOption.AllDirectories)
.Where(f => !EsTemporal(f))
.ToArray();
// ==== Validar formato de nombre === //
//string pattern = @"^\d{2}-\d{2}-\d{4}-\d{7}$";
//bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombreRaiz, pattern);
//if (!esValido)
//{
// _repo.MarcarCarpetaProcesada(carpetaRaiz, "Formato Incorrecto");
// Console.WriteLine($"[SKIP] Formato Expediente Incorrecto: {nombreRaiz}");
// return;
//}
bool esValido = Helpers.EsValidaNomeclaturaCarpeta(nombreRaiz);
if (!esValido)
{
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Formato Incorrecto");
Console.WriteLine($"[SKIP] Formato Expediente Incorrecto: {nombreRaiz}");
return;
}
if (archivos.Length == 0)
{
Console.WriteLine($"[INFO] Sin archivos en {carpetaRaiz}");
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Sin Archivos");
return;
}
// Reintentos para archivos en uso
int intento = 0;
while (intento <= _maxReintentos)
{
var pendientes = archivos.Where(f => File.Exists(f) && !FileUtil.IsFileReady(f)).ToArray();
if (pendientes.Length == 0) break;
if (intento == _maxReintentos)
{
Console.WriteLine($"[WARN] Archivos bloqueados tras {_maxReintentos} intentos. Se omite: {carpetaRaiz}");
return;
}
Console.WriteLine($"[WAIT] {pendientes.Length} archivos bloqueados en {carpetaRaiz}. Reintento {intento + 1}/{_maxReintentos} en {_reintentoDelay.TotalMinutes} min.");
await Task.Delay(_reintentoDelay);
intento++;
}
// Filtrar archivos ya procesados (persistente en SQLite)
var archivosAProcesar = new List<string>(archivos.Length);
await _dbSemaforo.WaitAsync();
try
{
foreach (var f in archivos)
{
if (_repo.EstaArchivoProcesado(f)) continue;
archivosAProcesar.Add(f);
}
}
finally
{
_dbSemaforo.Release();
}
if (archivosAProcesar.Count == 0)
{
Console.WriteLine($"[INFO] Todos los archivos ya fueron procesados en {carpetaRaiz}");
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesado");
return;
}
// Crear ZIP aplanado
var rutaZip = Path.Combine(Path.GetDirectoryName(carpetaRaiz)!, $"{nombreRaiz}.zip");
if (File.Exists(rutaZip)) File.Delete(rutaZip);
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesando");
int totalArchivos = archivosAProcesar.Count;
int archivosCompletos = 0;
foreach (var archivo in archivosAProcesar)
{
var nombreArchivo = Path.GetFileName(archivo);
// Seguridad adicional: esperar per-file si justo se bloquea
if (!FileUtil.WaitAllFilesReady(new[] { archivo }, _perFileTimeoutSeconds))
{
Console.WriteLine($"[SKIP] Bloqueado: {archivo}");
continue;
}
// Revisar si contiene informacion el archivo
if (Helpers.ObtenerTamanoEnBytes(archivo) <= 0)
{
Console.WriteLine($"[SKIP] Sin Informacion: {archivo}");
totalArchivos--;
continue;
}
// Seguridad adicional: no permitir subir archivos .exe, .bat, etc.
if (!Helpers.ValidarArchivo(archivo))
{
Console.WriteLine($"[SKIP] Extension no valida: {archivo}");
continue;
}
// Registrar como procesado antes de subir, para evitar duplicados si se cae después
var sha1 = FileUtil.TryGetSHA1(archivo); // opcional, puede ser null
await _dbSemaforo.WaitAsync();
try
{
_repo.RegistrarArchivoProcesado(archivo, nombreArchivo, carpetaRaiz, $"{nombreRaiz}.zip", sha1);
}
finally
{
_dbSemaforo.Release();
}
bool respuesa = false;
// 🔌 HOOK: Registrar en API
try
{
respuesa = await RegistrarArchivoEnAPI(archivo, nombreRaiz);
await _dbSemaforo.WaitAsync();
try
{
if (respuesa)
{
_repo.ActualizarEstadoArchivo(archivo, "Procesado");
archivosCompletos++;
}
else
{
_repo.ActualizarEstadoArchivo(archivo, "Pendiente");
}
}
finally
{
_dbSemaforo.Release();
}
}
catch (Exception ex)
{
Console.WriteLine($"[API ERR] {ex.Message}");
}
Console.WriteLine($" + {nombreArchivo}");
}
if (archivosCompletos == totalArchivos)
{
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Procesado");
}
else
{
_repo.MarcarCarpetaProcesada(carpetaRaiz, "Pendiente");
}
Console.WriteLine($"Proceso Completado: {carpetaRaiz}");
}
private static bool EsTemporal(string path)
{
var name = Path.GetFileName(path);
if (string.IsNullOrEmpty(name)) return true;
// comunes durante edición/descarga/renombre
if (name.EndsWith(".tmp", StringComparison.OrdinalIgnoreCase)) return true;
if (name.EndsWith(".part", StringComparison.OrdinalIgnoreCase)) return true;
if (name.EndsWith(".crdownload", StringComparison.OrdinalIgnoreCase)) return true;
if (name.EndsWith("~", StringComparison.OrdinalIgnoreCase)) return true;
if (name.StartsWith("~$", StringComparison.OrdinalIgnoreCase)) return true; // MS Office
return false;
}
// Implementa tus integraciones reales aquí
private void SubirArchivoFTP(string rutaZip)
{
// TODO: tu implementación real de FTP
Console.WriteLine($"[FTP] Subido: {rutaZip}");
}
private async Task<bool> RegistrarArchivoEnAPI(string rutaArchivo, string pedimento)
{
// TODO: tu implementación real de API
try
{
var config = ConfiguracionJSON.LoadFromJson();
string Token = Globales.accesToken ?? "";
if (string.IsNullOrWhiteSpace(DominioEFC))
{
logger.LogError("No se ha configurado el dominio", null);
return false;
}
if (!string.IsNullOrEmpty(Token))
{
using var apiClient = new ApiClient(timeout: TimeSpan.FromSeconds(600), maxRetries: 3, retryDelay: TimeSpan.FromSeconds(60));
string sfuente = "";
int expedienteLogistico = Properties.Settings.Default.ExpLogistico;
int expedienteWinsaai = Properties.Settings.Default.ExpWinsaai;
if (expedienteWinsaai > 0 && expedienteLogistico > 0)
{
sfuente = Properties.Settings.Default.ExpLogistico.ToString();
}
else if (expedienteWinsaai > 0)
{
sfuente = Properties.Settings.Default.ExpWinsaai.ToString();
}
else if (expedienteLogistico > 0)
{
sfuente = Properties.Settings.Default.ExpLogistico.ToString();
}
else
{
sfuente = "5";
}
// Verifica que el archivo exista
if (!File.Exists(rutaArchivo))
{
return false;
}
Dictionary<string, string> metadatos = new Dictionary<string, string>
{
{ "fuente", sfuente },
{ "clave_pedimento", "" },
{ "pedimento", "" },
{ "patente", "" },
{ "aduana", "" },
{ "tipo_operacion", "" },
{ "contribuyente", "" },
{ "curp_apoderado", "" },
{ "fecha_pago", "" },
{ "partidas", "" },
};
//if (Helpers.EsValidaNomeclaturaSAAIM3(rutaArchivo))
//{
// // Validar contenido del archivo SAAI M3
// var registros = SaaiM3Helper.LeerArchivo(rutaArchivo);
// var resultados = SaaiM3Helper.BuscarPorTipo(registros, "501");
// foreach (var reg in resultados)
// {
// metadatos["clave_pedimento"] = reg.Campos[5];
// metadatos["pedimento"] = reg.Campos[2];
// metadatos["patente"] = reg.Campos[1];
// metadatos["aduana"] = reg.Campos[3];
// metadatos["tipo_operacion"] = reg.Campos[4];
// metadatos["contribuyente"] = reg.Campos[8];
// metadatos["curp_apoderado"] = reg.Campos[9];
// break;
// }
// resultados = SaaiM3Helper.BuscarPorTipo(registros, "506");
// foreach (var reg in resultados)
// {
// string tipoFechaPago = reg.Campos[2];
// if (tipoFechaPago == "2")
// {
// string fechaOriginal = reg.Campos[3];
// DateTime fecha = DateTime.ParseExact(fechaOriginal, "ddMMyyyy", null);
// metadatos["fecha_pago"] = fecha.ToString("yyyy-MM-dd");
// break;
// }
// }
// // Numero de partidas
// resultados = SaaiM3Helper.BuscarPorTipo(registros, "551");
// metadatos["partidas"] = resultados.Count.ToString();
//}
//else if (Helpers.EsArchivoXMl(rutaArchivo))
//{
// //
// // Validar contenido del XML Pedimento Completo
// string xml = File.ReadAllText(rutaArchivo);
// var parser = new PedimentoXmlParser(xml);
// var (tieneError, numeroOperacion) = parser.GetResultadoOperacion();
// string numeroPedimento = parser.GetNumeroPedimento();
// var encabezado = parser.GetEncabezado();
// var importador = parser.GetImportador();
// var fechas = parser.GetFechas();
// var partidas = parser.GetPartidas();
// if (!tieneError && encabezado.Count > 0)
// {
// string[] partes = pedimento.Split("-");
// metadatos["pedimento"] = numeroPedimento;
// metadatos["clave_pedimento"] = encabezado["ClavePedimento"];
// metadatos["patente"] = partes[2];
// metadatos["aduana"] = encabezado["AduanaES"];
// metadatos["tipo_operacion"] = encabezado["TipoOperacion"];
// metadatos["contribuyente"] = importador["RFC"];
// metadatos["curp_apoderado"] = encabezado["CurpApoderado"]; ;
// metadatos["partidas"] = partidas.Count.ToString();
// foreach (var fecha in fechas)
// {
// if (fecha["TipoClave"] == "2")
// {
// string[] partesFecha = fecha["Fecha"].Split("-");
// metadatos["fecha_pago"] = partesFecha[0] + "-" + partesFecha[1] + "-" + partesFecha[2];
// break;
// }
// }
// }
//}
if (Helpers.EsArchivoXMl(rutaArchivo))
{
//
// Validar contenido del XML Pedimento Completo
string xml = File.ReadAllText(rutaArchivo);
var parser = new PedimentoXmlParser(xml);
var (tieneError, numeroOperacion) = parser.GetResultadoOperacion();
string numeroPedimento = parser.GetNumeroPedimento();
var encabezado = parser.GetEncabezado();
var importador = parser.GetImportador();
var fechas = parser.GetFechas();
var partidas = parser.GetPartidas();
if (!tieneError && encabezado.Count > 0)
{
string[] partes = pedimento.Split("-");
metadatos["pedimento"] = numeroPedimento;
metadatos["clave_pedimento"] = encabezado["ClavePedimento"];
metadatos["patente"] = partes[2];
metadatos["aduana"] = encabezado["AduanaES"];
metadatos["tipo_operacion"] = encabezado["TipoOperacion"];
metadatos["contribuyente"] = importador["RFC"];
metadatos["curp_apoderado"] = encabezado["CurpApoderado"];
metadatos["partidas"] = partidas.Count.ToString();
foreach (var fecha in fechas)
{
if (fecha["TipoClave"] == "2")
{
string[] partesFecha = fecha["Fecha"].Split("-");
metadatos["fecha_pago"] = partesFecha[0] + "-" + partesFecha[1] + "-" + partesFecha[2];
break;
}
}
}
}
string nombreZip = $"{pedimento}.zip";
string rutaZip = Helpers.CrearZipArchivoEnTemp(rutaArchivo, nombreZip);
string UrlPostArchivoZip = DominioEFC + ApiGetPedimentoDesk;
string respuestaJson = await apiClient.PostMultipartZipAsync(
url: UrlPostArchivoZip,
filePath: rutaZip,
zipFileName: nombreZip,
metadatos: metadatos
);
string tempFolder = Path.GetDirectoryName(rutaZip) ?? "";
// Borra toda la carpeta temporal
if (Directory.Exists(tempFolder))
{
Directory.Delete(tempFolder, true);
}
if (!apiClient.IsJson(respuestaJson))
{
return false;
}
if (!apiClient.HasJsonData(respuestaJson))
{
return false;
}
if (JsonHelper.TryParse(respuestaJson, out var root))
{
var JsonData = JsonHelper.ToDictionary(root);
if (JsonData == null)
{
return false;
}
else if (JsonData.ContainsKey("tieneError"))
{
bool tieneError = Convert.ToBoolean(JsonData["tieneError"]);
if (tieneError)
{
return false;
}
else
{
return true;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
else
{
logger.LogError("Error en la configuracion del Id de Usuario:" + DominioEFC, new Exception("Error Id Usuario"));
return false;
}
}
catch (Exception ex)
{
logger.LogError("Error inesperado SubirArchivoApiAsync", ex);
return false;
}
Console.WriteLine($"[API] Registrado: {rutaArchivo}");
return true;
}
public async Task ReprocesarArchivosPendientesAsync(bool iniciarAlFinal = true)
{
// Limpieza automática antes de reprocesar
_repo.LimpiarRegistrosInexistentes();
// Volver a registrar todos los expedientes para procesar todo en caso de que no este actualizada la base de datos
await BarridoInicialAsync();
// await ProcesarArchivosPendientesAsync();
if (iniciarAlFinal)
{
Console.WriteLine("Iniciando monitoreo despues de reprocesar pendientes...");
Iniciar();
}
}
public async Task EscaneoManual()
{
_MonitoreoTimer = true;
// Volver a registrar todos los expedientes para procesar todo en caso de que no este actualizada la base de datos
await BarridoInicialAsync();
await ProcesarPilaAsync();
_MonitoreoTimer = false;
}
//private async Task ProcesarArchivosPendientesAsync()
//{
// Console.WriteLine("Iniciando barrido inicial de carpetas...");
// await Task.Run( async () =>
// {
// try
// {
// // Obtener lista de pendientes después de limpieza
// var pendientes = _repo.ObtenerArchivosPendientes();
// if (!pendientes.Any())
// {
// Console.WriteLine("No hay archivos pendientes por reprocesar.");
// return;
// }
// // Agrupamos por carpeta raíz
// var grupos = pendientes.GroupBy(p => p.CarpetaRaiz);
// foreach (var grupo in grupos)
// {
// string carpetaRaiz = grupo.Key;
// // Validamos que los archivos sigan existiendo
// var archivosValidos = grupo
// .Where(p => File.Exists(p.RutaArchivo))
// .ToList();
// if (!archivosValidos.Any())
// {
// Console.WriteLine($"No se encontraron archivos válidos en {carpetaRaiz} para reprocesar.");
// continue;
// }
// string nombreRaiz = Path.GetFileName(carpetaRaiz);
// try
// {
// foreach (var archivo in archivosValidos)
// {
// try
// {
// bool respuesa = await RegistrarArchivoEnAPI(archivo.RutaArchivo, nombreRaiz);
// if (respuesa)
// {
// _repo.ActualizarEstadoArchivo(archivo.RutaArchivo, "Procesado");
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine($"[API ERR] {ex.Message}");
// }
// }
// Console.WriteLine($"Reprocesados {archivosValidos.Count} archivos de {carpetaRaiz}");
// }
// catch (Exception ex)
// {
// Console.WriteLine($"Error reprocesando {carpetaRaiz}: {ex.Message}");
// }
// finally
// {
// Console.WriteLine("Terminado: Reprocesar Archivos Pendientes");
// }
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine($"Error Reprocesar Archivos Pendientes: {ex.Message}");
// }
// });
// }
private async Task BarridoInicialAsync()
{
Console.WriteLine("Iniciando barrido inicial de carpetas...");
await Task.Run(() => {
try
{
if (!Directory.Exists(_carpetaBase)) return;
// Obtiene las subcarpetas (hijos directos)
string[] carpetasHijos = Directory.GetDirectories(_carpetaBase);
if (_aplicaWinsaii)
{
foreach (var carpetaHijo in carpetasHijos)
{
// Obtiene las subcarpetas de cada hijo (nietos)
string[] carpetasNietos = Directory.GetDirectories(carpetaHijo);
foreach (var carpetaNieto in carpetasNietos)
{
if (!Helpers.EsValidaNomeclaturaCarpeta(carpetaNieto)) continue;
_repo.UpsertCarpeta(ruta: carpetaNieto, nombre: Path.GetFileName(carpetaNieto), tipo: "Nieto", estado: "Nuevo");
EncolarSiNoEsta(carpetaNieto);
}
}
}
else
{
foreach (var carpetaHijo in carpetasHijos)
{
if (!Helpers.EsValidaNomeclaturaCarpeta(carpetaHijo)) continue;
_repo.UpsertCarpeta(ruta: carpetaHijo, nombre: Path.GetFileName(carpetaHijo), tipo: "Hijo", estado: "Nuevo");
EncolarSiNoEsta(carpetaHijo);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error al barrer carpeta {_carpetaBase}: {ex.Message}");
}
finally
{
//OnDatosActualizados();
}
});
}
public bool ExisteConfiguracionExpediente()
{
return _repo.ExisteConfiguracionExpediente();
}
//private void OnDatosActualizados()
//{
// DatosActualizados?.Invoke(this, EventArgs.Empty);
//}
// Método para disparar evento
private void OnDatosActualizados(string carpetaRaiz)
{
DatosActualizados?.Invoke(this, new DatosActualizadosEventArgs(carpetaRaiz));
}
public void Dispose()
{
try { _watcher?.Dispose(); } catch { }
//_repo?.Dispose();
_semaforo?.Dispose();
_dbSemaforo?.Dispose();
}
}
}

98
Classes/ProcessLogger.cs Normal file
View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public class ProcessLogger
{
private readonly string _logDirectory;
private readonly long _maxFileSizeBytes;
private readonly object _lock = new object();
private DateTime _currentLogDate;
private string _currentLogFilePath;
public ProcessLogger(string logDirectory = "Logs", string? logFileName = null, long maxFileSizeBytes = 1 * 1024 * 1024) // 1 MB
{
_logDirectory = logDirectory;
_maxFileSizeBytes = maxFileSizeBytes;
_currentLogDate = DateTime.Now;
if (!Directory.Exists(_logDirectory))
{
Directory.CreateDirectory(_logDirectory);
}
_currentLogFilePath = GetLogFilePath(_currentLogDate, logFileName);
}
public void LogInfo(string message) => Log("INFO", message);
public void LogWarning(string message) => Log("WARNING", message);
public void LogError(string message, Exception? ex = null)
{
string fullMessage = message;
if (ex != null)
{
fullMessage += $"{Environment.NewLine}Exception: {ex.Message}{Environment.NewLine}StackTrace: {ex.StackTrace}";
}
Log("ERROR", fullMessage);
}
private void Log(string level, string message)
{
string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{level}] {message}";
lock (_lock)
{
RotateLogFileIfNeeded();
File.AppendAllText(_currentLogFilePath, logEntry + Environment.NewLine);
}
}
private void RotateLogFileIfNeeded()
{
DateTime now = DateTime.Now;
// Cambio de día: nuevo archivo
if (now.Date != _currentLogDate.Date)
{
_currentLogDate = now;
_currentLogFilePath = GetLogFilePath(_currentLogDate);
return;
}
// Excede tamaño máximo: crear nuevo archivo con sufijo incremental
if (File.Exists(_currentLogFilePath) &&
new FileInfo(_currentLogFilePath).Length >= _maxFileSizeBytes)
{
int index = 1;
string newPath;
do
{
newPath = GetLogFilePath(_currentLogDate, null, index++);
} while (File.Exists(newPath));
_currentLogFilePath = newPath;
}
}
private string GetLogFilePath(DateTime date, string? customName = null, int index = 0)
{
string datePart = date.ToString("yyyyMMdd");
string baseName = string.IsNullOrWhiteSpace(customName)
? $"log_{datePart}"
: Path.GetFileNameWithoutExtension(customName);
string extension = ".txt";
string fileName = index == 0
? $"{baseName}{extension}"
: $"{baseName}_{index}{extension}";
return Path.Combine(_logDirectory, fileName);
}
}
}

872
Classes/SQLiteHelper.cs Normal file
View File

@@ -0,0 +1,872 @@
using EFCDesk.Entidades;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Data.Common;
using System.Data.SQLite;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
namespace EFCDesk.Classes
{
public class SQLiteHelper
{
private string _connectionString;
public SQLiteHelper(string databasePath)
{
_connectionString = $"Data Source={databasePath};Version=3;Journal Mode=WAL;Pooling=true;Cache Size=10000;Synchronous=OFF;";
InitializeDatabase();
}
private void InitializeDatabase()
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
// Configuración para mejor concurrencia
using (var pragmaCmd = new SQLiteCommand("PRAGMA busy_timeout = 30000;", connection))
{
pragmaCmd.ExecuteNonQuery();
}
string createConfiguracionTableQuery = @"
CREATE TABLE IF NOT EXISTS Configuracion (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
IniciarExpedienteWindows INTEGER NOT NULL DEFAULT 0,
FolderParaGenerarExpediente TEXT,
DepurarExpediente INTEGER,
FolderParaDepurarExpediente TEXT,
UsarEstructuraPedimentosWinsaai INTEGER,
UsarExpedienteLogistico INTEGER,
ServidorFTP TEXT,
UsuarioFTP TEXT,
PasswordFTP TEXT,
PuertoFTP INTEGER,
ModoPasivoFTP INTEGER
);";
string createArchivosProcesadosTableQuery = @"
CREATE TABLE IF NOT EXISTS ArchivosProcesados (
IdArchivo INTEGER PRIMARY KEY AUTOINCREMENT,
NombreArchivo TEXT NOT NULL,
RutaArchivo TEXT NOT NULL UNIQUE,
Estado TEXT NOT NULL DEFAULT 'Pendiente',
FechaProcesado DATETIME DEFAULT NULL,
FolderExpediente TEXT NOT NULL,
CarpetaRaiz TEXT NOT NULL,
HashContenido TEXT, -- opcional
ArchivoZip TEXT NOT NULL
);";
string createErrorLogTableQuery = @"
CREATE TABLE IF NOT EXISTS ErrorLog (
Id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
LineaError TEXT,
Clase TEXT,
Metodo TEXT,
Error TEXT,
Comentario TEXT,
Fecha TEXT
);";
string createCarpetasTableQuery = @"
CREATE TABLE IF NOT EXISTS Carpetas (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Ruta TEXT NOT NULL UNIQUE,
Nombre TEXT NOT NULL,
Tipo TEXT NOT NULL, -- Hijo o Nieto
Estado TEXT NOT NULL, -- Nuevo o Procesado
FechaCreado DATETIME DEFAULT NULL
);";
string createIndex = @"
CREATE INDEX IF NOT EXISTS IX_Carpetas_Estado ON Carpetas(Estado);
CREATE INDEX IF NOT EXISTS IX_Archivos_Ruta ON ArchivosProcesados(RutaArchivo);
";
string pragmaModeQuery = "PRAGMA journal_mode=WAL;";
// Ejecutar las consultas para crear las tablas
using (var command = new SQLiteCommand(connection))
{
command.CommandText = createConfiguracionTableQuery;
command.ExecuteNonQuery();
command.CommandText = createArchivosProcesadosTableQuery;
command.ExecuteNonQuery();
command.CommandText = createErrorLogTableQuery;
command.ExecuteNonQuery();
command.CommandText = createCarpetasTableQuery;
command.ExecuteNonQuery();
command.CommandText = createIndex;
command.ExecuteNonQuery();
command.CommandText = pragmaModeQuery;
command.ExecuteNonQuery();
}
}
}
catch (SQLiteException ex)
{
MessageBox.Show(ex.ToString());
}
}
public SQLiteConnection GetConnection()
{
return new SQLiteConnection(_connectionString);
}
private async Task<SQLiteConnection> GetOpenConnectionAsync(int maxRetries = 3)
{
int retryCount = 0;
while (retryCount < maxRetries)
{
try
{
var connection = new SQLiteConnection(_connectionString);
await connection.OpenAsync();
return connection;
}
catch (SQLiteException ex) when (ex.ResultCode == SQLiteErrorCode.Busy && retryCount < maxRetries - 1)
{
retryCount++;
await Task.Delay(100 * retryCount); // Backoff exponencial
}
}
throw new InvalidOperationException("No se pudo establecer conexión después de varios intentos");
}
public List<(string ArchivoZip, string Estado)> ObtenerArchivosZIP()
{
var lista = new List<(string ArchivoZip, string Estado)>();
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string query = "SELECT DISTINCT ArchivoZip, Estado from ArchivosProcesados;";
using (var command = new SQLiteCommand(query, connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
lista.Add((
reader.GetString(0), // CarpetaCliente
reader.GetString(1) // CarpetaPedimento
//reader.GetString(2) // NombreArchivo
//reader.GetString(3) // FechaProcesado
));
}
}
}
return lista;
}
public List<(string Archivo, string Zip, DateTime Fecha, string Estado)> ObtenerArchivosProcesados(string archivoZIP)
{
var lista = new List<(string Archivo, string Zip, DateTime Fecha, string Estado)>();
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string query = "SELECT NombreArchivo, ArchivoZip, FechaProcesado, Estado FROM ArchivosProcesados WHERE ArchivoZip = @archivoZIP;";
using (var command = new SQLiteCommand(query, connection))
{
// Agregar el parámetro con su valor
command.Parameters.AddWithValue("@archivoZIP", archivoZIP);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
string nombreArchivo = reader.GetString(0);
string archivoZip = reader.GetString(1);
string Estatus = reader.GetString(3);
DateTime fechaProcesado = DateTime.MinValue; // Valor por defecto
if (!reader.IsDBNull(2))
{
fechaProcesado = reader.GetDateTime(2); // Obtener como DateTime directamente
}
lista.Add((nombreArchivo, archivoZip, fechaProcesado, Estatus));
}
}
}
}
return lista;
}
public void RegistrarArchivoProcesado(string nombreArchivo, string rutaArchivo, string estado, DateTime fechaProcesado, string folderExpediente, string archivoZip)
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
// Verificar si el archivo ya existe en la tabla
string checkQuery = @"
SELECT COUNT(1)
FROM ArchivosProcesados
WHERE NombreArchivo = @NombreArchivo;";
using (var checkCommand = new SQLiteCommand(checkQuery, connection))
{
checkCommand.Parameters.AddWithValue("@NombreArchivo", nombreArchivo);
long count = (long)checkCommand.ExecuteScalar();
if (count > 0)
{
// Si ya existe, no hacer nada
return;
}
}
// Insertar el registro si no existe
string insertQuery = @"
INSERT INTO ArchivosProcesados (NombreArchivo, RutaArchivo, Estado, FechaProcesado, FolderExpediente, ArchivoZip)
VALUES (@NombreArchivo, @RutaArchivo, @Estado, @FechaProcesado, @FolderExpediente, @Archivozip);";
using (var command = new SQLiteCommand(insertQuery, connection))
{
command.Parameters.AddWithValue("@NombreArchivo", nombreArchivo);
command.Parameters.AddWithValue("@RutaArchivo", rutaArchivo);
command.Parameters.AddWithValue("@Estado", estado);
command.Parameters.AddWithValue("@FechaProcesado", fechaProcesado);
command.Parameters.AddWithValue("@FolderExpediente", folderExpediente);
command.Parameters.AddWithValue("@Archivozip", archivoZip);
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public void AgregarRegistroErrorLog(Exception ex, string sClase, string sMetodo, string sComentario = "")
{
string sLineaError = "";
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
sLineaError = ex.StackTrace.ToString();
int last = sLineaError.LastIndexOf("\\");
sLineaError = sLineaError.Substring(last, sLineaError.Length - last).Replace("\\", "");
DateTime thisDayHour = DateTime.Now;
string sFechaHora = thisDayHour.ToString("yyyyMMddHHmmss");
string sFecha = sFechaHora.Substring(0, 8);
string insertQuery = @"
INSERT INTO ErrorLog (LineaError, Clase, Metodo, Error, Comentario, Fecha)
VALUES (@LineaError, @Clase, @Metodo, @Error, @Comentario, @Fecha);";
using (var command = new SQLiteCommand(insertQuery, connection))
{
command.Parameters.AddWithValue("@LineaError", sLineaError);
command.Parameters.AddWithValue("@Clase", sClase);
command.Parameters.AddWithValue("@Metodo", sMetodo);
command.Parameters.AddWithValue("@Error", ex.Message.ToString());
command.Parameters.AddWithValue("@Comentario", sComentario);
command.Parameters.AddWithValue("@Fecha", sFechaHora);
command.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
}
}
public List<(int id, string lineaError, string error, string comentarios, string fecha)> GetRegistrosErrorLog()
{
var lista = new List<(int id, string lineaError, string error, string comentarios, string fecha)>();
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string query = "SELECT Id, LineaError, Error, Comentario, Fecha FROM ErrorLog;";
using (var command = new SQLiteCommand(query, connection))
{
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
int idLog = reader.GetInt32(0);
lista.Add((
idLog,
reader.IsDBNull(1) ? "" : reader.GetString(1), // ✅ Manejo de valores NULL
reader.IsDBNull(2) ? "" : reader.GetString(2),
reader.IsDBNull(3) ? "" : reader.GetString(3),
reader.IsDBNull(4) ? "" : reader.GetString(4)
));
}
}
}
}
return lista;
}
public bool ExisteConfiguracionExpediente()
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
// Verificar si hay registros en la tabla ArchivosProcesados
string checkQuery = "SELECT COUNT(1) FROM Configuracion;";
int registrosExistentes;
using (var command = new SQLiteCommand(checkQuery, connection))
{
registrosExistentes = Convert.ToInt32(command.ExecuteScalar());
}
// Si hay registros, no realizar el escaneo inicial
if (registrosExistentes == 0)
{
return false;
}
}
return true;
}
public List<(string Ruta, string Nombre, string Tipo)> ObtenerPendientes()
{
var lista = new List<(string, string, string)>();
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string query = "SELECT Ruta, Nombre, Tipo FROM Carpetas WHERE Estado IN('Nuevo','Pendiente')";
using (var command = new SQLiteCommand(query, connection))
{
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
lista.Add((reader.GetString(0), reader.GetString(1), reader.GetString(2)));
}
}
}
}
return lista;
}
public List<(string RutaArchivo, string NombreArchivo, string CarpetaRaiz, string ArchivoZip)> ObtenerArchivosPendientes()
{
var lista = new List<(string RutaArchivo, string NombreArchivo, string CarpetaRaiz, string ArchivoZip)>();
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string sql = @"
SELECT RutaArchivo, NombreArchivo, CarpetaRaiz, ArchivoZip
FROM ArchivosProcesados
WHERE Estado = 'Pendiente'
ORDER BY CarpetaRaiz, ArchivoZip, NombreArchivo;";
using (var cmd = new SQLiteCommand(sql, connection))
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string ruta = reader.GetString(0);
string nombre = reader.GetString(1);
string carpetaRaiz = reader.GetString(2);
string zip = reader.GetString(3);
lista.Add((ruta, nombre, carpetaRaiz, zip));
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error al obtener archivos pendientes: {ex.Message}");
}
return lista;
}
public List<(string ArchivoZip, string Estado, string fechaCreacion)> ObtenerCarpetas(string buscarRuta = "*")
{
var lista = new List<(string Nombre, string Estado, string fechaCreacion)>();
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string query = "";
if (buscarRuta == "*")
{
query = "SELECT Id, Nombre, Estado, FechaCreado from Carpetas ORDER BY FechaCreado DESC LIMIT 1000;";
}
else
{
query = "SELECT Id, Nombre, Estado, FechaCreado from Carpetas WHERE Ruta=@RutaCarpeta LIMIT 1;";
}
using (var command = new SQLiteCommand(query, connection))
{
if (buscarRuta != "*") command.Parameters.AddWithValue("@RutaCarpeta", buscarRuta);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
lista.Add((
reader.GetString(1) + ".zip", // NombreCarpeta
reader.GetString(2), // Estado
reader.GetString(3) // Fecha Creacion
));
}
}
}
connection.Close();
}
return lista;
}
public void UpsertCarpeta(string ruta, string nombre, string tipo, string estado)
{
try
{
string fecha = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
// Insertar el registro si no existe
//string insertQuery = @"
// INSERT INTO Carpetas (Ruta, Nombre, Tipo, Estado)
// VALUES (@r, @n, @t, @e)
// ON CONFLICT(Ruta) DO UPDATE SET
// Tipo=excluded.Tipo,
// Estado=excluded.Estado,
// Nombre=excluded.Nombre;
// ";
string insertQuery = @"
INSERT INTO Carpetas (Ruta, Nombre, Tipo, Estado, FechaCreado)
VALUES (@r, @n, @t, @e, @f)
ON CONFLICT(Ruta) DO NOTHING;
";
using (var command = new SQLiteCommand(insertQuery, connection))
{
command.Parameters.AddWithValue("@r", ruta);
command.Parameters.AddWithValue("@n", nombre);
command.Parameters.AddWithValue("@t", tipo);
command.Parameters.AddWithValue("@e", estado);
command.Parameters.AddWithValue("@f", fecha);
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public void MarcarCarpetaProcesada(string ruta, string estado)
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string updateQuery = "UPDATE Carpetas SET Estado=@e WHERE Ruta=@r";
using (var command = new SQLiteCommand(updateQuery, connection))
{
command.Parameters.AddWithValue("@r", ruta);
command.Parameters.AddWithValue("@e", estado);
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public bool EstaArchivoProcesado(string rutaArchivo)
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string updateQuery = "SELECT 1 FROM ArchivosProcesados WHERE RutaArchivo=@r AND Estado='Procesado' LIMIT 1";
using (var command = new SQLiteCommand(updateQuery, connection))
{
command.Parameters.AddWithValue("@r", rutaArchivo);
return command.ExecuteScalar() != null;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
return false;
}
}
public void RegistrarArchivoProcesado(string rutaArchivo, string nombreArchivo, string carpetaRaiz, string archivoZip, string? hashContenido)
{
try
{
string fecha = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
// Insertar el registro si no existe
string insertQuery = @"
INSERT OR IGNORE INTO ArchivosProcesados (RutaArchivo, NombreArchivo, CarpetaRaiz, HashContenido, ArchivoZip, FechaProcesado, FolderExpediente)
VALUES (@r, @n, @cr, @h, @az, @f, @fe)";
using (var command = new SQLiteCommand(insertQuery, connection))
{
command.Parameters.AddWithValue("@r", rutaArchivo);
command.Parameters.AddWithValue("@n", nombreArchivo);
command.Parameters.AddWithValue("@cr", carpetaRaiz);
command.Parameters.AddWithValue("@h", (object?)hashContenido ?? DBNull.Value);
command.Parameters.AddWithValue("@az", archivoZip);
command.Parameters.AddWithValue("@f", fecha);
command.Parameters.AddWithValue("@fe", "");
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public void MarcarArchivosZipComoProcesados(string archivoZip)
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string sql = @"
UPDATE ArchivosProcesados
SET Estado = 'Procesado',
FechaProcesado = COALESCE(FechaProcesado, datetime('now'))
WHERE ArchivoZip = @zip
AND Estado <> 'Procesado';";
using (var cmd = new SQLiteCommand(sql, connection))
{
// Ojo: si guardas solo el nombre (ej. "Carpeta1.zip"),
// pásalo igual aquí. Si guardas ruta completa, pasa la ruta completa.
cmd.Parameters.AddWithValue("@zip", archivoZip);
cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public void ActualizarEstadoArchivo(string rutaArchivo, string nuevoEstado)
{
try
{
string fecha = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string sql = @"
UPDATE ArchivosProcesados
SET Estado = @estado,
FechaProcesado = COALESCE(@fecha, FechaProcesado)
WHERE RutaArchivo = @ruta;";
using (var cmd = new SQLiteCommand(sql, connection))
{
cmd.Parameters.AddWithValue("@estado", nuevoEstado);
cmd.Parameters.AddWithValue("@ruta", rutaArchivo);
cmd.Parameters.AddWithValue("@fecha", fecha);
cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public void LimpiarRegistrosInexistentes()
{
try
{
int archivosEliminados = 0;
int carpetasEliminados = 0;
// Eliminar los registros inexistentes de archivos
using (var conn = new SQLiteConnection(_connectionString))
{
conn.Open();
// Obtener todos los registros guardados
using (var cmd = new SQLiteCommand("SELECT RutaArchivo FROM ArchivosProcesados", conn))
using (var reader = cmd.ExecuteReader())
{
var rutasAEliminar = new List<string>();
while (reader.Read())
{
string ruta = reader.GetString(0);
// Si el archivo ya no existe, lo marcamos para borrar del registro
if (!File.Exists(ruta))
rutasAEliminar.Add(ruta);
}
reader.Close();
// Borrar registros inexistentes
foreach (var ruta in rutasAEliminar)
{
using (var deleteCmd = new SQLiteCommand("DELETE FROM ArchivosProcesados WHERE RutaArchivo = @ruta", conn))
{
deleteCmd.Parameters.AddWithValue("@ruta", ruta);
archivosEliminados += deleteCmd.ExecuteNonQuery();
}
}
}
conn.Close();
}
// Eliminar los registros inexistentes de carpetas
using (var conn = new SQLiteConnection(_connectionString))
{
conn.Open();
// Obtener todos los registros guardados
using (var cmd = new SQLiteCommand("SELECT Ruta FROM Carpetas", conn))
using (var reader = cmd.ExecuteReader())
{
var rutasAEliminar = new List<string>();
while (reader.Read())
{
string ruta = reader.GetString(0);
// Si el archivo ya no existe, lo marcamos para borrar del registro
if (!Directory.Exists(ruta))
rutasAEliminar.Add(ruta);
}
reader.Close();
// Borrar registros inexistentes
foreach (var ruta in rutasAEliminar)
{
using (var deleteCmd = new SQLiteCommand("DELETE FROM Carpetas WHERE Ruta = @ruta", conn))
{
deleteCmd.Parameters.AddWithValue("@ruta", ruta);
carpetasEliminados += deleteCmd.ExecuteNonQuery();
}
}
}
conn.Close();
}
Console.WriteLine($"Limpieza completada: {carpetasEliminados} registros eliminados de CarpetasProcesados.");
Console.WriteLine($"Limpieza completada: {archivosEliminados} registros eliminados de ArchivosProcesados.");
}
catch (Exception ex)
{
Console.WriteLine($"Error en limpieza de registros inexistentes: {ex.Message}");
}
}
public bool ArchivoExiste(string rutaArchivo)
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string sql = @"SELECT COUNT(*) FROM ArchivosPendientes WHERE RutaArchivo = @Ruta";
using (var cmd = new SQLiteCommand(sql, connection))
{
cmd.Parameters.AddWithValue("@Ruta", rutaArchivo);
return Convert.ToInt32(cmd.ExecuteScalar()) > 0;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
return false;
}
}
public void GuardarArchivoPendiente(string rutaArchivo, string nombreArchivo, string carpetaRaiz, string archivoZip, string? hashContenido)
{
try
{
string fecha = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
// Insertar el registro si no existe
string insertQuery = @"
INSERT OR IGNORE INTO ArchivosProcesados (RutaArchivo, NombreArchivo, CarpetaRaiz, HashContenido, ArchivoZip, FechaProcesado, FolderExpediente, Estado)
VALUES (@r, @n, @cr, @h, @az, @f, @fe, 'Pendiente')";
using (var command = new SQLiteCommand(insertQuery, connection))
{
command.Parameters.AddWithValue("@r", rutaArchivo);
command.Parameters.AddWithValue("@n", nombreArchivo);
command.Parameters.AddWithValue("@cr", carpetaRaiz);
command.Parameters.AddWithValue("@h", (object?)hashContenido ?? DBNull.Value);
command.Parameters.AddWithValue("@az", archivoZip);
command.Parameters.AddWithValue("@f", fecha);
command.Parameters.AddWithValue("@fe", "");
command.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public List<ExpedienteInfo> ObtenerExpedientes(long pagina, long tamanioPagina = 1000, string buscarExpediente = "*")
{
long pageNumber = pagina; // pedimos la segunda página
long pageSize = tamanioPagina;
var lista = new List<ExpedienteInfo>();
long offset = (pageNumber - 1) * pageSize;
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string query = "";
if (buscarExpediente == "*")
{
query = "SELECT Id, Nombre, Estado, FechaCreado, Ruta from Carpetas ORDER BY Nombre DESC LIMIT @pageSize OFFSET @offset;";
}
else
{
query = "SELECT Id, Nombre, Estado, FechaCreado, Ruta from Carpetas WHERE Nombre LIKE '%' || @Expediente || '%' LIMIT @pageSize OFFSET @offset;";
}
using (var command = new SQLiteCommand(query, connection))
{
if (buscarExpediente != "*") command.Parameters.AddWithValue("@Expediente", buscarExpediente);
command.Parameters.AddWithValue("@pageSize", pageSize);
command.Parameters.AddWithValue("@offset", offset);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var exp = new ExpedienteInfo
{
Expediente = reader.GetString(1),
Estado = reader.GetString(2),
FechaCreacion = reader.GetString(3),
Ruta = reader.GetString(4)
};
lista.Add(exp);
}
}
}
connection.Close();
}
return lista;
}
public async Task<long> TotalExpedientes(string buscarExpediente = "*")
{
try
{
using (var connection = new SQLiteConnection(_connectionString))
{
connection.Open();
string updateQuery = "";
if (buscarExpediente == "*")
{
updateQuery = "SELECT COUNT(*) AS Total FROM Carpetas;";
}
else
{
updateQuery = "SELECT COUNT(*) AS Total FROM Carpetas WHERE Nombre LIKE '%' || @Expediente || '%';";
}
using (var command = new SQLiteCommand(updateQuery, connection))
{
if (buscarExpediente != "*") command.Parameters.AddWithValue("@Expediente", buscarExpediente);
var result = await command.ExecuteScalarAsync();
return result == null ? 0 : Convert.ToInt64(result);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
return 0;
}
}
//public void Dispose()
//{
// _conn?.Dispose();
// _conn = null;
//}
}
}

100
Classes/SaaiM3Helper.cs Normal file
View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public static class SaaiM3Helper
{
public class Registro
{
public string Tipo { get; set; }
public string[] Campos { get; set; }
}
// -----------------------------
// Cargar archivo completo
// -----------------------------
public static List<Registro> LeerArchivo(string rutaArchivo)
{
var registros = new List<Registro>();
foreach (var linea in File.ReadLines(rutaArchivo))
{
if (String.IsNullOrWhiteSpace(linea))
continue;
var partes = linea.Split('|');
registros.Add(new Registro
{
Tipo = partes[0],
Campos = partes
});
}
return registros;
}
// --------------------------------------
// Buscar por tipo (ej. "551")
// --------------------------------------
public static List<Registro> BuscarPorTipo(List<Registro> registros, string tipo)
{
var lista = new List<Registro>();
foreach (var r in registros)
{
if (r.Tipo == tipo)
lista.Add(r);
}
return lista;
}
// -----------------------------------------------------------------------------------
// Buscar por tipo y por valor en un campo específico
// Ej: Buscar "551" donde Campos[2] == "4000204"
// -----------------------------------------------------------------------------------
public static List<Registro> BuscarPorTipoYCampo(List<Registro> registros, string tipo, int indexCampo, string valor)
{
var lista = new List<Registro>();
foreach (var r in registros)
{
if (r.Tipo == tipo)
{
if (r.Campos.Length > indexCampo && r.Campos[indexCampo] == valor)
{
lista.Add(r);
}
}
}
return lista;
}
// ----------------------------------------
// Búsqueda parcial (contiene)
// ----------------------------------------
public static List<Registro> BuscarPorTipoYCampoParcial(List<Registro> registros, string tipo, int indexCampo, string contiene)
{
var lista = new List<Registro>();
foreach (var r in registros)
{
if (r.Tipo == tipo)
{
if (r.Campos.Length > indexCampo &&
r.Campos[indexCampo].Contains(contiene))
{
lista.Add(r);
}
}
}
return lista;
}
}
}

View File

@@ -0,0 +1,174 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Classes
{
public static class SecureDataHandler
{
private const string SettingKey = "IdUsuario";
// Genera entropía dinámica a partir de datos de hardware y usuario
private static byte[] GetEntropy()
{
string machineName = Environment.MachineName;
string userName = Environment.UserName;
string cpu = Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER") ?? "";
string sysDrive = Environment.GetEnvironmentVariable("SystemDrive") ?? "";
//string exeHash = GetExecutableHash();
string mac = GetMacAddress() ?? "";
string combo = $"MiAppSalt|{machineName}|{userName}|{cpu}|{sysDrive}|{mac}";
return Encoding.UTF8.GetBytes(combo);
}
// Calcula hash SHA256 del ejecutable para validar que no ha sido copiado o modificado
private static string GetExecutableHash()
{
string exePath = Application.ExecutablePath;
using (var sha = SHA256.Create())
using (var stream = File.OpenRead(exePath))
{
byte[] hash = sha.ComputeHash(stream);
return Convert.ToBase64String(hash);
}
}
private static string? GetMacAddress()
{
var nic = System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces()
.FirstOrDefault(n =>
n.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up &&
n.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback &&
n.GetPhysicalAddress().GetAddressBytes().Length > 0);
if (nic == null) return null;
// Sin ":"
return string.Concat(nic.GetPhysicalAddress()
.GetAddressBytes()
.Select(b => b.ToString("X2")));
}
public static void SaveData(string data)
{
if (data == null) throw new ArgumentNullException(nameof(data));
byte[] bytes = Encoding.UTF8.GetBytes(data);
byte[] encrypted = ProtectedData.Protect(bytes, GetEntropy(), DataProtectionScope.CurrentUser);
string encryptedBase64 = Convert.ToBase64String(encrypted);
Properties.Settings.Default[SettingKey] = encryptedBase64;
Properties.Settings.Default.Save();
ClearBytes(bytes);
ClearBytes(encrypted);
}
public static SecureString? ReadDataAsSecureString()
{
string? encryptedBase64 = Properties.Settings.Default[SettingKey] as string;
if (string.IsNullOrEmpty(encryptedBase64)) return null;
byte[] encrypted = Convert.FromBase64String(encryptedBase64);
byte[]? decrypted = null;
try
{
decrypted = ProtectedData.Unprotect(encrypted, GetEntropy(), DataProtectionScope.CurrentUser);
string? data = Encoding.UTF8.GetString(decrypted);
var secure = new SecureString();
if (data != null)
{
foreach (char c in data) secure.AppendChar(c);
ClearString(ref data);
}
secure.MakeReadOnly();
return secure;
}
catch (CryptographicException)
{
// Los datos no se pueden desencriptar → devolver null en vez de corromper
return null;
}
finally
{
if (decrypted != null) ClearBytes(decrypted);
ClearBytes(encrypted);
}
}
public static string? ReadDataAsPlainText()
{
SecureString? ss = ReadDataAsSecureString();
if (ss == null) return null;
try { return SecureStringToString(ss); }
finally { ss.Dispose(); }
}
public static void DeleteData()
{
Properties.Settings.Default[SettingKey] = null;
Properties.Settings.Default.Save();
}
public static bool IsDataValid()
{
string? encryptedBase64 = Properties.Settings.Default[SettingKey] as string;
if (string.IsNullOrEmpty(encryptedBase64)) return false;
byte[] encrypted = Convert.FromBase64String(encryptedBase64);
try
{
byte[] decrypted = ProtectedData.Unprotect(encrypted, GetEntropy(), DataProtectionScope.CurrentUser);
ClearBytes(decrypted);
return true;
}
catch
{
return false;
}
}
private static string? SecureStringToString(SecureString secure)
{
if (secure == null) return null;
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.SecureStringToGlobalAllocUnicode(secure);
return Marshal.PtrToStringUni(ptr);
}
finally
{
if (ptr != IntPtr.Zero) Marshal.ZeroFreeGlobalAllocUnicode(ptr);
}
}
private static void ClearBytes(byte[] buf)
{
if (buf == null) return;
for (int i = 0; i < buf.Length; i++) buf[i] = 0;
}
private static unsafe void ClearString(ref string? s)
{
if (s == null) return;
fixed (char* p = s)
{
for (int i = 0; i < s.Length; i++) p[i] = '\0';
}
s = null;
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EFCDesk.Classes
{
public class TextBoxConPaste : TextBox
{
private const int WM_PASTE = 0x0302;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PASTE)
{
// Después de pegar, limpiar portapapeles
Clipboard.Clear();
}
}
}
}

BIN
EFC.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

64
EFCDesk.csproj Normal file
View File

@@ -0,0 +1,64 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<ApplicationIcon>EFC.ico</ApplicationIcon>
<ErrorReport>send</ErrorReport>
<Copyright>Aduanasoft©2025</Copyright>
<FileVersion>26.2.1.1</FileVersion>
</PropertyGroup>
<ItemGroup>
<Content Include="EFC.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.Compatibility" Version="10.0.1" />
<PackageReference Include="System.Data.SQLite" Version="1.0.119" />
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationCore">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\PresentationCore.dll</HintPath>
</Reference>
<Reference Include="PresentationFramework">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\PresentationFramework.dll</HintPath>
</Reference>
<Reference Include="WindowsFormsIntegration">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\WindowsFormsIntegration.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>

30
EFCDesk.sln Normal file
View File

@@ -0,0 +1,30 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35707.178
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCDesk", "EFCDesk.csproj", "{A510EA07-1B6E-4C77-AADB-FC5E8FBF9F35}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{223F68B7-0792-415C-999C-5A25795956F8}"
ProjectSection(SolutionItems) = preProject
appsettings.json = appsettings.json
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A510EA07-1B6E-4C77-AADB-FC5E8FBF9F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A510EA07-1B6E-4C77-AADB-FC5E8FBF9F35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A510EA07-1B6E-4C77-AADB-FC5E8FBF9F35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A510EA07-1B6E-4C77-AADB-FC5E8FBF9F35}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ADAC6B80-72AB-4C92-A505-7CD25DF17ED3}
EndGlobalSection
EndGlobal

23
Entidades/Documentos.cs Normal file
View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Entidades
{
public class Documentos
{
public string id { get; set; }
public string organizacion { get; set; }
public string pedimento { get; set; }
public string pedimento_numero { get; set; }
public string archivo { get; set; }
public int document_type { get; set; }
public int size { get; set; }
public string extension { get; set; }
public int fuente { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Entidades
{
// Clase auxiliar para manejar expedientes en memoria
public class ExpedienteInfo
{
public string Expediente { get; set; } = "";
public string Clave { get; set; } = "";
public string Estado { get; set; } = "";
public string FechaCreacion { get; set; } = "";
public string Ruta { get; set; } = "";
public string Ticks { get; set; } = "";
}
}

37
Entidades/Pedimentos.cs Normal file
View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCDesk.Entidades
{
public class Pedimentos
{
public string id { get; set; } // Se usa Guid para el campo 'id' que es un UUID
public string? pedimento { get; set; }
public string? pedimento_app { get; set; }
public string? patente { get; set; }
public string? aduana { get; set; }
public string? regimen { get; set; } // Asumí que puede ser opcional, por lo que es un string
public string? clave_pedimento { get; set; }
public string? fecha_inicio { get; set; }
public string? fecha_fin { get; set; }
public string? fecha_pago { get; set; }
public bool alerta { get; set; }
public string? contribuyente { get; set; }
public string? agente_aduanal { get; set; }
public string? curp_apoderado { get; set; }
public string? importe_total { get; set; } // Usé decimal para valores monetarios
public string? saldo_disponible { get; set; }
public string? importe_pedimento { get; set; }
public bool? existe_expediente { get; set; }
public bool? remesas { get; set; }
public int? numero_partidas { get; set; }
public string? numero_operacion { get; set; }
public string? created_at { get; set; }
public string? updated_at { get; set; }
public string? organizacion { get; set; } // Usé Guid para el campo 'organizacion'
public int? tipo_operacion { get; set; }
}
}

60
Forms/FormAvanceAPI.Designer.cs generated Normal file
View File

@@ -0,0 +1,60 @@
namespace EFCDesk.Forms
{
partial class FormAvanceAPI
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
button1 = new Button();
SuspendLayout();
//
// button1
//
button1.Location = new Point(339, 32);
button1.Name = "button1";
button1.Size = new Size(75, 23);
button1.TabIndex = 0;
button1.Text = "button1";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// FormAvanceAPI
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(440, 311);
Controls.Add(button1);
FormBorderStyle = FormBorderStyle.None;
Name = "FormAvanceAPI";
Text = "FormAvanceAPI";
ResumeLayout(false);
}
#endregion
private Button button1;
}
}

217
Forms/FormAvanceAPI.cs Normal file
View File

@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Xml;
using EFCDesk.Classes;
using System.Windows.Media.Media3D;
namespace EFCDesk.Forms
{
public partial class FormAvanceAPI : Form
{
private readonly (string Label, float Value, Color Color)[] _data;
private int? _hoveredIndex = null;
static float totalPedimentos = 0;
static float totalPendientes = 0;
static float totalProcesando = 0;
static float totalProcesados = 0;
public FormAvanceAPI()
{
InitializeComponent();
ConsultarDatosAPI();
_data = new[]
{
("Pendientes", totalPendientes, Color.FromArgb(46, 134, 222)),
("Procesados", totalProcesados, Color.FromArgb(231, 76, 60)),
("Procesando", totalProcesando, Color.FromArgb(39, 174, 96))
};
this.Text = "Gráfico Interactivo";
this.Size = new Size(800, 600);
this.DoubleBuffered = true;
this.Paint += OnPaint;
this.MouseMove += OnMouseMove;
}
private void ConsultarDatosAPI()
{
try
{
var config = ConfiguracionJSON.LoadFromJson();
string cryptUser = General.CodificarBase64(config.idUsuarioExp.ToString());
dynamic root = config.Consulta(config.DominioExp + "/api/avance/" + cryptUser);
if (root is XmlElement)
{
XmlNodeList nodes = root.SelectNodes("/xml/Resultado");
if (root.InnerText != "" && root.InnerText != "Error")
{
foreach (XmlNode node in nodes)
{
totalPedimentos = float.Parse(node["totalPedimentos"].InnerText);
totalPendientes = float.Parse(node["totalPendientes"].InnerText);
totalProcesando = float.Parse(node["totalProcesando"].InnerText);
totalProcesados = float.Parse(node["totalProcesados"].InnerText);
}
}
}
}
catch (Exception ex)
{
string errores = "";
string sNombreClase = System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType?.Name;
string currentMethod = System.Reflection.MethodBase.GetCurrentMethod().Name;
//MyClass.LogErrores(ex, sNombreClase, currentMethod);
}
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
var rect = new Rectangle(50, 50, 400, 400);
if (!rect.Contains(e.Location))
{
if (_hoveredIndex.HasValue)
{
_hoveredIndex = null;
this.Invalidate();
}
return;
}
float total = _data.Sum(item => item.Value);
float startAngle = 0f;
for (int i = 0; i < _data.Length; i++)
{
float sweepAngle = 360f * (_data[i].Value / total);
using (var path = new GraphicsPath())
{
path.AddPie(rect, startAngle, sweepAngle);
if (path.IsVisible(e.Location))
{
if (_hoveredIndex != i)
{
_hoveredIndex = i;
this.Invalidate();
}
return;
}
}
startAngle += sweepAngle;
}
if (_hoveredIndex.HasValue)
{
_hoveredIndex = null;
this.Invalidate();
}
}
private void OnPaint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
var rect = new Rectangle(50, 50, 400, 400);
float total = _data.Sum(item => item.Value);
float startAngle = 0f;
// Dibujar el gráfico de pastel
for (int i = 0; i < _data.Length; i++)
{
float sweepAngle = 360f * (_data[i].Value / total);
var color = _hoveredIndex == i ?
ControlPaint.Light(_data[i].Color, 0.3f) :
_data[i].Color;
using (var brush = new SolidBrush(color))
{
g.FillPie(brush, rect, startAngle, sweepAngle);
g.DrawPie(Pens.Black, rect, startAngle, sweepAngle);
}
startAngle += sweepAngle;
}
// Dibujar leyenda mejorada
DrawLegend(g);
// Mostrar tooltip si hay elemento hover
if (_hoveredIndex.HasValue)
{
var item = _data[_hoveredIndex.Value];
var text = $"{item.Label}\n{item.Value}% ({item.Value / total:P0})";
using (var font = new Font("Arial", 12, FontStyle.Bold))
using (var brush = new SolidBrush(Color.FromArgb(220, Color.Black)))
{
var size = g.MeasureString(text, font);
var tooltipRect = new Rectangle(
rect.Right + 20,
rect.Top + (_hoveredIndex.Value * 40),
(int)size.Width + 20,
(int)size.Height + 10);
g.FillRectangle(brush, tooltipRect);
g.DrawRectangle(Pens.Gray, tooltipRect);
g.DrawString(text, font, Brushes.White,
tooltipRect.X + 10,
tooltipRect.Y + 5);
}
}
}
private void DrawLegend(Graphics g)
{
int x = 500;
int y = 100;
const int boxSize = 20;
const int spacing = 30;
using (var font = new Font("Arial", 12))
using (var boldFont = new Font("Arial", 12, FontStyle.Bold))
{
for (int i = 0; i < _data.Length; i++)
{
var item = _data[i];
var currentFont = _hoveredIndex == i ? boldFont : font;
// Cuadro de color
using (var brush = new SolidBrush(item.Color))
{
g.FillRectangle(brush, x, y, boxSize, boxSize);
g.DrawRectangle(Pens.Black, x, y, boxSize, boxSize);
}
// Texto
g.DrawString($"{item.Label}: {item.Value}%",
currentFont,
Brushes.Black,
x + boxSize + 10,
y);
y += spacing;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}

120
Forms/FormAvanceAPI.resx Normal file
View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

59
Forms/FormCargarInformacion.Designer.cs generated Normal file
View File

@@ -0,0 +1,59 @@
namespace EFCDesk.Forms
{
partial class FormCargarInformacion
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
progressBar1 = new ProgressBar();
SuspendLayout();
//
// progressBar1
//
progressBar1.Location = new Point(12, 262);
progressBar1.Name = "progressBar1";
progressBar1.Size = new Size(406, 11);
progressBar1.TabIndex = 0;
//
// FormCargarInformacion
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
BackgroundImage = Properties.Resources.splash4;
ClientSize = new Size(430, 285);
Controls.Add(progressBar1);
FormBorderStyle = FormBorderStyle.None;
Name = "FormCargarInformacion";
Text = "FormCargarInformacion";
Load += FormCargarInformacion_Load;
ResumeLayout(false);
}
#endregion
private ProgressBar progressBar1;
}
}

View File

@@ -0,0 +1,28 @@
using EFCDesk.Classes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EFCDesk.Forms
{
public partial class FormCargarInformacion : Form
{
public FormCargarInformacion()
{
InitializeComponent();
}
private void FormCargarInformacion_Load(object sender, EventArgs e)
{
var databasePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db");
var sqliteHelper = new SQLiteHelper(databasePath);
this.Close();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,495 @@
namespace EFCDesk.Forms
{
partial class FormConfiguracionExpediente
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormConfiguracionExpediente));
tabControl1 = new TabControl();
tabGeneral = new TabPage();
groupBox1 = new GroupBox();
buttonCerrarSesion = new Button();
labelUsuario = new Label();
groupBoxEspacio = new GroupBox();
labelEspacioUsado = new Label();
tabPage2 = new TabPage();
groupBox4 = new GroupBox();
buttonCambiarFolderDepuracion = new Button();
textBoxFolderExpedienteDepuracion = new TextBox();
checkBoxDepurarFolderExpediente = new CheckBox();
groupBox3 = new GroupBox();
buttonCambiarFolderExpediente = new Button();
textBoxFolderExpediente = new TextBox();
label1 = new Label();
tabPage1 = new TabPage();
label6 = new Label();
txtDiminioEFC = new TextBox();
groupBox5 = new GroupBox();
checkBoxExpedienteLogistico = new CheckBox();
checkBoxPedimentosWinsaai = new CheckBox();
tabPage3 = new TabPage();
checkBoxModoPasivoFTP = new CheckBox();
label5 = new Label();
label4 = new Label();
label3 = new Label();
label2 = new Label();
textBoxPuertoFTP = new TextBox();
textBoxUsuarioFTP = new TextBox();
textBoxServidorFTP = new TextBox();
textBoxPasswordFTP = new TextBox();
button4 = new Button();
button5 = new Button();
tabControl1.SuspendLayout();
tabGeneral.SuspendLayout();
groupBox1.SuspendLayout();
groupBoxEspacio.SuspendLayout();
tabPage2.SuspendLayout();
groupBox4.SuspendLayout();
groupBox3.SuspendLayout();
tabPage1.SuspendLayout();
groupBox5.SuspendLayout();
tabPage3.SuspendLayout();
SuspendLayout();
//
// tabControl1
//
tabControl1.Controls.Add(tabGeneral);
tabControl1.Controls.Add(tabPage2);
tabControl1.Controls.Add(tabPage1);
tabControl1.Controls.Add(tabPage3);
tabControl1.Location = new Point(12, 14);
tabControl1.Name = "tabControl1";
tabControl1.SelectedIndex = 0;
tabControl1.Size = new Size(296, 282);
tabControl1.TabIndex = 0;
//
// tabGeneral
//
tabGeneral.Controls.Add(groupBox1);
tabGeneral.Controls.Add(groupBoxEspacio);
tabGeneral.Location = new Point(4, 26);
tabGeneral.Name = "tabGeneral";
tabGeneral.Padding = new Padding(3);
tabGeneral.Size = new Size(288, 252);
tabGeneral.TabIndex = 0;
tabGeneral.Text = "General";
tabGeneral.UseVisualStyleBackColor = true;
//
// groupBox1
//
groupBox1.Controls.Add(buttonCerrarSesion);
groupBox1.Controls.Add(labelUsuario);
groupBox1.Location = new Point(6, 74);
groupBox1.Name = "groupBox1";
groupBox1.Size = new Size(276, 64);
groupBox1.TabIndex = 1;
groupBox1.TabStop = false;
groupBox1.Text = "Cuenta";
//
// buttonCerrarSesion
//
buttonCerrarSesion.Location = new Point(165, 26);
buttonCerrarSesion.Name = "buttonCerrarSesion";
buttonCerrarSesion.Size = new Size(105, 23);
buttonCerrarSesion.TabIndex = 1;
buttonCerrarSesion.Text = " Cerrar sesión...";
buttonCerrarSesion.UseVisualStyleBackColor = true;
buttonCerrarSesion.Click += button1_Click;
//
// labelUsuario
//
labelUsuario.AutoSize = true;
labelUsuario.Font = new Font("Century Gothic", 9F, FontStyle.Bold, GraphicsUnit.Point, 0);
labelUsuario.Location = new Point(18, 28);
labelUsuario.Name = "labelUsuario";
labelUsuario.Size = new Size(53, 16);
labelUsuario.TabIndex = 0;
labelUsuario.Text = "Usuario:";
//
// groupBoxEspacio
//
groupBoxEspacio.Controls.Add(labelEspacioUsado);
groupBoxEspacio.Location = new Point(6, 7);
groupBoxEspacio.Name = "groupBoxEspacio";
groupBoxEspacio.Size = new Size(276, 64);
groupBoxEspacio.TabIndex = 0;
groupBoxEspacio.TabStop = false;
groupBoxEspacio.Text = "Espacio";
//
// labelEspacioUsado
//
labelEspacioUsado.AutoSize = true;
labelEspacioUsado.Font = new Font("Century Gothic", 9F, FontStyle.Bold, GraphicsUnit.Point, 0);
labelEspacioUsado.Location = new Point(18, 28);
labelEspacioUsado.Name = "labelEspacioUsado";
labelEspacioUsado.Size = new Size(119, 16);
labelEspacioUsado.TabIndex = 0;
labelEspacioUsado.Text = "0% de 0.0GB usado";
//
// tabPage2
//
tabPage2.Controls.Add(groupBox4);
tabPage2.Controls.Add(groupBox3);
tabPage2.Location = new Point(4, 26);
tabPage2.Name = "tabPage2";
tabPage2.Padding = new Padding(3);
tabPage2.Size = new Size(288, 252);
tabPage2.TabIndex = 1;
tabPage2.Text = "Archivos";
tabPage2.UseVisualStyleBackColor = true;
//
// groupBox4
//
groupBox4.Controls.Add(buttonCambiarFolderDepuracion);
groupBox4.Controls.Add(textBoxFolderExpedienteDepuracion);
groupBox4.Controls.Add(checkBoxDepurarFolderExpediente);
groupBox4.Location = new Point(6, 146);
groupBox4.Name = "groupBox4";
groupBox4.Size = new Size(276, 80);
groupBox4.TabIndex = 1;
groupBox4.TabStop = false;
groupBox4.Text = " Depuració de folder Expediente";
groupBox4.Visible = false;
//
// buttonCambiarFolderDepuracion
//
buttonCambiarFolderDepuracion.Location = new Point(195, 43);
buttonCambiarFolderDepuracion.Name = "buttonCambiarFolderDepuracion";
buttonCambiarFolderDepuracion.Size = new Size(75, 23);
buttonCambiarFolderDepuracion.TabIndex = 3;
buttonCambiarFolderDepuracion.Text = "Cambiar";
buttonCambiarFolderDepuracion.UseVisualStyleBackColor = true;
buttonCambiarFolderDepuracion.Click += buttonCambiarFolderDepuracion_Click;
//
// textBoxFolderExpedienteDepuracion
//
textBoxFolderExpedienteDepuracion.Location = new Point(6, 44);
textBoxFolderExpedienteDepuracion.Name = "textBoxFolderExpedienteDepuracion";
textBoxFolderExpedienteDepuracion.Size = new Size(187, 22);
textBoxFolderExpedienteDepuracion.TabIndex = 3;
//
// checkBoxDepurarFolderExpediente
//
checkBoxDepurarFolderExpediente.AutoSize = true;
checkBoxDepurarFolderExpediente.Font = new Font("Century Gothic", 6.75F, FontStyle.Regular, GraphicsUnit.Point, 0);
checkBoxDepurarFolderExpediente.Location = new Point(6, 21);
checkBoxDepurarFolderExpediente.Name = "checkBoxDepurarFolderExpediente";
checkBoxDepurarFolderExpediente.Size = new Size(257, 17);
checkBoxDepurarFolderExpediente.TabIndex = 0;
checkBoxDepurarFolderExpediente.Text = " Al subir folder de Expediente mover a otra carpeta.";
checkBoxDepurarFolderExpediente.UseVisualStyleBackColor = true;
//
// groupBox3
//
groupBox3.Controls.Add(buttonCambiarFolderExpediente);
groupBox3.Controls.Add(textBoxFolderExpediente);
groupBox3.Controls.Add(label1);
groupBox3.Location = new Point(6, 7);
groupBox3.Name = "groupBox3";
groupBox3.Size = new Size(276, 136);
groupBox3.TabIndex = 0;
groupBox3.TabStop = false;
groupBox3.Text = "Ubicación de folder Expediente";
//
// buttonCambiarFolderExpediente
//
buttonCambiarFolderExpediente.Location = new Point(197, 104);
buttonCambiarFolderExpediente.Name = "buttonCambiarFolderExpediente";
buttonCambiarFolderExpediente.Size = new Size(75, 23);
buttonCambiarFolderExpediente.TabIndex = 2;
buttonCambiarFolderExpediente.Text = "Cambiar";
buttonCambiarFolderExpediente.UseVisualStyleBackColor = true;
buttonCambiarFolderExpediente.Click += buttonCambiarFolderExpediente_Click;
//
// textBoxFolderExpediente
//
textBoxFolderExpediente.Location = new Point(6, 104);
textBoxFolderExpediente.Name = "textBoxFolderExpediente";
textBoxFolderExpediente.Size = new Size(187, 22);
textBoxFolderExpediente.TabIndex = 1;
textBoxFolderExpediente.TextChanged += textBox1_TextChanged;
//
// label1
//
label1.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
label1.Location = new Point(6, 20);
label1.Name = "label1";
label1.Size = new Size(264, 87);
label1.TabIndex = 0;
label1.Text = "Elija donde se encontrará su Expediente ubicado en su computadora. Todos los archivos de Expediente deberán encontrarse en este folder para ser subido a la plataforma web.";
//
// tabPage1
//
tabPage1.Controls.Add(label6);
tabPage1.Controls.Add(txtDiminioEFC);
tabPage1.Controls.Add(groupBox5);
tabPage1.Location = new Point(4, 26);
tabPage1.Name = "tabPage1";
tabPage1.Padding = new Padding(3);
tabPage1.Size = new Size(288, 252);
tabPage1.TabIndex = 2;
tabPage1.Text = "Avanzados";
tabPage1.UseVisualStyleBackColor = true;
//
// label6
//
label6.AutoSize = true;
label6.Location = new Point(6, 93);
label6.Name = "label6";
label6.Size = new Size(84, 17);
label6.TabIndex = 15;
label6.Text = "Dominio EFC:";
//
// txtDiminioEFC
//
txtDiminioEFC.Location = new Point(6, 113);
txtDiminioEFC.Name = "txtDiminioEFC";
txtDiminioEFC.Size = new Size(276, 22);
txtDiminioEFC.TabIndex = 2;
//
// groupBox5
//
groupBox5.Controls.Add(checkBoxExpedienteLogistico);
groupBox5.Controls.Add(checkBoxPedimentosWinsaai);
groupBox5.Location = new Point(6, 6);
groupBox5.Name = "groupBox5";
groupBox5.Size = new Size(276, 84);
groupBox5.TabIndex = 0;
groupBox5.TabStop = false;
groupBox5.Text = " Estructura de archivos";
//
// checkBoxExpedienteLogistico
//
checkBoxExpedienteLogistico.AutoSize = true;
checkBoxExpedienteLogistico.Location = new Point(13, 44);
checkBoxExpedienteLogistico.Name = "checkBoxExpedienteLogistico";
checkBoxExpedienteLogistico.Size = new Size(151, 21);
checkBoxExpedienteLogistico.TabIndex = 1;
checkBoxExpedienteLogistico.Text = "Expediente Logístico";
checkBoxExpedienteLogistico.UseVisualStyleBackColor = true;
//
// checkBoxPedimentosWinsaai
//
checkBoxPedimentosWinsaai.AutoSize = true;
checkBoxPedimentosWinsaai.Location = new Point(13, 21);
checkBoxPedimentosWinsaai.Name = "checkBoxPedimentosWinsaai";
checkBoxPedimentosWinsaai.Size = new Size(154, 21);
checkBoxPedimentosWinsaai.TabIndex = 0;
checkBoxPedimentosWinsaai.Text = " Pedimentos WinSAAI";
checkBoxPedimentosWinsaai.UseVisualStyleBackColor = true;
//
// tabPage3
//
tabPage3.Controls.Add(checkBoxModoPasivoFTP);
tabPage3.Controls.Add(label5);
tabPage3.Controls.Add(label4);
tabPage3.Controls.Add(label3);
tabPage3.Controls.Add(label2);
tabPage3.Controls.Add(textBoxPuertoFTP);
tabPage3.Controls.Add(textBoxUsuarioFTP);
tabPage3.Controls.Add(textBoxServidorFTP);
tabPage3.Controls.Add(textBoxPasswordFTP);
tabPage3.Location = new Point(4, 24);
tabPage3.Name = "tabPage3";
tabPage3.Padding = new Padding(3);
tabPage3.Size = new Size(288, 254);
tabPage3.TabIndex = 3;
tabPage3.Text = "FTP";
tabPage3.UseVisualStyleBackColor = true;
//
// checkBoxModoPasivoFTP
//
checkBoxModoPasivoFTP.AutoSize = true;
checkBoxModoPasivoFTP.Location = new Point(89, 117);
checkBoxModoPasivoFTP.Name = "checkBoxModoPasivoFTP";
checkBoxModoPasivoFTP.Size = new Size(105, 21);
checkBoxModoPasivoFTP.TabIndex = 18;
checkBoxModoPasivoFTP.Text = "Modo pasivo";
checkBoxModoPasivoFTP.UseVisualStyleBackColor = true;
//
// label5
//
label5.AutoSize = true;
label5.Location = new Point(6, 91);
label5.Name = "label5";
label5.Size = new Size(53, 17);
label5.TabIndex = 17;
label5.Text = " Puerto:";
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(6, 62);
label4.Name = "label4";
label4.Size = new Size(83, 17);
label4.TabIndex = 16;
label4.Text = " Contraseña:";
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(6, 36);
label3.Name = "label3";
label3.Size = new Size(57, 17);
label3.TabIndex = 15;
label3.Text = " Usuario:";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(6, 10);
label2.Name = "label2";
label2.Size = new Size(82, 17);
label2.TabIndex = 14;
label2.Text = "Servidor FTP:";
//
// textBoxPuertoFTP
//
textBoxPuertoFTP.Location = new Point(89, 89);
textBoxPuertoFTP.Name = "textBoxPuertoFTP";
textBoxPuertoFTP.Size = new Size(81, 22);
textBoxPuertoFTP.TabIndex = 13;
//
// textBoxUsuarioFTP
//
textBoxUsuarioFTP.Location = new Point(89, 33);
textBoxUsuarioFTP.Name = "textBoxUsuarioFTP";
textBoxUsuarioFTP.Size = new Size(193, 22);
textBoxUsuarioFTP.TabIndex = 11;
//
// textBoxServidorFTP
//
textBoxServidorFTP.Location = new Point(89, 7);
textBoxServidorFTP.Name = "textBoxServidorFTP";
textBoxServidorFTP.Size = new Size(193, 22);
textBoxServidorFTP.TabIndex = 10;
//
// textBoxPasswordFTP
//
textBoxPasswordFTP.Location = new Point(89, 61);
textBoxPasswordFTP.Name = "textBoxPasswordFTP";
textBoxPasswordFTP.Size = new Size(193, 22);
textBoxPasswordFTP.TabIndex = 12;
textBoxPasswordFTP.UseSystemPasswordChar = true;
//
// button4
//
button4.Location = new Point(139, 305);
button4.Name = "button4";
button4.Size = new Size(81, 28);
button4.TabIndex = 3;
button4.Text = " Guardar";
button4.UseVisualStyleBackColor = true;
button4.Click += button4_Click;
//
// button5
//
button5.Location = new Point(226, 305);
button5.Name = "button5";
button5.Size = new Size(78, 28);
button5.TabIndex = 4;
button5.Text = " Cancelar";
button5.UseVisualStyleBackColor = true;
button5.Click += button5_Click;
//
// FormConfiguracionExpediente
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = SystemColors.Control;
ClientSize = new Size(315, 342);
Controls.Add(button5);
Controls.Add(button4);
Controls.Add(tabControl1);
Font = new Font("Century Gothic", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
FormBorderStyle = FormBorderStyle.FixedDialog;
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
MinimizeBox = false;
Name = "FormConfiguracionExpediente";
StartPosition = FormStartPosition.CenterScreen;
Text = "Configuración Expediente";
Load += FormConfiguracionExpediente_Load;
Shown += FormConfiguracionExpediente_Shown;
tabControl1.ResumeLayout(false);
tabGeneral.ResumeLayout(false);
groupBox1.ResumeLayout(false);
groupBox1.PerformLayout();
groupBoxEspacio.ResumeLayout(false);
groupBoxEspacio.PerformLayout();
tabPage2.ResumeLayout(false);
groupBox4.ResumeLayout(false);
groupBox4.PerformLayout();
groupBox3.ResumeLayout(false);
groupBox3.PerformLayout();
tabPage1.ResumeLayout(false);
tabPage1.PerformLayout();
groupBox5.ResumeLayout(false);
groupBox5.PerformLayout();
tabPage3.ResumeLayout(false);
tabPage3.PerformLayout();
ResumeLayout(false);
}
#endregion
private TabControl tabControl1;
private TabPage tabGeneral;
private GroupBox groupBoxEspacio;
private TabPage tabPage2;
private GroupBox groupBox1;
private Button buttonCerrarSesion;
private Label labelUsuario;
private Label labelEspacioUsado;
private GroupBox groupBox3;
private Label label1;
private TabPage tabPage1;
private TextBox textBoxFolderExpediente;
private Button buttonCambiarFolderExpediente;
private GroupBox groupBox4;
private Button buttonCambiarFolderDepuracion;
private TextBox textBoxFolderExpedienteDepuracion;
private CheckBox checkBoxDepurarFolderExpediente;
private GroupBox groupBox5;
private CheckBox checkBoxExpedienteLogistico;
private CheckBox checkBoxPedimentosWinsaai;
private Button button4;
private Button button5;
private TabPage tabPage3;
private CheckBox checkBoxModoPasivoFTP;
private Label label5;
private Label label4;
private Label label3;
private Label label2;
private TextBox textBoxPuertoFTP;
private TextBox textBoxUsuarioFTP;
private TextBox textBoxServidorFTP;
private TextBox textBoxPasswordFTP;
private Label label6;
private TextBox txtDiminioEFC;
}
}

View File

@@ -0,0 +1,242 @@
using EFCDesk.Classes;
using Microsoft.VisualBasic.ApplicationServices;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
namespace EFCDesk.Forms
{
public partial class FormConfiguracionExpediente : Form
{
SQLiteHelper sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
public FormConfiguracionExpediente()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private string convertir(double size)
{
try
{
string[] unit = new string[] { "B", "KB", "MB", "GB", "TB", "PB" };
double i = Math.Floor(Math.Log(size, 1024));
double y = Math.Pow(1024, i);
double r = Math.Round(size / y);
return r.ToString() + " " + unit[Convert.ToInt32(i)];
}
catch (Exception e)
{
}
return "0" + " " + "KB";
}
//private void getCapacidad()
//{
// var config = ConfiguracionJSON.LoadFromJson();
// string crypUser = General.CodificarBase64(config.UsuarioExp);
// dynamic root = config.Consulta(config.DominioExp + "/api/getLicencia/" + crypUser);
// if (root is XmlElement)
// {
// XmlNodeList nodes = root.SelectNodes("/xml/item");
// if (root.InnerText != "")
// {
// foreach (XmlNode node in nodes)
// {
// double u = Convert.ToDouble(node["usado"].InnerText);
// double c = Convert.ToDouble(node["capacidad"].InnerText);
// int porcentaje = 0;
// if (c > 0)
// {
// porcentaje = Convert.ToInt32((u * 100) / c);
// }
// string usado = convertir(u);
// string capacidad = convertir(c);
// labelEspacioUsado.Text = porcentaje.ToString() + "% de " + capacidad + " usado";
// labelUsuario.Text = "Usuario: " + config.UsuarioExp;
// }
// }
// }
//}
private void FormConfiguracionExpediente_Load(object sender, EventArgs e)
{
Globales.configJson = ConfiguracionJSON.LoadFromJson();
labelUsuario.Text = "Usuario: " + Globales.configJson.UsuarioExp ?? "No definido";
TabPage? tabOculta;
tabOculta = tabControl1.TabPages["tabPage3"];
if (tabOculta != null)
{
tabControl1.TabPages.Remove(tabOculta);
}
var config = ConfiguracionExpediente.ObtenerDesdeBaseDeDatos(sqliteHelper);
textBoxFolderExpediente.Text = config.FolderParaGenerarExpediente;
if (config.DepurarExpediente)
{
checkBoxDepurarFolderExpediente.Checked = true;
}
textBoxFolderExpedienteDepuracion.Text = config.FolderParaDepurarExpediente;
if (config.UsarEstructuraPedimentosWinsaai)
{
checkBoxPedimentosWinsaai.Checked = true;
}
if (config.UsarExpedienteLogistico)
{
checkBoxExpedienteLogistico.Checked = true;
}
textBoxServidorFTP.Text = config.ServidorFTP;
textBoxUsuarioFTP.Text = config.UsuarioFTP;
textBoxPasswordFTP.Text = config.PasswordFTP;
textBoxPuertoFTP.Text = config.PuertoFTP.ToString();
if (config.ModoPasivoFTP)
{
checkBoxModoPasivoFTP.Checked = true;
}
// getCapacidad();
}
private void button4_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBoxFolderExpediente.Text))
{
MessageBox.Show("Favor de seleccionar una ruta para su expediente.");
return;
}
var config = new ConfiguracionExpediente();
var configJson = new ConfiguracionJSON();
configJson.FolderExpediente = textBoxFolderExpediente.Text;
config.FolderParaGenerarExpediente = textBoxFolderExpediente.Text;
if (checkBoxDepurarFolderExpediente.Checked)
{
config.DepurarExpediente = true;
}
config.FolderParaDepurarExpediente = textBoxFolderExpedienteDepuracion.Text;
if (checkBoxPedimentosWinsaai.Checked)
{
config.UsarEstructuraPedimentosWinsaai = true;
configJson.ExpWinsaai = 1;
Properties.Settings.Default.ExpWinsaai = 1;
Properties.Settings.Default.Save();
}
else
{
configJson.ExpWinsaai = 0;
Properties.Settings.Default.ExpWinsaai = 0;
Properties.Settings.Default.Save();
}
if (checkBoxExpedienteLogistico.Checked)
{
config.UsarExpedienteLogistico = true;
configJson.ExpWinsaai = 3;
Properties.Settings.Default.ExpLogistico = 3;
Properties.Settings.Default.Save();
}
else
{
Properties.Settings.Default.ExpLogistico = 0;
configJson.ExpWinsaai = 0;
Properties.Settings.Default.Save();
}
config.ServidorFTP = textBoxServidorFTP.Text;
config.UsuarioFTP = textBoxUsuarioFTP.Text;
config.PasswordFTP = textBoxPasswordFTP.Text;
if (int.TryParse(textBoxPuertoFTP.Text, out int numero))
{
config.PuertoFTP = numero;
}
config.ModoPasivoFTP = checkBoxModoPasivoFTP.Checked;
config.GuardarEnBaseDeDatos(sqliteHelper);
Properties.Settings.Default.urlEFC = txtDiminioEFC.Text;
Properties.Settings.Default.Save();
configJson.DominioExp = txtDiminioEFC.Text.Trim();
configJson.SaveToJson();
Application.Restart();
}
private void buttonCambiarFolderExpediente_Click(object sender, EventArgs e)
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
textBoxFolderExpediente.Text = fbd.SelectedPath.ToString();
}
}
}
private void buttonCambiarFolderDepuracion_Click(object sender, EventArgs e)
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
textBoxFolderExpedienteDepuracion.Text = fbd.SelectedPath.ToString();
}
}
}
private void textBoxServidorFTP_TextChanged(object sender, EventArgs e)
{
}
private void label4_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
SecureDataHandler.DeleteData();
Application.Restart();
}
private void button5_Click(object sender, EventArgs e)
{
this.Close();
}
private void FormConfiguracionExpediente_Shown(object sender, EventArgs e)
{
var configJson = new ConfiguracionJSON();
configJson = ConfiguracionJSON.LoadFromJson();
string? urlEFC = configJson.DominioExp;
txtDiminioEFC.Text = urlEFC;
}
}
}

View File

@@ -0,0 +1,377 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
AAAgAAAAAQAgAAAAAAAABAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAlpWVALW0swdWV1pIMTI0pycl
I+MoJBz7KCQd+ygmI+M0NDanXF1fSL+9vAefnp4AAAAAAAAAAAD///8AV1dXAH59fhg1NjeSKiMW7llA
EP+MYhT/o3IX/6JyF/+OZyP/XEUf/yskF+46Oz2RiIeHGGJhYQD///8AbGpqAIKBgRguLi6xQTAP/6d1
GP/Qkh7/1JQe/9OUHv/Ynjj/5LJo/9mhRf+lcxb/QjAQ/zQ0NLCOjY0Yd3Z1APf18wY3ODmSQjAQ/7yE
G//TlB7/0JIe/9CSHv/Qkh//3alX/+S0dP/frF7/1Zcm/7uDGv9CMRH/Pz9Bkf///wZdXWBKLCUY7ad1
GP/TlB7/0JIe/9CSHv/Qkh7/0JIe/9mhRf/js3H/47Nx/9ulTf/TlSD/pnQX/y8oG+1oaWtINzg6qFtB
Ef/Qkh7/0JIe/9CSHv/Qkh3/0JEd/9CRHP/RlCL/3KdS/+Ozcf/ism7/1548/9CSHf9bQRL/P0BCpiwq
KOSNYxX/05Qe/9CSHf/Qkh//05cq/9WbNP/UmjL/0ZUl/9OXKv/frWH/5LRz/9+sYP/VliT/i2IU/zIx
LuItKCH7o3MX/9KTHv/SlSb/26VO/+Gwaf/js3D/361k/92pWv/eq17/4bBq/+Kxbf/bplD/05Uh/6Jy
F/8yLib6Lioj+6Z3Jv/Ynz//3atf/+S3e//dq2D/26ZW/9mjT//YoEn/2KFL/9igSv/WnkP/1Jk2/9WZ
M/+kdib/My8o+jAuK+SRazD/4K1h/+Gzc//jtnn/1p1E/9OZOv/Umjv/1Jo7/9SaO//Umjv/1Jo8/9Sa
PP/YnT7/jmgp/zY0MuM+P0CpYk0t/9+tZv/jtXf/5bh//96tZf/bqFr/1p5F/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/15GH/9HSEmna2tsSjQvKO64lGb/6LyC/+W5gP/luYH/5bmA/+Cva//Wnkb/1Jo7/9Sa
PP/Umjz/15w9/6l7L/81LiTtdnZ4Sf///wZFRUaTTD8v/9CodP/ovIL/5bmA/+W5gP/luYH/4bJw/9ad
Q//Umjz/15w9/7+LNv9HNxz/TU1Okv///waDgoEAmpmZGT4+PbJNQC//uJVn/+W5gP/pvIL/6LuC/+i7
gP/cplH/1Jo7/6l7L/9INx3/RENDsaSjoxiNi4sA////AHNycgCamZgZSUlKkzcyK+9mUzv/m31X/7SR
ZP+0kWP/k284/15GH/83MCXvT09QkqKhoRh9e3sA////AAAAAAAAAAAAtrW0ANTS0Qdzc3RKSEhJqTk3
NuU5NTH8OTYy/Do4N+VLS02oeXl7SdrY1we9u7sAAAAAAAAAAADgBwAAwAMAAIABAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAMADAADgBwAAKAAAACAAAABAAAAAAQAgAAAA
AAAAEAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ezrAP//
/wS1s7IphYODa2VkY6xPTk3YQEBA8To5Ofw6Ojn8QkFB8VFQUNhoZ2erioiHarq4tyj///8E8O/uAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+HgAP//
/wOhoJ83Z2Zllzk5ON8YGBn7BQYI/wAAAf8BAQD/AwIA/wMCAP8BAQD/AAAB/wYHCf8aGhv7Pj093m5t
bJapp6Y1////A+fl5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIWD
ggC+vLsacXBviTMyMuoJCQr/AgEA/xwTBP9IMwz/cE8S/4phFv+WaRf/lmkX/4phFv9vTxL/RzIL/xsU
CP8CAQH/CwsM/zk4OOl6eXiIxsTDGZSSkQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPTz
8gAAAAAApKKhNlNSUcITExP+AgEA/y8hCP9/WhT/uIEc/86RHv/TlB//1JQe/9OUHv/TlB7/05Qe/9SW
JP/Wn0P/wpRO/35aGP8tIAf/AgEA/xYWF/5cW1vBrqyrNAAAAAD29fQAAAAAAAAAAAAAAAAAAAAAAAAA
AADw7+4AAAAAAJ2bmkFEQ0PZBgYH/xMOA/9xUBL/wYcd/9OUH//Skx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/TmC7/3apa/+Ozcv/grF3/1JUh/8CHHP9vThL/Eg0D/wkJCf9NTUzYp6alQB4dHQDx8O8AAAAAAAAA
AAAAAAAA+/r5AHh2dQCmpKQ2RURD2QQEBP8kGQb/mm0Y/9GTHv/Rkx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh3/0pYo/9+sYf/jtHL/47Ny/+CuZf/Slif/0ZMd/9GTHv+Yaxj/IhgG/wYGBv9PTk7XsbCvNIuJ
iQD49/YAAAAAAAAAAACwrq0AxsTDG1VUVMIGBwf/JBoG/6d1Gv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/YoEH/47Ny/+Ozcf/js3H/47Nw/9igQf/Qkh3/0JIe/9OUHv+kdBn/IhgG/wkK
Cv9hYGDA0M7MGbm3twAAAAAA0c7NAP///wJ2dHSKFBQV/xMNA/+bbRj/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9mjSf/jtHL/47Nx/+Ozcf/js3L/4K9m/9OYLv/Qkh3/0JIe/9OU
Hv+Yaxj/EgwC/xoaG/+DgoGI////As7MywCZl5YAqKalODc2NuoBAQD/clET/9GTHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zs1/+Kxbf/js3H/47Nx/+Ozcf/js3L/3apa/9GU
JP/Qkh3/0JIe/9GTHv9vTxL/AQEA/0FBQei0srE2qKalAP///wNubWyYCwsM/zAiCP/BiB3/0ZMe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/QkyD/26VQ/+Ozcv/js3H/47Nx/+Oz
cf/js3H/2qNK/9CSH//Qkh7/0ZMe/8CHHf8uIAf/DxAR/3x7epX///8CvLq5Kz8/Pt8BAQD/gFsU/9OU
H//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/SlSb/3qpb/+Oz
cv/js3H/47Nx/+Ozcf/isW3/1pw5/9CSHf/Qkh7/05Qf/35ZFP8BAQD/S0tK3cjGxSmOjIxuHBwd+x0U
BP+5ghz/0pMe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/Tlyr/3qte/+Ozcv/js3H/47Nx/+Ozcv/grWP/05cq/9CSHf/Skx7/t4Ec/xsSA/8kJCX7nJuaam9t
ba4HCAr/SjQM/86RHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JId/9CRHf/Qkh3/0JEd/9CR
Hf/Qkh3/0JIe/9CSHf/Tlyv/36xh/+Ozcv/js3H/47Nx/+Ozcv/bpVD/0JIf/9CSHv/OkR7/RzIM/wwN
Dv99fHurWFdX2gABAv9yURL/05Qf/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIe/9KVJv/VmzX/2KBB/9mi
R//YoUX/154+/9OYLf/Qkh//0JIf/9CSHv/Zokf/47Ny/+Ozcf/js3H/47Ny/9+tYf/RlCP/0JIe/9OU
H/9wTxL/AgME/2ZlZdhKSUnzAgEA/4xjFv/UlB7/0JIe/9CSHv/Qkh7/0JId/9KVJ//Zokf/361j/+Ky
bv/js3L/47Ny/+Ozcv/frWP/26VP/9ulTv/cqFX/3alY/+CuZv/js3H/47Nx/+Ozcf/jtHP/3ahX/9CT
IP/Qkh7/1JQe/4phFv8CAgH/V1ZW8UNCQv4EAwD/mGsX/9OUHv/Qkh3/0JId/9CSHf/UmTH/36xf/+Oz
cf/js3L/47Ny/+Ozcv/js3L/4bFr/9ynVf/isWz/47Ny/+O0c//jtHP/47Ry/+Ozcf/jsnD/4rFs/92q
Wv/TmC7/0JId/9CSHf/TlB7/lmkX/wQDAP9QT0/8REND/gQDAP+ZbR7/1Zcp/9KVKf/Sliz/1Jo2/+Gw
a//kt3r/5LZ5/+O1d//gr2n/365n/+KycP/erWT/2qVV/9qlVP/Zo07/2qVT/9umVv/bpVX/2qRQ/9ih
SP/WnT7/05cx/9KVK//SlSv/0pUq/9WXKv+Xax7/BAMA/1FQUPxNTEzzAgEB/5BpKv/XnDz/1p5F/96s
ZP/dqmH/5bmA/+W5gP/luYD/3Kpf/9WbP//Umz7/1p1E/9WdQ//Umjz/1Jo7/9SaO//Umjv/1Jo7/9Sa
O//Umjv/1Jo7/9SaO//Umjz/1Jo8/9SaPP/Umjz/2J09/41mKf8CAgH/WllZ8V5dXNsBAgP/dlYj/9ed
Pf/drGP/4bJx/96tZv/luYH/5bmB/+K0dv/WnUT/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/XnD3/clMh/wMEBf9sa2rYd3Z1rwkK
DP9MOBf/1Z1E/+KzdP/ZpFL/3Kle/+W5gf/luYH/4rNz/9WcQP/Umjv/1Jo8/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9KZPP9JNRX/Dw8R/4WE
g6uZl5ZvIiIi/B4VB//Ck0v/4rJu/9WcQf/frmn/5bmB/+W5gP/kuH7/3apf/9adQ//Umz3/16BJ/9ad
Q//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Wmzz/u4g2/xwU
B/8rKyv7paSja8bDwixKSkngAgEA/4ttRP/nuHv/365p/+S3ff/luYD/5bmA/+W5gP/luYD/4rR1/+Cw
bf/jtXj/2aRS/9SZOv/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ec
Pf+BXib/AgIB/1dWVd7OzMsp////A359fJkPEBD/Niwf/9WteP/nuoL/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYH/5bqB/+W5gf/hsXD/16BJ/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI84/y8iDv8VFhf/i4mIl////wKqqKcAtrSzOkVFROoDAgH/f2dI/+e6gf/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtXj/2qZX/9SaPf/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WbPf9zVCL/AwIB/1FQT+m/vbw3tLKxAMzKyQD///8Di4mIjB4eHv8WEgz/rIxh/+i8
gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/kuH3/26dZ/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/nXIu/xMNBf8lJSX/lpSUif///wLIxsUAAAAAAL27ugDRz84cbGtqxAwM
Df8qIhj/updp/+i8gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtnr/16BL/9Sa
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
Lf0DAwP/AAAA/wAAAP8OCgP/Py0M/31ZFf+tehv/xose/9CSHv/TlB//1JUf/9SVH//UlR//1JUf/9OU
H//Qkh7/xYoc/6x6H/+BYjD/PzAY/wwJAv8AAAD/AAAA/wUFBf83Njb8iIaGvcbDwjj///8A5+XkAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc2tkA////BLCu
rV5gX17jEhIR/wAAAP8AAAD/DQoD/1A5Dv+gcRr/yo4e/9OUH//SlB7/0ZIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHf/Qkh//1Zsz/9+rWv/ltG7/zpc2/51vGP9NNw7/DAkD/wAAAP8AAAD/GBcX/2xr
a+G4trVb////A9jW1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANbU
0gD///4FqKalck1MTPEGBgb/AAAA/wICAf81Jgr/mWwZ/82QHv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9GUJP/ao0r/4rFr/+O0cv/ism3/1Zox/9OUHf/MkB7/lmoY/zMk
Cv8CAQH/AAAA/woKCv9bWlnwsbCvbvf08wXS0M8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA1NLRAP///wSopqVySEdG9AMDA/8AAAD/CgcC/2JFEf/Ahx3/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0pUm/92pV//js3H/47Nx/+Ozcf/ism//1Zw3/9CR
Hf/Qkh7/05Qe/7+GHf9eQxH/CQYC/wAAAP8GBgX/VVRU87KxsG7///8Dz8zLAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADS0M8AAAAAALGvrl9PTk3xAwMD/wAAAP8RDAT/floV/86RHv/Rkx7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh//26VO/+Ozcv/js3H/47Nx/+Oz
cf/js3L/2aNK/9CSHf/Qkh7/0JIe/9KTHv/NkB7/e1cV/w8LBP8AAAD/BgYG/11cXPC6uLdbERAQAMrI
xwAAAAAAAAAAAAAAAAAAAAAAAAAAAMzKyQCurKsAwb++PGJhYeMHBwf/AAAA/xEMBP+IYRf/0ZMf/9GS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Tlyv/4a9p/+Oz
cv/js3H/47Nx/+Ozcf/js3L/361j/9KWJ//Qkh3/0JIe/9CSHv/Rkh7/0JIe/4ReFv8PCwT/AAAA/wsL
C/9ycXDhyMXEObu5uADCwL8AAAAAAAAAAAAAAAAAAAAAAMXDwgDb2dcXgX9+wBMTE/8AAAD/CgcC/39a
Ff/Rkx//0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CR
Hf/VnDj/47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9qkS//Qkh//0JIe/9CSHv/Qkh7/0JIe/9CS
Hv97VxX/CQYC/wAAAP8cHBv/kI+OvNrY1xXFw8IAAAAAAAAAAAAAAAAAxcPCAP///wCko6J+MjEx/gAA
AP8BAQH/Y0YR/86RHv/Rkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/VnDf/4rJv/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+Kxbf/WnTr/0JId/9CS
Hv/Qkh7/0JIe/9GSHv/NkB7/X0MR/wEBAf8AAAD/QD8//bGvrnoAAAAAwb++AAAAAAAAAAAAvry7AMrI
xy9jYmLjAwMD/wAAAP83Jwv/wYgd/9GTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Slif/4K5k/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/grmX/05cs/9CSHf/Qkh7/0JIe/9CSHv/Skx7/v4Yd/zQlCv8AAAD/BwcH/3RzcuDPzcsswb++AAAA
AADBv74A////ApuZmJIjIiL/AAAA/w4KA/+abRn/05Qe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/2KFE/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/3alY/9GUI//Qkh7/0JIe/9CSHv/Qkh7/05Qe/5dqGP8NCQP/AAAA/y8v
Lv+pp6aN////AcC+vQDAvr0Az83MKWRjYuICAgL/AAAA/1I6D//OkB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0ZQj/92p
WP/js3L/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9miR//Qkh7/0JIe/9CSHv/Qkh7/0JIe/82Q
Hv9ONw7/AAAA/wYGBv92dHTg09DPJsG/vgB/fn0AqaemdS8uLv8AAAD/DwsD/6JyGv/TlB7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JId/9OXK//frWL/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+KxbP/Vmzb/0JId/9CS
Hv/Qkh7/0JIe/9OUHv+ecBn/DQoD/wAAAP89PTz/tbSzcKOhoAD39fMOgYB/vQwMDP8AAAD/QS8M/8uP
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/UmTH/4K5m/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/frGH/0pYo/9CSHf/Qkh7/0JIe/9CSHv/Kjh7/PiwM/wAAAP8UFBT/kpGQuvLv7gzLycg4WVhY6gAA
AP8BAQH/gFsV/9OUH//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zo0/+CvZ//js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/26ZR/9CTIP/Qkh7/0JIe/9CSHv/TlB//fFgV/wAAAP8BAQH/bGtq6NHO
zTSzsbBxNzY2/AAAAP8UDgT/r3sb/9KTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9Wb
Nf/hr2j/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/4rJv/9adPP/Qkh3/0JIe/9CSHv/SlB7/rHkb/xIN
BP8AAAD/R0ZG/L68u2ycm5qmHh4d/wAAAP8zJAr/x4we/9GSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9CRHf/Qkh7/0JIf/9CTIP/Qkh//0JIe/9CSHf/QkR3/0JId/9CS
Hv/Qkh7/0JIe/9CSHf/Xnz//47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ry/92pWP/QkyD/0JIe/9CS
Hv/Rkh7/xYse/y8iCf8AAAD/Kioq/6upqKGJiIfODw4O/wAAAP9TOw//0JIf/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/RkyL/1Jkw/9efQf/apU7/3KhW/9ypWv/cqFj/26ZS/9mi
R//WnDn/0ZUl/9CRHP/Qkh3/0JId/9CRHf/UmTH/4rFt/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ny/96r
X//RkyL/0JIe/9CSHv/Qkh7/0JIe/084Dv8AAAD/GBcX/5qYmMp6eXjpBgYG/wAAAP9tTRP/05Qf/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0ZQk/9efPv/eqlz/4rFs/+Ozcf/jtHL/47Ry/+O0
cv/jtHL/47Rz/+KxbP/bplL/1p4+/9igQv/Zo0n/2qRN/9ulT//eqlz/47Nx/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Rz/9yoVv/Qkh//0JIe/9CSHv/Qkh7/05Qf/2lLEv8AAAD/DQ0M/4yKiuVvbm74AgIC/wAA
AP9/WhX/1JUf/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/VmjT/3qtd/+OzcP/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/4K9n/9ihRf/cqFf/4rFs/+Ozcv/js3L/47Ry/+O0cv/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/jtHL/4bFr/9WbNv/Qkh3/0JIe/9CSHv/Qkh7/1JUf/3tXFf8AAAD/BwcH/4KA
gPRraWn/AQEB/wEBAf+IYBb/1JQe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIf/9efP//hsGr/47Ny/+Oz
cf/js3H/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3L/26dT/92qW//ktHP/47Ny/+Ozcv/js3L/47Ny/+Oz
cv/js3L/47Ny/+Ozcv/js3L/47Nw/+KxbP/eq13/1Zw4/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/1JQe/4Nd
Ff8AAAD/BQUF/359fPxramr/AQEB/wEBAf+IYBj/1JUi/9GTIv/RkyP/0ZMj/9GTI//RkyT/16BC/+Kz
cf/ktXb/5LV1/+S1dv/ktXb/5LV2/+Kzc//is3L/47R1/+S2d//jtHX/2qVS/96tZ//dq2H/26ZV/9um
Vf/cqVz/3qtg/96rYf/eq2D/3ald/9ynV//apE//2KBF/9WbOf/Sliv/0ZQk/9GUJf/RlCT/0ZMj/9GT
I//RkyL/1JYi/4NdF/8AAAD/BQUF/399ffxycXH4AwMD/wAAAP+CXiT/15w5/9SZOf/UmTn/1Zs+/9eg
Sv/VnUL/4bJy/+W5gf/luYD/5bmA/+W5gP/kt3z/3Klf/9egS//XoEn/2aNQ/9yqX//cqV//1ZxB/9Wc
Qf/Umj3/1Jo7/9SaO//Umjz/1Jo9/9SaPf/Umj3/1Jo8/9SaO//UmTr/1Jk6/9SZOv/Umjv/1Jo7/9Sa
O//Umjr/1Jk6/9SZOf/UmTn/15w5/31bI/8AAAD/CAgI/4SDgvV/fX3pCAgI/wAAAP9xUyP/15w9/9Sa
PP/Umz7/3ati/+O1eP/aplj/5Ld8/+W5gP/luYD/5bmA/+W5gP/dq2H/1Jo8/9SaO//Umjv/1Jo7/9Sa
O//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/2xPIP8AAAD/Dg4O/5COjuWQjo3PERER/wAA
AP9WPxv/1Zs9/9SaO//Zo1D/5Lh+/+Gycv/bp1r/5bl//+W5gP/luYD/5bmA/+O1eP/Wn0f/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/1E7Gf8AAAD/Gxsb/5+e
ncqkoqGnIyMj/wAAAP81JxH/y5Q7/9WbPv/fr2r/5bmA/9qmV//ZpFP/5bl//+W5gP/luYD/5bmB/+Cw
bf/Umz7/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/yZM6/zEk
D/8AAAD/MTAw/7GvrqK5t7ZyQD8//QAAAP8VEAj/s4I0/9mgR//jtnr/4LBt/9WbP//Yo1D/5Lh//+W5
gP/luYD/5bmB/+Gycf/Vm0D/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/WnD3/sIAz/xMOBv8AAAD/UVBP/MLAv23OzMs5ZmVk6wAAAP8CAQH/hGEn/92nVf/kt33/2KNQ/9OZ
Of/bp1r/5bmA/+W5gP/luYD/5bmA/+S4fv/cqV3/1Zs//9SZO//Umjv/1Jk7/9WdQv/VnED/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/gF0m/wEAAP8DAwP/eHZ26dHOzTXs6egPj46NvxISEv8AAAD/RDIV/9em
X//luH7/2KNQ/9aeR//hsnL/5bmB/+W5gP/luYD/5bmA/+W5gP/luH//369r/9mkUv/Xn0j/2KJP/+Cw
bf/Zo1H/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Oljv/QC8U/wAAAP8cGxv/n52cu+Ti4A2amJcAtLKxdjw7
O/8AAAD/EAwG/7GNW//ovIL/47V4/+K1d//luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W4
f//kt3v/5Lh+/+W5gf/bqFz/1Jk7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ecPf+jdzD/DgoF/wAAAP9MS0v/vbu6crKw
rwDBv74A0c7NK3d1deMGBgb/AAAA/11LNf/jt3//5bmB/+W5gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/itHb/2KFM/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9GYPP9RPBn/AAAA/wsL
C/+HhoXh0c/OKMG/vgDAvr0A////AqupqZQxMTD/AAAA/xEOCv+si2H/6LyC/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYH/47V5/9unWv/VnED/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/5tx
Lv8OCgX/AAAA/0A/P/+1tLOQ////AcC+vQDAvr0AwsC/AM3LyjF6eXjkCQkJ/wAAAP8/MyT/1q14/+a6
gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W5
gP/fr2r/1p5F/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI44/zcoEf8AAAD/Dw8P/4qIh+LOzMsuwsC/AAAAAAAAAAAAwb++AP///wG1s7KBRkZF/gAA
AP8CAgH/cFtA/+O4f//muYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYH/4LFv/9aeRf/Umjv/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WaPP/SmDz/Y0ke/wEBAf8AAAD/VlVU/r27unz///8AwL69AAAAAAAAAAAAAAAAAMTC
wQDU0tEYmZiXwiIiIf8AAAD/DAoH/5B1Uv/nuoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/9+uav/Vmz//1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPf+AXif/CgcE/wAAAP8tLSz/paSjv9HPzhbDwcAAAAAAAAAA
AAAAAAAAAAAAAMC+vQC/vbwAycbFP39+feUQEBD/AAAA/xURDf+bflj/57qB/+a5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W4f//apVX/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/1Zs9/4plKf8RDQb/AAAA/xgXF/+NjIviysjHO8PB
wADAvr0AAAAAAAAAAAAAAAAAAAAAAAAAAADEwsEA////AMC+vWJtbGvyCgoK/wAAAP8VEQ3/kXZT/+S4
gP/muoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W6
gf/fr2r/1Jo9/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPP/SmDz/gV4n/xENBv8AAAD/Dw8P/3t6
efHEwsFefnx8AMG/vgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx8XEAOHf3QS7ubh2aGZm9goK
Cv8AAAD/DQsI/3JdQf/WrXj/6LyC/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gf/hsnL/1ZtA/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/8SPOP9jSR7/CgcE/wAA
AP8PDw//dXRz9MC+vXLW1NMDxMLBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMrH
xgDa2NYGvLq5dnBvbvISERH/AAAA/wMDAv9ANCX/rYxi/+O3f//ou4L/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/hsnL/1ZxA/9SaPP/Umjz/1Jo8/9ecPf/RmDz/nHIu/zco
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
AAD/4AAAB/8AAP/4AAAf/wAA//8AAP//AAA=
</value>
</data>
</root>

465
Forms/FormConfiguracionJSON.Designer.cs generated Normal file
View File

@@ -0,0 +1,465 @@
namespace EFCDesk.Forms
{
partial class FormConfiguracionJSON
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormConfiguracionJSON));
tabControl1 = new TabControl();
tabPage1 = new TabPage();
textBoxProxyGenericoPassword = new TextBox();
textBoxProxyGenericoUsuario = new TextBox();
textBoxProxyGenericoPuertoServidor = new TextBox();
textBoxProxyGenericoNombreServidor = new TextBox();
label5 = new Label();
label4 = new Label();
checkBoxProxyGenericoAuthProxy = new CheckBox();
label3 = new Label();
label2 = new Label();
radioProxyGenericoHTTP = new RadioButton();
radioProxyGenericoNinguno = new RadioButton();
label1 = new Label();
tabPage2 = new TabPage();
textBoxProxyFTPPassword = new TextBox();
textBoxProxyFTPUsuario = new TextBox();
textBoxProxyFTPPuerto = new TextBox();
textBoxProxyFTPNombreServidor = new TextBox();
label6 = new Label();
label7 = new Label();
checkBoxProxyFTPAuth = new CheckBox();
label8 = new Label();
label9 = new Label();
radioButtonProxyFTP = new RadioButton();
radioButtonProxyFTPNinguno = new RadioButton();
label10 = new Label();
tabPage3 = new TabPage();
label12 = new Label();
textBoxDominio = new TextBox();
label11 = new Label();
buttonGuardar = new Button();
buttonCancelar = new Button();
tabControl1.SuspendLayout();
tabPage1.SuspendLayout();
tabPage2.SuspendLayout();
tabPage3.SuspendLayout();
SuspendLayout();
//
// tabControl1
//
tabControl1.Controls.Add(tabPage1);
tabControl1.Controls.Add(tabPage2);
tabControl1.Controls.Add(tabPage3);
tabControl1.Location = new Point(6, 11);
tabControl1.Name = "tabControl1";
tabControl1.SelectedIndex = 0;
tabControl1.Size = new Size(343, 307);
tabControl1.TabIndex = 0;
//
// tabPage1
//
tabPage1.Controls.Add(textBoxProxyGenericoPassword);
tabPage1.Controls.Add(textBoxProxyGenericoUsuario);
tabPage1.Controls.Add(textBoxProxyGenericoPuertoServidor);
tabPage1.Controls.Add(textBoxProxyGenericoNombreServidor);
tabPage1.Controls.Add(label5);
tabPage1.Controls.Add(label4);
tabPage1.Controls.Add(checkBoxProxyGenericoAuthProxy);
tabPage1.Controls.Add(label3);
tabPage1.Controls.Add(label2);
tabPage1.Controls.Add(radioProxyGenericoHTTP);
tabPage1.Controls.Add(radioProxyGenericoNinguno);
tabPage1.Controls.Add(label1);
tabPage1.Location = new Point(4, 26);
tabPage1.Name = "tabPage1";
tabPage1.Padding = new Padding(3);
tabPage1.Size = new Size(335, 277);
tabPage1.TabIndex = 0;
tabPage1.Text = "Proxy Genérico";
tabPage1.UseVisualStyleBackColor = true;
//
// textBoxProxyGenericoPassword
//
textBoxProxyGenericoPassword.Location = new Point(95, 228);
textBoxProxyGenericoPassword.Name = "textBoxProxyGenericoPassword";
textBoxProxyGenericoPassword.Size = new Size(221, 22);
textBoxProxyGenericoPassword.TabIndex = 11;
//
// textBoxProxyGenericoUsuario
//
textBoxProxyGenericoUsuario.Location = new Point(95, 199);
textBoxProxyGenericoUsuario.Name = "textBoxProxyGenericoUsuario";
textBoxProxyGenericoUsuario.Size = new Size(221, 22);
textBoxProxyGenericoUsuario.TabIndex = 10;
//
// textBoxProxyGenericoPuertoServidor
//
textBoxProxyGenericoPuertoServidor.Location = new Point(123, 140);
textBoxProxyGenericoPuertoServidor.Name = "textBoxProxyGenericoPuertoServidor";
textBoxProxyGenericoPuertoServidor.Size = new Size(193, 22);
textBoxProxyGenericoPuertoServidor.TabIndex = 9;
//
// textBoxProxyGenericoNombreServidor
//
textBoxProxyGenericoNombreServidor.Location = new Point(11, 112);
textBoxProxyGenericoNombreServidor.Name = "textBoxProxyGenericoNombreServidor";
textBoxProxyGenericoNombreServidor.Size = new Size(305, 22);
textBoxProxyGenericoNombreServidor.TabIndex = 8;
//
// label5
//
label5.AutoSize = true;
label5.Location = new Point(6, 231);
label5.Name = "label5";
label5.Size = new Size(83, 17);
label5.TabIndex = 7;
label5.Text = " Contraseña:";
label5.Click += label5_Click;
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(6, 202);
label4.Name = "label4";
label4.Size = new Size(57, 17);
label4.TabIndex = 6;
label4.Text = " Usuario:";
//
// checkBoxProxyGenericoAuthProxy
//
checkBoxProxyGenericoAuthProxy.AutoSize = true;
checkBoxProxyGenericoAuthProxy.Location = new Point(11, 170);
checkBoxProxyGenericoAuthProxy.Name = "checkBoxProxyGenericoAuthProxy";
checkBoxProxyGenericoAuthProxy.Size = new Size(230, 21);
checkBoxProxyGenericoAuthProxy.TabIndex = 5;
checkBoxProxyGenericoAuthProxy.Text = " Utilizar Autentificación para Proxy";
checkBoxProxyGenericoAuthProxy.UseVisualStyleBackColor = true;
checkBoxProxyGenericoAuthProxy.CheckedChanged += checkBoxProxyGenericoAuthProxy_CheckedChanged;
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(8, 140);
label3.Name = "label3";
label3.Size = new Size(109, 17);
label3.TabIndex = 4;
label3.Text = " Puerto del Proxy:";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(8, 92);
label2.Name = "label2";
label2.Size = new Size(171, 17);
label2.TabIndex = 3;
label2.Text = " Nombre del Servidor Proxy:";
//
// radioProxyGenericoHTTP
//
radioProxyGenericoHTTP.AutoSize = true;
radioProxyGenericoHTTP.Location = new Point(18, 56);
radioProxyGenericoHTTP.Name = "radioProxyGenericoHTTP";
radioProxyGenericoHTTP.Size = new Size(54, 21);
radioProxyGenericoHTTP.TabIndex = 2;
radioProxyGenericoHTTP.TabStop = true;
radioProxyGenericoHTTP.Text = " HTTP";
radioProxyGenericoHTTP.UseVisualStyleBackColor = true;
radioProxyGenericoHTTP.CheckedChanged += radioProxyGenericoHTTP_CheckedChanged;
//
// radioProxyGenericoNinguno
//
radioProxyGenericoNinguno.AutoSize = true;
radioProxyGenericoNinguno.Location = new Point(18, 35);
radioProxyGenericoNinguno.Name = "radioProxyGenericoNinguno";
radioProxyGenericoNinguno.Size = new Size(78, 21);
radioProxyGenericoNinguno.TabIndex = 1;
radioProxyGenericoNinguno.TabStop = true;
radioProxyGenericoNinguno.Text = " Ninguno";
radioProxyGenericoNinguno.UseVisualStyleBackColor = true;
radioProxyGenericoNinguno.CheckedChanged += radioProxyGenericoNinguno_CheckedChanged;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(6, 15);
label1.Name = "label1";
label1.Size = new Size(146, 17);
label1.TabIndex = 0;
label1.Text = "Tipo de proxy genérico:";
//
// tabPage2
//
tabPage2.Controls.Add(textBoxProxyFTPPassword);
tabPage2.Controls.Add(textBoxProxyFTPUsuario);
tabPage2.Controls.Add(textBoxProxyFTPPuerto);
tabPage2.Controls.Add(textBoxProxyFTPNombreServidor);
tabPage2.Controls.Add(label6);
tabPage2.Controls.Add(label7);
tabPage2.Controls.Add(checkBoxProxyFTPAuth);
tabPage2.Controls.Add(label8);
tabPage2.Controls.Add(label9);
tabPage2.Controls.Add(radioButtonProxyFTP);
tabPage2.Controls.Add(radioButtonProxyFTPNinguno);
tabPage2.Controls.Add(label10);
tabPage2.Location = new Point(4, 26);
tabPage2.Name = "tabPage2";
tabPage2.Padding = new Padding(3);
tabPage2.Size = new Size(335, 277);
tabPage2.TabIndex = 1;
tabPage2.Text = "Proxy FTP";
tabPage2.UseVisualStyleBackColor = true;
//
// textBoxProxyFTPPassword
//
textBoxProxyFTPPassword.Location = new Point(96, 227);
textBoxProxyFTPPassword.Name = "textBoxProxyFTPPassword";
textBoxProxyFTPPassword.Size = new Size(221, 22);
textBoxProxyFTPPassword.TabIndex = 23;
//
// textBoxProxyFTPUsuario
//
textBoxProxyFTPUsuario.Location = new Point(96, 198);
textBoxProxyFTPUsuario.Name = "textBoxProxyFTPUsuario";
textBoxProxyFTPUsuario.Size = new Size(221, 22);
textBoxProxyFTPUsuario.TabIndex = 22;
//
// textBoxProxyFTPPuerto
//
textBoxProxyFTPPuerto.Location = new Point(124, 139);
textBoxProxyFTPPuerto.Name = "textBoxProxyFTPPuerto";
textBoxProxyFTPPuerto.Size = new Size(193, 22);
textBoxProxyFTPPuerto.TabIndex = 21;
//
// textBoxProxyFTPNombreServidor
//
textBoxProxyFTPNombreServidor.Location = new Point(12, 111);
textBoxProxyFTPNombreServidor.Name = "textBoxProxyFTPNombreServidor";
textBoxProxyFTPNombreServidor.Size = new Size(305, 22);
textBoxProxyFTPNombreServidor.TabIndex = 20;
//
// label6
//
label6.AutoSize = true;
label6.Location = new Point(7, 230);
label6.Name = "label6";
label6.Size = new Size(83, 17);
label6.TabIndex = 19;
label6.Text = " Contraseña:";
//
// label7
//
label7.AutoSize = true;
label7.Location = new Point(7, 201);
label7.Name = "label7";
label7.Size = new Size(57, 17);
label7.TabIndex = 18;
label7.Text = " Usuario:";
//
// checkBoxProxyFTPAuth
//
checkBoxProxyFTPAuth.AutoSize = true;
checkBoxProxyFTPAuth.Location = new Point(12, 169);
checkBoxProxyFTPAuth.Name = "checkBoxProxyFTPAuth";
checkBoxProxyFTPAuth.Size = new Size(230, 21);
checkBoxProxyFTPAuth.TabIndex = 17;
checkBoxProxyFTPAuth.Text = " Utilizar Autentificación para Proxy";
checkBoxProxyFTPAuth.UseVisualStyleBackColor = true;
checkBoxProxyFTPAuth.CheckedChanged += checkBoxProxyFTPAuth_CheckedChanged;
//
// label8
//
label8.AutoSize = true;
label8.Location = new Point(9, 139);
label8.Name = "label8";
label8.Size = new Size(109, 17);
label8.TabIndex = 16;
label8.Text = " Puerto del Proxy:";
//
// label9
//
label9.AutoSize = true;
label9.Location = new Point(9, 91);
label9.Name = "label9";
label9.Size = new Size(171, 17);
label9.TabIndex = 15;
label9.Text = " Nombre del Servidor Proxy:";
//
// radioButtonProxyFTP
//
radioButtonProxyFTP.AutoSize = true;
radioButtonProxyFTP.Location = new Point(19, 55);
radioButtonProxyFTP.Name = "radioButtonProxyFTP";
radioButtonProxyFTP.Size = new Size(47, 21);
radioButtonProxyFTP.TabIndex = 14;
radioButtonProxyFTP.Text = " FTP";
radioButtonProxyFTP.UseVisualStyleBackColor = true;
radioButtonProxyFTP.CheckedChanged += radioButtonProxyFTP_CheckedChanged;
//
// radioButtonProxyFTPNinguno
//
radioButtonProxyFTPNinguno.AutoSize = true;
radioButtonProxyFTPNinguno.Checked = true;
radioButtonProxyFTPNinguno.Location = new Point(19, 34);
radioButtonProxyFTPNinguno.Name = "radioButtonProxyFTPNinguno";
radioButtonProxyFTPNinguno.Size = new Size(78, 21);
radioButtonProxyFTPNinguno.TabIndex = 13;
radioButtonProxyFTPNinguno.TabStop = true;
radioButtonProxyFTPNinguno.Text = " Ninguno";
radioButtonProxyFTPNinguno.UseVisualStyleBackColor = true;
radioButtonProxyFTPNinguno.CheckedChanged += radioButtonProxyFTPNinguno_CheckedChanged;
//
// label10
//
label10.AutoSize = true;
label10.Location = new Point(7, 14);
label10.Name = "label10";
label10.Size = new Size(110, 17);
label10.TabIndex = 12;
label10.Text = "Tipo de proxy FTP:";
//
// tabPage3
//
tabPage3.Controls.Add(label12);
tabPage3.Controls.Add(textBoxDominio);
tabPage3.Controls.Add(label11);
tabPage3.Location = new Point(4, 26);
tabPage3.Name = "tabPage3";
tabPage3.Padding = new Padding(3);
tabPage3.Size = new Size(335, 277);
tabPage3.TabIndex = 2;
tabPage3.Text = "Dominio";
tabPage3.UseVisualStyleBackColor = true;
//
// label12
//
label12.AutoSize = true;
label12.ForeColor = SystemColors.ControlDark;
label12.Location = new Point(66, 36);
label12.Name = "label12";
label12.Size = new Size(220, 17);
label12.TabIndex = 22;
label12.Text = "Ejemplo: http://efc.aduanasoft.com";
//
// textBoxDominio
//
textBoxDominio.Location = new Point(66, 11);
textBoxDominio.Name = "textBoxDominio";
textBoxDominio.Size = new Size(259, 22);
textBoxDominio.TabIndex = 21;
//
// label11
//
label11.AutoSize = true;
label11.Location = new Point(6, 14);
label11.Name = "label11";
label11.Size = new Size(54, 17);
label11.TabIndex = 16;
label11.Text = "EFC API:";
//
// buttonGuardar
//
buttonGuardar.Location = new Point(159, 324);
buttonGuardar.Name = "buttonGuardar";
buttonGuardar.Size = new Size(89, 26);
buttonGuardar.TabIndex = 1;
buttonGuardar.Text = " Guardar";
buttonGuardar.UseVisualStyleBackColor = true;
buttonGuardar.Click += button1_Click;
//
// buttonCancelar
//
buttonCancelar.Location = new Point(252, 324);
buttonCancelar.Name = "buttonCancelar";
buttonCancelar.Size = new Size(89, 26);
buttonCancelar.TabIndex = 2;
buttonCancelar.Text = " Cancelar";
buttonCancelar.UseVisualStyleBackColor = true;
buttonCancelar.Click += buttonCancelar_Click;
//
// FormConfiguracionJSON
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(352, 356);
Controls.Add(buttonCancelar);
Controls.Add(buttonGuardar);
Controls.Add(tabControl1);
Font = new Font("Century Gothic", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
FormBorderStyle = FormBorderStyle.FixedDialog;
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
MinimizeBox = false;
Name = "FormConfiguracionJSON";
StartPosition = FormStartPosition.CenterScreen;
Text = "Configuración de conexión";
Load += FormConfiguracionJSON_Load;
tabControl1.ResumeLayout(false);
tabPage1.ResumeLayout(false);
tabPage1.PerformLayout();
tabPage2.ResumeLayout(false);
tabPage2.PerformLayout();
tabPage3.ResumeLayout(false);
tabPage3.PerformLayout();
ResumeLayout(false);
}
#endregion
private TabControl tabControl1;
private TabPage tabPage1;
private TabPage tabPage2;
private Button buttonGuardar;
private Button buttonCancelar;
private Label label3;
private Label label2;
private RadioButton radioProxyGenericoHTTP;
private RadioButton radioProxyGenericoNinguno;
private Label label1;
private TabPage tabPage3;
private Label label5;
private Label label4;
private CheckBox checkBoxProxyGenericoAuthProxy;
private TextBox textBoxProxyGenericoPassword;
private TextBox textBoxProxyGenericoUsuario;
private TextBox textBoxProxyGenericoPuertoServidor;
private TextBox textBoxProxyGenericoNombreServidor;
private TextBox textBoxProxyFTPPassword;
private TextBox textBoxProxyFTPUsuario;
private TextBox textBoxProxyFTPPuerto;
private TextBox textBoxProxyFTPNombreServidor;
private Label label6;
private Label label7;
private CheckBox checkBoxProxyFTPAuth;
private Label label8;
private Label label9;
private RadioButton radioButtonProxyFTP;
private RadioButton radioButtonProxyFTPNinguno;
private Label label10;
private Label label11;
private Label label12;
private TextBox textBoxDominio;
}
}

View File

@@ -0,0 +1,250 @@
using EFCDesk.Classes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls.Primitives;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;
namespace EFCDesk.Forms
{
public partial class FormConfiguracionJSON : Form
{
private ConfiguracionJSON _config;
public FormConfiguracionJSON()
{
InitializeComponent();
_config = ConfiguracionJSON.LoadFromJson();
// Cargar los valores actuales en los controles
if (_config.ProxyNingunoGenerico)
{
radioProxyGenericoHTTP.Checked = true;
radioProxyGenericoNinguno.Checked = false;
textBoxProxyGenericoNombreServidor.Text = _config.ServidorProxyGenerico;
textBoxProxyGenericoPuertoServidor.Text = _config.PuertoProxyGenerico.ToString();
}
else
{
radioProxyGenericoNinguno.Checked = true;
textBoxProxyGenericoNombreServidor.Enabled = false;
textBoxProxyGenericoPuertoServidor.Enabled = false;
}
if (_config.AuthProxyGenerico)
{
textBoxProxyGenericoUsuario.Text = _config.UsuarioProxyGenerico;
textBoxProxyGenericoPassword.Text = _config.PasswordProxyGenerico;
checkBoxProxyGenericoAuthProxy.Checked = true;
textBoxProxyGenericoUsuario.Enabled = true;
textBoxProxyGenericoPassword.Enabled = true;
}
else
{
textBoxProxyGenericoUsuario.Enabled = false;
textBoxProxyGenericoPassword.Enabled = false;
}
if (_config.ProxyFTPNinguno)
{
radioButtonProxyFTPNinguno.Checked = false;
radioButtonProxyFTP.Checked = true;
textBoxProxyFTPNombreServidor.Text = _config.ServidorProxyFTP;
textBoxProxyFTPPuerto.Text = _config.PuertoProxyFTP.ToString();
}
else
{
radioButtonProxyFTPNinguno.Checked = true;
textBoxProxyFTPNombreServidor.Enabled = false;
textBoxProxyFTPPuerto.Enabled = false;
}
if (_config.AuthProxyFTP)
{
textBoxProxyFTPUsuario.Text = _config.UsuarioProxyFTP;
textBoxProxyFTPPassword.Text = _config.PasswordProxyFTP;
checkBoxProxyFTPAuth.Checked = true;
textBoxProxyFTPUsuario.Enabled = true;
textBoxProxyFTPPassword.Enabled = true;
}
else
{
textBoxProxyFTPUsuario.Enabled = false;
textBoxProxyFTPPassword.Enabled = false;
}
textBoxDominio.Text = _config.DominioExp;
}
private void label5_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
if (radioProxyGenericoNinguno.Checked)
{
_config.ProxyNingunoGenerico = false;
_config.ServidorProxyGenerico = "";
int.TryParse(textBoxProxyGenericoPuertoServidor.Text, out int puerto);
_config.PuertoProxyGenerico = puerto;
}
else
{
_config.ProxyNingunoGenerico = true;
_config.ServidorProxyGenerico = textBoxProxyGenericoNombreServidor.Text;
_config.PuertoProxyGenerico = 0;
}
if (checkBoxProxyGenericoAuthProxy.Checked)
{
_config.AuthProxyGenerico = true;
_config.UsuarioProxyGenerico = textBoxProxyGenericoUsuario.Text;
_config.PasswordProxyGenerico = textBoxProxyGenericoPassword.Text;
}
else
{
_config.AuthProxyGenerico = false;
_config.UsuarioProxyGenerico = "";
_config.PasswordProxyGenerico = "";
}
if (radioButtonProxyFTPNinguno.Checked)
{
_config.ProxyFTPNinguno = false;
_config.ServidorProxyFTP = "";
_config.PuertoProxyFTP = 0;
}
else
{
_config.ProxyFTPNinguno = true;
_config.ServidorProxyFTP = textBoxProxyFTPNombreServidor.Text;
int.TryParse(textBoxProxyFTPPuerto.Text, out int puerto);
_config.PuertoProxyFTP = puerto;
/*if (radioButton1.Checked)
{
MyClass.configuracion("tipoproxyFTP", "SOCKS5");
}*/
}
if (checkBoxProxyFTPAuth.Checked)
{
_config.AuthProxyFTP = true;
_config.UsuarioProxyFTP = textBoxProxyFTPUsuario.Text;
_config.PasswordProxyFTP = textBoxProxyFTPPassword.Text;
}
else
{
_config.AuthProxyFTP = false;
_config.UsuarioProxyFTP = "";
_config.PasswordProxyFTP = "";
}
_config.DominioExp = textBoxDominio.Text;
Properties.Settings.Default.urlEFC = _config.DominioExp;
Properties.Settings.Default.Save();
_config.SaveToJson();
Application.Restart();
}
private void radioProxyGenericoNinguno_CheckedChanged(object sender, EventArgs e)
{
if (radioProxyGenericoNinguno.Checked == true)
{
textBoxProxyGenericoNombreServidor.Enabled = false;
textBoxProxyGenericoPuertoServidor.Enabled = false;
}
}
private void radioProxyGenericoHTTP_CheckedChanged(object sender, EventArgs e)
{
if (radioProxyGenericoHTTP.Checked == true)
{
textBoxProxyGenericoNombreServidor.Enabled = true;
textBoxProxyGenericoPuertoServidor.Enabled = true;
}
}
private void buttonCancelar_Click(object sender, EventArgs e)
{
this.Close();
}
private void FormConfiguracionJSON_Load(object sender, EventArgs e)
{
TabPage? tabOculta;
tabOculta = tabControl1.TabPages["tabPage1"];
if (tabOculta != null) {
tabControl1.TabPages.Remove(tabOculta);
}
// Mostrarla de nuevo
// tabControl1.TabPages.Add(tabOculta);
tabOculta = tabControl1.TabPages["tabPage2"];
if (tabOculta != null) {
tabControl1.TabPages.Remove(tabOculta);
}
}
private void checkBoxProxyGenericoAuthProxy_CheckedChanged(object sender, EventArgs e)
{
if (!checkBoxProxyGenericoAuthProxy.Checked)
{
textBoxProxyGenericoUsuario.Enabled = false;
textBoxProxyGenericoPassword.Enabled = false;
}
else
{
textBoxProxyGenericoUsuario.Enabled = true;
textBoxProxyGenericoPassword.Enabled = true;
}
}
private void radioButtonProxyFTPNinguno_CheckedChanged(object sender, EventArgs e)
{
if (radioButtonProxyFTPNinguno.Checked == true)
{
textBoxProxyFTPNombreServidor.Enabled = false;
textBoxProxyFTPPuerto.Enabled = false;
}
}
private void radioButtonProxyFTP_CheckedChanged(object sender, EventArgs e)
{
if (radioButtonProxyFTP.Checked == true)
{
textBoxProxyFTPNombreServidor.Enabled = true;
textBoxProxyFTPPuerto.Enabled = true;
}
}
private void checkBoxProxyFTPAuth_CheckedChanged(object sender, EventArgs e)
{
if (!checkBoxProxyFTPAuth.Checked)
{
textBoxProxyFTPUsuario.Enabled = false;
textBoxProxyFTPPassword.Enabled = false;
}
else
{
textBoxProxyFTPUsuario.Enabled = true;
textBoxProxyFTPPassword.Enabled = true;
}
}
}
}

View File

@@ -0,0 +1,377 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
AAAgAAAAAQAgAAAAAAAABAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAlpWVALW0swdWV1pIMTI0pycl
I+MoJBz7KCQd+ygmI+M0NDanXF1fSL+9vAefnp4AAAAAAAAAAAD///8AV1dXAH59fhg1NjeSKiMW7llA
EP+MYhT/o3IX/6JyF/+OZyP/XEUf/yskF+46Oz2RiIeHGGJhYQD///8AbGpqAIKBgRguLi6xQTAP/6d1
GP/Qkh7/1JQe/9OUHv/Ynjj/5LJo/9mhRf+lcxb/QjAQ/zQ0NLCOjY0Yd3Z1APf18wY3ODmSQjAQ/7yE
G//TlB7/0JIe/9CSHv/Qkh//3alX/+S0dP/frF7/1Zcm/7uDGv9CMRH/Pz9Bkf///wZdXWBKLCUY7ad1
GP/TlB7/0JIe/9CSHv/Qkh7/0JIe/9mhRf/js3H/47Nx/9ulTf/TlSD/pnQX/y8oG+1oaWtINzg6qFtB
Ef/Qkh7/0JIe/9CSHv/Qkh3/0JEd/9CRHP/RlCL/3KdS/+Ozcf/ism7/1548/9CSHf9bQRL/P0BCpiwq
KOSNYxX/05Qe/9CSHf/Qkh//05cq/9WbNP/UmjL/0ZUl/9OXKv/frWH/5LRz/9+sYP/VliT/i2IU/zIx
LuItKCH7o3MX/9KTHv/SlSb/26VO/+Gwaf/js3D/361k/92pWv/eq17/4bBq/+Kxbf/bplD/05Uh/6Jy
F/8yLib6Lioj+6Z3Jv/Ynz//3atf/+S3e//dq2D/26ZW/9mjT//YoEn/2KFL/9igSv/WnkP/1Jk2/9WZ
M/+kdib/My8o+jAuK+SRazD/4K1h/+Gzc//jtnn/1p1E/9OZOv/Umjv/1Jo7/9SaO//Umjv/1Jo8/9Sa
PP/YnT7/jmgp/zY0MuM+P0CpYk0t/9+tZv/jtXf/5bh//96tZf/bqFr/1p5F/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/15GH/9HSEmna2tsSjQvKO64lGb/6LyC/+W5gP/luYH/5bmA/+Cva//Wnkb/1Jo7/9Sa
PP/Umjz/15w9/6l7L/81LiTtdnZ4Sf///wZFRUaTTD8v/9CodP/ovIL/5bmA/+W5gP/luYH/4bJw/9ad
Q//Umjz/15w9/7+LNv9HNxz/TU1Okv///waDgoEAmpmZGT4+PbJNQC//uJVn/+W5gP/pvIL/6LuC/+i7
gP/cplH/1Jo7/6l7L/9INx3/RENDsaSjoxiNi4sA////AHNycgCamZgZSUlKkzcyK+9mUzv/m31X/7SR
ZP+0kWP/k284/15GH/83MCXvT09QkqKhoRh9e3sA////AAAAAAAAAAAAtrW0ANTS0Qdzc3RKSEhJqTk3
NuU5NTH8OTYy/Do4N+VLS02oeXl7SdrY1we9u7sAAAAAAAAAAADgBwAAwAMAAIABAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAMADAADgBwAAKAAAACAAAABAAAAAAQAgAAAA
AAAAEAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ezrAP//
/wS1s7IphYODa2VkY6xPTk3YQEBA8To5Ofw6Ojn8QkFB8VFQUNhoZ2erioiHarq4tyj///8E8O/uAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+HgAP//
/wOhoJ83Z2Zllzk5ON8YGBn7BQYI/wAAAf8BAQD/AwIA/wMCAP8BAQD/AAAB/wYHCf8aGhv7Pj093m5t
bJapp6Y1////A+fl5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIWD
ggC+vLsacXBviTMyMuoJCQr/AgEA/xwTBP9IMwz/cE8S/4phFv+WaRf/lmkX/4phFv9vTxL/RzIL/xsU
CP8CAQH/CwsM/zk4OOl6eXiIxsTDGZSSkQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPTz
8gAAAAAApKKhNlNSUcITExP+AgEA/y8hCP9/WhT/uIEc/86RHv/TlB//1JQe/9OUHv/TlB7/05Qe/9SW
JP/Wn0P/wpRO/35aGP8tIAf/AgEA/xYWF/5cW1vBrqyrNAAAAAD29fQAAAAAAAAAAAAAAAAAAAAAAAAA
AADw7+4AAAAAAJ2bmkFEQ0PZBgYH/xMOA/9xUBL/wYcd/9OUH//Skx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/TmC7/3apa/+Ozcv/grF3/1JUh/8CHHP9vThL/Eg0D/wkJCf9NTUzYp6alQB4dHQDx8O8AAAAAAAAA
AAAAAAAA+/r5AHh2dQCmpKQ2RURD2QQEBP8kGQb/mm0Y/9GTHv/Rkx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh3/0pYo/9+sYf/jtHL/47Ny/+CuZf/Slif/0ZMd/9GTHv+Yaxj/IhgG/wYGBv9PTk7XsbCvNIuJ
iQD49/YAAAAAAAAAAACwrq0AxsTDG1VUVMIGBwf/JBoG/6d1Gv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/YoEH/47Ny/+Ozcf/js3H/47Nw/9igQf/Qkh3/0JIe/9OUHv+kdBn/IhgG/wkK
Cv9hYGDA0M7MGbm3twAAAAAA0c7NAP///wJ2dHSKFBQV/xMNA/+bbRj/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9mjSf/jtHL/47Nx/+Ozcf/js3L/4K9m/9OYLv/Qkh3/0JIe/9OU
Hv+Yaxj/EgwC/xoaG/+DgoGI////As7MywCZl5YAqKalODc2NuoBAQD/clET/9GTHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zs1/+Kxbf/js3H/47Nx/+Ozcf/js3L/3apa/9GU
JP/Qkh3/0JIe/9GTHv9vTxL/AQEA/0FBQei0srE2qKalAP///wNubWyYCwsM/zAiCP/BiB3/0ZMe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/QkyD/26VQ/+Ozcv/js3H/47Nx/+Oz
cf/js3H/2qNK/9CSH//Qkh7/0ZMe/8CHHf8uIAf/DxAR/3x7epX///8CvLq5Kz8/Pt8BAQD/gFsU/9OU
H//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/SlSb/3qpb/+Oz
cv/js3H/47Nx/+Ozcf/isW3/1pw5/9CSHf/Qkh7/05Qf/35ZFP8BAQD/S0tK3cjGxSmOjIxuHBwd+x0U
BP+5ghz/0pMe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/Tlyr/3qte/+Ozcv/js3H/47Nx/+Ozcv/grWP/05cq/9CSHf/Skx7/t4Ec/xsSA/8kJCX7nJuaam9t
ba4HCAr/SjQM/86RHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JId/9CRHf/Qkh3/0JEd/9CR
Hf/Qkh3/0JIe/9CSHf/Tlyv/36xh/+Ozcv/js3H/47Nx/+Ozcv/bpVD/0JIf/9CSHv/OkR7/RzIM/wwN
Dv99fHurWFdX2gABAv9yURL/05Qf/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIe/9KVJv/VmzX/2KBB/9mi
R//YoUX/154+/9OYLf/Qkh//0JIf/9CSHv/Zokf/47Ny/+Ozcf/js3H/47Ny/9+tYf/RlCP/0JIe/9OU
H/9wTxL/AgME/2ZlZdhKSUnzAgEA/4xjFv/UlB7/0JIe/9CSHv/Qkh7/0JId/9KVJ//Zokf/361j/+Ky
bv/js3L/47Ny/+Ozcv/frWP/26VP/9ulTv/cqFX/3alY/+CuZv/js3H/47Nx/+Ozcf/jtHP/3ahX/9CT
IP/Qkh7/1JQe/4phFv8CAgH/V1ZW8UNCQv4EAwD/mGsX/9OUHv/Qkh3/0JId/9CSHf/UmTH/36xf/+Oz
cf/js3L/47Ny/+Ozcv/js3L/4bFr/9ynVf/isWz/47Ny/+O0c//jtHP/47Ry/+Ozcf/jsnD/4rFs/92q
Wv/TmC7/0JId/9CSHf/TlB7/lmkX/wQDAP9QT0/8REND/gQDAP+ZbR7/1Zcp/9KVKf/Sliz/1Jo2/+Gw
a//kt3r/5LZ5/+O1d//gr2n/365n/+KycP/erWT/2qVV/9qlVP/Zo07/2qVT/9umVv/bpVX/2qRQ/9ih
SP/WnT7/05cx/9KVK//SlSv/0pUq/9WXKv+Xax7/BAMA/1FQUPxNTEzzAgEB/5BpKv/XnDz/1p5F/96s
ZP/dqmH/5bmA/+W5gP/luYD/3Kpf/9WbP//Umz7/1p1E/9WdQ//Umjz/1Jo7/9SaO//Umjv/1Jo7/9Sa
O//Umjv/1Jo7/9SaO//Umjz/1Jo8/9SaPP/Umjz/2J09/41mKf8CAgH/WllZ8V5dXNsBAgP/dlYj/9ed
Pf/drGP/4bJx/96tZv/luYH/5bmB/+K0dv/WnUT/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/XnD3/clMh/wMEBf9sa2rYd3Z1rwkK
DP9MOBf/1Z1E/+KzdP/ZpFL/3Kle/+W5gf/luYH/4rNz/9WcQP/Umjv/1Jo8/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9KZPP9JNRX/Dw8R/4WE
g6uZl5ZvIiIi/B4VB//Ck0v/4rJu/9WcQf/frmn/5bmB/+W5gP/kuH7/3apf/9adQ//Umz3/16BJ/9ad
Q//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Wmzz/u4g2/xwU
B/8rKyv7paSja8bDwixKSkngAgEA/4ttRP/nuHv/365p/+S3ff/luYD/5bmA/+W5gP/luYD/4rR1/+Cw
bf/jtXj/2aRS/9SZOv/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ec
Pf+BXib/AgIB/1dWVd7OzMsp////A359fJkPEBD/Niwf/9WteP/nuoL/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYH/5bqB/+W5gf/hsXD/16BJ/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI84/y8iDv8VFhf/i4mIl////wKqqKcAtrSzOkVFROoDAgH/f2dI/+e6gf/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtXj/2qZX/9SaPf/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WbPf9zVCL/AwIB/1FQT+m/vbw3tLKxAMzKyQD///8Di4mIjB4eHv8WEgz/rIxh/+i8
gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/kuH3/26dZ/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/nXIu/xMNBf8lJSX/lpSUif///wLIxsUAAAAAAL27ugDRz84cbGtqxAwM
Df8qIhj/updp/+i8gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtnr/16BL/9Sa
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
Lf0DAwP/AAAA/wAAAP8OCgP/Py0M/31ZFf+tehv/xose/9CSHv/TlB//1JUf/9SVH//UlR//1JUf/9OU
H//Qkh7/xYoc/6x6H/+BYjD/PzAY/wwJAv8AAAD/AAAA/wUFBf83Njb8iIaGvcbDwjj///8A5+XkAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc2tkA////BLCu
rV5gX17jEhIR/wAAAP8AAAD/DQoD/1A5Dv+gcRr/yo4e/9OUH//SlB7/0ZIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHf/Qkh//1Zsz/9+rWv/ltG7/zpc2/51vGP9NNw7/DAkD/wAAAP8AAAD/GBcX/2xr
a+G4trVb////A9jW1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANbU
0gD///4FqKalck1MTPEGBgb/AAAA/wICAf81Jgr/mWwZ/82QHv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9GUJP/ao0r/4rFr/+O0cv/ism3/1Zox/9OUHf/MkB7/lmoY/zMk
Cv8CAQH/AAAA/woKCv9bWlnwsbCvbvf08wXS0M8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA1NLRAP///wSopqVySEdG9AMDA/8AAAD/CgcC/2JFEf/Ahx3/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0pUm/92pV//js3H/47Nx/+Ozcf/ism//1Zw3/9CR
Hf/Qkh7/05Qe/7+GHf9eQxH/CQYC/wAAAP8GBgX/VVRU87KxsG7///8Dz8zLAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADS0M8AAAAAALGvrl9PTk3xAwMD/wAAAP8RDAT/floV/86RHv/Rkx7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh//26VO/+Ozcv/js3H/47Nx/+Oz
cf/js3L/2aNK/9CSHf/Qkh7/0JIe/9KTHv/NkB7/e1cV/w8LBP8AAAD/BgYG/11cXPC6uLdbERAQAMrI
xwAAAAAAAAAAAAAAAAAAAAAAAAAAAMzKyQCurKsAwb++PGJhYeMHBwf/AAAA/xEMBP+IYRf/0ZMf/9GS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Tlyv/4a9p/+Oz
cv/js3H/47Nx/+Ozcf/js3L/361j/9KWJ//Qkh3/0JIe/9CSHv/Rkh7/0JIe/4ReFv8PCwT/AAAA/wsL
C/9ycXDhyMXEObu5uADCwL8AAAAAAAAAAAAAAAAAAAAAAMXDwgDb2dcXgX9+wBMTE/8AAAD/CgcC/39a
Ff/Rkx//0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CR
Hf/VnDj/47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9qkS//Qkh//0JIe/9CSHv/Qkh7/0JIe/9CS
Hv97VxX/CQYC/wAAAP8cHBv/kI+OvNrY1xXFw8IAAAAAAAAAAAAAAAAAxcPCAP///wCko6J+MjEx/gAA
AP8BAQH/Y0YR/86RHv/Rkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/VnDf/4rJv/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+Kxbf/WnTr/0JId/9CS
Hv/Qkh7/0JIe/9GSHv/NkB7/X0MR/wEBAf8AAAD/QD8//bGvrnoAAAAAwb++AAAAAAAAAAAAvry7AMrI
xy9jYmLjAwMD/wAAAP83Jwv/wYgd/9GTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Slif/4K5k/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/grmX/05cs/9CSHf/Qkh7/0JIe/9CSHv/Skx7/v4Yd/zQlCv8AAAD/BwcH/3RzcuDPzcsswb++AAAA
AADBv74A////ApuZmJIjIiL/AAAA/w4KA/+abRn/05Qe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/2KFE/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/3alY/9GUI//Qkh7/0JIe/9CSHv/Qkh7/05Qe/5dqGP8NCQP/AAAA/y8v
Lv+pp6aN////AcC+vQDAvr0Az83MKWRjYuICAgL/AAAA/1I6D//OkB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0ZQj/92p
WP/js3L/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9miR//Qkh7/0JIe/9CSHv/Qkh7/0JIe/82Q
Hv9ONw7/AAAA/wYGBv92dHTg09DPJsG/vgB/fn0AqaemdS8uLv8AAAD/DwsD/6JyGv/TlB7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JId/9OXK//frWL/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+KxbP/Vmzb/0JId/9CS
Hv/Qkh7/0JIe/9OUHv+ecBn/DQoD/wAAAP89PTz/tbSzcKOhoAD39fMOgYB/vQwMDP8AAAD/QS8M/8uP
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/UmTH/4K5m/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/frGH/0pYo/9CSHf/Qkh7/0JIe/9CSHv/Kjh7/PiwM/wAAAP8UFBT/kpGQuvLv7gzLycg4WVhY6gAA
AP8BAQH/gFsV/9OUH//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zo0/+CvZ//js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/26ZR/9CTIP/Qkh7/0JIe/9CSHv/TlB//fFgV/wAAAP8BAQH/bGtq6NHO
zTSzsbBxNzY2/AAAAP8UDgT/r3sb/9KTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9Wb
Nf/hr2j/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/4rJv/9adPP/Qkh3/0JIe/9CSHv/SlB7/rHkb/xIN
BP8AAAD/R0ZG/L68u2ycm5qmHh4d/wAAAP8zJAr/x4we/9GSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9CRHf/Qkh7/0JIf/9CTIP/Qkh//0JIe/9CSHf/QkR3/0JId/9CS
Hv/Qkh7/0JIe/9CSHf/Xnz//47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ry/92pWP/QkyD/0JIe/9CS
Hv/Rkh7/xYse/y8iCf8AAAD/Kioq/6upqKGJiIfODw4O/wAAAP9TOw//0JIf/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/RkyL/1Jkw/9efQf/apU7/3KhW/9ypWv/cqFj/26ZS/9mi
R//WnDn/0ZUl/9CRHP/Qkh3/0JId/9CRHf/UmTH/4rFt/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ny/96r
X//RkyL/0JIe/9CSHv/Qkh7/0JIe/084Dv8AAAD/GBcX/5qYmMp6eXjpBgYG/wAAAP9tTRP/05Qf/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0ZQk/9efPv/eqlz/4rFs/+Ozcf/jtHL/47Ry/+O0
cv/jtHL/47Rz/+KxbP/bplL/1p4+/9igQv/Zo0n/2qRN/9ulT//eqlz/47Nx/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Rz/9yoVv/Qkh//0JIe/9CSHv/Qkh7/05Qf/2lLEv8AAAD/DQ0M/4yKiuVvbm74AgIC/wAA
AP9/WhX/1JUf/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/VmjT/3qtd/+OzcP/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/4K9n/9ihRf/cqFf/4rFs/+Ozcv/js3L/47Ry/+O0cv/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/jtHL/4bFr/9WbNv/Qkh3/0JIe/9CSHv/Qkh7/1JUf/3tXFf8AAAD/BwcH/4KA
gPRraWn/AQEB/wEBAf+IYBb/1JQe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIf/9efP//hsGr/47Ny/+Oz
cf/js3H/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3L/26dT/92qW//ktHP/47Ny/+Ozcv/js3L/47Ny/+Oz
cv/js3L/47Ny/+Ozcv/js3L/47Nw/+KxbP/eq13/1Zw4/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/1JQe/4Nd
Ff8AAAD/BQUF/359fPxramr/AQEB/wEBAf+IYBj/1JUi/9GTIv/RkyP/0ZMj/9GTI//RkyT/16BC/+Kz
cf/ktXb/5LV1/+S1dv/ktXb/5LV2/+Kzc//is3L/47R1/+S2d//jtHX/2qVS/96tZ//dq2H/26ZV/9um
Vf/cqVz/3qtg/96rYf/eq2D/3ald/9ynV//apE//2KBF/9WbOf/Sliv/0ZQk/9GUJf/RlCT/0ZMj/9GT
I//RkyL/1JYi/4NdF/8AAAD/BQUF/399ffxycXH4AwMD/wAAAP+CXiT/15w5/9SZOf/UmTn/1Zs+/9eg
Sv/VnUL/4bJy/+W5gf/luYD/5bmA/+W5gP/kt3z/3Klf/9egS//XoEn/2aNQ/9yqX//cqV//1ZxB/9Wc
Qf/Umj3/1Jo7/9SaO//Umjz/1Jo9/9SaPf/Umj3/1Jo8/9SaO//UmTr/1Jk6/9SZOv/Umjv/1Jo7/9Sa
O//Umjr/1Jk6/9SZOf/UmTn/15w5/31bI/8AAAD/CAgI/4SDgvV/fX3pCAgI/wAAAP9xUyP/15w9/9Sa
PP/Umz7/3ati/+O1eP/aplj/5Ld8/+W5gP/luYD/5bmA/+W5gP/dq2H/1Jo8/9SaO//Umjv/1Jo7/9Sa
O//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/2xPIP8AAAD/Dg4O/5COjuWQjo3PERER/wAA
AP9WPxv/1Zs9/9SaO//Zo1D/5Lh+/+Gycv/bp1r/5bl//+W5gP/luYD/5bmA/+O1eP/Wn0f/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/1E7Gf8AAAD/Gxsb/5+e
ncqkoqGnIyMj/wAAAP81JxH/y5Q7/9WbPv/fr2r/5bmA/9qmV//ZpFP/5bl//+W5gP/luYD/5bmB/+Cw
bf/Umz7/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/yZM6/zEk
D/8AAAD/MTAw/7GvrqK5t7ZyQD8//QAAAP8VEAj/s4I0/9mgR//jtnr/4LBt/9WbP//Yo1D/5Lh//+W5
gP/luYD/5bmB/+Gycf/Vm0D/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/WnD3/sIAz/xMOBv8AAAD/UVBP/MLAv23OzMs5ZmVk6wAAAP8CAQH/hGEn/92nVf/kt33/2KNQ/9OZ
Of/bp1r/5bmA/+W5gP/luYD/5bmA/+S4fv/cqV3/1Zs//9SZO//Umjv/1Jk7/9WdQv/VnED/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/gF0m/wEAAP8DAwP/eHZ26dHOzTXs6egPj46NvxISEv8AAAD/RDIV/9em
X//luH7/2KNQ/9aeR//hsnL/5bmB/+W5gP/luYD/5bmA/+W5gP/luH//369r/9mkUv/Xn0j/2KJP/+Cw
bf/Zo1H/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Oljv/QC8U/wAAAP8cGxv/n52cu+Ti4A2amJcAtLKxdjw7
O/8AAAD/EAwG/7GNW//ovIL/47V4/+K1d//luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W4
f//kt3v/5Lh+/+W5gf/bqFz/1Jk7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ecPf+jdzD/DgoF/wAAAP9MS0v/vbu6crKw
rwDBv74A0c7NK3d1deMGBgb/AAAA/11LNf/jt3//5bmB/+W5gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/itHb/2KFM/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9GYPP9RPBn/AAAA/wsL
C/+HhoXh0c/OKMG/vgDAvr0A////AqupqZQxMTD/AAAA/xEOCv+si2H/6LyC/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYH/47V5/9unWv/VnED/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/5tx
Lv8OCgX/AAAA/0A/P/+1tLOQ////AcC+vQDAvr0AwsC/AM3LyjF6eXjkCQkJ/wAAAP8/MyT/1q14/+a6
gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W5
gP/fr2r/1p5F/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI44/zcoEf8AAAD/Dw8P/4qIh+LOzMsuwsC/AAAAAAAAAAAAwb++AP///wG1s7KBRkZF/gAA
AP8CAgH/cFtA/+O4f//muYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYH/4LFv/9aeRf/Umjv/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WaPP/SmDz/Y0ke/wEBAf8AAAD/VlVU/r27unz///8AwL69AAAAAAAAAAAAAAAAAMTC
wQDU0tEYmZiXwiIiIf8AAAD/DAoH/5B1Uv/nuoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/9+uav/Vmz//1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPf+AXif/CgcE/wAAAP8tLSz/paSjv9HPzhbDwcAAAAAAAAAA
AAAAAAAAAAAAAMC+vQC/vbwAycbFP39+feUQEBD/AAAA/xURDf+bflj/57qB/+a5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W4f//apVX/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/1Zs9/4plKf8RDQb/AAAA/xgXF/+NjIviysjHO8PB
wADAvr0AAAAAAAAAAAAAAAAAAAAAAAAAAADEwsEA////AMC+vWJtbGvyCgoK/wAAAP8VEQ3/kXZT/+S4
gP/muoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W6
gf/fr2r/1Jo9/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPP/SmDz/gV4n/xENBv8AAAD/Dw8P/3t6
efHEwsFefnx8AMG/vgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx8XEAOHf3QS7ubh2aGZm9goK
Cv8AAAD/DQsI/3JdQf/WrXj/6LyC/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gf/hsnL/1ZtA/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/8SPOP9jSR7/CgcE/wAA
AP8PDw//dXRz9MC+vXLW1NMDxMLBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMrH
xgDa2NYGvLq5dnBvbvISERH/AAAA/wMDAv9ANCX/rYxi/+O3f//ou4L/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/hsnL/1ZxA/9SaPP/Umjz/1Jo8/9ecPf/RmDz/nHIu/zco
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
AAD/4AAAB/8AAP/4AAAf/wAA//8AAP//AAA=
</value>
</data>
</root>

63
Forms/FormErrorLog.Designer.cs generated Normal file
View File

@@ -0,0 +1,63 @@
namespace EFCDesk.Forms
{
partial class FormErrorLog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
dataGridView1 = new DataGridView();
((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit();
SuspendLayout();
//
// dataGridView1
//
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.AllowUserToOrderColumns = true;
dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView1.Location = new Point(12, 12);
dataGridView1.Name = "dataGridView1";
dataGridView1.ReadOnly = true;
dataGridView1.Size = new Size(349, 313);
dataGridView1.TabIndex = 0;
//
// FormErrorLog
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(373, 337);
Controls.Add(dataGridView1);
Name = "FormErrorLog";
Text = "Expediente Electronico";
((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit();
ResumeLayout(false);
}
#endregion
private DataGridView dataGridView1;
}
}

24
Forms/FormErrorLog.cs Normal file
View File

@@ -0,0 +1,24 @@
using EFCDesk.Classes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EFCDesk.Forms
{
public partial class FormErrorLog : Form
{
private static SQLiteHelper sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
public FormErrorLog()
{
InitializeComponent();
ErrorLog errorLog = new ErrorLog();
dataGridView1.DataSource = errorLog.GetRegistrosErrorLog(sqliteHelper);
}
}
}

120
Forms/FormErrorLog.resx Normal file
View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

198
Forms/FormExpedientes.Designer.cs generated Normal file
View File

@@ -0,0 +1,198 @@
namespace EFCDesk.Forms
{
partial class FormExpedientes
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormExpedientes));
edt_BuscarExpediente = new TextBox();
label1 = new Label();
dgwExpedientes = new DataGridView();
BTN_Buscar = new Button();
edt_Pagina = new TextBox();
btn_inicio = new Button();
btn_anterior = new Button();
btn_siguiente = new Button();
btn_ultimo = new Button();
lblPaginacion = new Label();
((System.ComponentModel.ISupportInitialize)dgwExpedientes).BeginInit();
SuspendLayout();
//
// edt_BuscarExpediente
//
edt_BuscarExpediente.Location = new Point(65, 6);
edt_BuscarExpediente.Name = "edt_BuscarExpediente";
edt_BuscarExpediente.PlaceholderText = "Buscar Expediente...";
edt_BuscarExpediente.Size = new Size(258, 23);
edt_BuscarExpediente.TabIndex = 0;
edt_BuscarExpediente.TextAlign = HorizontalAlignment.Center;
edt_BuscarExpediente.KeyPress += edt_BuscarExpediente_KeyPress;
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Segoe UI", 9F, FontStyle.Bold);
label1.Location = new Point(12, 9);
label1.Name = "label1";
label1.Size = new Size(47, 15);
label1.TabIndex = 1;
label1.Text = "Buscar:";
//
// dgwExpedientes
//
dgwExpedientes.AllowUserToAddRows = false;
dgwExpedientes.AllowUserToDeleteRows = false;
dgwExpedientes.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dgwExpedientes.Location = new Point(12, 35);
dgwExpedientes.Name = "dgwExpedientes";
dgwExpedientes.ReadOnly = true;
dgwExpedientes.RowHeadersVisible = false;
dgwExpedientes.Size = new Size(559, 258);
dgwExpedientes.TabIndex = 2;
//
// BTN_Buscar
//
BTN_Buscar.BackgroundImage = (Image)resources.GetObject("BTN_Buscar.BackgroundImage");
BTN_Buscar.BackgroundImageLayout = ImageLayout.Zoom;
BTN_Buscar.Cursor = Cursors.Hand;
BTN_Buscar.FlatAppearance.BorderSize = 0;
BTN_Buscar.FlatStyle = FlatStyle.Flat;
BTN_Buscar.Location = new Point(326, 6);
BTN_Buscar.Name = "BTN_Buscar";
BTN_Buscar.Size = new Size(30, 23);
BTN_Buscar.TabIndex = 8;
BTN_Buscar.UseVisualStyleBackColor = true;
BTN_Buscar.Click += BTN_Buscar_Click;
//
// edt_Pagina
//
edt_Pagina.Location = new Point(471, 6);
edt_Pagina.Name = "edt_Pagina";
edt_Pagina.ReadOnly = true;
edt_Pagina.Size = new Size(100, 23);
edt_Pagina.TabIndex = 11;
edt_Pagina.TextAlign = HorizontalAlignment.Center;
edt_Pagina.Visible = false;
//
// btn_inicio
//
btn_inicio.Font = new Font("Segoe UI", 12F, FontStyle.Bold);
btn_inicio.Location = new Point(417, 296);
btn_inicio.Name = "btn_inicio";
btn_inicio.Size = new Size(34, 33);
btn_inicio.TabIndex = 12;
btn_inicio.Text = "|<";
btn_inicio.TextAlign = ContentAlignment.MiddleRight;
btn_inicio.UseVisualStyleBackColor = true;
btn_inicio.Click += btn_inicio_Click;
//
// btn_anterior
//
btn_anterior.Font = new Font("Segoe UI", 12F, FontStyle.Bold);
btn_anterior.Location = new Point(457, 296);
btn_anterior.Name = "btn_anterior";
btn_anterior.Size = new Size(34, 33);
btn_anterior.TabIndex = 13;
btn_anterior.Text = "<";
btn_anterior.TextAlign = ContentAlignment.MiddleRight;
btn_anterior.UseVisualStyleBackColor = true;
btn_anterior.Click += btn_anterior_Click;
//
// btn_siguiente
//
btn_siguiente.Font = new Font("Segoe UI", 12F, FontStyle.Bold);
btn_siguiente.Location = new Point(497, 296);
btn_siguiente.Name = "btn_siguiente";
btn_siguiente.Size = new Size(34, 33);
btn_siguiente.TabIndex = 14;
btn_siguiente.Text = ">";
btn_siguiente.TextAlign = ContentAlignment.MiddleRight;
btn_siguiente.UseVisualStyleBackColor = true;
btn_siguiente.Click += btn_siguiente_Click;
//
// btn_ultimo
//
btn_ultimo.Font = new Font("Segoe UI", 12F, FontStyle.Bold);
btn_ultimo.Location = new Point(537, 296);
btn_ultimo.Name = "btn_ultimo";
btn_ultimo.Size = new Size(34, 33);
btn_ultimo.TabIndex = 15;
btn_ultimo.Text = ">|";
btn_ultimo.TextAlign = ContentAlignment.MiddleRight;
btn_ultimo.UseVisualStyleBackColor = true;
btn_ultimo.Click += btn_ultimo_Click;
//
// lblPaginacion
//
lblPaginacion.AutoSize = true;
lblPaginacion.Location = new Point(12, 296);
lblPaginacion.Name = "lblPaginacion";
lblPaginacion.Size = new Size(209, 15);
lblPaginacion.TabIndex = 16;
lblPaginacion.Text = " [Registro 1 de 1000][Página 1 de 1000]";
lblPaginacion.TextAlign = ContentAlignment.MiddleLeft;
//
// FormExpedientes
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(583, 340);
Controls.Add(lblPaginacion);
Controls.Add(btn_ultimo);
Controls.Add(btn_siguiente);
Controls.Add(btn_anterior);
Controls.Add(btn_inicio);
Controls.Add(edt_Pagina);
Controls.Add(BTN_Buscar);
Controls.Add(dgwExpedientes);
Controls.Add(label1);
Controls.Add(edt_BuscarExpediente);
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
Name = "FormExpedientes";
StartPosition = FormStartPosition.CenterScreen;
Text = "FormExpedientes";
Shown += FormExpedientes_Shown;
((System.ComponentModel.ISupportInitialize)dgwExpedientes).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox edt_BuscarExpediente;
private Label label1;
private DataGridView dgwExpedientes;
private Button BTN_Buscar;
private TextBox edt_Pagina;
private Button btn_inicio;
private Button btn_anterior;
private Button btn_siguiente;
private Button btn_ultimo;
private Label lblPaginacion;
}
}

260
Forms/FormExpedientes.cs Normal file
View File

@@ -0,0 +1,260 @@
using EFCDesk.Classes;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EFCDesk.Forms
{
public partial class FormExpedientes : Form
{
private class Paginacion
{
public long _registro;
public long _registros;
public long _pagina;
public long _paginas;
}
private static SQLiteHelper _sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
private long paginacion = 1000;
private bool _clickPorCodigo = false;
private Paginacion _paginacion = new Paginacion();
public FormExpedientes()
{
InitializeComponent();
dgwExpedientes.SelectionChanged += dgwExpedientes_SelectionChanged!;
dgwExpedientes.AutoGenerateColumns = true;
dgwExpedientes.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}
private async Task CargarVistaExpedientes(int pagina, string buscarExpediente = "*")
{
// Limpiar la fuente de datos
dgwExpedientes.DataSource = null;
// 1) Trabajo pesado en segundo plano
DataTable? dt = await Task.Run(() =>
{
var listaExpedientes = _sqliteHelper.ObtenerExpedientes(pagina: pagina, tamanioPagina: paginacion, buscarExpediente: buscarExpediente);
if (listaExpedientes == null || listaExpedientes.Count == 0)
return null;
DataTable table = new DataTable();
table.Columns.Add("Expediente", typeof(string));
table.Columns.Add("Ruta", typeof(string));
table.Columns.Add("Estatus", typeof(string));
table.Columns.Add("Fecha Registro", typeof(string));
foreach (var exp in listaExpedientes)
{
var row = table.NewRow();
row["Expediente"] = exp.Expediente;
row["Ruta"] = exp.Ruta;
row["Estatus"] = exp.Estado;
row["Fecha Registro"] = exp.FechaCreacion;
table.Rows.Add(row);
}
return table;
});
long totalPaginas = await TotalPaginas(edt_BuscarExpediente.Text);
// 2) Volver al UI thread para asignar el origen
if (dt != null)
{
// Deshabilitar el redimensionamiento de ALTOS de filas
dgwExpedientes.AllowUserToResizeRows = false;
dgwExpedientes.DataSource = dt;
dgwExpedientes.Columns["Expediente"].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dgwExpedientes.Columns["Expediente"].Frozen = true;
dgwExpedientes.Columns["Expediente"].Width = 100;
dgwExpedientes.Columns["Ruta"].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dgwExpedientes.Columns["Ruta"].Width = 300;
dgwExpedientes.Columns["Estatus"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
dgwExpedientes.Columns["Estatus"].Width = 100;
dgwExpedientes.Columns["Fecha Registro"].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
dgwExpedientes.Columns["Fecha Registro"].Width = 180;
_ = Task.Run(() =>
{
long total = dgwExpedientes.RowCount;
_paginacion._registro = 1;
_paginacion._registros = total;
_paginacion._pagina = pagina;
_paginacion._paginas = totalPaginas;
ActualizarEtiqueta();
});
}
else
{
_paginacion._registro = 0;
_paginacion._registros = 0;
_paginacion._pagina = 0;
_paginacion._paginas = 0;
ActualizarEtiqueta();
}
}
private async void FormExpedientes_Shown(object sender, EventArgs e)
{
edt_Pagina.Text = "1";
await CargarVistaExpedientes(pagina: 1);
}
private async void BTN_Buscar_Click(object sender, EventArgs e)
{
string busqueda = edt_BuscarExpediente.Text.Trim();
if (string.IsNullOrEmpty(busqueda))
{
busqueda = "*";
}
int pag = int.Parse(edt_Pagina.Text);
if (_clickPorCodigo)
{
// fue llamado desde código
await CargarVistaExpedientes(buscarExpediente: busqueda, pagina: pag);
_clickPorCodigo = false; // reset
}
else
{
// fue el usuario
await CargarVistaExpedientes(buscarExpediente: busqueda, pagina: 1);
}
}
private async void btn_siguiente_Click(object sender, EventArgs e)
{
long totalPaginas = await TotalPaginas(edt_BuscarExpediente.Text);
long pag = (int.Parse(edt_Pagina.Text) + 1);
if (pag > totalPaginas) return;
edt_Pagina.Text = pag.ToString();
_clickPorCodigo = true;
BTN_Buscar.PerformClick();
}
private void btn_anterior_Click(object sender, EventArgs e)
{
int pag = (int.Parse(edt_Pagina.Text) - 1);
if (pag <= 0)
{
return;
}
edt_Pagina.Text = pag.ToString();
_clickPorCodigo = true;
BTN_Buscar.PerformClick();
}
private void btn_inicio_Click(object sender, EventArgs e)
{
edt_Pagina.Text = "1";
_clickPorCodigo = true;
BTN_Buscar.PerformClick();
}
private async void btn_ultimo_Click(object sender, EventArgs e)
{
long totalPaginas = await TotalPaginas(edt_BuscarExpediente.Text);
edt_Pagina.Text = totalPaginas.ToString();
_clickPorCodigo = true;
BTN_Buscar.PerformClick();
}
private async Task<long> TotalPaginas(string busqueda)
{
long total = 0;
if (string.IsNullOrEmpty(busqueda))
{
total = await _sqliteHelper.TotalExpedientes("*");
}
else if (string.IsNullOrWhiteSpace(busqueda))
{
total = await _sqliteHelper.TotalExpedientes("*");
}
else
{
total = await _sqliteHelper.TotalExpedientes(busqueda);
}
long resto = total % paginacion;
long totalPaginas = ((total - resto) / paginacion);
if (resto > 0) totalPaginas += 1;
return totalPaginas;
}
private void ActualizarEtiqueta()
{
// Si el llamado llega desde otro hilo, lo redirigimos al UI
if (lblPaginacion.InvokeRequired)
{
lblPaginacion.BeginInvoke((MethodInvoker)(() =>
lblPaginacion.Text = $"[Registro {_paginacion._registro.ToString()} de {_paginacion._registros.ToString()}][Página {_paginacion._pagina.ToString()} de {_paginacion._paginas.ToString()}]"));
return;
}
// Ya estamos en el hilo UI
lblPaginacion.Text = $"[Registro {_paginacion._registro.ToString()} de {_paginacion._registros.ToString()}][Página {_paginacion._pagina.ToString()} de {_paginacion._paginas.ToString()}]";
}
private void dgwExpedientes_SelectionChanged(object sender, EventArgs e)
{
if (dgwExpedientes.CurrentRow == null) return;
int indiceFila = dgwExpedientes.CurrentRow.Index;
_paginacion._registro = (indiceFila + 1);
ActualizarEtiqueta();
}
private void edt_BuscarExpediente_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Return)
{
e.Handled = true;
BTN_Buscar.PerformClick();
}
}
}
}

135
Forms/FormExpedientes.resx Normal file
View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="BTN_Buscar.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAfpJREFUWEftlr8rhVEYxy9SGCgxGJSyWGSwSZnEYDP5H2SzMzHhD7AoJmWyWqT8
KAtJDAYGTAwyKPH5vHXqDrrvOe99hfKtT91zes9znvPr+d7Kv/6SRmAFTuAJ3uEVrmALZqAFStcoHMNH
BI8wB01QtxphCVypwR9gGcagExqgDQZhFtyZkMgB9EBhOfkmGOwNFqAV8jQFt+C4G+iFQnLlBnkGV5yi
LjgEx5+Bu5Qkz9xtd+Wpkwd1wAWYxJodKQoXzm2vR0PgIqTfjhj51JzcCxdz5nlaB+OtZq0I+c4d4G0v
Q8NgvLusFaHwlIqe/VdyN43Zl7VyZIXzY995WdoDY45nrRyFomORKUvbYMzprJUja7sfJ7/dGtoFY1qk
cqWx+LHltSxdgjF9lrnS1fzY2l6G9AOP9QWa7ciTlmoCvoYyNA/G28laEdLPtVQHRZ1ZDbVDeIITdsRK
P3eQrqaxFNUGGGc/ayXIPxP6uYN1NY0lVYvgeM9+wI5UeXn0c4PoalE3GLntYeVyDd1QSP6Z0M8NpKNp
LNb2r2TCXrh7CCt3cn+fQ+EkLEj6uQmEVXmxLK9WOIuM7zxUUPHM3XYndfK6k1D6uZaqq4WJqnHFPrVJ
qFapSQTpahqLtd2n6v2oVWS+JYlUVSdxasdPyCSc/Chr/et3qFL5BH2hlRT2cx6UAAAAAElFTkSuQmCC
</value>
</data>
</root>

327
Forms/FormMain.Designer.cs generated Normal file
View File

@@ -0,0 +1,327 @@
namespace EFCDesk.Forms
{
partial class FormMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain));
panel1 = new Panel();
btn_VisorExpedientes = new Button();
ProcesoManual = new Button();
buttonErrorLog = new Button();
buttonAbrirFolderMov = new Button();
buttonAbrirFolder = new Button();
buttonAbrirExpediente = new Button();
buttonConfiguracion = new Button();
panel2 = new Panel();
labelTotalExpedientes = new Label();
labelUsuario = new Label();
labelStatus = new Label();
listViewExpedientes = new ListView();
fileSystemWatcher = new FileSystemWatcher();
imageList1 = new ImageList(components);
mynotifyicon = new NotifyIcon(components);
contextMenuStrip1 = new ContextMenuStrip(components);
cerrarExpedienteElectronicoToolStripMenuItem = new ToolStripMenuItem();
listViewArchivosProcesados = new ListView();
panel1.SuspendLayout();
panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)fileSystemWatcher).BeginInit();
contextMenuStrip1.SuspendLayout();
SuspendLayout();
//
// panel1
//
panel1.BackColor = Color.White;
panel1.Controls.Add(btn_VisorExpedientes);
panel1.Controls.Add(ProcesoManual);
panel1.Controls.Add(buttonErrorLog);
panel1.Controls.Add(buttonAbrirFolderMov);
panel1.Controls.Add(buttonAbrirFolder);
panel1.Controls.Add(buttonAbrirExpediente);
panel1.Controls.Add(buttonConfiguracion);
panel1.Location = new Point(3, 6);
panel1.Name = "panel1";
panel1.Size = new Size(49, 315);
panel1.TabIndex = 0;
//
// btn_VisorExpedientes
//
btn_VisorExpedientes.BackgroundImage = (Image)resources.GetObject("btn_VisorExpedientes.BackgroundImage");
btn_VisorExpedientes.BackgroundImageLayout = ImageLayout.Zoom;
btn_VisorExpedientes.Cursor = Cursors.Hand;
btn_VisorExpedientes.FlatAppearance.BorderSize = 0;
btn_VisorExpedientes.FlatStyle = FlatStyle.Flat;
btn_VisorExpedientes.Location = new Point(6, 126);
btn_VisorExpedientes.Name = "btn_VisorExpedientes";
btn_VisorExpedientes.Size = new Size(30, 23);
btn_VisorExpedientes.TabIndex = 8;
btn_VisorExpedientes.UseVisualStyleBackColor = true;
btn_VisorExpedientes.Click += btn_VisorExpedientes_Click;
//
// ProcesoManual
//
ProcesoManual.BackgroundImage = (Image)resources.GetObject("ProcesoManual.BackgroundImage");
ProcesoManual.BackgroundImageLayout = ImageLayout.Zoom;
ProcesoManual.Cursor = Cursors.Hand;
ProcesoManual.FlatAppearance.BorderSize = 0;
ProcesoManual.FlatStyle = FlatStyle.Flat;
ProcesoManual.Location = new Point(5, 88);
ProcesoManual.Name = "ProcesoManual";
ProcesoManual.Size = new Size(30, 23);
ProcesoManual.TabIndex = 7;
ProcesoManual.UseVisualStyleBackColor = true;
ProcesoManual.Click += ProcesoManual_Click;
//
// buttonErrorLog
//
buttonErrorLog.BackgroundImage = (Image)resources.GetObject("buttonErrorLog.BackgroundImage");
buttonErrorLog.BackgroundImageLayout = ImageLayout.Zoom;
buttonErrorLog.Cursor = Cursors.Hand;
buttonErrorLog.FlatAppearance.BorderSize = 0;
buttonErrorLog.FlatStyle = FlatStyle.Flat;
buttonErrorLog.Location = new Point(6, 227);
buttonErrorLog.Name = "buttonErrorLog";
buttonErrorLog.Size = new Size(31, 34);
buttonErrorLog.TabIndex = 6;
buttonErrorLog.UseVisualStyleBackColor = true;
buttonErrorLog.Visible = false;
buttonErrorLog.Click += buttonErrorLog_Click;
//
// buttonAbrirFolderMov
//
buttonAbrirFolderMov.BackgroundImage = (Image)resources.GetObject("buttonAbrirFolderMov.BackgroundImage");
buttonAbrirFolderMov.BackgroundImageLayout = ImageLayout.Zoom;
buttonAbrirFolderMov.Cursor = Cursors.Hand;
buttonAbrirFolderMov.FlatAppearance.BorderSize = 0;
buttonAbrirFolderMov.FlatStyle = FlatStyle.Flat;
buttonAbrirFolderMov.Location = new Point(7, 267);
buttonAbrirFolderMov.Name = "buttonAbrirFolderMov";
buttonAbrirFolderMov.Size = new Size(31, 34);
buttonAbrirFolderMov.TabIndex = 5;
buttonAbrirFolderMov.UseVisualStyleBackColor = true;
buttonAbrirFolderMov.Visible = false;
buttonAbrirFolderMov.Click += buttonAbrirFolderMov_Click;
//
// buttonAbrirFolder
//
buttonAbrirFolder.BackgroundImage = (Image)resources.GetObject("buttonAbrirFolder.BackgroundImage");
buttonAbrirFolder.BackgroundImageLayout = ImageLayout.Zoom;
buttonAbrirFolder.Cursor = Cursors.Hand;
buttonAbrirFolder.FlatAppearance.BorderSize = 0;
buttonAbrirFolder.FlatStyle = FlatStyle.Flat;
buttonAbrirFolder.Location = new Point(4, 8);
buttonAbrirFolder.Name = "buttonAbrirFolder";
buttonAbrirFolder.Size = new Size(31, 34);
buttonAbrirFolder.TabIndex = 4;
buttonAbrirFolder.UseVisualStyleBackColor = true;
buttonAbrirFolder.Click += buttonAbrirFolder_Click;
//
// buttonAbrirExpediente
//
buttonAbrirExpediente.BackgroundImage = (Image)resources.GetObject("buttonAbrirExpediente.BackgroundImage");
buttonAbrirExpediente.BackgroundImageLayout = ImageLayout.Zoom;
buttonAbrirExpediente.Cursor = Cursors.Hand;
buttonAbrirExpediente.FlatAppearance.BorderSize = 0;
buttonAbrirExpediente.FlatStyle = FlatStyle.Flat;
buttonAbrirExpediente.Location = new Point(7, 187);
buttonAbrirExpediente.Name = "buttonAbrirExpediente";
buttonAbrirExpediente.Size = new Size(31, 34);
buttonAbrirExpediente.TabIndex = 3;
buttonAbrirExpediente.UseVisualStyleBackColor = true;
buttonAbrirExpediente.Visible = false;
buttonAbrirExpediente.Click += buttonAbrirExpediente_Click;
//
// buttonConfiguracion
//
buttonConfiguracion.BackgroundImage = (Image)resources.GetObject("buttonConfiguracion.BackgroundImage");
buttonConfiguracion.BackgroundImageLayout = ImageLayout.Zoom;
buttonConfiguracion.Cursor = Cursors.Hand;
buttonConfiguracion.FlatAppearance.BorderSize = 0;
buttonConfiguracion.FlatStyle = FlatStyle.Flat;
buttonConfiguracion.Location = new Point(4, 48);
buttonConfiguracion.Name = "buttonConfiguracion";
buttonConfiguracion.Size = new Size(31, 34);
buttonConfiguracion.TabIndex = 2;
buttonConfiguracion.UseVisualStyleBackColor = true;
buttonConfiguracion.Click += buttonConfiguracion_Click;
//
// panel2
//
panel2.BackColor = Color.White;
panel2.Controls.Add(labelTotalExpedientes);
panel2.Controls.Add(labelUsuario);
panel2.Controls.Add(labelStatus);
panel2.Location = new Point(3, 320);
panel2.Name = "panel2";
panel2.Size = new Size(444, 40);
panel2.TabIndex = 1;
panel2.Paint += panel2_Paint;
//
// labelTotalExpedientes
//
labelTotalExpedientes.AutoSize = true;
labelTotalExpedientes.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
labelTotalExpedientes.Location = new Point(9, 21);
labelTotalExpedientes.Name = "labelTotalExpedientes";
labelTotalExpedientes.Size = new Size(40, 16);
labelTotalExpedientes.TabIndex = 8;
labelTotalExpedientes.Text = "label1";
//
// labelUsuario
//
labelUsuario.AutoSize = true;
labelUsuario.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
labelUsuario.Location = new Point(263, 18);
labelUsuario.Name = "labelUsuario";
labelUsuario.Size = new Size(40, 16);
labelUsuario.TabIndex = 7;
labelUsuario.Text = "label1";
labelUsuario.Visible = false;
labelUsuario.Click += label1_Click;
//
// labelStatus
//
labelStatus.AutoSize = true;
labelStatus.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
labelStatus.Location = new Point(9, 3);
labelStatus.Name = "labelStatus";
labelStatus.Size = new Size(138, 16);
labelStatus.TabIndex = 0;
labelStatus.Text = "Sin cambios detectados";
//
// listViewExpedientes
//
listViewExpedientes.BorderStyle = BorderStyle.None;
listViewExpedientes.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
listViewExpedientes.HeaderStyle = ColumnHeaderStyle.Nonclickable;
listViewExpedientes.Location = new Point(45, 6);
listViewExpedientes.Name = "listViewExpedientes";
listViewExpedientes.Size = new Size(182, 314);
listViewExpedientes.TabIndex = 2;
listViewExpedientes.UseCompatibleStateImageBehavior = false;
listViewExpedientes.View = View.Tile;
listViewExpedientes.MouseClick += listViewExpedientes_MouseClick;
//
// fileSystemWatcher
//
fileSystemWatcher.EnableRaisingEvents = true;
fileSystemWatcher.SynchronizingObject = this;
//
// imageList1
//
imageList1.ColorDepth = ColorDepth.Depth32Bit;
imageList1.ImageSize = new Size(16, 16);
imageList1.TransparentColor = Color.Transparent;
//
// mynotifyicon
//
mynotifyicon.BalloonTipIcon = ToolTipIcon.Info;
mynotifyicon.BalloonTipText = "Su expediente electronico se estará actualizando";
mynotifyicon.BalloonTipTitle = "Expediente electronico";
mynotifyicon.ContextMenuStrip = contextMenuStrip1;
mynotifyicon.Icon = (Icon)resources.GetObject("mynotifyicon.Icon");
mynotifyicon.Text = "Expediente electronico";
mynotifyicon.Visible = true;
mynotifyicon.Click += mynotifyicon_Click;
//
// contextMenuStrip1
//
contextMenuStrip1.Items.AddRange(new ToolStripItem[] { cerrarExpedienteElectronicoToolStripMenuItem });
contextMenuStrip1.Name = "contextMenuStrip1";
contextMenuStrip1.Size = new Size(230, 26);
//
// cerrarExpedienteElectronicoToolStripMenuItem
//
cerrarExpedienteElectronicoToolStripMenuItem.Name = "cerrarExpedienteElectronicoToolStripMenuItem";
cerrarExpedienteElectronicoToolStripMenuItem.Size = new Size(229, 22);
cerrarExpedienteElectronicoToolStripMenuItem.Text = "Cerrar expediente electronico";
cerrarExpedienteElectronicoToolStripMenuItem.Click += cerrarExpedienteElectronicoToolStripMenuItem_Click;
//
// listViewArchivosProcesados
//
listViewArchivosProcesados.BorderStyle = BorderStyle.None;
listViewArchivosProcesados.HeaderStyle = ColumnHeaderStyle.Nonclickable;
listViewArchivosProcesados.Location = new Point(227, 6);
listViewArchivosProcesados.Name = "listViewArchivosProcesados";
listViewArchivosProcesados.Size = new Size(220, 314);
listViewArchivosProcesados.TabIndex = 3;
listViewArchivosProcesados.UseCompatibleStateImageBehavior = false;
listViewArchivosProcesados.View = View.Details;
//
// FormMain
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
BackgroundImage = (Image)resources.GetObject("$this.BackgroundImage");
ClientSize = new Size(453, 367);
Controls.Add(listViewArchivosProcesados);
Controls.Add(listViewExpedientes);
Controls.Add(panel2);
Controls.Add(panel1);
Font = new Font("Century Gothic", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
FormBorderStyle = FormBorderStyle.None;
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
MinimizeBox = false;
Name = "FormMain";
Text = "FormMain";
Load += FormMain_Load;
Shown += FormMain_Shown;
panel1.ResumeLayout(false);
panel2.ResumeLayout(false);
panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)fileSystemWatcher).EndInit();
contextMenuStrip1.ResumeLayout(false);
ResumeLayout(false);
}
#endregion
private Panel panel1;
private Panel panel2;
private Button buttonConfiguracion;
private ListView listViewExpedientes;
private FileSystemWatcher fileSystemWatcher;
private Button buttonAbrirFolderMov;
private Button buttonAbrirFolder;
private Button buttonAbrirExpediente;
private ImageList imageList1;
private NotifyIcon mynotifyicon;
private ListView listViewArchivosProcesados;
private Label labelStatus;
private ContextMenuStrip contextMenuStrip1;
private ToolStripMenuItem revisarExpedientesToolStripMenuItem;
private ToolStripMenuItem cerrarExpedienteElectronicoToolStripMenuItem;
private Button buttonErrorLog;
private Label labelUsuario;
private Label labelTotalExpedientes;
private Button ProcesoManual;
private Button btn_VisorExpedientes;
}
}

1909
Forms/FormMain.cs Normal file

File diff suppressed because it is too large Load Diff

611
Forms/FormMain.resx Normal file
View File

@@ -0,0 +1,611 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="btn_VisorExpedientes.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wAAADsABataJCQAAAfpJREFUWEftlr8rhVEYxy9SGCgxGJSyWGSwSZnEYDP5H2SzMzHhD7AoJmWyWqT8
KAtJDAYGTAwyKPH5vHXqDrrvOe99hfKtT91zes9znvPr+d7Kv/6SRmAFTuAJ3uEVrmALZqAFStcoHMNH
BI8wB01QtxphCVypwR9gGcagExqgDQZhFtyZkMgB9EBhOfkmGOwNFqAV8jQFt+C4G+iFQnLlBnkGV5yi
LjgEx5+Bu5Qkz9xtd+Wpkwd1wAWYxJodKQoXzm2vR0PgIqTfjhj51JzcCxdz5nlaB+OtZq0I+c4d4G0v
Q8NgvLusFaHwlIqe/VdyN43Zl7VyZIXzY995WdoDY45nrRyFomORKUvbYMzprJUja7sfJ7/dGtoFY1qk
cqWx+LHltSxdgjF9lrnS1fzY2l6G9AOP9QWa7ciTlmoCvoYyNA/G28laEdLPtVQHRZ1ZDbVDeIITdsRK
P3eQrqaxFNUGGGc/ayXIPxP6uYN1NY0lVYvgeM9+wI5UeXn0c4PoalE3GLntYeVyDd1QSP6Z0M8NpKNp
LNb2r2TCXrh7CCt3cn+fQ+EkLEj6uQmEVXmxLK9WOIuM7zxUUPHM3XYndfK6k1D6uZaqq4WJqnHFPrVJ
qFapSQTpahqLtd2n6v2oVWS+JYlUVSdxasdPyCSc/Chr/et3qFL5BH2hlRT2cx6UAAAAAElFTkSuQmCC
</value>
</data>
<data name="ProcesoManual.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAABIVJREFUaEPV
ml2IVVUUxzcKo4wgQzj0koLomIUMBT3FiKAPIzjkixEyCOZDQQ8V+TQzMuPHi2+Kooii4kOIzxK9pUQE
lYovOlDTB0FKUVaIWvhR//+ZtY5r77vuPffMPZc5LvjN3R9r773+Z+9z79n7TBj+cKRjYH1gFzgMPgM/
g0fgieEncBkcAfRd6fVVFrewDLAl4Dvwn8Bg20k/BtfAR+A5r28PWF+Ut5m5ABsGDKgTHoDjYLk3hgLb
Cz6IyqRiKStKsDDvIIRl4Hdgr+5DcBtMC79ImfXRtM3fB3tAj/ZvxpkC9GkUIA6T4mA7TNOaXxR1EsIa
sA+8C14BvbZefBaDQUCfj8GfwBuD6StgrWlLUerjC8gysyrpWEQkYC7AesFb4GvgjXEXvAm4bGx5cwFZ
wexM0NG7OprvWIAFxvvoJkjH89KtBWSFT9db2onmKxVAYFxiBwG/nbyxSwnQNdeMygUosM3gHxnHo3AJ
bQHNroLmuylgQsZJx9Z0y5u4H/wKbMM/TJp0TQCs1f3XloCz4qjcAfyK5FWx5d24BzT4InwBsNdAqnaH
qdffCdZVKgA2Lv3asZulmwq4KA7q/Kl1FB+9SlUL6GGfbZI/BWRtpYPVgDcugyN8knzROiowXq2Gn/r5
YvZPCIeAThE5nzrWldk/IfwIrID1qWNdgL0NToJhyYdXga57fn4PFqQN6wBsm8Soy3wdCO9LgXLUa1wH
YPtNnGQ3CKeBnYFtXuM6ANsqMWqs50D4SjJaWMletRvAXpAYNdarIHtUYAHhM3gt1z9hbBKjxstNUaZE
Vc14DesE7FuJVWOOBEx7jeoEY5RYcwH8ozxLApRoBn7wGtUJGA/IGGs+A7+ZDI81ooelOsHYJEYVcAuE
L6RAGfAa1wHYyyZO8jkIJ4DOAD9HvcZ1AMYzVRvrMRDek4wWHvAa1wHYGYlRY30HZL9ufwMW8vhvyGs8
38C46eH9yjgJ9y8rtZJrawy8njasC7A3AK+6zsD1rDx1rCuwSxK8CpjIylPH+QLGJTLepG4I6NIh/4L+
rC5x5Pest5H2qHRfLH0yuMmknA9w16VOZ+BUXp848+zfKm2Fe7XmCkwFkFwE06ac8NhxVV6vCXGmAF1j
dr1pWvPRVaoCGAVo/4SHaRuBvhjROPZH7aJMsQCmKw+ewKwAHY+vnuzYN0B0JpV2UiQgu/O7AcwTYNPc
yAw2tIsyre+Bv0DXnpNg9h7w2O62izLFM0AR+XlplcCKZsBdunGm/Zv4E/CSbdspsCIBTDeIiDONS4hv
Hvm6yZ6bKjxYugA2gI4PAmBFS0iZitpFmXgG9phyPodw82Cvin4SHk3y0XYUrAINgmD8kRwAO8EBsCmp
b2cGNP30dyLpRAVEKqXuecCDJE9Amr4HZoC+6OY2kDsp68Pv9/zhEUaBHL9dlmbttAPphBV7bVkKjC9C
+C7BW1ZlGfPGKEOcSf6RohUwvnrisbzdZOvVbSfNPYj7DqIMbmFZYDzh5iEx37F9A/TFoA2am5EvAY/G
uQtc4fVVjpHwP3WFUQkgzFYnAAAAAElFTkSuQmCC
</value>
</data>
<data name="buttonErrorLog.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAlRJREFUeF7tmr/LT1Ecx79JDAaSRbJISWKQRRaJiUEPJcnCIMwGO0mkDLL4Ewwi
i0EWq90skWwiSXi9nzp1un3O/fF8Leee96tew/c+937rvJ/z/Zxfd2GMMcYYY4wxxhhjjDHGzIc9eA43
rH4yvezFX/gX3+AmND2soMJKOrQB1uNzdGgTUO16hmNCW4f78RJex6t4HLdhUwyFthPv4FfM70n+Rt1/
HpuhFNot/JFdG/It7sImiEJbi5/wIDbB/wjtHW7FZriNURBjbC6s3TilZuU2F5Z4gFEYQzYZ1kb8jlEg
fTYZljiKUSB9NhuWuIxRKCW7YWklcBbv4gldCNBkWKuFWXANo2Aio571EPN7bmCOwtJk+Atq9VA9Y3tY
6Wf4E7v3ptBSWOn6K6yeMTWsr2a9x+iZm5iHlTyFVbMZo16SHCrwR3DKKPsSq0eNiBo3FFZCvXRsaPrn
aCpTNSex27BuWBoN7+Nn/IB6JmdKaIexel5jalDUsy5i3midC5zGhBbwUc2K1EBTPTvwI5Z+htHyKYU2
dbdDU5lZcABLNUvFPWq8QtMGYvS3krPoYWPQvv4fjEKY4ixq2FiWDU0DQ/Wj5FSuYBTGGB9hU3SXO1NU
vdNmZTMsE5a8h82wbFhSz+t7mkDnjpqnRUFMsanQtuMLjIKI1On4Y+w7YW8CvVvxFL9hHkRSC+wnuA9F
6YS9qdCE5lNaHVzA9KLKMdyCXRzaGiiFplewTIEotDNoeshD0zKrmZdYlkEbktqEPLT6yRhjjDHGGGOM
McYYY4ypncXiHwDC8NaKd9TGAAAAAElFTkSuQmCC
</value>
</data>
<data name="buttonAbrirFolderMov.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAOxJREFUeF7t07Ftw0AQBVEWIbgsZ4IKdOa+nLgJa2NiAF4kDq15wIQH/At2S5Ik
SZIkSZLk//mc/k7qMV3KbfqZ6DOv6Hf6mC7ja6KPvLLv6RLOPMV990nt7FPcpz9NwynuU58mDTakRWMN
JW+KzsGQFo01pEVjDWnRWENaNHa1I/RmNS0au9oRerOaFo01pEVjDWnRWENaNNaQFo01pEVjDWnRWEPJ
m6JzMKRFYw1p0VhDWjTWkBaNXe0IvVlNi8audoTerKZFYw1p0VhDWjTWkBaNNaRFYw1p0VhDWjTWUJIk
SZIkSZIk17ZtT5MFz0WDR+g5AAAAAElFTkSuQmCC
</value>
</data>
<data name="buttonAbrirFolder.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAKxJREFUeF7t08FJBVEURMHBNIzN2IxGDOOHom/hzga/q6aZKjj75sK9AAAAAAAA
AG7s9fQ4ff2j99MtvZw+Tukof3VLb6d0jGe6pc9TOsYzAb+kV2k1IQ1vNSENbzUhDW81IQ1vNSENbzUh
DW81IQ1vNSENbzUhDW81IQ1vNSENbzUhDW81IQ1vNSENbzUhDW81IQ1vNSENbzUhDW81IQ1vBQAAAAAA
AAD8uK5vAw7ws5Gd92YAAAAASUVORK5CYII=
</value>
</data>
<data name="buttonAbrirExpediente.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAABK5JREFUeF7tm1+oFUUcxy8RhoQaYYpIFmGJhAa+SG+iiQgVPehDJD5E4oMgkvrg
QxGKhH+JQEQRoYeQRKKEyCTEjFBCRJEIRJQQMSLSCCVCtO/HewZ+DLPn7uyud/dcfx/4cM9ZOLuzszsz
v9/M3CHHcRzHcRzHcRzHcRzHaY5xcpqc2ZPPT0unB5WyVn4tL8n/5P2EN+VP8iP5qnykeEpSSWdlqnLK
eEVullPkmOVJyRvC25KqhCrelp/KyXJM8Ya8JlM3HbwrF8kX5Pie0+Vs+ZbkjbolU7/9Q66UA89jcpu8
J1M3infkcXlC9uMJ+a8Mv6OC7XnwgGTgGEhogkdlfFNWmtQcCY/3/haxQNrfHpb7ZPwwvpNce6CgwCel
vZGUO2RZ6P/sb/lO2LFTxpXGiDowlUYz/EraGyhyrizLh5Lf/CbXy7dlqlkGv5EjvbWd4GOZuoGUu2UO
z/b+8lDOyNQ5rbnnH3XelKmCF7lf5jJJfibjc/0tGTx+NMdwuewkE+R1aQvbzwvyeZnLXpk635cSnpE2
hPldEix3DjpwewMpqdBQqX/JKpH6S5K+i/NslOvkn71jsyTQNxKuhOvmDC6jAjdOiBAKmJLgMsRI82RO
hw80RfLNUDk2pyQ0OSXfe/BtGPsAKVun0iietK2cWIb9rbIuayTn2/PgW3/ih7hJdoZfZCgYiXH4vERS
cNKcJmCUJFwIbypx2FIZvz1kBa/J0zKUhTJ2gpdlKBTS3G5IRq2mIZxA+ioi/RCwkjKtkuSdpEdFCT5l
bZ0PZCgQFQXMIPw6/LFRGFXt2xzbL2dFyto6NgX6lgOCEGPG8MdGoe+yFZDrMdk6jH62UK/Ih8U5aa+V
K/FZq0yUtkA0CZLihwGdO/2ivV4VGRBaI+7wGRWZKWiahbJovj9XMoHWiCsMdkmG+yYpM1VU1s5VGDME
BLJAdN4E/UbGXMOMRyukKuxd+Y9kTow+jSW09+U7sirMrNrr1LHVNyzu9FlnhM+lPR6sulDBeftNFubY
aqcPNqxgPgyKhn9GuS8kq0G5bJGpcyIBc+p4bOthBdgOeTsHhM3hUl6VVSqN/NDmqiTXNPdl5lg/OxG4
2tQoJLjkebagKS/KKvsmGEgYVHjjQgfO3D2pWOo61k6kRnHHzzwXCbA9ViSzri/KJmBicaQ5OcraCeyw
T1hh37qRZKaBCs6dUEzBnFvqGtiZ6R1gci4UjKccL7qW9YisM3fGgkfqvNiJ5hiIZzc/kT+b7zmukFWJ
F3uDlK1TU9Rg59AJWDfI3GT5kJwqq1IUznRuEQTiZTZChzIdcZC+rE5QGQ8+wc4us0G8kPu9pHnaY0U2
0SmnuoHOLuQGGCVtgZnuKTM1Q3OqA3P9cUpWZnWpdXI2oyAj42JZJx5jFSnePjAwm1GArUY/SHsDKdkH
UfemWEE6L+15eVsHco/YSBvqWBarCudnG2fc3AdyQ12A5lm0ZZPRa77MhdUoAuV48QUHesumpd+m4Mvy
oFwt2S9BQs5NU9mEKqxFvi5Je9iqnqr8MbMp2EIz8W3nFfB/bKiB/+tMTei7npOMnsjnMd3cHMdxHMdx
HMdxHMdxnFFkaOh/A3Bij7cnWYUAAAAASUVORK5CYII=
</value>
</data>
<data name="buttonConfiguracion.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAwtJREFUeF7tmk/IDVEYh28SSf4kkiSSbGwkZaXsJCUpSVkIK0oSSUlC2dhYSMqC
hZQkJVlaSCGRJBtlYaEkJSkL4fnlm5pO79y5893B/Pk99XS/bnPPPe/5zj3zznvOwBhjjDHGGGOMMcYY
Y0yHmDPxWsYaXP3nz36yHm/jV5ynN0p4gL/wCe7B6dh5puJOfIYKPvMoDmMV5q+Xn/E8zsTOcgHTwOVH
HDZjLmL0uXfYaaKZkrkbIzSDNJuizxzHznMPo+Df4lrUwOknKnfhWYyu/4GLsPNsxGgAqnoTe8NrjAah
ipuxF2hNeoTRIFRRM6wTd0gFofQhQmvOc4wGYDJqpi7DIqZNvDaac/gBz2A+mFn4AqPAv+Mt1CK/Eufi
DFyKm/ASfsHosy8xP9OUBB/BN6i+NBrNLA1WFsxPvI/b8PrEe6l3cTmWsRCvYtTGHdyA+g4Nfva++lI0
2xvBdswHMkwN5jGcglXYh0opojYj1afGkj3vjeJhnCwHMGozUn1qJMOy+NQbOC5qI2o7Un1rHOqUsnj9
1KJOZ37DxTguWtPUVvQdeVXdWIeNRXdG3Z0+YRSAFu66KLoJaCCvYKvqZ6o+nMI0mDoX4egmo3+W0pJW
orwqDWgJ1kW0bm7B1qLySxpQnZXSBZi2vx9bSzRgdTIb0/bHSVf+O3sxDUizoi5WYNp+oxPVYfyLRV+P
XGn7rVv0nVaMiBPXivjRaBL44bsiUeZdpMs7oDujNmWzzo5SQFSl9W8VEMs2iBuB7pBRiVpl5KeYDzQz
X6LW4KmcrXq8bg5lJepXmE8jWlWiFmWbIHXsGGVqsFq/CVKGgriG0QBU8THOx15Qx+63tth6gzZho0Go
qga+82gdK0oLTuMOVI52Eg+hjgTooEp0vZ4sOk9U8pE60lS09a8TPdFnZGOz+LrQIbgocB2aKyLN7/Je
xs6iwE/ge0wDL5spOi+Wv14/04OonK3zKE/bill1Y5TnPSWkqk48RD05VH2k6gxKPEddh3px4tAYY4wx
xhhjjDHGGGP6wGDwGy4sWQnlp0d2AAAAAElFTkSuQmCC
</value>
</data>
<metadata name="fileSystemWatcher.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="$this.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAF0AAAA5CAIAAADbdrDYAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vAAADrwBlbxySQAAAHZJREFUaEPtx7EJADAMwLD8P+eqXtWCN9MTDFo0sycffuAHfuAHfuAHfuAHfuAH
fuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAHfuAH
fuAHfuAHfuDn2XMBkS5RGzcRhIgAAAAASUVORK5CYII=
</value>
</data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
AAAgAAAAAQAgAAAAAAAABAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAlpWVALW0swdWV1pIMTI0pycl
I+MoJBz7KCQd+ygmI+M0NDanXF1fSL+9vAefnp4AAAAAAAAAAAD///8AV1dXAH59fhg1NjeSKiMW7llA
EP+MYhT/o3IX/6JyF/+OZyP/XEUf/yskF+46Oz2RiIeHGGJhYQD///8AbGpqAIKBgRguLi6xQTAP/6d1
GP/Qkh7/1JQe/9OUHv/Ynjj/5LJo/9mhRf+lcxb/QjAQ/zQ0NLCOjY0Yd3Z1APf18wY3ODmSQjAQ/7yE
G//TlB7/0JIe/9CSHv/Qkh//3alX/+S0dP/frF7/1Zcm/7uDGv9CMRH/Pz9Bkf///wZdXWBKLCUY7ad1
GP/TlB7/0JIe/9CSHv/Qkh7/0JIe/9mhRf/js3H/47Nx/9ulTf/TlSD/pnQX/y8oG+1oaWtINzg6qFtB
Ef/Qkh7/0JIe/9CSHv/Qkh3/0JEd/9CRHP/RlCL/3KdS/+Ozcf/ism7/1548/9CSHf9bQRL/P0BCpiwq
KOSNYxX/05Qe/9CSHf/Qkh//05cq/9WbNP/UmjL/0ZUl/9OXKv/frWH/5LRz/9+sYP/VliT/i2IU/zIx
LuItKCH7o3MX/9KTHv/SlSb/26VO/+Gwaf/js3D/361k/92pWv/eq17/4bBq/+Kxbf/bplD/05Uh/6Jy
F/8yLib6Lioj+6Z3Jv/Ynz//3atf/+S3e//dq2D/26ZW/9mjT//YoEn/2KFL/9igSv/WnkP/1Jk2/9WZ
M/+kdib/My8o+jAuK+SRazD/4K1h/+Gzc//jtnn/1p1E/9OZOv/Umjv/1Jo7/9SaO//Umjv/1Jo8/9Sa
PP/YnT7/jmgp/zY0MuM+P0CpYk0t/9+tZv/jtXf/5bh//96tZf/bqFr/1p5F/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/15GH/9HSEmna2tsSjQvKO64lGb/6LyC/+W5gP/luYH/5bmA/+Cva//Wnkb/1Jo7/9Sa
PP/Umjz/15w9/6l7L/81LiTtdnZ4Sf///wZFRUaTTD8v/9CodP/ovIL/5bmA/+W5gP/luYH/4bJw/9ad
Q//Umjz/15w9/7+LNv9HNxz/TU1Okv///waDgoEAmpmZGT4+PbJNQC//uJVn/+W5gP/pvIL/6LuC/+i7
gP/cplH/1Jo7/6l7L/9INx3/RENDsaSjoxiNi4sA////AHNycgCamZgZSUlKkzcyK+9mUzv/m31X/7SR
ZP+0kWP/k284/15GH/83MCXvT09QkqKhoRh9e3sA////AAAAAAAAAAAAtrW0ANTS0Qdzc3RKSEhJqTk3
NuU5NTH8OTYy/Do4N+VLS02oeXl7SdrY1we9u7sAAAAAAAAAAADgBwAAwAMAAIABAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAMADAADgBwAAKAAAACAAAABAAAAAAQAgAAAA
AAAAEAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ezrAP//
/wS1s7IphYODa2VkY6xPTk3YQEBA8To5Ofw6Ojn8QkFB8VFQUNhoZ2erioiHarq4tyj///8E8O/uAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+HgAP//
/wOhoJ83Z2Zllzk5ON8YGBn7BQYI/wAAAf8BAQD/AwIA/wMCAP8BAQD/AAAB/wYHCf8aGhv7Pj093m5t
bJapp6Y1////A+fl5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIWD
ggC+vLsacXBviTMyMuoJCQr/AgEA/xwTBP9IMwz/cE8S/4phFv+WaRf/lmkX/4phFv9vTxL/RzIL/xsU
CP8CAQH/CwsM/zk4OOl6eXiIxsTDGZSSkQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPTz
8gAAAAAApKKhNlNSUcITExP+AgEA/y8hCP9/WhT/uIEc/86RHv/TlB//1JQe/9OUHv/TlB7/05Qe/9SW
JP/Wn0P/wpRO/35aGP8tIAf/AgEA/xYWF/5cW1vBrqyrNAAAAAD29fQAAAAAAAAAAAAAAAAAAAAAAAAA
AADw7+4AAAAAAJ2bmkFEQ0PZBgYH/xMOA/9xUBL/wYcd/9OUH//Skx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/TmC7/3apa/+Ozcv/grF3/1JUh/8CHHP9vThL/Eg0D/wkJCf9NTUzYp6alQB4dHQDx8O8AAAAAAAAA
AAAAAAAA+/r5AHh2dQCmpKQ2RURD2QQEBP8kGQb/mm0Y/9GTHv/Rkx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh3/0pYo/9+sYf/jtHL/47Ny/+CuZf/Slif/0ZMd/9GTHv+Yaxj/IhgG/wYGBv9PTk7XsbCvNIuJ
iQD49/YAAAAAAAAAAACwrq0AxsTDG1VUVMIGBwf/JBoG/6d1Gv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/YoEH/47Ny/+Ozcf/js3H/47Nw/9igQf/Qkh3/0JIe/9OUHv+kdBn/IhgG/wkK
Cv9hYGDA0M7MGbm3twAAAAAA0c7NAP///wJ2dHSKFBQV/xMNA/+bbRj/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9mjSf/jtHL/47Nx/+Ozcf/js3L/4K9m/9OYLv/Qkh3/0JIe/9OU
Hv+Yaxj/EgwC/xoaG/+DgoGI////As7MywCZl5YAqKalODc2NuoBAQD/clET/9GTHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zs1/+Kxbf/js3H/47Nx/+Ozcf/js3L/3apa/9GU
JP/Qkh3/0JIe/9GTHv9vTxL/AQEA/0FBQei0srE2qKalAP///wNubWyYCwsM/zAiCP/BiB3/0ZMe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/QkyD/26VQ/+Ozcv/js3H/47Nx/+Oz
cf/js3H/2qNK/9CSH//Qkh7/0ZMe/8CHHf8uIAf/DxAR/3x7epX///8CvLq5Kz8/Pt8BAQD/gFsU/9OU
H//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/SlSb/3qpb/+Oz
cv/js3H/47Nx/+Ozcf/isW3/1pw5/9CSHf/Qkh7/05Qf/35ZFP8BAQD/S0tK3cjGxSmOjIxuHBwd+x0U
BP+5ghz/0pMe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/Tlyr/3qte/+Ozcv/js3H/47Nx/+Ozcv/grWP/05cq/9CSHf/Skx7/t4Ec/xsSA/8kJCX7nJuaam9t
ba4HCAr/SjQM/86RHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JId/9CRHf/Qkh3/0JEd/9CR
Hf/Qkh3/0JIe/9CSHf/Tlyv/36xh/+Ozcv/js3H/47Nx/+Ozcv/bpVD/0JIf/9CSHv/OkR7/RzIM/wwN
Dv99fHurWFdX2gABAv9yURL/05Qf/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIe/9KVJv/VmzX/2KBB/9mi
R//YoUX/154+/9OYLf/Qkh//0JIf/9CSHv/Zokf/47Ny/+Ozcf/js3H/47Ny/9+tYf/RlCP/0JIe/9OU
H/9wTxL/AgME/2ZlZdhKSUnzAgEA/4xjFv/UlB7/0JIe/9CSHv/Qkh7/0JId/9KVJ//Zokf/361j/+Ky
bv/js3L/47Ny/+Ozcv/frWP/26VP/9ulTv/cqFX/3alY/+CuZv/js3H/47Nx/+Ozcf/jtHP/3ahX/9CT
IP/Qkh7/1JQe/4phFv8CAgH/V1ZW8UNCQv4EAwD/mGsX/9OUHv/Qkh3/0JId/9CSHf/UmTH/36xf/+Oz
cf/js3L/47Ny/+Ozcv/js3L/4bFr/9ynVf/isWz/47Ny/+O0c//jtHP/47Ry/+Ozcf/jsnD/4rFs/92q
Wv/TmC7/0JId/9CSHf/TlB7/lmkX/wQDAP9QT0/8REND/gQDAP+ZbR7/1Zcp/9KVKf/Sliz/1Jo2/+Gw
a//kt3r/5LZ5/+O1d//gr2n/365n/+KycP/erWT/2qVV/9qlVP/Zo07/2qVT/9umVv/bpVX/2qRQ/9ih
SP/WnT7/05cx/9KVK//SlSv/0pUq/9WXKv+Xax7/BAMA/1FQUPxNTEzzAgEB/5BpKv/XnDz/1p5F/96s
ZP/dqmH/5bmA/+W5gP/luYD/3Kpf/9WbP//Umz7/1p1E/9WdQ//Umjz/1Jo7/9SaO//Umjv/1Jo7/9Sa
O//Umjv/1Jo7/9SaO//Umjz/1Jo8/9SaPP/Umjz/2J09/41mKf8CAgH/WllZ8V5dXNsBAgP/dlYj/9ed
Pf/drGP/4bJx/96tZv/luYH/5bmB/+K0dv/WnUT/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/XnD3/clMh/wMEBf9sa2rYd3Z1rwkK
DP9MOBf/1Z1E/+KzdP/ZpFL/3Kle/+W5gf/luYH/4rNz/9WcQP/Umjv/1Jo8/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9KZPP9JNRX/Dw8R/4WE
g6uZl5ZvIiIi/B4VB//Ck0v/4rJu/9WcQf/frmn/5bmB/+W5gP/kuH7/3apf/9adQ//Umz3/16BJ/9ad
Q//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Wmzz/u4g2/xwU
B/8rKyv7paSja8bDwixKSkngAgEA/4ttRP/nuHv/365p/+S3ff/luYD/5bmA/+W5gP/luYD/4rR1/+Cw
bf/jtXj/2aRS/9SZOv/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ec
Pf+BXib/AgIB/1dWVd7OzMsp////A359fJkPEBD/Niwf/9WteP/nuoL/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYH/5bqB/+W5gf/hsXD/16BJ/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI84/y8iDv8VFhf/i4mIl////wKqqKcAtrSzOkVFROoDAgH/f2dI/+e6gf/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtXj/2qZX/9SaPf/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WbPf9zVCL/AwIB/1FQT+m/vbw3tLKxAMzKyQD///8Di4mIjB4eHv8WEgz/rIxh/+i8
gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/kuH3/26dZ/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/nXIu/xMNBf8lJSX/lpSUif///wLIxsUAAAAAAL27ugDRz84cbGtqxAwM
Df8qIhj/updp/+i8gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtnr/16BL/9Sa
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
Lf0DAwP/AAAA/wAAAP8OCgP/Py0M/31ZFf+tehv/xose/9CSHv/TlB//1JUf/9SVH//UlR//1JUf/9OU
H//Qkh7/xYoc/6x6H/+BYjD/PzAY/wwJAv8AAAD/AAAA/wUFBf83Njb8iIaGvcbDwjj///8A5+XkAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc2tkA////BLCu
rV5gX17jEhIR/wAAAP8AAAD/DQoD/1A5Dv+gcRr/yo4e/9OUH//SlB7/0ZIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHf/Qkh//1Zsz/9+rWv/ltG7/zpc2/51vGP9NNw7/DAkD/wAAAP8AAAD/GBcX/2xr
a+G4trVb////A9jW1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANbU
0gD///4FqKalck1MTPEGBgb/AAAA/wICAf81Jgr/mWwZ/82QHv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9GUJP/ao0r/4rFr/+O0cv/ism3/1Zox/9OUHf/MkB7/lmoY/zMk
Cv8CAQH/AAAA/woKCv9bWlnwsbCvbvf08wXS0M8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA1NLRAP///wSopqVySEdG9AMDA/8AAAD/CgcC/2JFEf/Ahx3/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0pUm/92pV//js3H/47Nx/+Ozcf/ism//1Zw3/9CR
Hf/Qkh7/05Qe/7+GHf9eQxH/CQYC/wAAAP8GBgX/VVRU87KxsG7///8Dz8zLAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADS0M8AAAAAALGvrl9PTk3xAwMD/wAAAP8RDAT/floV/86RHv/Rkx7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh//26VO/+Ozcv/js3H/47Nx/+Oz
cf/js3L/2aNK/9CSHf/Qkh7/0JIe/9KTHv/NkB7/e1cV/w8LBP8AAAD/BgYG/11cXPC6uLdbERAQAMrI
xwAAAAAAAAAAAAAAAAAAAAAAAAAAAMzKyQCurKsAwb++PGJhYeMHBwf/AAAA/xEMBP+IYRf/0ZMf/9GS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Tlyv/4a9p/+Oz
cv/js3H/47Nx/+Ozcf/js3L/361j/9KWJ//Qkh3/0JIe/9CSHv/Rkh7/0JIe/4ReFv8PCwT/AAAA/wsL
C/9ycXDhyMXEObu5uADCwL8AAAAAAAAAAAAAAAAAAAAAAMXDwgDb2dcXgX9+wBMTE/8AAAD/CgcC/39a
Ff/Rkx//0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CR
Hf/VnDj/47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9qkS//Qkh//0JIe/9CSHv/Qkh7/0JIe/9CS
Hv97VxX/CQYC/wAAAP8cHBv/kI+OvNrY1xXFw8IAAAAAAAAAAAAAAAAAxcPCAP///wCko6J+MjEx/gAA
AP8BAQH/Y0YR/86RHv/Rkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/VnDf/4rJv/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+Kxbf/WnTr/0JId/9CS
Hv/Qkh7/0JIe/9GSHv/NkB7/X0MR/wEBAf8AAAD/QD8//bGvrnoAAAAAwb++AAAAAAAAAAAAvry7AMrI
xy9jYmLjAwMD/wAAAP83Jwv/wYgd/9GTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Slif/4K5k/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/grmX/05cs/9CSHf/Qkh7/0JIe/9CSHv/Skx7/v4Yd/zQlCv8AAAD/BwcH/3RzcuDPzcsswb++AAAA
AADBv74A////ApuZmJIjIiL/AAAA/w4KA/+abRn/05Qe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/2KFE/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/3alY/9GUI//Qkh7/0JIe/9CSHv/Qkh7/05Qe/5dqGP8NCQP/AAAA/y8v
Lv+pp6aN////AcC+vQDAvr0Az83MKWRjYuICAgL/AAAA/1I6D//OkB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0ZQj/92p
WP/js3L/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9miR//Qkh7/0JIe/9CSHv/Qkh7/0JIe/82Q
Hv9ONw7/AAAA/wYGBv92dHTg09DPJsG/vgB/fn0AqaemdS8uLv8AAAD/DwsD/6JyGv/TlB7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JId/9OXK//frWL/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+KxbP/Vmzb/0JId/9CS
Hv/Qkh7/0JIe/9OUHv+ecBn/DQoD/wAAAP89PTz/tbSzcKOhoAD39fMOgYB/vQwMDP8AAAD/QS8M/8uP
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/UmTH/4K5m/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/frGH/0pYo/9CSHf/Qkh7/0JIe/9CSHv/Kjh7/PiwM/wAAAP8UFBT/kpGQuvLv7gzLycg4WVhY6gAA
AP8BAQH/gFsV/9OUH//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zo0/+CvZ//js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/26ZR/9CTIP/Qkh7/0JIe/9CSHv/TlB//fFgV/wAAAP8BAQH/bGtq6NHO
zTSzsbBxNzY2/AAAAP8UDgT/r3sb/9KTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9Wb
Nf/hr2j/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/4rJv/9adPP/Qkh3/0JIe/9CSHv/SlB7/rHkb/xIN
BP8AAAD/R0ZG/L68u2ycm5qmHh4d/wAAAP8zJAr/x4we/9GSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9CRHf/Qkh7/0JIf/9CTIP/Qkh//0JIe/9CSHf/QkR3/0JId/9CS
Hv/Qkh7/0JIe/9CSHf/Xnz//47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ry/92pWP/QkyD/0JIe/9CS
Hv/Rkh7/xYse/y8iCf8AAAD/Kioq/6upqKGJiIfODw4O/wAAAP9TOw//0JIf/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/RkyL/1Jkw/9efQf/apU7/3KhW/9ypWv/cqFj/26ZS/9mi
R//WnDn/0ZUl/9CRHP/Qkh3/0JId/9CRHf/UmTH/4rFt/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ny/96r
X//RkyL/0JIe/9CSHv/Qkh7/0JIe/084Dv8AAAD/GBcX/5qYmMp6eXjpBgYG/wAAAP9tTRP/05Qf/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0ZQk/9efPv/eqlz/4rFs/+Ozcf/jtHL/47Ry/+O0
cv/jtHL/47Rz/+KxbP/bplL/1p4+/9igQv/Zo0n/2qRN/9ulT//eqlz/47Nx/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Rz/9yoVv/Qkh//0JIe/9CSHv/Qkh7/05Qf/2lLEv8AAAD/DQ0M/4yKiuVvbm74AgIC/wAA
AP9/WhX/1JUf/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/VmjT/3qtd/+OzcP/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/4K9n/9ihRf/cqFf/4rFs/+Ozcv/js3L/47Ry/+O0cv/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/jtHL/4bFr/9WbNv/Qkh3/0JIe/9CSHv/Qkh7/1JUf/3tXFf8AAAD/BwcH/4KA
gPRraWn/AQEB/wEBAf+IYBb/1JQe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIf/9efP//hsGr/47Ny/+Oz
cf/js3H/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3L/26dT/92qW//ktHP/47Ny/+Ozcv/js3L/47Ny/+Oz
cv/js3L/47Ny/+Ozcv/js3L/47Nw/+KxbP/eq13/1Zw4/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/1JQe/4Nd
Ff8AAAD/BQUF/359fPxramr/AQEB/wEBAf+IYBj/1JUi/9GTIv/RkyP/0ZMj/9GTI//RkyT/16BC/+Kz
cf/ktXb/5LV1/+S1dv/ktXb/5LV2/+Kzc//is3L/47R1/+S2d//jtHX/2qVS/96tZ//dq2H/26ZV/9um
Vf/cqVz/3qtg/96rYf/eq2D/3ald/9ynV//apE//2KBF/9WbOf/Sliv/0ZQk/9GUJf/RlCT/0ZMj/9GT
I//RkyL/1JYi/4NdF/8AAAD/BQUF/399ffxycXH4AwMD/wAAAP+CXiT/15w5/9SZOf/UmTn/1Zs+/9eg
Sv/VnUL/4bJy/+W5gf/luYD/5bmA/+W5gP/kt3z/3Klf/9egS//XoEn/2aNQ/9yqX//cqV//1ZxB/9Wc
Qf/Umj3/1Jo7/9SaO//Umjz/1Jo9/9SaPf/Umj3/1Jo8/9SaO//UmTr/1Jk6/9SZOv/Umjv/1Jo7/9Sa
O//Umjr/1Jk6/9SZOf/UmTn/15w5/31bI/8AAAD/CAgI/4SDgvV/fX3pCAgI/wAAAP9xUyP/15w9/9Sa
PP/Umz7/3ati/+O1eP/aplj/5Ld8/+W5gP/luYD/5bmA/+W5gP/dq2H/1Jo8/9SaO//Umjv/1Jo7/9Sa
O//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/2xPIP8AAAD/Dg4O/5COjuWQjo3PERER/wAA
AP9WPxv/1Zs9/9SaO//Zo1D/5Lh+/+Gycv/bp1r/5bl//+W5gP/luYD/5bmA/+O1eP/Wn0f/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/1E7Gf8AAAD/Gxsb/5+e
ncqkoqGnIyMj/wAAAP81JxH/y5Q7/9WbPv/fr2r/5bmA/9qmV//ZpFP/5bl//+W5gP/luYD/5bmB/+Cw
bf/Umz7/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/yZM6/zEk
D/8AAAD/MTAw/7GvrqK5t7ZyQD8//QAAAP8VEAj/s4I0/9mgR//jtnr/4LBt/9WbP//Yo1D/5Lh//+W5
gP/luYD/5bmB/+Gycf/Vm0D/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/WnD3/sIAz/xMOBv8AAAD/UVBP/MLAv23OzMs5ZmVk6wAAAP8CAQH/hGEn/92nVf/kt33/2KNQ/9OZ
Of/bp1r/5bmA/+W5gP/luYD/5bmA/+S4fv/cqV3/1Zs//9SZO//Umjv/1Jk7/9WdQv/VnED/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/gF0m/wEAAP8DAwP/eHZ26dHOzTXs6egPj46NvxISEv8AAAD/RDIV/9em
X//luH7/2KNQ/9aeR//hsnL/5bmB/+W5gP/luYD/5bmA/+W5gP/luH//369r/9mkUv/Xn0j/2KJP/+Cw
bf/Zo1H/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Oljv/QC8U/wAAAP8cGxv/n52cu+Ti4A2amJcAtLKxdjw7
O/8AAAD/EAwG/7GNW//ovIL/47V4/+K1d//luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W4
f//kt3v/5Lh+/+W5gf/bqFz/1Jk7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ecPf+jdzD/DgoF/wAAAP9MS0v/vbu6crKw
rwDBv74A0c7NK3d1deMGBgb/AAAA/11LNf/jt3//5bmB/+W5gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/itHb/2KFM/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9GYPP9RPBn/AAAA/wsL
C/+HhoXh0c/OKMG/vgDAvr0A////AqupqZQxMTD/AAAA/xEOCv+si2H/6LyC/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYH/47V5/9unWv/VnED/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/5tx
Lv8OCgX/AAAA/0A/P/+1tLOQ////AcC+vQDAvr0AwsC/AM3LyjF6eXjkCQkJ/wAAAP8/MyT/1q14/+a6
gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W5
gP/fr2r/1p5F/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI44/zcoEf8AAAD/Dw8P/4qIh+LOzMsuwsC/AAAAAAAAAAAAwb++AP///wG1s7KBRkZF/gAA
AP8CAgH/cFtA/+O4f//muYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYH/4LFv/9aeRf/Umjv/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WaPP/SmDz/Y0ke/wEBAf8AAAD/VlVU/r27unz///8AwL69AAAAAAAAAAAAAAAAAMTC
wQDU0tEYmZiXwiIiIf8AAAD/DAoH/5B1Uv/nuoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/9+uav/Vmz//1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPf+AXif/CgcE/wAAAP8tLSz/paSjv9HPzhbDwcAAAAAAAAAA
AAAAAAAAAAAAAMC+vQC/vbwAycbFP39+feUQEBD/AAAA/xURDf+bflj/57qB/+a5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W4f//apVX/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/1Zs9/4plKf8RDQb/AAAA/xgXF/+NjIviysjHO8PB
wADAvr0AAAAAAAAAAAAAAAAAAAAAAAAAAADEwsEA////AMC+vWJtbGvyCgoK/wAAAP8VEQ3/kXZT/+S4
gP/muoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W6
gf/fr2r/1Jo9/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPP/SmDz/gV4n/xENBv8AAAD/Dw8P/3t6
efHEwsFefnx8AMG/vgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx8XEAOHf3QS7ubh2aGZm9goK
Cv8AAAD/DQsI/3JdQf/WrXj/6LyC/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gf/hsnL/1ZtA/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/8SPOP9jSR7/CgcE/wAA
AP8PDw//dXRz9MC+vXLW1NMDxMLBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMrH
xgDa2NYGvLq5dnBvbvISERH/AAAA/wMDAv9ANCX/rYxi/+O3f//ou4L/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/hsnL/1ZxA/9SaPP/Umjz/1Jo8/9ecPf/RmDz/nHIu/zco
Ef8CAgH/AAAA/xgYGP99e3vxwL69ctPR0AXHxMMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADMyskA3NrZBMG/vmKEg4LlJiYl/wAAAP8AAAD/EQ4K/1xLNP+zkWX/4LV9/+m8
gv/nu4H/5rqA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/hsXD/1Zw//9acPP/XnD3/zpY7/6R3
MP9SPBn/DgoF/wAAAP8BAQH/Ly4u/4+OjePEwsFf09HQBMjGxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0M7NAPn39QHJx8Y+oJ6dw09OTv0MDAz/AAAA/wAA
AP8RDgr/STsq/45zUP/BnGz/27F7/+W5gP/ovIL/6byC/+m8gv/pvIL/6byC/+m8g//gsG3/ypQ8/7GB
NP+BXif/QTAU/w4LBf8AAAD/AAAA/xAQEP9aWVj9p6alwMrIxzzl4+IBysjHAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN3b2gDHxcQA0tDPGLq4
t4CFhIPlPDs7/woKCv8AAAD/AAAA/wICAf8WEg3/OC0g/1tKNP94YUT/jHFP/5d6Vf+Ye1b/jnNR/3tk
R/9ZRiz/MiUQ/xQOB/8CAgH/AAAA/wAAAP8NDQ3/REND/46MjOS+vLt+0M7NFsrIxwDQzs0AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA2dfWAOfk4wLOzMowtLKxlIaEhORLS0r+Gxsb/wQEBP8AAAD/AAAA/wAAAP8AAAD/AAAA/wEB
Af8CAQH/AAAA/wAAAP8AAAD/AAAA/wAAAP8FBQX/Hx8f/1JRUf6Ni4vjuLa1ks3Lyi7d2tkC09HQAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc2tkA5OLhA9DOzSq9u7p2oJ6ev3t6eetVVFP9NTQ0/x8f
Hv8SEhL/CwsL/wgICP8JCAj/CwsL/xMTE/8hICD/ODc3/1lYV/yAfn7rpaOivsC+vXXQzswp3tzbA9jV
1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX08wD///8A3tvaDtDN
zDnDwcBytbOyp6Wko9CYlpXqjo2M+YqIiP+KiYj/j46N+JqYl+mnpqXPtrW0psTCwXHQzcw429nYDgAA
AADy8O8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD//wAA//8AAP/4AAAf/wAA/+AAAAf/AAD/wAAAA/8AAP8AAAAB/wAA/gAAAAB/AAD8AAAAAD8AAPgA
AAAAHwAA+AAAAAAfAADwAAAAAA8AAOAAAAAABwAA4AAAAAAHAADAAAAAAAMAAIAAAAAAAQAAgAAAAAAB
AACAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAwAAAAAADAADAAAAAAAcAAOAA
AAAABwAA8AAAAAAPAAD4AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/8AAAAP/
AAD/4AAAB/8AAP/4AAAf/wAA//8AAP//AAA=
</value>
</data>
<metadata name="imageList1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>169, 17</value>
</metadata>
<metadata name="mynotifyicon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>280, 17</value>
</metadata>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>405, 17</value>
</metadata>
<data name="mynotifyicon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
E/9FpkD/6vXq///////6/fr/hMSB/xySFv8bkhX/HJIW/xySFv8ckhb+AAAAAGZmZgBjY2Mw39/f7tbW
1uBLS0shTk5OAAAAAAAAAAAAAAAAAAAAAAAbkhUAG5IVWBySFv0ckhb/HJIW/xySFv8ckhb/HJIW/xqR
FP8bkhX/HJIW/yCUGv+w2a7////////////x+PD/eb51/x6TGP8ckhb/HJIW/xySFvgAAAAAoKCgAIeH
h1Hs7Oz/wcHBuQAAAAgbGxsAAAAAAAAAAAAEBAQAAAAAAUk3SRlCgz92HpIY+xySFv8ckhb/HJIW/xyS
Fv8ckhb/HJIW/xySFv8ckhb/GZAT/2CyW//2+/b////////////C4sH/JJYe/xySFv8ckhb/HJIW4gAA
AADd3d0AmZmZbfDw8P+wsLCZ////ABMTEwAAAAAAhoaGAEdHRxqYmJiBzMvM2Mvbyvg3njH/GpEU/xyS
Fv8ckhb/HJIW/xySFv8ckhb/HJIW/xySFv8bkhX/J5ch/8Dhvv///////////6fVpf8ckhb/HJIW/xyS
Fv8ckha0AAAAAP///wCkpKR68fHx/6ampob///8ABQUFAJycnABfX18tu7u7wfLy8v7/////+v36/2a2
Yf8YkBL/HJIW/xySFv8ckhb/HJIW/xySFv8ckhb/HJIW/xySFv8ZkBP/Y7Rf//b79f//////ms6X/xqR
FP8ckhb/HJIW+xySFmwAAAAA////AKWlpXvx8fH/pKSkgv///wAICAgFJycnHLq6urz6+vr///////b2
9v7o5+j4nceb/SCTGv8ckhb/HJIW/xySFv8ckhb/HJIW/xySFv8ckhb/HJIW/xuSFf8jlR3/r9it////
//+bz5j/GpEU/xySFv8ckhbUHJIWIgAAAADy8vIAnZ2dc/Dw8P+pqamO////AJKSknOSkpLK5OTk9///
///4+Pj/sbGxrW5sbkZne2ZgIY4czBySFv8ckhb/HJIW/xySFv8ckhb/HJIW/xySFv8ckhb/HJIW/xqR
FP9DpT7/4fHg/6fVpf8bkhX/HJIW/RySFnQckhYAAAAAALS0tACPj49b7u7u/7m5uaVJSUkv0dHR46qq
qvfv7+/+/////97e3utnZ2c0dHV0ABySFgAckhZCHJIW6BySFv8ckhb/HJIW/xySFv8ckhb/HJIW/xyS
Fv8ckhb/HJIW/xqRFP9ntmP/n9Gd/x+UGf8ckha3HJIWExySFgAAAAAAenp6AHJycjzk5OT2y8vLyYqK
ioPS0tLphYWFo/Ly8vz/////0tLS3T8/Px0/Pz8AAAAAAAs8CQIckhZjHJIW8BySFv8ckhb/HJIW/xyS
Fv8ckhb/HJIW/xySFv8ckhb/HJIW/x6TGP84oDP/Jo8h4x2FGDIcgBcAHJIWAAAAAABCQkIAPDw8GdHR
0dfd3d3ypKSk27CwsLKUlJSL9/f3///////v7+/7oqKik0ZGRidra2tLbm5uVwA2AAIckhZcHJIW3xyS
Fv8ckhb/HJIW/xySFv8ckhb/HJIW/xySFv8ckhb/HZMX/1qvVv+Bn3+uAAAABRshGwAAAAAAAAAAABMT
EwAAAAACsLCwn/Hx8f/b29v/2dnZ6t7e3u3////////////////z8/P91dXV5tzc3PKysrKuAAAABgD/
AAAckhYuHJIWmRySFuMckhb8HJIW/xySFv8ckhb/HJIW9xmNE9J1r3Pr4eng/5mXmW77+vsADwcQAAAA
AAAAAAAAAAAAAKenpwCBgYFR5+fn+P///////////////////////////////////////////////+Pj
4/GOjo50Hh4eCzlYNwAckhYEHJIWJhySFlcckhZ5HJIWgRySFnAYkxFDUHJPSt3c3evY2NjkWlpaKWRk
ZAAAAAAAAAAAAAAAAAAAAAAAPj4+ACEhIRC/v7/A/v7+////////////////////////////////////
/////////////+np6fqjo6OWKCgoD0dHRwAAAAAAAAAAAAAAAAAAAAAAMi4yAAAAAAeurq+f8fHx/6io
qJUAAAACGRkZAAAAAAAAAAAAAAAAAAAAAAABAQEA0tLSAIKCglbk5OT1////////////////////////
/////////////////////////////+zs7PyZmZl/AAAAARkZGQAAAAAAAAAAAA4ODgD///8AhoaGYObm
5vfU1NTiYGBgL3V1dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyMjIAAAAACKqqqp319fX/////////
/////////////////////////////////////////////9TU1OJbW1soY2NjAAAAAAAHBwcA////AHFx
cUXV1dXi6urq/JKSknD///8AERERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoaGgATU1NH76+
vsT6+vr/////////////////////////////////////////////////7Ozs+4aGhlCdnZ0AGRkZAAAA
AAJ2dnZP0NDQ3vHx8f+pqameFhYWDD8/PwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAChoaEAYGBgL8LCwsv5+fn////////////////////////////////////////////u7u79jY2NVcrK
ygBBQUEdl5eXg93d3e3y8vL/r6+vqj8/PxdeXl4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACwsLAAWlpaKbS0tLbu7u78/////////////////////////////////////+vr
6/t/f3+BmJiYf8rKytTy8vL+5ubm9qKiopU9PT0VX19fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiYmIAODg4E5KSknnPz8/f8vLy/v7+/v//////////////
////////+fn5/+Xl5fvz8/P/7e3t/MTExM+BgYFdFBQUCDU1NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCQkAAAAAAVNTUyaTk5N3vLy8v9bW
1ubk5OT16urq+enp6fni4uLz09PT4LW1tbKHh4dkQEBAGf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAXFxcOUFBQLnBwcE1+fn5bfHx8WWtra0dFRUUmCQkJCSMjIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AD//wAAP/wAAB/4AAAP8BAAB+BgAAfg4AADwcAAA4PAAAOHw
AADh8AAAw/AAAMPwAADDwAAAx4AAAMcAAADEAAAAxAAAAcAMAAHADAADwAAAA8AAgAfgAEAH4AA/B/AA
Hw/wAB4f+AAYH/wAED/+AAB//wAA//+AA///8A//
</value>
</data>
</root>

179
Forms/Login.Designer.cs generated Normal file
View File

@@ -0,0 +1,179 @@
using EFCDesk.Classes;
namespace EFCDesk
{
partial class Login
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Login));
pictureBox1 = new PictureBox();
label2 = new Label();
textBoxContrasenia = new TextBoxConPaste();
buttonInicioSesion = new Button();
label3 = new Label();
buttonOpciones = new Button();
label1 = new Label();
txtUsuario = new TextBox();
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
SuspendLayout();
//
// pictureBox1
//
pictureBox1.Image = (Image)resources.GetObject("pictureBox1.Image");
pictureBox1.Location = new Point(12, 15);
pictureBox1.Margin = new Padding(4);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new Size(102, 118);
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.TabIndex = 0;
pictureBox1.TabStop = false;
//
// label2
//
label2.AutoSize = true;
label2.Font = new Font("Century Gothic", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
label2.Location = new Point(126, 77);
label2.Margin = new Padding(4, 0, 4, 0);
label2.Name = "label2";
label2.Size = new Size(107, 21);
label2.TabIndex = 3;
label2.Text = "Contraseña:";
//
// textBoxContrasenia
//
textBoxContrasenia.Location = new Point(126, 104);
textBoxContrasenia.Margin = new Padding(4);
textBoxContrasenia.Name = "textBoxContrasenia";
textBoxContrasenia.Size = new Size(247, 27);
textBoxContrasenia.TabIndex = 4;
textBoxContrasenia.TextAlign = HorizontalAlignment.Center;
textBoxContrasenia.UseSystemPasswordChar = true;
textBoxContrasenia.TextChanged += textBoxContrasenia_TextChanged;
textBoxContrasenia.KeyDown += textBoxContrasenia_KeyDown;
//
// buttonInicioSesion
//
buttonInicioSesion.BackgroundImage = (Image)resources.GetObject("buttonInicioSesion.BackgroundImage");
buttonInicioSesion.Cursor = Cursors.Hand;
buttonInicioSesion.FlatStyle = FlatStyle.Flat;
buttonInicioSesion.ForeColor = Color.White;
buttonInicioSesion.Location = new Point(15, 150);
buttonInicioSesion.Margin = new Padding(4);
buttonInicioSesion.Name = "buttonInicioSesion";
buttonInicioSesion.Size = new Size(357, 38);
buttonInicioSesion.TabIndex = 5;
buttonInicioSesion.Text = "Iniciar Sesión";
buttonInicioSesion.UseVisualStyleBackColor = true;
buttonInicioSesion.Click += buttonInicioSesion_Click;
//
// label3
//
label3.AutoSize = true;
label3.Font = new Font("Century Gothic", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
label3.ForeColor = SystemColors.AppWorkspace;
label3.Location = new Point(12, 201);
label3.Name = "label3";
label3.Size = new Size(77, 17);
label3.TabIndex = 6;
label3.Text = "Aduanasoft";
//
// buttonOpciones
//
buttonOpciones.Cursor = Cursors.Hand;
buttonOpciones.FlatAppearance.BorderSize = 0;
buttonOpciones.FlatStyle = FlatStyle.Flat;
buttonOpciones.Font = new Font("Century Gothic", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
buttonOpciones.ForeColor = Color.DodgerBlue;
buttonOpciones.Location = new Point(280, 191);
buttonOpciones.Margin = new Padding(3, 4, 3, 4);
buttonOpciones.Name = "buttonOpciones";
buttonOpciones.Size = new Size(90, 29);
buttonOpciones.TabIndex = 7;
buttonOpciones.Text = "Opciones";
buttonOpciones.UseVisualStyleBackColor = true;
buttonOpciones.Click += buttonOpciones_Click;
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Century Gothic", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
label1.Location = new Point(126, 15);
label1.Margin = new Padding(4, 0, 4, 0);
label1.Name = "label1";
label1.Size = new Size(70, 21);
label1.TabIndex = 8;
label1.Text = "Usuario:";
//
// txtUsuario
//
txtUsuario.Location = new Point(126, 39);
txtUsuario.Name = "txtUsuario";
txtUsuario.Size = new Size(247, 27);
txtUsuario.TabIndex = 9;
txtUsuario.TextAlign = HorizontalAlignment.Center;
//
// Login
//
AutoScaleDimensions = new SizeF(9F, 19F);
AutoScaleMode = AutoScaleMode.Font;
BackColor = Color.White;
ClientSize = new Size(379, 226);
Controls.Add(txtUsuario);
Controls.Add(label1);
Controls.Add(buttonOpciones);
Controls.Add(label3);
Controls.Add(buttonInicioSesion);
Controls.Add(textBoxContrasenia);
Controls.Add(label2);
Controls.Add(pictureBox1);
Font = new Font("Century Gothic", 12F, FontStyle.Bold, GraphicsUnit.Point, 0);
FormBorderStyle = FormBorderStyle.FixedDialog;
Icon = (Icon)resources.GetObject("$this.Icon");
Margin = new Padding(4);
MaximizeBox = false;
Name = "Login";
StartPosition = FormStartPosition.CenterScreen;
Text = "Expediente Electrónico";
Shown += Login_Shown;
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private PictureBox pictureBox1;
private Label label2;
private TextBoxConPaste textBoxContrasenia;
private Button buttonInicioSesion;
private Label label3;
private Button buttonOpciones;
private Label label1;
private TextBox txtUsuario;
}
}

321
Forms/Login.cs Normal file
View File

@@ -0,0 +1,321 @@
using EFCDesk.Classes;
using EFCDesk.Forms;
using System.Data.SQLite;
using System.Xml;
using System.Xml.Linq;
using static EFCDesk.Program;
namespace EFCDesk
{
public partial class Login : Form
{
private bool ExisteConfiguracionExpediente()
{
using (var connection = sqliteHelper.GetConnection())
{
connection.Open();
// Verificar si hay registros en la tabla ArchivosProcesados
string checkQuery = "SELECT COUNT(1) FROM Configuracion;";
int registrosExistentes;
using (var command = new SQLiteCommand(checkQuery, connection))
{
registrosExistentes = Convert.ToInt32(command.ExecuteScalar());
}
// Si hay registros, no realizar el escaneo inicial
if (registrosExistentes == 0)
{
return false;
}
}
return true;
}
private void VistaConfiguracionExpediente()
{
//FormCargarInformacion info = new FormCargarInformacion();
//info.Show();
MessageBox.Show("Debe capturar la configuraci<63>n inicial para el env<6E>o de los archivos a expediente electr<74>nico", "Configuraci<63>n", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Hide();
FormConfiguracionExpediente configExp = new FormConfiguracionExpediente();
configExp.ShowDialog();
try
{
configExp.Dispose();
this.Visible = true;
}
catch (Exception ex) { }
}
private static SQLiteHelper sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
public Login()
{
InitializeComponent();
}
private void buttonOpciones_Click(object sender, EventArgs e)
{
FormConfiguracionJSON configuracion = new FormConfiguracionJSON();
configuracion.ShowDialog();
}
private async void buttonInicioSesion_Click(object sender, EventArgs e)
{
//var config = ConfiguracionJSON.LoadFromJson();
//Cursor.Current = Cursors.WaitCursor;
//string user = textBoxUsuario.Text.Trim();
//string pass = textBoxContrasenia.Text.Trim();
//if (user == "")
//{
// MessageBox.Show("Debe ingresar el usuario");
// textBoxUsuario.Focus();
// return;
//}
//if (pass == "")
//{
// MessageBox.Show("Debe ingresar la contrase<73>a");
// textBoxContrasenia.Focus();
// return;
//}
//if ((user == "admin") && (pass == "teamweb"))
//{
// //frmAdmin configuracion = new frmAdmin();
// //configuracion.ShowDialog();
//}
//else
//{
// try
// {
// string crypUser = General.CodificarBase64(user);
// string crypPass = General.CodificarBase64(pass);
// string cadena = crypUser + "|" + crypPass;
// string liga = config.DominioExp + "/api/auth/" + cadena;
// dynamic root = config.Consulta(liga);
// if (root is XmlElement)
// {
// string id = "";
// string mensaje = "";
// XmlNodeList nodes = root.SelectNodes("/xml/item");
// foreach (XmlNode node in nodes)
// {
// id = node["login"].InnerText;
// mensaje = node["mensaje"].InnerText;
// }
// if (id != "0")
// {
// //this.Hide();
// /**/
// /*
// SplashScreenEspera Espera = new SplashScreenEspera();
// Espera.ShowDialog();
// */
// /*
// Globales.DirRootExpediente = MyClass.configuracion("folder");
// if (!Directory.Exists(Globales.DirRootExpediente))
// {
// string Folder = "C:" + Path.DirectorySeparatorChar + "EFC";
// MyClass.configuracion("folder", Folder);
// Globales.DirRootExpediente = Folder;
// Directory.CreateDirectory(Globales.DirRootExpediente);
// }
// */
// /*actualizar config*/
// config.UsuarioExp = user;
// config.PasswordExp = pass;
// int.TryParse(id, out int idInt);
// config.idUsuarioExp = idInt;
// config.SaveToJson();
// this.Hide();
// FormCargarInformacion info = new FormCargarInformacion();
// info.Show();
// //Application.Run(new frmMain());
// using (var connection = sqliteHelper.GetConnection())
// {
// connection.Open();
// // Verificar si hay registros en la tabla ArchivosProcesados
// string checkQuery = "SELECT COUNT(1) FROM Configuracion;";
// int registrosExistentes;
// using (var command = new SQLiteCommand(checkQuery, connection))
// {
// registrosExistentes = Convert.ToInt32(command.ExecuteScalar());
// }
// // Si hay registros, no realizar el escaneo inicial
// if (registrosExistentes == 0)
// {
// FormConfiguracionExpediente configExp = new FormConfiguracionExpediente();
// configExp.Show();
// }
// else
// {
// FormMain Main = new FormMain();
// Main.Show();
// }
// }
// }
// else
// {
// MessageBox.Show(mensaje);
// return;
// }
// }
// else if (root is Exception)
// {
// MessageBox.Show(root.ToString());
// return;
// }
// else
// {
// MessageBox.Show("Error: No se hizo el login correctamente. Contacte a su proveedor");
// return;
// }
// }
// catch (Exception ex)
// {
// MessageBox.Show(ex.ToString());
// }
//}
//cursor.current = cursors.default;
if (!ExisteConfiguracionExpediente())
{
VistaConfiguracionExpediente();
return;
}
string user = txtUsuario.Text.Trim();
string pass = textBoxContrasenia.Text.Trim();
bool EsvalidoDatos = Utils.Util.StringsValidos(user, pass);
if(!EsvalidoDatos)
{
MessageBox.Show("Debe ingresar el usuario y contrase<73>a", "Informaci<63>n", MessageBoxButtons.OK);
return;
}
var configJson = ConfiguracionJSON.LoadFromJson();
Cursor.Current = Cursors.WaitCursor;
try
{
configJson.UsuarioExp = user;
configJson.PasswordExp = pass;
if (Properties.Settings.Default.urlEFC.ToString() == "")
{
MessageBox.Show("No se ha configurado el dominio de expediente electronico", "Informaci<63>n", MessageBoxButtons.OK);
return;
}
if (configJson.FolderExpediente == null)
{
MessageBox.Show("No se ha configurado la ruta de expediente(s)", "Informaci<63>n", MessageBoxButtons.OK);
return;
}
bool Esvalido = Utils.Util.StringsValidos(configJson.UsuarioExp, configJson.PasswordExp);
if (!Esvalido)
{
MessageBox.Show("No se ha configurado el usuario o contrase<73>a de expediente electronico", "Informaci<63>n", MessageBoxButtons.OK);
return;
}
else
{
textBoxContrasenia.Text = configJson.PasswordExp ?? String.Empty;
}
if (string.IsNullOrWhiteSpace(textBoxContrasenia.Text))
{
MessageBox.Show("Ingresa el Id de usuario", "Informaci<63>n", MessageBoxButtons.OK);
textBoxContrasenia.Focus();
return;
}
configJson.SaveToJson();
bool EsLoginValido = await Utils.Util.Login(txtUsuario.Text, textBoxContrasenia.Text);
if (!EsLoginValido)
{
MessageBox.Show("No se pudo hacer login.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//string token = textBoxContrasenia.Text;
//using var apiClient = new ApiClient(timeout: TimeSpan.FromSeconds(10), maxRetries: 3, retryDelay: TimeSpan.FromSeconds(2));
//string response = await apiClient.GetAsync(url: config.DominioExp+ "/api/v1/customs/pedimentos/", token);
Cursor.Current = Cursors.Default;
//SecureDataHandler.SaveData(textBoxContrasenia.Text);
//textBoxContrasenia.Text = string.Empty;
this.Hide();
FormMain Main = new FormMain(Globales.gMonitor);
Main.Show();
}
catch (ApiException ex)
{
MessageBox.Show($"API respondi<64> con error: {ex.Message} (C<>digo {ex.StatusCode})");
}
catch (Exception ex)
{
MessageBox.Show($"Error en la petici<63>n: {ex.Message}");
}
Cursor.Current = Cursors.Default;
}
private void textBoxContrasenia_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
//buttonInicioSesion_Click(this, new EventArgs());
buttonInicioSesion.PerformClick();
}
}
private void Login_Shown(object sender, EventArgs e)
{
if (!ExisteConfiguracionExpediente())
{
VistaConfiguracionExpediente();
}
}
private void textBoxContrasenia_TextChanged(object sender, EventArgs e)
{
}
}
}

31197
Forms/Login.resx Normal file

File diff suppressed because it is too large Load Diff

195
Forms/RegistroExpirado.Designer.cs generated Normal file
View File

@@ -0,0 +1,195 @@
namespace EFCDesk.Forms
{
partial class RegistroExpirado
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RegistroExpirado));
label1 = new Label();
pictureBox1 = new PictureBox();
label2 = new Label();
label3 = new Label();
label4 = new Label();
label5 = new Label();
label6 = new Label();
linkLabel1 = new LinkLabel();
linkLabel2 = new LinkLabel();
panel1 = new Panel();
panel2 = new Panel();
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
SuspendLayout();
//
// label1
//
label1.AutoSize = true;
label1.Font = new Font("Century Gothic", 15.75F, FontStyle.Bold, GraphicsUnit.Point, 0);
label1.Location = new Point(207, 22);
label1.Name = "label1";
label1.Size = new Size(187, 25);
label1.TabIndex = 0;
label1.Text = "Registro Expirado";
//
// pictureBox1
//
pictureBox1.Image = Properties.Resources.CUATRO;
pictureBox1.Location = new Point(12, 54);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new Size(181, 146);
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.TabIndex = 1;
pictureBox1.TabStop = false;
//
// label2
//
label2.AutoSize = true;
label2.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
label2.Location = new Point(207, 63);
label2.Name = "label2";
label2.Size = new Size(317, 16);
label2.TabIndex = 2;
label2.Text = " Lo sentimos, el periodo de registro se encuentra expirado.";
//
// label3
//
label3.AutoSize = true;
label3.Font = new Font("Century Gothic", 8F, FontStyle.Regular, GraphicsUnit.Point, 0);
label3.Location = new Point(209, 79);
label3.Name = "label3";
label3.Size = new Size(201, 16);
label3.TabIndex = 3;
label3.Text = "Favor de comunicarse con nosotros.";
//
// label4
//
label4.AutoSize = true;
label4.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
label4.Location = new Point(209, 113);
label4.Name = "label4";
label4.Size = new Size(119, 16);
label4.TabIndex = 4;
label4.Text = " Ing. Eduardo Ramos";
//
// label5
//
label5.AutoSize = true;
label5.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
label5.Location = new Point(212, 125);
label5.Name = "label5";
label5.Size = new Size(70, 16);
label5.TabIndex = 5;
label5.Text = "Aduanasoft";
//
// label6
//
label6.AutoSize = true;
label6.Font = new Font("Century Gothic", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 0);
label6.Location = new Point(207, 168);
label6.Name = "label6";
label6.Size = new Size(94, 16);
label6.TabIndex = 6;
label6.Text = "Soporte Técnico";
//
// linkLabel1
//
linkLabel1.AutoSize = true;
linkLabel1.Location = new Point(207, 183);
linkLabel1.Name = "linkLabel1";
linkLabel1.Size = new Size(207, 17);
linkLabel1.TabIndex = 7;
linkLabel1.TabStop = true;
linkLabel1.Text = "soportesitar@aduanasoft.com.mx";
linkLabel1.LinkClicked += linkLabel1_LinkClicked;
//
// linkLabel2
//
linkLabel2.AutoSize = true;
linkLabel2.Location = new Point(207, 200);
linkLabel2.Name = "linkLabel2";
linkLabel2.Size = new Size(184, 17);
linkLabel2.TabIndex = 8;
linkLabel2.TabStop = true;
linkLabel2.Text = "bodega@aduanasoft.com.mx";
linkLabel2.LinkClicked += linkLabel2_LinkClicked;
//
// panel1
//
panel1.BackColor = SystemColors.ActiveCaption;
panel1.Location = new Point(202, -3);
panel1.Name = "panel1";
panel1.Size = new Size(2, 230);
panel1.TabIndex = 9;
//
// panel2
//
panel2.BackColor = SystemColors.ActiveCaption;
panel2.Location = new Point(205, 50);
panel2.Name = "panel2";
panel2.Size = new Size(323, 2);
panel2.TabIndex = 10;
//
// RegistroExpirado
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(529, 228);
Controls.Add(panel2);
Controls.Add(panel1);
Controls.Add(linkLabel2);
Controls.Add(linkLabel1);
Controls.Add(label6);
Controls.Add(label5);
Controls.Add(label4);
Controls.Add(label3);
Controls.Add(label2);
Controls.Add(pictureBox1);
Controls.Add(label1);
Font = new Font("Century Gothic", 9F, FontStyle.Regular, GraphicsUnit.Point, 0);
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "RegistroExpirado";
StartPosition = FormStartPosition.CenterScreen;
Text = "Registro Expirado";
Load += RegistroExpirado_Load;
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label label1;
private PictureBox pictureBox1;
private Label label2;
private Label label3;
private Label label4;
private Label label5;
private Label label6;
private LinkLabel linkLabel1;
private LinkLabel linkLabel2;
private Panel panel1;
private Panel panel2;
}
}

35
Forms/RegistroExpirado.cs Normal file
View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace EFCDesk.Forms
{
public partial class RegistroExpirado : Form
{
public RegistroExpirado()
{
InitializeComponent();
}
private void RegistroExpirado_Load(object sender, EventArgs e)
{
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("mailto:soportesitar@aduanasoft.com.mx");
}
private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
System.Diagnostics.Process.Start("mailto:bodega@aduanasoft.com.mx");
}
}
}

377
Forms/RegistroExpirado.resx Normal file
View File

@@ -0,0 +1,377 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAqBAAAJ4EAAAwMAAAAQAgAKglAABGFQAAKAAAABAA
AAAgAAAAAQAgAAAAAAAABAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAlpWVALW0swdWV1pIMTI0pycl
I+MoJBz7KCQd+ygmI+M0NDanXF1fSL+9vAefnp4AAAAAAAAAAAD///8AV1dXAH59fhg1NjeSKiMW7llA
EP+MYhT/o3IX/6JyF/+OZyP/XEUf/yskF+46Oz2RiIeHGGJhYQD///8AbGpqAIKBgRguLi6xQTAP/6d1
GP/Qkh7/1JQe/9OUHv/Ynjj/5LJo/9mhRf+lcxb/QjAQ/zQ0NLCOjY0Yd3Z1APf18wY3ODmSQjAQ/7yE
G//TlB7/0JIe/9CSHv/Qkh//3alX/+S0dP/frF7/1Zcm/7uDGv9CMRH/Pz9Bkf///wZdXWBKLCUY7ad1
GP/TlB7/0JIe/9CSHv/Qkh7/0JIe/9mhRf/js3H/47Nx/9ulTf/TlSD/pnQX/y8oG+1oaWtINzg6qFtB
Ef/Qkh7/0JIe/9CSHv/Qkh3/0JEd/9CRHP/RlCL/3KdS/+Ozcf/ism7/1548/9CSHf9bQRL/P0BCpiwq
KOSNYxX/05Qe/9CSHf/Qkh//05cq/9WbNP/UmjL/0ZUl/9OXKv/frWH/5LRz/9+sYP/VliT/i2IU/zIx
LuItKCH7o3MX/9KTHv/SlSb/26VO/+Gwaf/js3D/361k/92pWv/eq17/4bBq/+Kxbf/bplD/05Uh/6Jy
F/8yLib6Lioj+6Z3Jv/Ynz//3atf/+S3e//dq2D/26ZW/9mjT//YoEn/2KFL/9igSv/WnkP/1Jk2/9WZ
M/+kdib/My8o+jAuK+SRazD/4K1h/+Gzc//jtnn/1p1E/9OZOv/Umjv/1Jo7/9SaO//Umjv/1Jo8/9Sa
PP/YnT7/jmgp/zY0MuM+P0CpYk0t/9+tZv/jtXf/5bh//96tZf/bqFr/1p5F/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/15GH/9HSEmna2tsSjQvKO64lGb/6LyC/+W5gP/luYH/5bmA/+Cva//Wnkb/1Jo7/9Sa
PP/Umjz/15w9/6l7L/81LiTtdnZ4Sf///wZFRUaTTD8v/9CodP/ovIL/5bmA/+W5gP/luYH/4bJw/9ad
Q//Umjz/15w9/7+LNv9HNxz/TU1Okv///waDgoEAmpmZGT4+PbJNQC//uJVn/+W5gP/pvIL/6LuC/+i7
gP/cplH/1Jo7/6l7L/9INx3/RENDsaSjoxiNi4sA////AHNycgCamZgZSUlKkzcyK+9mUzv/m31X/7SR
ZP+0kWP/k284/15GH/83MCXvT09QkqKhoRh9e3sA////AAAAAAAAAAAAtrW0ANTS0Qdzc3RKSEhJqTk3
NuU5NTH8OTYy/Do4N+VLS02oeXl7SdrY1we9u7sAAAAAAAAAAADgBwAAwAMAAIABAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAMADAADgBwAAKAAAACAAAABAAAAAAQAgAAAA
AAAAEAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ezrAP//
/wS1s7IphYODa2VkY6xPTk3YQEBA8To5Ofw6Ojn8QkFB8VFQUNhoZ2erioiHarq4tyj///8E8O/uAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4+HgAP//
/wOhoJ83Z2Zllzk5ON8YGBn7BQYI/wAAAf8BAQD/AwIA/wMCAP8BAQD/AAAB/wYHCf8aGhv7Pj093m5t
bJapp6Y1////A+fl5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIWD
ggC+vLsacXBviTMyMuoJCQr/AgEA/xwTBP9IMwz/cE8S/4phFv+WaRf/lmkX/4phFv9vTxL/RzIL/xsU
CP8CAQH/CwsM/zk4OOl6eXiIxsTDGZSSkQD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPTz
8gAAAAAApKKhNlNSUcITExP+AgEA/y8hCP9/WhT/uIEc/86RHv/TlB//1JQe/9OUHv/TlB7/05Qe/9SW
JP/Wn0P/wpRO/35aGP8tIAf/AgEA/xYWF/5cW1vBrqyrNAAAAAD29fQAAAAAAAAAAAAAAAAAAAAAAAAA
AADw7+4AAAAAAJ2bmkFEQ0PZBgYH/xMOA/9xUBL/wYcd/9OUH//Skx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/TmC7/3apa/+Ozcv/grF3/1JUh/8CHHP9vThL/Eg0D/wkJCf9NTUzYp6alQB4dHQDx8O8AAAAAAAAA
AAAAAAAA+/r5AHh2dQCmpKQ2RURD2QQEBP8kGQb/mm0Y/9GTHv/Rkx7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh3/0pYo/9+sYf/jtHL/47Ny/+CuZf/Slif/0ZMd/9GTHv+Yaxj/IhgG/wYGBv9PTk7XsbCvNIuJ
iQD49/YAAAAAAAAAAACwrq0AxsTDG1VUVMIGBwf/JBoG/6d1Gv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/YoEH/47Ny/+Ozcf/js3H/47Nw/9igQf/Qkh3/0JIe/9OUHv+kdBn/IhgG/wkK
Cv9hYGDA0M7MGbm3twAAAAAA0c7NAP///wJ2dHSKFBQV/xMNA/+bbRj/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9mjSf/jtHL/47Nx/+Ozcf/js3L/4K9m/9OYLv/Qkh3/0JIe/9OU
Hv+Yaxj/EgwC/xoaG/+DgoGI////As7MywCZl5YAqKalODc2NuoBAQD/clET/9GTHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zs1/+Kxbf/js3H/47Nx/+Ozcf/js3L/3apa/9GU
JP/Qkh3/0JIe/9GTHv9vTxL/AQEA/0FBQei0srE2qKalAP///wNubWyYCwsM/zAiCP/BiB3/0ZMe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/QkyD/26VQ/+Ozcv/js3H/47Nx/+Oz
cf/js3H/2qNK/9CSH//Qkh7/0ZMe/8CHHf8uIAf/DxAR/3x7epX///8CvLq5Kz8/Pt8BAQD/gFsU/9OU
H//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/SlSb/3qpb/+Oz
cv/js3H/47Nx/+Ozcf/isW3/1pw5/9CSHf/Qkh7/05Qf/35ZFP8BAQD/S0tK3cjGxSmOjIxuHBwd+x0U
BP+5ghz/0pMe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hf/Tlyr/3qte/+Ozcv/js3H/47Nx/+Ozcv/grWP/05cq/9CSHf/Skx7/t4Ec/xsSA/8kJCX7nJuaam9t
ba4HCAr/SjQM/86RHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JId/9CRHf/Qkh3/0JEd/9CR
Hf/Qkh3/0JIe/9CSHf/Tlyv/36xh/+Ozcv/js3H/47Nx/+Ozcv/bpVD/0JIf/9CSHv/OkR7/RzIM/wwN
Dv99fHurWFdX2gABAv9yURL/05Qf/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIe/9KVJv/VmzX/2KBB/9mi
R//YoUX/154+/9OYLf/Qkh//0JIf/9CSHv/Zokf/47Ny/+Ozcf/js3H/47Ny/9+tYf/RlCP/0JIe/9OU
H/9wTxL/AgME/2ZlZdhKSUnzAgEA/4xjFv/UlB7/0JIe/9CSHv/Qkh7/0JId/9KVJ//Zokf/361j/+Ky
bv/js3L/47Ny/+Ozcv/frWP/26VP/9ulTv/cqFX/3alY/+CuZv/js3H/47Nx/+Ozcf/jtHP/3ahX/9CT
IP/Qkh7/1JQe/4phFv8CAgH/V1ZW8UNCQv4EAwD/mGsX/9OUHv/Qkh3/0JId/9CSHf/UmTH/36xf/+Oz
cf/js3L/47Ny/+Ozcv/js3L/4bFr/9ynVf/isWz/47Ny/+O0c//jtHP/47Ry/+Ozcf/jsnD/4rFs/92q
Wv/TmC7/0JId/9CSHf/TlB7/lmkX/wQDAP9QT0/8REND/gQDAP+ZbR7/1Zcp/9KVKf/Sliz/1Jo2/+Gw
a//kt3r/5LZ5/+O1d//gr2n/365n/+KycP/erWT/2qVV/9qlVP/Zo07/2qVT/9umVv/bpVX/2qRQ/9ih
SP/WnT7/05cx/9KVK//SlSv/0pUq/9WXKv+Xax7/BAMA/1FQUPxNTEzzAgEB/5BpKv/XnDz/1p5F/96s
ZP/dqmH/5bmA/+W5gP/luYD/3Kpf/9WbP//Umz7/1p1E/9WdQ//Umjz/1Jo7/9SaO//Umjv/1Jo7/9Sa
O//Umjv/1Jo7/9SaO//Umjz/1Jo8/9SaPP/Umjz/2J09/41mKf8CAgH/WllZ8V5dXNsBAgP/dlYj/9ed
Pf/drGP/4bJx/96tZv/luYH/5bmB/+K0dv/WnUT/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/XnD3/clMh/wMEBf9sa2rYd3Z1rwkK
DP9MOBf/1Z1E/+KzdP/ZpFL/3Kle/+W5gf/luYH/4rNz/9WcQP/Umjv/1Jo8/9SaO//Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9KZPP9JNRX/Dw8R/4WE
g6uZl5ZvIiIi/B4VB//Ck0v/4rJu/9WcQf/frmn/5bmB/+W5gP/kuH7/3apf/9adQ//Umz3/16BJ/9ad
Q//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Wmzz/u4g2/xwU
B/8rKyv7paSja8bDwixKSkngAgEA/4ttRP/nuHv/365p/+S3ff/luYD/5bmA/+W5gP/luYD/4rR1/+Cw
bf/jtXj/2aRS/9SZOv/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ec
Pf+BXib/AgIB/1dWVd7OzMsp////A359fJkPEBD/Niwf/9WteP/nuoL/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYH/5bqB/+W5gf/hsXD/16BJ/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI84/y8iDv8VFhf/i4mIl////wKqqKcAtrSzOkVFROoDAgH/f2dI/+e6gf/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtXj/2qZX/9SaPf/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WbPf9zVCL/AwIB/1FQT+m/vbw3tLKxAMzKyQD///8Di4mIjB4eHv8WEgz/rIxh/+i8
gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/kuH3/26dZ/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/nXIu/xMNBf8lJSX/lpSUif///wLIxsUAAAAAAL27ugDRz84cbGtqxAwM
Df8qIhj/updp/+i8gv/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/jtnr/16BL/9Sa
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
Lf0DAwP/AAAA/wAAAP8OCgP/Py0M/31ZFf+tehv/xose/9CSHv/TlB//1JUf/9SVH//UlR//1JUf/9OU
H//Qkh7/xYoc/6x6H/+BYjD/PzAY/wwJAv8AAAD/AAAA/wUFBf83Njb8iIaGvcbDwjj///8A5+XkAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc2tkA////BLCu
rV5gX17jEhIR/wAAAP8AAAD/DQoD/1A5Dv+gcRr/yo4e/9OUH//SlB7/0ZIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHf/Qkh//1Zsz/9+rWv/ltG7/zpc2/51vGP9NNw7/DAkD/wAAAP8AAAD/GBcX/2xr
a+G4trVb////A9jW1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANbU
0gD///4FqKalck1MTPEGBgb/AAAA/wICAf81Jgr/mWwZ/82QHv/TlB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9GUJP/ao0r/4rFr/+O0cv/ism3/1Zox/9OUHf/MkB7/lmoY/zMk
Cv8CAQH/AAAA/woKCv9bWlnwsbCvbvf08wXS0M8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA1NLRAP///wSopqVySEdG9AMDA/8AAAD/CgcC/2JFEf/Ahx3/05Qe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0pUm/92pV//js3H/47Nx/+Ozcf/ism//1Zw3/9CR
Hf/Qkh7/05Qe/7+GHf9eQxH/CQYC/wAAAP8GBgX/VVRU87KxsG7///8Dz8zLAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADS0M8AAAAAALGvrl9PTk3xAwMD/wAAAP8RDAT/floV/86RHv/Rkx7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh//26VO/+Ozcv/js3H/47Nx/+Oz
cf/js3L/2aNK/9CSHf/Qkh7/0JIe/9KTHv/NkB7/e1cV/w8LBP8AAAD/BgYG/11cXPC6uLdbERAQAMrI
xwAAAAAAAAAAAAAAAAAAAAAAAAAAAMzKyQCurKsAwb++PGJhYeMHBwf/AAAA/xEMBP+IYRf/0ZMf/9GS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Tlyv/4a9p/+Oz
cv/js3H/47Nx/+Ozcf/js3L/361j/9KWJ//Qkh3/0JIe/9CSHv/Rkh7/0JIe/4ReFv8PCwT/AAAA/wsL
C/9ycXDhyMXEObu5uADCwL8AAAAAAAAAAAAAAAAAAAAAAMXDwgDb2dcXgX9+wBMTE/8AAAD/CgcC/39a
Ff/Rkx//0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CR
Hf/VnDj/47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9qkS//Qkh//0JIe/9CSHv/Qkh7/0JIe/9CS
Hv97VxX/CQYC/wAAAP8cHBv/kI+OvNrY1xXFw8IAAAAAAAAAAAAAAAAAxcPCAP///wCko6J+MjEx/gAA
AP8BAQH/Y0YR/86RHv/Rkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CRHf/VnDf/4rJv/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+Kxbf/WnTr/0JId/9CS
Hv/Qkh7/0JIe/9GSHv/NkB7/X0MR/wEBAf8AAAD/QD8//bGvrnoAAAAAwb++AAAAAAAAAAAAvry7AMrI
xy9jYmLjAwMD/wAAAP83Jwv/wYgd/9GTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/Slif/4K5k/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/grmX/05cs/9CSHf/Qkh7/0JIe/9CSHv/Skx7/v4Yd/zQlCv8AAAD/BwcH/3RzcuDPzcsswb++AAAA
AADBv74A////ApuZmJIjIiL/AAAA/w4KA/+abRn/05Qe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/2KFE/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/3alY/9GUI//Qkh7/0JIe/9CSHv/Qkh7/05Qe/5dqGP8NCQP/AAAA/y8v
Lv+pp6aN////AcC+vQDAvr0Az83MKWRjYuICAgL/AAAA/1I6D//OkB7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0ZQj/92p
WP/js3L/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/9miR//Qkh7/0JIe/9CSHv/Qkh7/0JIe/82Q
Hv9ONw7/AAAA/wYGBv92dHTg09DPJsG/vgB/fn0AqaemdS8uLv8AAAD/DwsD/6JyGv/TlB7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JId/9OXK//frWL/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Nx/+KxbP/Vmzb/0JId/9CS
Hv/Qkh7/0JIe/9OUHv+ecBn/DQoD/wAAAP89PTz/tbSzcKOhoAD39fMOgYB/vQwMDP8AAAD/QS8M/8uP
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/UmTH/4K5m/+Ozcv/js3H/47Nx/+Ozcf/js3H/47Nx/+Oz
cv/frGH/0pYo/9CSHf/Qkh7/0JIe/9CSHv/Kjh7/PiwM/wAAAP8UFBT/kpGQuvLv7gzLycg4WVhY6gAA
AP8BAQH/gFsV/9OUH//Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/1Zo0/+CvZ//js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/26ZR/9CTIP/Qkh7/0JIe/9CSHv/TlB//fFgV/wAAAP8BAQH/bGtq6NHO
zTSzsbBxNzY2/AAAAP8UDgT/r3sb/9KTHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9Wb
Nf/hr2j/47Ny/+Ozcf/js3H/47Nx/+Ozcf/js3H/4rJv/9adPP/Qkh3/0JIe/9CSHv/SlB7/rHkb/xIN
BP8AAAD/R0ZG/L68u2ycm5qmHh4d/wAAAP8zJAr/x4we/9GSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JId/9CRHf/Qkh7/0JIf/9CTIP/Qkh//0JIe/9CSHf/QkR3/0JId/9CS
Hv/Qkh7/0JIe/9CSHf/Xnz//47Jw/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ry/92pWP/QkyD/0JIe/9CS
Hv/Rkh7/xYse/y8iCf8AAAD/Kioq/6upqKGJiIfODw4O/wAAAP9TOw//0JIf/9CSHv/Qkh7/0JIe/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHf/RkyL/1Jkw/9efQf/apU7/3KhW/9ypWv/cqFj/26ZS/9mi
R//WnDn/0ZUl/9CRHP/Qkh3/0JId/9CRHf/UmTH/4rFt/+Ozcf/js3H/47Nx/+Ozcf/js3H/47Ny/96r
X//RkyL/0JIe/9CSHv/Qkh7/0JIe/084Dv8AAAD/GBcX/5qYmMp6eXjpBgYG/wAAAP9tTRP/05Qf/9CS
Hv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0ZQk/9efPv/eqlz/4rFs/+Ozcf/jtHL/47Ry/+O0
cv/jtHL/47Rz/+KxbP/bplL/1p4+/9igQv/Zo0n/2qRN/9ulT//eqlz/47Nx/+Ozcf/js3H/47Nx/+Oz
cf/js3H/47Rz/9yoVv/Qkh//0JIe/9CSHv/Qkh7/05Qf/2lLEv8AAAD/DQ0M/4yKiuVvbm74AgIC/wAA
AP9/WhX/1JUf/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/0JIe/9CSHv/VmjT/3qtd/+OzcP/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/js3L/4K9n/9ihRf/cqFf/4rFs/+Ozcv/js3L/47Ry/+O0cv/js3L/47Nx/+Oz
cf/js3H/47Nx/+Ozcf/jtHL/4bFr/9WbNv/Qkh3/0JIe/9CSHv/Qkh7/1JUf/3tXFf8AAAD/BwcH/4KA
gPRraWn/AQEB/wEBAf+IYBb/1JQe/9CSHv/Qkh7/0JIe/9CSHv/Qkh3/0JIf/9efP//hsGr/47Ny/+Oz
cf/js3H/47Nx/+Ozcf/js3H/47Nx/+Ozcf/js3L/26dT/92qW//ktHP/47Ny/+Ozcv/js3L/47Ny/+Oz
cv/js3L/47Ny/+Ozcv/js3L/47Nw/+KxbP/eq13/1Zw4/9CSHv/Qkh7/0JIe/9CSHv/Qkh7/1JQe/4Nd
Ff8AAAD/BQUF/359fPxramr/AQEB/wEBAf+IYBj/1JUi/9GTIv/RkyP/0ZMj/9GTI//RkyT/16BC/+Kz
cf/ktXb/5LV1/+S1dv/ktXb/5LV2/+Kzc//is3L/47R1/+S2d//jtHX/2qVS/96tZ//dq2H/26ZV/9um
Vf/cqVz/3qtg/96rYf/eq2D/3ald/9ynV//apE//2KBF/9WbOf/Sliv/0ZQk/9GUJf/RlCT/0ZMj/9GT
I//RkyL/1JYi/4NdF/8AAAD/BQUF/399ffxycXH4AwMD/wAAAP+CXiT/15w5/9SZOf/UmTn/1Zs+/9eg
Sv/VnUL/4bJy/+W5gf/luYD/5bmA/+W5gP/kt3z/3Klf/9egS//XoEn/2aNQ/9yqX//cqV//1ZxB/9Wc
Qf/Umj3/1Jo7/9SaO//Umjz/1Jo9/9SaPf/Umj3/1Jo8/9SaO//UmTr/1Jk6/9SZOv/Umjv/1Jo7/9Sa
O//Umjr/1Jk6/9SZOf/UmTn/15w5/31bI/8AAAD/CAgI/4SDgvV/fX3pCAgI/wAAAP9xUyP/15w9/9Sa
PP/Umz7/3ati/+O1eP/aplj/5Ld8/+W5gP/luYD/5bmA/+W5gP/dq2H/1Jo8/9SaO//Umjv/1Jo7/9Sa
O//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/2xPIP8AAAD/Dg4O/5COjuWQjo3PERER/wAA
AP9WPxv/1Zs9/9SaO//Zo1D/5Lh+/+Gycv/bp1r/5bl//+W5gP/luYD/5bmA/+O1eP/Wn0f/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/1E7Gf8AAAD/Gxsb/5+e
ncqkoqGnIyMj/wAAAP81JxH/y5Q7/9WbPv/fr2r/5bmA/9qmV//ZpFP/5bl//+W5gP/luYD/5bmB/+Cw
bf/Umz7/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/yZM6/zEk
D/8AAAD/MTAw/7GvrqK5t7ZyQD8//QAAAP8VEAj/s4I0/9mgR//jtnr/4LBt/9WbP//Yo1D/5Lh//+W5
gP/luYD/5bmB/+Gycf/Vm0D/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/WnD3/sIAz/xMOBv8AAAD/UVBP/MLAv23OzMs5ZmVk6wAAAP8CAQH/hGEn/92nVf/kt33/2KNQ/9OZ
Of/bp1r/5bmA/+W5gP/luYD/5bmA/+S4fv/cqV3/1Zs//9SZO//Umjv/1Jk7/9WdQv/VnED/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/XnD3/gF0m/wEAAP8DAwP/eHZ26dHOzTXs6egPj46NvxISEv8AAAD/RDIV/9em
X//luH7/2KNQ/9aeR//hsnL/5bmB/+W5gP/luYD/5bmA/+W5gP/luH//369r/9mkUv/Xn0j/2KJP/+Cw
bf/Zo1H/1Jo7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Oljv/QC8U/wAAAP8cGxv/n52cu+Ti4A2amJcAtLKxdjw7
O/8AAAD/EAwG/7GNW//ovIL/47V4/+K1d//luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W4
f//kt3v/5Lh+/+W5gf/bqFz/1Jk7/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9ecPf+jdzD/DgoF/wAAAP9MS0v/vbu6crKw
rwDBv74A0c7NK3d1deMGBgb/AAAA/11LNf/jt3//5bmB/+W5gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/itHb/2KFM/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9GYPP9RPBn/AAAA/wsL
C/+HhoXh0c/OKMG/vgDAvr0A////AqupqZQxMTD/AAAA/xEOCv+si2H/6LyC/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYH/47V5/9unWv/VnED/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/5tx
Lv8OCgX/AAAA/0A/P/+1tLOQ////AcC+vQDAvr0AwsC/AM3LyjF6eXjkCQkJ/wAAAP8/MyT/1q14/+a6
gf/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/+W5
gP/fr2r/1p5F/9SaO//Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Vmzz/xI44/zcoEf8AAAD/Dw8P/4qIh+LOzMsuwsC/AAAAAAAAAAAAwb++AP///wG1s7KBRkZF/gAA
AP8CAgH/cFtA/+O4f//muYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYH/4LFv/9aeRf/Umjv/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9WaPP/SmDz/Y0ke/wEBAf8AAAD/VlVU/r27unz///8AwL69AAAAAAAAAAAAAAAAAMTC
wQDU0tEYmZiXwiIiIf8AAAD/DAoH/5B1Uv/nuoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmB/9+uav/Vmz//1Jo8/9SaPP/Umjz/1Jo8/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPf+AXif/CgcE/wAAAP8tLSz/paSjv9HPzhbDwcAAAAAAAAAA
AAAAAAAAAAAAAMC+vQC/vbwAycbFP39+feUQEBD/AAAA/xURDf+bflj/57qB/+a5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W4f//apVX/1Jo7/9Sa
PP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9SaPP/Vmjz/1Zs9/4plKf8RDQb/AAAA/xgXF/+NjIviysjHO8PB
wADAvr0AAAAAAAAAAAAAAAAAAAAAAAAAAADEwsEA////AMC+vWJtbGvyCgoK/wAAAP8VEQ3/kXZT/+S4
gP/muoH/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W6
gf/fr2r/1Jo9/9SaPP/Umjz/1Jo8/9SaPP/Umjz/1Jo8/9WbPP/SmDz/gV4n/xENBv8AAAD/Dw8P/3t6
efHEwsFefnx8AMG/vgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx8XEAOHf3QS7ubh2aGZm9goK
Cv8AAAD/DQsI/3JdQf/WrXj/6LyC/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gf/hsnL/1ZtA/9SaPP/Umjz/1Jo8/9SaPP/Umjz/15w9/8SPOP9jSR7/CgcE/wAA
AP8PDw//dXRz9MC+vXLW1NMDxMLBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMrH
xgDa2NYGvLq5dnBvbvISERH/AAAA/wMDAv9ANCX/rYxi/+O3f//ou4L/5bmA/+W5gP/luYD/5bmA/+W5
gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/hsnL/1ZxA/9SaPP/Umjz/1Jo8/9ecPf/RmDz/nHIu/zco
Ef8CAgH/AAAA/xgYGP99e3vxwL69ctPR0AXHxMMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADMyskA3NrZBMG/vmKEg4LlJiYl/wAAAP8AAAD/EQ4K/1xLNP+zkWX/4LV9/+m8
gv/nu4H/5rqA/+W5gP/luYD/5bmA/+W5gP/luYD/5bmA/+W5gf/hsXD/1Zw//9acPP/XnD3/zpY7/6R3
MP9SPBn/DgoF/wAAAP8BAQH/Ly4u/4+OjePEwsFf09HQBMjGxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0M7NAPn39QHJx8Y+oJ6dw09OTv0MDAz/AAAA/wAA
AP8RDgr/STsq/45zUP/BnGz/27F7/+W5gP/ovIL/6byC/+m8gv/pvIL/6byC/+m8g//gsG3/ypQ8/7GB
NP+BXif/QTAU/w4LBf8AAAD/AAAA/xAQEP9aWVj9p6alwMrIxzzl4+IBysjHAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN3b2gDHxcQA0tDPGLq4
t4CFhIPlPDs7/woKCv8AAAD/AAAA/wICAf8WEg3/OC0g/1tKNP94YUT/jHFP/5d6Vf+Ye1b/jnNR/3tk
R/9ZRiz/MiUQ/xQOB/8CAgH/AAAA/wAAAP8NDQ3/REND/46MjOS+vLt+0M7NFsrIxwDQzs0AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA2dfWAOfk4wLOzMowtLKxlIaEhORLS0r+Gxsb/wQEBP8AAAD/AAAA/wAAAP8AAAD/AAAA/wEB
Af8CAQH/AAAA/wAAAP8AAAD/AAAA/wAAAP8FBQX/Hx8f/1JRUf6Ni4vjuLa1ks3Lyi7d2tkC09HQAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc2tkA5OLhA9DOzSq9u7p2oJ6ev3t6eetVVFP9NTQ0/x8f
Hv8SEhL/CwsL/wgICP8JCAj/CwsL/xMTE/8hICD/ODc3/1lYV/yAfn7rpaOivsC+vXXQzswp3tzbA9jV
1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX08wD///8A3tvaDtDN
zDnDwcBytbOyp6Wko9CYlpXqjo2M+YqIiP+KiYj/j46N+JqYl+mnpqXPtrW0psTCwXHQzcw429nYDgAA
AADy8O8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAD//wAA//8AAP/4AAAf/wAA/+AAAAf/AAD/wAAAA/8AAP8AAAAB/wAA/gAAAAB/AAD8AAAAAD8AAPgA
AAAAHwAA+AAAAAAfAADwAAAAAA8AAOAAAAAABwAA4AAAAAAHAADAAAAAAAMAAIAAAAAAAQAAgAAAAAAB
AACAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAwAAAAAADAADAAAAAAAcAAOAA
AAAABwAA8AAAAAAPAAD4AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/8AAAAP/
AAD/4AAAB/8AAP/4AAAf/wAA//8AAP//AAA=
</value>
</data>
</root>

30
HelpersXml/XmlHelper.cs Normal file
View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace EFCDesk.HelpersXml
{
public static class XmlHelper
{
public static string Value(XElement? parent, XName elementName)
=> parent?.Element(elementName)?.Value?.Trim() ?? string.Empty;
public static string Value(XElement? parent, string elementName)
=> parent?.Element(elementName)?.Value?.Trim() ?? string.Empty;
public static decimal? Decimal(XElement parent, XName elementName)
{
var value = Value(parent, elementName);
if (decimal.TryParse(value, out var result))
return result;
return null;
}
public static List<XElement> Elements(XElement? parent, XName elementName)
=> parent?.Elements(elementName)?.ToList() ?? new List<XElement>();
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace EFCDesk.HelpersXml
{
public sealed class XmlNamespaces
{
public readonly XNamespace S =
"http://schemas.xmlsoap.org/soap/envelope/";
public readonly XNamespace ns2 =
"http://www.ventanillaunica.gob.mx/pedimentos/ws/oxml/consultarpedimentocompleto";
public readonly XNamespace ns3 =
"http://www.ventanillaunica.gob.mx/common/ws/oxml/respuesta";
public readonly XNamespace comunes =
"http://www.ventanillaunica.gob.mx/pedimentos/ws/oxml/comunes";
}
}

63
Instalador/Setup.iss Normal file
View File

@@ -0,0 +1,63 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppId "{{94A052F4-0724-4D72-ACE7-A1C874EE64F3}}"
#define MyAppName "EFCDesk"
#define MyAppExeName "EFCDesk.exe"
#define MyAppVersion GetFileVersion("..\bin\Debug\net8.0-windows\" + MyAppExeName)
#define MyAppPublisher "ADUANASOFT"
#define MyAppURL "https://efc-aduanasoft.com"
#define MyAppAssocName MyAppName + " Setup"
#define MyAppAssocExt ".exe"
#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt
#define SourceDir "..\bin\Debug\net8.0-windows"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={#MyAppId}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
ChangesAssociations=yes
DisableProgramGroupPage=yes
; Remove the following line to run in administrative install mode (install for all users.)
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
OutputDir=setup
OutputBaseFilename={#MyAppName}_v{#MyAppVersion}_setup
SetupIconFile=app.ico
UninstallDisplayIcon={app}\app.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "app.ico"; DestDir: "{app}"; Flags: ignoreversion
; Copia TODO el contenido de net8.0-windows
Source: "{#SourceDir}\*"; DestDir: "{app}";Flags: recursesubdirs createallsubdirs ignoreversion;Excludes: "Logs,historico.db,appSettings.json"
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Registry]
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: ""
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";IconFilename: "{app}\app.ico"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

63
Instalador/Setup.~is Normal file
View File

@@ -0,0 +1,63 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppId "{{94A052F4-0724-4D72-ACE7-A1C874EE64F3}}"
#define MyAppName "EFCDesk"
#define MyAppExeName "EFCDesk.exe"
#define MyAppVersion GetFileVersion("..\bin\Debug\net8.0-windows\" + MyAppExeName)
#define MyAppPublisher "ADUANASOFT"
#define MyAppURL "https://efc-aduanasoft.com"
#define MyAppAssocName MyAppName + " Setup"
#define MyAppAssocExt ".exe"
#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt
#define SourceDir "..\bin\Debug\net8.0-windows"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={#MyAppId}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
ChangesAssociations=yes
DisableProgramGroupPage=yes
; Remove the following line to run in administrative install mode (install for all users.)
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
OutputDir=setup
OutputBaseFilename={#MyAppName}_v{#MyAppVersion}_setup
SetupIconFile=app.ico
UninstallDisplayIcon={app}\app.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "app.ico"; DestDir: "{app}"; Flags: ignoreversion
; Copia TODO el contenido de net8.0-windows
Source: "{#SourceDir}\*"; DestDir: "{app}";Flags: recursesubdirs createallsubdirs ignoreversion;Excludes: "Logs,historico.db,appSettings.json"
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Registry]
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: ""
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";IconFilename: "{app}\app.ico"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

BIN
Instalador/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

9
Leer.txt Normal file
View File

@@ -0,0 +1,9 @@
Para generar el instalador se debe tener instalado el programa de "Inno Setup Compiler".
Luego en la carpeta de "Instalador" debe estar el sctipt .iss, que es el que tiene la configuracion
para crear el instalador.
Tambien dentro de "Instalador" debe estar al carpeta de "setup" que es donde se crea el instalador .exe y
al cual apunta el script de salida.
Para aumentar la version de liberacion, en las propiedades del proyecto hay que buscar donde diga "Version del archivo"
y ajustar la version. Esta version es tomada de forma automatica por el script, asi que no hay necesidad de actualizarlo
manualmente. Generandose despues de la compilacion en el inno un .exe similar a este "EFCDesk_v26.1.1.1_setup.exe" en la
carpeta de setup.

View File

@@ -0,0 +1,212 @@
using EFCDesk.HelpersXml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Xml.Linq;
namespace EFCDesk.Parsers
{
public class PedimentoXmlParser
{
private readonly XDocument _doc;
private readonly XmlNamespaces _ns = new();
public PedimentoXmlParser(string xml)
{
_doc = XDocument.Parse(xml);
}
private XElement? Pedimento => _doc
.Element(_ns.S + "Envelope")
?.Element(_ns.S + "Body")
?.Element(_ns.ns2 + "consultarPedimentoCompletoRespuesta")
?.Element(_ns.ns2 + "pedimento");
// NUmero Pedimento
public string GetNumeroPedimento()
{
if (Pedimento == null)
return string.Empty;
return Pedimento.Element(_ns.ns2 + "pedimento")?.Value ?? string.Empty;
}
// Respuesta
public (bool TieneError, string NumeroOperacion) GetResultadoOperacion()
{
var respuesta =
_doc
.Element(_ns.S + "Envelope")
?.Element(_ns.S + "Body")
?.Element(_ns.ns2 + "consultarPedimentoCompletoRespuesta");
if (respuesta == null)
return (false, string.Empty);
bool tieneError =
bool.TryParse(
respuesta.Element(_ns.ns3 + "tieneError")?.Value,
out var error
) && error;
string numeroOperacion =
respuesta.Element(_ns.ns2 + "numeroOperacion")?.Value?.Trim()
?? string.Empty;
return (tieneError, numeroOperacion);
}
// Encabezado
public Dictionary<string, string> GetEncabezado()
{
var enc = Pedimento?.Element(_ns.ns2 + "encabezado");
if (enc == null) return new();
return new Dictionary<string, string>
{
["TipoOperacion"] =
XmlHelper.Value(enc.Element(_ns.ns2 + "tipoOperacion"), _ns.ns2 + "clave"),
["ClavePedimento"] =
XmlHelper.Value(enc.Element(_ns.ns2 + "claveDocumento"), _ns.ns2 + "clave"),
["Destino"] =
XmlHelper.Value(enc.Element(_ns.ns2 + "destino"), _ns.ns2 + "descripcion"),
["AduanaES"] =
XmlHelper.Value(enc.Element(_ns.ns2 + "aduanaEntradaSalida"), _ns.ns2 + "clave"),
["TipoCambio"] =
XmlHelper.Value(enc, _ns.ns2 + "tipoCambio"),
["PesoBruto"] =
XmlHelper.Value(enc, _ns.ns2 + "pesoBruto"),
["ValorDolares"] =
XmlHelper.Value(enc, _ns.ns2 + "valorDolares"),
["ValorAduanalTotal"] =
XmlHelper.Value(enc, _ns.ns2 + "valorAduanalTotal"),
["ValorComercialTotal"] =
XmlHelper.Value(enc, _ns.ns2 + "valorComercialTotal"),
["CurpApoderado"] =
XmlHelper.Value(enc, _ns.ns2 + "curpApoderadomandatario")
};
}
// Importador / Exportador
public Dictionary<string, string> GetImportador()
{
var imp = Pedimento?.Element(_ns.ns2 + "importadorExportador");
if (imp == null) return new();
var dom = imp.Element(_ns.ns2 + "domicilio");
return new Dictionary<string, string>
{
["RFC"] = XmlHelper.Value(imp, _ns.ns2 + "rfc"),
["RazonSocial"] = XmlHelper.Value(imp, _ns.ns2 + "razonSocial"),
["Calle"] = XmlHelper.Value(dom, _ns.ns2 + "calle"),
["NumeroExterior"] = XmlHelper.Value(dom, _ns.ns2 + "numeroExterior"),
["Ciudad"] = XmlHelper.Value(dom, _ns.ns2 + "ciudadMunicipio"),
["CodigoPostal"] = XmlHelper.Value(dom, _ns.ns2 + "codigoPostal"),
["Pais"] = XmlHelper.Value(imp.Element(_ns.ns2 + "pais"), "descripcion")
};
}
// Fechas
public List<Dictionary<string, string>> GetFechas()
{
var imp = Pedimento?.Element(_ns.ns2 + "importadorExportador");
if (imp == null) return new();
var fechas = imp.Elements(_ns.ns2 + "fechas");
return fechas.Select(f => new Dictionary<string, string>
{
["Fecha"] = XmlHelper.Value(f, _ns.ns2 + "fecha"),
["TipoClave"] = XmlHelper.Value(f.Element(_ns.ns2 + "tipo"), _ns.ns2 + "clave"),
["TipoDescripcion"] = XmlHelper.Value(f.Element(_ns.ns2 + "tipo"), _ns.ns2 + "descripcion")
}).ToList();
}
// Tasas
public List<Dictionary<string, string>> GetTasas()
{
var tasas = XmlHelper.Elements(Pedimento, _ns.ns2 + "tasas");
return tasas.Select(t => new Dictionary<string, string>
{
["ContribucionClave"] =
XmlHelper.Value(t.Element(_ns.ns2 + "contribucion"), _ns.ns2 + "clave"),
["ContribucionDescripcion"] =
XmlHelper.Value(t.Element(_ns.ns2 + "contribucion"), _ns.ns2 + "descripcion"),
["TipoTasa"] =
XmlHelper.Value(t.Element(_ns.ns2 + "tipoTasa"), "descripcion"),
["TasaAplicable"] =
XmlHelper.Value(t, _ns.ns2 + "tasaAplicable"),
["FormaPago"] =
XmlHelper.Value(t.Element(_ns.ns2 + "formaPago"), "descripcion"),
["Importe"] =
XmlHelper.Value(t, _ns.ns2 + "importe")
}).ToList();
}
// Facturas
public List<Dictionary<string, string>> GetFacturas()
{
var facturas = XmlHelper.Elements(Pedimento, _ns.ns2 + "facturas");
return facturas.Select(f => new Dictionary<string, string>
{
["Fecha"] = XmlHelper.Value(f, _ns.ns2 + "fecha"),
["Numero"] = XmlHelper.Value(f, _ns.ns2 + "numero"),
["Moneda"] = XmlHelper.Value(f.Element(_ns.ns2 + "moneda"), _ns.ns2 + "descripcion"),
["ValorDolares"] = XmlHelper.Value(f, _ns.ns2 + "valorDolares"),
["Proveedor"] = XmlHelper.Value(f, _ns.ns2 + "proveedorComprador")
}).ToList();
}
// Identificadores
public List<Dictionary<string, string>> GetIdentificadores()
{
var root = Pedimento?.Element(_ns.ns2 + "identificadores");
if (root == null) return new();
return root.Elements(_ns.ns2 + "identificadores")
.Select(i => new Dictionary<string, string>
{
["Clave"] =
XmlHelper.Value(i.Element("claveIdentificador"), "clave"),
["Descripcion"] =
XmlHelper.Value(i.Element("claveIdentificador"), "descripcion"),
["Complemento1"] =
XmlHelper.Value(i, "complemento1")
}).ToList();
}
// Partidas
public List<string> GetPartidas()
{
if (Pedimento == null)
return new List<string>();
return Pedimento
.Elements(_ns.ns2 + "partidas")
.Select(p => p.Value?.Trim())
.Where(v => !string.IsNullOrEmpty(v))
.ToList()!;
}
}
}

156
Program.cs Normal file
View File

@@ -0,0 +1,156 @@
using EFCDesk.Classes;
using EFCDesk.Forms;
using System.Threading;
namespace EFCDesk
{
public static class Globales
{
public static MonitorCarpetas gMonitor;
public static ProcessLogger logger = new ProcessLogger();
public static ConfiguracionJSON configJson = ConfiguracionJSON.LoadFromJson();
public static string accesToken = "";
public static string refresToken = "";
}
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static async Task Main()
{
/**/
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string carpetaBase = @"C:\EFC";
if (!Directory.Exists(Globales.configJson.FolderExpediente))
{
string folder = "C:" + Path.DirectorySeparatorChar + "EFC";
// Asigna el valor al objeto de configuraci<63>n
Globales.configJson.FolderExpediente = folder;
// Guarda los cambios en el archivo JSON
Globales.configJson.SaveToJson();
Directory.CreateDirectory(folder);
carpetaBase = folder;
}
else
{
carpetaBase = Globales.configJson.FolderExpediente;
}
Properties.Settings.Default.urlEFC = Globales.configJson.DominioExp;
Properties.Settings.Default.Save();
Globales.gMonitor = new MonitorCarpetas(
carpetaBase: carpetaBase,
maxConcurrent: 10,
perFileTimeoutSeconds: 30,
maxReintentos: 10
);
//string? data = SecureDataHandler.ReadDataAsPlainText();
//if (string.IsNullOrEmpty(data))
//{
// Application.Run(new Login());
//} else if (!SecureDataHandler.IsDataValid())
//{
// MessageBox.Show("Id Usuario incorrecto. favor de revisar.","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
// Application.Run(new Login());
//} else
//{
// // Antes de llamar a cualquier m<>todo sobre Globales.gMonitor, verifica que no sea null
// if (Globales.gMonitor != null && !Globales.gMonitor.ExisteConfiguracionExpediente())
// {
// Application.Run(new Login());
// }
// else
// {
// if (Globales.gMonitor != null)
// {
// Application.Run(new FormMain(Globales.gMonitor));
// }
// else
// {
// MessageBox.Show("Error interno: el monitor de carpetas no est<73> inicializado.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
// Application.Exit();
// }
// }
// // Al terminar la aplicaci<63>n, liberar el recurso manualmente
// Globales.gMonitor?.Dispose();
//}
bool Esvalido = Utils.Util.StringsValidos(Globales.configJson.UsuarioExp, Globales.configJson.PasswordExp);
if (!Esvalido)
{
MessageBox.Show("Debe ingresar Usuario y contraseña.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Run(new Login());
}
else
{
// Intentar login automático para obtener tokens
bool loginExitoso = await Utils.Util.Login(Globales.configJson.UsuarioExp ?? "", Globales.configJson.PasswordExp ?? "");
if (!loginExitoso)
{
MessageBox.Show("Error en el inicio de sesión automático. Por favor, verifique sus credenciales.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Run(new Login());
return;
}
// Antes de llamar a cualquier m<>todo sobre Globales.gMonitor, verifica que no sea null
if (Globales.gMonitor != null && !Globales.gMonitor.ExisteConfiguracionExpediente())
{
Application.Run(new Login());
}
else
{
if (Globales.gMonitor != null)
{
Application.Run(new FormMain(Globales.gMonitor));
}
else
{
MessageBox.Show("Error interno: el monitor de carpetas no está inicializado.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
// Al terminar la aplicaci<63>n, liberar el recurso manualmente
Globales.gMonitor?.Dispose();
}
//else
//{
// // Antes de llamar a cualquier m<>todo sobre Globales.gMonitor, verifica que no sea null
// if (Globales.gMonitor != null && !Globales.gMonitor.ExisteConfiguracionExpediente())
// {
// Application.Run(new Login());
// }
// else
// {
// if (Globales.gMonitor != null)
// {
// Application.Run(new FormMain(Globales.gMonitor));
// }
// else
// {
// MessageBox.Show("Error interno: el monitor de carpetas no est<73> inicializado.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
// Application.Exit();
// }
// }
// // Al terminar la aplicaci<63>n, liberar el recurso manualmente
// Globales.gMonitor?.Dispose();
//}
}
}
}

103
Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace EFCDesk.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EFCDesk.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap appbar_folder {
get {
object obj = ResourceManager.GetObject("appbar_folder", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap appbar_folder2 {
get {
object obj = ResourceManager.GetObject("appbar_folder2", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap CUATRO {
get {
object obj = ResourceManager.GetObject("CUATRO", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap splash4 {
get {
object obj = ResourceManager.GetObject("splash4", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

133
Properties/Resources.resx Normal file
View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="appbar_folder" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\appbar.folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="appbar_folder2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\appbar.folder2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CUATRO" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\CUATRO.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="splash4" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\splash4.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

74
Properties/Settings.Designer.cs generated Normal file
View File

@@ -0,0 +1,74 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Este código fue generado por una herramienta.
// Versión de runtime:4.0.30319.42000
//
// Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si
// se vuelve a generar el código.
// </auto-generated>
//------------------------------------------------------------------------------
namespace EFCDesk.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string IdUsuario {
get {
return ((string)(this["IdUsuario"]));
}
set {
this["IdUsuario"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string urlEFC {
get {
return ((string)(this["urlEFC"]));
}
set {
this["urlEFC"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int ExpWinsaai {
get {
return ((int)(this["ExpWinsaai"]));
}
set {
this["ExpWinsaai"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int ExpLogistico {
get {
return ((int)(this["ExpLogistico"]));
}
set {
this["ExpLogistico"] = value;
}
}
}
}

View File

@@ -0,0 +1,18 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="EFCDesk.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="IdUsuario" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="urlEFC" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="ExpWinsaai" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="ExpLogistico" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
</Settings>
</SettingsFile>

BIN
Resources/CUATRO.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
Resources/appbar.folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
Resources/splash4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

250
Utils/Util.cs Normal file
View File

@@ -0,0 +1,250 @@
using EFCDesk.Classes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Net.NetworkInformation;
namespace EFCDesk.Utils
{
public static class Util
{
private const string CLAVE_MAESTRA = "EFCDesk_MasterKey_2026";
public static bool StringsValidos(params string?[] valores)
{
return valores != null && valores.All(v => !string.IsNullOrWhiteSpace(v));
}
public static bool TieneValor<T>(T? valor)
{
return valor != null;
}
public static string ValorSeguro(string? valor, string valorPorDefecto = "")
{
return string.IsNullOrWhiteSpace(valor) ? valorPorDefecto : valor;
}
public static bool EsNumeroPositivo(int valor)
{
return valor > 0;
}
public static async Task<bool> Login(string usuario, string password)
{
Globales.configJson = ConfiguracionJSON.LoadFromJson();
bool Esvalido = StringsValidos(Globales.configJson.DominioExp);
if (!Esvalido)
{
MessageBox.Show("La configuración del dominio es inválida. Por favor, revise la configuración.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
Esvalido = StringsValidos(usuario, password);
if (!Esvalido)
{
MessageBox.Show("Debe ingresar Usuario y contraseña.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Globales.configJson.UsuarioExp = "";
Globales.configJson.PasswordExp = "";
Globales.configJson.SaveToJson();
return false;
}
using var apiClient = new ApiClient(timeout: TimeSpan.FromSeconds(600), maxRetries: 3, retryDelay: TimeSpan.FromSeconds(60));
// Crear diccionario con los datos
var loginData = new Dictionary<string, object>
{
{ "username", usuario},
{ "password", password}
};
string ApiPostLogin = Globales.configJson.DominioExp + apiClient.EndpointLoginToken();
string respuestaJson = await apiClient.PostJsonWithoutAuthAsync(url: ApiPostLogin, data: loginData);
if (!apiClient.IsJson(respuestaJson))
{
return false;
}
if (!apiClient.HasJsonData(respuestaJson))
{
return false;
}
if (JsonHelper.TryParse(respuestaJson, out var root))
{
var JsonData = JsonHelper.ToDictionary(root);
if (JsonData == null)
{
return false;
}
else
{
if (JsonData.ContainsKey("access"))
{
Globales.accesToken = JsonData["access"]?.ToString() ?? "";
}
if (JsonData.ContainsKey("refresh"))
{
Globales.refresToken = JsonData["refresh"]?.ToString() ?? "";
}
if (JsonData.ContainsKey("detail"))
{
string detalle = JsonData["detail"]?.ToString() ?? "Detalle desconocido";
MessageBox.Show(detalle, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
if (JsonData.ContainsKey("success"))
{
bool success = Convert.ToBoolean(JsonData["success"]);
if (!success)
{
string mensaje = JsonData["message"]?.ToString() ?? "Error desconocido";
MessageBox.Show(mensaje, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
if (string.IsNullOrEmpty(Globales.accesToken) || string.IsNullOrEmpty(Globales.refresToken))
{
MessageBox.Show("Error al obtener tokens de autenticación. Por favor, revise sus credenciales y la configuración del dominio.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
}
else
{
return false;
}
// Falta lógica para procesar la respuesta y devolver true/false según corresponda
// Por ahora, simplemente devolvemos true si la respuesta no es nula o vacía
return true;
}
private static string ObtenerMacAddress()
{
return NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up)
.Select(nic => nic.GetPhysicalAddress().ToString())
.FirstOrDefault() ?? "S0luc10n3501";
}
private static void DerivarClave(string password, string salt, out byte[] key, out byte[] iv)
{
key = Array.Empty<byte>();
iv = Array.Empty<byte>();
try
{
if (string.IsNullOrWhiteSpace(password))
throw new ArgumentException("Password inválido");
if (string.IsNullOrWhiteSpace(salt))
throw new ArgumentException("Salt inválido");
using var derivador = new Rfc2898DeriveBytes(
password,
Encoding.UTF8.GetBytes(salt),
100_000,
HashAlgorithmName.SHA256);
key = derivador.GetBytes(32); // AES-256
iv = derivador.GetBytes(16); // IV
}
catch (CryptographicException ex) { }
catch (Exception ex) { }
}
public static string Encriptar(string textoPlano, string? password = null, string? saltOpcional = null)
{
try
{
if (string.IsNullOrEmpty(textoPlano))
return string.Empty;
string salt = saltOpcional ?? ObtenerMacAddress();
string pass = password ?? CLAVE_MAESTRA;
DerivarClave(pass, salt, out var key, out var iv);
using var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
using var encryptor = aes.CreateEncryptor();
byte[] textoBytes = Encoding.UTF8.GetBytes(textoPlano);
byte[] textoEncriptado = encryptor.TransformFinalBlock(textoBytes, 0, textoBytes.Length);
return Convert.ToBase64String(textoEncriptado);
}
catch (CryptographicException ex)
{
return string.Empty;
}
catch (Exception ex)
{
return string.Empty;
}
}
public static string Desencriptar(string textoEncriptado, string? password = null, string? saltOpcional = null)
{
try
{
if (string.IsNullOrEmpty(textoEncriptado))
return string.Empty;
string salt = saltOpcional ?? ObtenerMacAddress();
string pass = password ?? CLAVE_MAESTRA;
DerivarClave(pass, salt, out var key, out var iv);
using var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
using var decryptor = aes.CreateDecryptor();
byte[] textoBytes = Convert.FromBase64String(textoEncriptado);
byte[] textoPlano = decryptor.TransformFinalBlock(textoBytes, 0, textoBytes.Length);
return Encoding.UTF8.GetString(textoPlano);
}
catch (FormatException ex)
{
return string.Empty;
}
catch (Exception ex)
{
return string.Empty;
}
}
}
}

38
publish.bat Normal file
View File

@@ -0,0 +1,38 @@
@echo off
REM ================================
REM PUBLICAR APP WINFORMS .NET
REM ================================
set PROJECT=EFCDesk.csproj
set OUTDIR=publish_final
echo ===============================
echo COMPILANDO EN MODO RELEASE...
echo ===============================
dotnet publish %PROJECT% -c Release -r win-x64 --self-contained true ^
/p:PublishSingleFile=true ^
/p:IncludeNativeLibrariesForSelfExtract=true ^
/p:EnableCompressionInSingleFile=true ^
-o %OUTDIR%
echo.
echo ========================================
echo BUSCANDO EL EXE FINAL...
echo ========================================
REM Buscar el .exe dentro de la carpeta de salida
for %%f in (%OUTDIR%\*.exe) do (
echo Se genero: %%~nxf
echo Copiando a carpeta FINAL...
mkdir dist 2>nul
copy /Y "%%f" "dist\"
)
echo.
echo ========================================
echo LISTO
echo Tu aplicacion esta en la carpeta: dist
echo ========================================
pause

38
publish_old.bat Normal file
View File

@@ -0,0 +1,38 @@
@echo off
REM ================================
REM PUBLICAR APP WINFORMS .NET
REM ================================
set PROJECT=EFCDesk.csproj
set OUTDIR=publish_final
echo ===============================
echo COMPILANDO EN MODO RELEASE...
echo ===============================
dotnet publish %PROJECT% -c Release -r win-x64 --self-contained true ^
/p:PublishSingleFile=true ^
/p:IncludeNativeLibrariesForSelfExtract=true ^
/p:EnableCompressionInSingleFile=true ^
-o %OUTDIR%
echo.
echo ========================================
echo BUSCANDO EL EXE FINAL...
echo ========================================
REM Buscar el .exe dentro de la carpeta de salida
for %%f in (%OUTDIR%\*.exe) do (
echo Se generó: %%~nxf
echo Copiando a carpeta FINAL...
mkdir AppFinal 2>nul
copy /Y "%%f" "AppFinal\"
)
echo.
echo ========================================
echo LISTO
echo Tu aplicación está en la carpeta: AppFinal
echo ========================================
pause