Imports System.IO Imports System.Threading Imports EgtDotNETBasis Imports EgwMultiEngineManager.Core Imports EgwMultiEngineManager.Data Imports EgwMultiEngineManager.Data.Constants Imports EgwWPFBaseLib Public Class MainWindowVM Inherits VMBase Public Event QuitApplication() Public Event WindowStatisticUpdate(Statistics As Statistics) Public Event AedificaStatisticUpdate(Statistics As Statistics) Private m_objMutex As Mutex Private m_bManageMutexRes As Boolean Private m_nInstance As Integer = 0 Private m_nDebug As Integer = 0 Private m_sLogFile As String Friend ReadOnly Property sLogFile As String Get Return m_sLogFile End Get End Property Private Const m_TitleMsg As String = "EgwMultiEngineManager" Private m_sDataRoot As String = String.Empty Friend ReadOnly Property sDataRoot As String Get Return m_sDataRoot End Get End Property Private m_sConfigDir As String = String.Empty Public ReadOnly Property sConfigDir As String Get Return m_sConfigDir End Get End Property Private m_sTempDir As String Friend ReadOnly Property sTempDir As String Get Return m_sTempDir End Get End Property Private m_Lock_StatisticsList As New Object Private m_StatisticsList As New Dictionary(Of String, Statistics) Friend Function GetValueFromKeyInStatisticsList(sGroupName As String) As Statistics SyncLock m_Lock_StatisticsList If m_StatisticsList.ContainsKey(sGroupName) Then Return m_StatisticsList(sGroupName).Copy() Else Return Nothing End If End SyncLock End Function Friend Sub SetValueToKeyInStatisticsList(sGroupName As String, Statistics As Statistics) SyncLock m_Lock_StatisticsList If m_StatisticsList.ContainsKey(sGroupName) Then m_StatisticsList(sGroupName) = Statistics Else m_StatisticsList.Add(sGroupName, Statistics) End If End SyncLock End Sub Friend Function GetStatisticsListKeyCollection() As List(Of String) SyncLock m_Lock_StatisticsList Return m_StatisticsList.Keys.ToList() End SyncLock End Function Private m_ExecEnvironmentList As New List(Of ExecEnvironmentManager) Public ReadOnly Property ExecEnvironmentList As List(Of ExecEnvironmentManager) Get Return m_ExecEnvironmentList End Get End Property ' Riferimento al gestore del server Redis Private m_RedisManager As RedisManager Friend ReadOnly Property RedisManager As RedisManager Get Return m_RedisManager End Get End Property Sub New() ' Avvio l'inizializzazione della mappa passandogli il riferimento al MainWindowVM Map.BeginInit(Me) ' Impostazione path radice per i dati m_sDataRoot = System.AppDomain.CurrentDomain.BaseDirectory If GetPrivateProfileString(ConstGen.S_DATA, ConstGen.K_DATAROOT, "", m_sDataRoot, m_sDataRoot & "\" & ConstGen.DAT_FILE_NAME) = 0 Then m_sDataRoot = System.AppDomain.CurrentDomain.BaseDirectory End If ' Impostazione direttorio di configurazione m_sConfigDir = m_sDataRoot & "\" & ConstGen.CONF_DIR IniFile.SetIniFile(m_sConfigDir & "\" & ConstIni.INI_FILE_NAME) m_sTempDir = m_sDataRoot & "\" & ConstGen.TEMP_DIR ' Inizializzazione generale di EgtInterface m_nDebug = GetMainPrivateProfileInt(S_GENERAL, K_DEBUG, 0) m_sLogFile = m_sTempDir & "\" & GENLOG_FILE_NAME.Replace("#", m_nInstance.ToString()) Dim sLogMsg As String = "User " & Environment.MachineName & "\" & Environment.UserName & " (" & m_nInstance.ToString() & ")" & vbLf & My.Application.Info.Title.ToString() & " ver. " & My.Application.Info.Version.Major.ToString() & "." & My.Application.Info.Version.Minor.ToString() & (ChrW(97 - 1 + My.Application.Info.Version.Build)).ToString() & My.Application.Info.Version.Revision.ToString() EgtInit(m_nDebug, m_sLogFile, sLogMsg) End Sub Sub Init() ' verifico istanze ManageInstance() If Not m_bManageMutexRes Then Return ' Impostazione direttorio per file temporanei m_sTempDir = m_sDataRoot & "\" & TEMP_DIR ' connessione a Redis Dim sConnection As String = "localhost" GetMainPrivateProfileString(S_GENERAL, K_REDISCONNECTION, "", sConnection) EgtOutLog("RedisConnection = " & sConnection) If String.IsNullOrWhiteSpace(sConnection) Then Dim sMsg As String = "Redis connection string is empty!" & Environment.NewLine & "The program will shutdown!" MessageBox.Show(sMsg, m_TitleMsg, MessageBoxButton.OK, MessageBoxImage.Error) EgtOutLog(sMsg) RaiseEvent QuitApplication() Return Else m_RedisManager = New RedisManager(sConnection) ExecEnvironmentManager.SetRedisManager(m_RedisManager) End If ' creazione manager dei processi Dim sCamExePath As String = "" GetMainPrivateProfileString(S_GENERAL, K_CAMEXEPATH, "", sCamExePath) EgtOutLog("CAMExePath = " & sCamExePath) If Not File.Exists(sCamExePath) Then Dim sMsg As String = "CAMExePath not found!" & Environment.NewLine & "The program will shutdown!" MessageBox.Show(sMsg, m_TitleMsg, MessageBoxButton.OK, MessageBoxImage.Error) EgtOutLog(sMsg) RaiseEvent QuitApplication() Return End If Dim sPipeLuaDir As String = "" GetMainPrivateProfileString(S_GENERAL, K_PIPELUADIR, "", sPipeLuaDir) EgtOutLog("PipeLuaDir = " & sPipeLuaDir) If Not File.Exists(sCamExePath) Then Dim sMsg As String = "PipeLuaDir not found!" & Environment.NewLine & "The program will shutdown!" MessageBox.Show(sMsg, m_TitleMsg, MessageBoxButton.OK, MessageBoxImage.Error) EgtOutLog(sMsg) RaiseEvent QuitApplication() Return End If ' imposto log per ExecProcessManager ExecProcessManager.SetEgtOutLog(AddressOf EgtOutLog) ' carico ambienti Redis Dim nGroupIndex As Integer = 1 Dim NewExecProcessManager As ExecEnvironmentManager = Nothing While ExecEnvironmentManager.CreateExecEnvironmentManager(ExecEnvironmentManager.EnvironmentCommunicationTypes.REDIS, nGroupIndex, NewExecProcessManager) If Not IsNothing(NewExecProcessManager) Then m_ExecEnvironmentList.Add(NewExecProcessManager) AddHandler NewExecProcessManager.StatisticUpdate, AddressOf NewExecProcessManager_StatisticUpdate End If NewExecProcessManager = Nothing nGroupIndex += 1 End While ' carico ambienti REST nGroupIndex = 1 NewExecProcessManager = Nothing While ExecEnvironmentManager.CreateExecEnvironmentManager(ExecEnvironmentManager.EnvironmentCommunicationTypes.REST, nGroupIndex, NewExecProcessManager) If Not IsNothing(NewExecProcessManager) Then m_ExecEnvironmentList.Add(NewExecProcessManager) AddHandler NewExecProcessManager.StatisticUpdate, AddressOf NewExecProcessManager_StatisticUpdate End If NewExecProcessManager = Nothing nGroupIndex += 1 End While End Sub Private Sub NewExecProcessManager_StatisticUpdate(sGroupName As String, Statistics As Statistics) SetValueToKeyInStatisticsList(sGroupName, Statistics) End Sub Private Sub ManageInstance() Dim bCreated As Boolean Try m_objMutex = New Mutex(True, "Global\EgwMultiEngineManager", bCreated) Catch bCreated = False End Try If bCreated Then ' Prima istanza m_nInstance = 1 ' Aggiorno stato istanze attive WriteMainPrivateProfileString(S_GENERAL, K_INSTANCES, m_nInstance.ToString) ' Rilascio il possesso del mutex m_objMutex.ReleaseMutex() Else ' Leggo il massimo numero di istanze ammesse Const MAX_INST As Integer = 32 Dim nMaxInst As Integer = GetMainPrivateProfileInt(S_GENERAL, K_MAXINST, 1) nMaxInst = Math.Max(1, Math.Min(nMaxInst, MAX_INST)) ' Richiedo il possesso del mutex Dim bOk As Boolean = False If m_objMutex.WaitOne(500) Then ' Cerco il primo indice di istanza libero (max 32) Dim nTmp As Integer = GetMainPrivateProfileInt(S_GENERAL, K_INSTANCES, 0) m_nInstance = 1 Dim nMask As Integer = 1 While (nTmp And nMask) <> 0 And m_nInstance <= MAX_INST m_nInstance += 1 nMask *= 2 End While ' Se nuova istanza nei limiti If m_nInstance <= nMaxInst Then bOk = True ' Aggiorno stato istanze attive nTmp += (1 << (m_nInstance - 1)) WriteMainPrivateProfileString(S_GENERAL, K_INSTANCES, nTmp.ToString()) End If ' Rilascio il possesso del mutex m_objMutex.ReleaseMutex() End If ' Se non è possibile continuare If Not bOk Then '' porto in primo piano la prima istanza 'Dim bFound As Boolean = False '' processi del programma a 32 bit 'Dim localProc As Process() = Process.GetProcessesByName("EgtCAM5R32") 'For Each p As Process In localProc ' If p.Id <> Process.GetCurrentProcess().Id Then ' bFound = True ' ShowWindow(p.MainWindowHandle, SW.SHOWMAXIMIZED) ' Exit For ' End If 'Next '' se non trovati processi a 32 bit provo a 64 bit 'If Not bFound Then ' localProc = Process.GetProcessesByName("EgtCAM5R64") ' For Each p As Process In localProc ' If p.Id <> Process.GetCurrentProcess().Id Then ' bFound = True ' ShowWindow(p.MainWindowHandle, SW.SHOWMAXIMIZED) ' Exit For ' End If ' Next 'End If ' esco dal programma RaiseEvent QuitApplication() m_bManageMutexRes = False Return End If End If m_bManageMutexRes = True Return End Sub Public Sub Quit() For Each ExecEnvironment In m_ExecEnvironmentList ExecEnvironment.Dispose() Next If Not IsNothing(m_RedisManager) Then m_RedisManager.Dispose() If m_bManageMutexRes Then ' Aggiorno istanze usate m_objMutex.WaitOne(1000) Dim nTmp As Integer = GetMainPrivateProfileInt(S_GENERAL, K_INSTANCES, 0) nTmp -= (1 << (m_nInstance - 1)) WriteMainPrivateProfileString(S_GENERAL, K_INSTANCES, nTmp.ToString()) m_objMutex.ReleaseMutex() ' Rilascio mutex If Not IsNothing(m_objMutex) Then m_objMutex.Close() End If End Sub Friend Sub OnClose() End Sub End Class