From 4186d0dbf413fa6c3df8afa8cff2e6736fa3e64b Mon Sep 17 00:00:00 2001 From: Craig Hawker Date: Thu, 17 Feb 2022 11:21:15 +0000 Subject: [PATCH] Added examples for logging. --- MFSamplesAndLibraries.sln | 27 +++- .../WithVAFExtensionsLibrary/Configuration.cs | 14 ++ .../VaultApplication.cs | 42 +++++ .../WithVAFExtensionsLibrary.csproj | 85 +++++++++++ .../WithVAFExtensionsLibrary/appdef.xml | 26 ++++ .../install-application.ps1 | 143 ++++++++++++++++++ .../Configuration.cs | 16 ++ .../VaultApplication.cs | 106 +++++++++++++ .../WithoutVAFExtensionsLibrary.csproj | 85 +++++++++++ .../WithoutVAFExtensionsLibrary/appdef.xml | 26 ++++ .../install-application.ps1 | 143 ++++++++++++++++++ 11 files changed, 710 insertions(+), 3 deletions(-) create mode 100644 Samples/VAF/Logging/WithVAFExtensionsLibrary/Configuration.cs create mode 100644 Samples/VAF/Logging/WithVAFExtensionsLibrary/VaultApplication.cs create mode 100644 Samples/VAF/Logging/WithVAFExtensionsLibrary/WithVAFExtensionsLibrary.csproj create mode 100644 Samples/VAF/Logging/WithVAFExtensionsLibrary/appdef.xml create mode 100644 Samples/VAF/Logging/WithVAFExtensionsLibrary/install-application.ps1 create mode 100644 Samples/VAF/Logging/WithoutVAFExtensionsLibrary/Configuration.cs create mode 100644 Samples/VAF/Logging/WithoutVAFExtensionsLibrary/VaultApplication.cs create mode 100644 Samples/VAF/Logging/WithoutVAFExtensionsLibrary/WithoutVAFExtensionsLibrary.csproj create mode 100644 Samples/VAF/Logging/WithoutVAFExtensionsLibrary/appdef.xml create mode 100644 Samples/VAF/Logging/WithoutVAFExtensionsLibrary/install-application.ps1 diff --git a/MFSamplesAndLibraries.sln b/MFSamplesAndLibraries.sln index fe01209..d32ab87 100644 --- a/MFSamplesAndLibraries.sln +++ b/MFSamplesAndLibraries.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29806.167 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "M-Files API", "M-Files API", "{BFC9716E-3A29-4482-9385-7301436D8010}" EndProject @@ -211,7 +211,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "COMAPI", "Samples\OAuth\COM EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RESTAPI", "Samples\OAuth\RESTAPI\RESTAPI.csproj", "{B349EDDE-A581-470A-BFB1-E40D5ED566C3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Samples\OAuth\Common\Common.csproj", "{5DC9C4F2-FAE0-4761-A149-A7EC065FEEFE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common", "Samples\OAuth\Common\Common.csproj", "{5DC9C4F2-FAE0-4761-A149-A7EC065FEEFE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Logging", "Logging", "{2F011880-7264-428F-912C-F81E49E296A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WithVAFExtensionsLibrary", "Samples\VAF\Logging\WithVAFExtensionsLibrary\WithVAFExtensionsLibrary.csproj", "{A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WithoutVAFExtensionsLibrary", "Samples\VAF\Logging\WithoutVAFExtensionsLibrary\WithoutVAFExtensionsLibrary.csproj", "{9FF77938-2F14-4713-83CB-F367F60CB037}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -376,6 +382,18 @@ Global {5DC9C4F2-FAE0-4761-A149-A7EC065FEEFE}.DebugWithoutDeployment|Any CPU.Build.0 = Debug|Any CPU {5DC9C4F2-FAE0-4761-A149-A7EC065FEEFE}.Release|Any CPU.ActiveCfg = Release|Any CPU {5DC9C4F2-FAE0-4761-A149-A7EC065FEEFE}.Release|Any CPU.Build.0 = Release|Any CPU + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}.DebugWithoutDeployment|Any CPU.ActiveCfg = Debug|Any CPU + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}.DebugWithoutDeployment|Any CPU.Build.0 = Debug|Any CPU + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B}.Release|Any CPU.Build.0 = Release|Any CPU + {9FF77938-2F14-4713-83CB-F367F60CB037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9FF77938-2F14-4713-83CB-F367F60CB037}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9FF77938-2F14-4713-83CB-F367F60CB037}.DebugWithoutDeployment|Any CPU.ActiveCfg = Debug|Any CPU + {9FF77938-2F14-4713-83CB-F367F60CB037}.DebugWithoutDeployment|Any CPU.Build.0 = Debug|Any CPU + {9FF77938-2F14-4713-83CB-F367F60CB037}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9FF77938-2F14-4713-83CB-F367F60CB037}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -436,6 +454,9 @@ Global {457F6827-29D0-4770-AE56-C90E41A078C0} = {E4F1D76B-0CF7-4A64-9B84-627C3BB26C69} {B349EDDE-A581-470A-BFB1-E40D5ED566C3} = {E4F1D76B-0CF7-4A64-9B84-627C3BB26C69} {5DC9C4F2-FAE0-4761-A149-A7EC065FEEFE} = {E4F1D76B-0CF7-4A64-9B84-627C3BB26C69} + {2F011880-7264-428F-912C-F81E49E296A8} = {64819656-F9ED-411C-827B-9EB4EBECF6E6} + {A28658F4-3DBF-43CC-8FCF-6ED1D296EE5B} = {2F011880-7264-428F-912C-F81E49E296A8} + {9FF77938-2F14-4713-83CB-F367F60CB037} = {2F011880-7264-428F-912C-F81E49E296A8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4F7B9423-0E07-4E5F-A84E-DBFCC4B91994} diff --git a/Samples/VAF/Logging/WithVAFExtensionsLibrary/Configuration.cs b/Samples/VAF/Logging/WithVAFExtensionsLibrary/Configuration.cs new file mode 100644 index 0000000..dd42eea --- /dev/null +++ b/Samples/VAF/Logging/WithVAFExtensionsLibrary/Configuration.cs @@ -0,0 +1,14 @@ +using MFiles.VAF.Configuration; +using MFiles.VAF.Configuration.JsonAdaptor; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace WithVAFExtensionsLibrary +{ + [DataContract] + public class Configuration + : MFiles.VAF.Extensions.Configuration.ConfigurationBase + { + } +} \ No newline at end of file diff --git a/Samples/VAF/Logging/WithVAFExtensionsLibrary/VaultApplication.cs b/Samples/VAF/Logging/WithVAFExtensionsLibrary/VaultApplication.cs new file mode 100644 index 0000000..c6b573f --- /dev/null +++ b/Samples/VAF/Logging/WithVAFExtensionsLibrary/VaultApplication.cs @@ -0,0 +1,42 @@ +using MFiles.VAF; +using MFiles.VAF.AppTasks; +using MFiles.VAF.Common; +using MFiles.VAF.Configuration; +using MFiles.VAF.Core; +using MFiles.VAF.Extensions.Dashboards; +using MFiles.VaultApplications.Logging; +using MFilesAPI; +using System; +using System.Diagnostics; + +namespace WithVAFExtensionsLibrary +{ + /// + /// This shows how to log in the VAF (https://developer.m-files.com/Frameworks/Logging/Vault-Application-Framework/) + /// using the VAF Extensions library. + /// + public class VaultApplication + : MFiles.VAF.Extensions.ConfigurableVaultApplicationBase + { + + /// + /// Registers a task queue with ID "LoggingWithVAFExtensionsLibrary". + /// + // Note: this queue ID must be unique to this application! + [TaskQueue] + public const string TaskQueueID = "LoggingWithVAFExtensionsLibrary"; + public const string TaskType = "WriteLogEntries"; + + /// + /// Processes items of type on queue + /// + [TaskProcessor(TaskQueueID, TaskType, TransactionMode = TransactionMode.Unsafe)] + [ShowOnDashboard("Write Log Entries", ShowRunCommand = true)] + public void WriteLogEntriesTaskProcessor(ITaskProcessingJob job) + { + // You can log at different levels: https://developer.m-files.com/Frameworks/Logging/#log-levels + this.Logger?.Trace("Starting job"); + } + + } +} \ No newline at end of file diff --git a/Samples/VAF/Logging/WithVAFExtensionsLibrary/WithVAFExtensionsLibrary.csproj b/Samples/VAF/Logging/WithVAFExtensionsLibrary/WithVAFExtensionsLibrary.csproj new file mode 100644 index 0000000..2c881a4 --- /dev/null +++ b/Samples/VAF/Logging/WithVAFExtensionsLibrary/WithVAFExtensionsLibrary.csproj @@ -0,0 +1,85 @@ + + + net45 + WithVAFExtensionsLibrary + WithVAFExtensionsLibrary + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;DONOTDEPLOY + prompt + 4 + + + true + false + bin\Debug\ + TRACE;DEBUG;DONOTDEPLOY + full + AnyCPU + prompt + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/VAF/Logging/WithVAFExtensionsLibrary/appdef.xml b/Samples/VAF/Logging/WithVAFExtensionsLibrary/appdef.xml new file mode 100644 index 0000000..b081d24 --- /dev/null +++ b/Samples/VAF/Logging/WithVAFExtensionsLibrary/appdef.xml @@ -0,0 +1,26 @@ + + + 7e09c613-ff73-4041-a8e4-0ac1c9974e46 + WithVAFExtensionsLibrary + Example of how to use the logging library using the VAF Extensions library. + + 0.1 + + 20.5.0.0 + false + + + WithVAFExtensionsLibrary + WithVAFExtensionsLibrary.dll + WithVAFExtensionsLibrary.VaultApplication + Install + Uninstall + Initialize + Uninitialize + StartOperations + + + diff --git a/Samples/VAF/Logging/WithVAFExtensionsLibrary/install-application.ps1 b/Samples/VAF/Logging/WithVAFExtensionsLibrary/install-application.ps1 new file mode 100644 index 0000000..4b6df0a --- /dev/null +++ b/Samples/VAF/Logging/WithVAFExtensionsLibrary/install-application.ps1 @@ -0,0 +1,143 @@ +param( + + [Parameter(Mandatory=$False)] + [string[]] $InstallGroups=@() + +) + +# Load M-Files API. +$null = [System.Reflection.Assembly]::LoadWithPartialName("Interop.MFilesAPI") + +# Load the version from the appdef file. +$version = ""; +try{ + [xml]$appDef = Get-Content "appdef.xml"; + $version = Select-Xml -Xml $appDef -XPath "//version" +} +catch{} + +# Application details +$appFilePath = "bin\Debug\WithVAFExtensionsLibrary-" + $version + ".mfappx" +$appGuid = "7e09c613-ff73-4041-a8e4-0ac1c9974e46" + +# Target vault +$vaultName = "Sample Vault" + +# Connection details +$authType = [MFilesAPI.MFAuthType]::MFAuthTypeLoggedOnWindowsUser +$userName = "" +$password = "" +$domain = "" +$spn = "" +$protocolSequence = "ncacn_ip_tcp" +$networkAddress = "localhost" +$endpoint = 2266 +$encryptedConnection = $false +$localComputerName = "" + +# Default to reporting an error if the script fails. +$ErrorActionPreference = 'Stop' + +# Append the current path so we have the full location (required in some situations). +$currentDir = Get-Location +$appFilePath = Join-Path $currentDir $appFilePath + +# If we are using install-application.user.json then parse the vault connections. +$doesInstallApplicationUserFileExist = $false +$vaultConnections = @() +try { + Write-Output " Parsing install-application.user.json (if available)..." + $jsonInput = Get-Content -Path install-application.user.json | ConvertFrom-Json + if($InstallGroups.Count -eq 0) { + Write-Output " No install groups given, proceeding with default." + $InstallGroups += "default" + } + ForEach($jsonConnection in $jsonInput.VaultConnections) { + $doesInstallApplicationUserFileExist = $true + + ForEach($ig in $InstallGroups) { + # if no groups, include to default + if(-not $jsonConnection.installGroups) { + if($InstallGroups -contains "default") { + $vaultConnections += $jsonConnection + Write-Output " Will deploy to $($jsonConnection.vaultName) on $($jsonConnection.networkAddress), as the declaration has no groups defined (included in default)." + } + break; # The connection has no groups, no further looping is needed + } + if($jsonConnection.InstallGroups -contains $ig) { + $vaultConnections += $jsonConnection + Write-Output " Will deploy to $($jsonConnection.vaultName) on $($jsonConnection.networkAddress), as the declaration has group $($ig) defined." + break; + } + } + } +} +catch [System.IO.FileNotFoundException], [System.Management.Automation.ItemNotFoundException] +{ + # This is fine; the user is probably not using this approach for deployment. + Write-Output " install-application.user.json file not found; using data from install-application.ps1." +} +catch { + # Write the exception out and throw so that we stop execution. + Write-Error -Exception $error[0].Exception + throw; +} +finally +{ + $error.clear(); +} +# If we are not using an external JSON file +# then use the connection/authentication information defined at the top of the file. +if(-not $doesInstallApplicationUserFileExist) { + $vaultConnections += [PSCustomObject]@{ + vaultName = $vaultName + authType = $authType + userName = $userName + password = $password + domain = $domain + spn = $spn + protocolSequence = $protocolSequence + networkAddress = $networkAddress + endpoint = $endpoint + encryptedConnection = $encryptedConnection + localComputerName = $localComputerName + } +} + +ForEach($vc in $vaultConnections) { + # Connect to M-Files Server. + Write-Host " Connecting to '$($vc.vaultName)' on $($vc.networkAddress)..." + $server = new-object MFilesAPI.MFilesServerApplicationClass + $tzi = new-object MFilesAPI.TimeZoneInformationClass + $tzi.LoadWithCurrentTimeZone() + $null = $server.ConnectAdministrativeEx( $tzi, $vc.authType, $vc.userName, $vc.password, $vc.domain, $vc.spn, $vc.protocolSequence, $vc.networkAddress, $vc.endpoint, $vc.encryptedConnection, $vc.localComputerName ) + # Get the target vault. + $vaultOnServer = $server.GetOnlineVaults().GetVaultByName( $vc.vaultName ) + # Login to vault. + $vault = $vaultOnServer.LogIn() + # Install application. + Write-Host " Installing application..." + try { + $vault.CustomApplicationManagementOperations.InstallCustomApplication( $appFilePath ) + # Restart vault. + Write-Host " Restarting vault..." + $server.VaultManagementOperations.TakeVaultOffline( $vaultOnServer.GUID, $true ) + $server.VaultManagementOperations.BringVaultOnline( $vaultOnServer.GUID ) + # Short sleep to prevent SQL errors on logging in. + Start-Sleep -Milliseconds 500 + # Login to vault again. + $vault = $vaultOnServer.LogIn() + } catch { + # Already exists + if($_.Exception -Match "0x80040031") { + Write-Host " This application version already exists on the vault, installation skipped" + } + else { + if($_.Exception -Match "0x8004091E") { + Write-Host " A newer version of this application is already installed on the vault, installation skipped" + } else { + throw + } + } + } +} \ No newline at end of file diff --git a/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/Configuration.cs b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/Configuration.cs new file mode 100644 index 0000000..22b77b3 --- /dev/null +++ b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/Configuration.cs @@ -0,0 +1,16 @@ +using MFiles.VAF.Configuration; +using MFiles.VAF.Configuration.JsonAdaptor; +using MFiles.VaultApplications.Logging.NLog; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace WithoutVAFExtensionsLibrary +{ + [DataContract] + public class Configuration + { + [DataMember] + public NLogLoggingConfiguration LoggingConfiguration { get; set; } = new NLogLoggingConfiguration(); + } +} \ No newline at end of file diff --git a/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/VaultApplication.cs b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/VaultApplication.cs new file mode 100644 index 0000000..24a3fb3 --- /dev/null +++ b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/VaultApplication.cs @@ -0,0 +1,106 @@ +using MFiles.VAF; +using MFiles.VAF.AppTasks; +using MFiles.VAF.Common; +using MFiles.VAF.Configuration; +using MFiles.VAF.Core; +using MFiles.VaultApplications.Logging; +using MFiles.VaultApplications.Logging.Resources; +using MFilesAPI; +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace WithoutVAFExtensionsLibrary +{ + /// + /// This shows how to log in the VAF (https://developer.m-files.com/Frameworks/Logging/Vault-Application-Framework/). + /// This sample does not require the VAF Extensions library. + /// + public class VaultApplication + : ConfigurableVaultApplicationBase + { + + /// + /// Handles the event. + /// + /// The vault/object environment. + [EventHandler(MFEventHandlerType.MFEventHandlerBeforeCheckInChangesFinalize)] + public void BeforeCheckInChangesFinalize(EventHandlerEnvironment env) + { + // You can log at different levels: https://developer.m-files.com/Frameworks/Logging/#log-levels + this.Logger?.Trace("Starting job"); + } + + #region Boilerplate required + + /// + /// The logger for this class. + /// + public ILogger Logger { get; private set; } + + /// + protected override void StartApplication() + { + base.StartApplication(); + +#if DEBUG + // Enable logging to any attached debugger, but do not launch the debugger. + LogManager.EnableLoggingToAttachedDebugger(launchDebugger: false); +#endif + + // Initialize the log manager and this class' logger. + LogManager.Initialize(this.PermanentVault, this.Configuration?.LoggingConfiguration); + this.Logger = LogManager.GetLogger(this.GetType()); + this.Logger?.Info("Logging started"); + + } + + /// + protected override void UninitializeApplication(Vault vault) + { + // Ensure all logging is stopped. + this.Logger?.Info("Logging stopping"); + LogManager.Shutdown(); + base.UninitializeApplication(vault); + } + + /// + protected override void OnConfigurationUpdated(Configuration oldConfiguration, bool updateExternals) + { + // Ensure that the logging configuration is updated. + this.Logger?.Info("Logging configuration updating"); + base.OnConfigurationUpdated(oldConfiguration, updateExternals); + LogManager.UpdateConfiguration(this.Configuration?.LoggingConfiguration); + this.Logger?.Info("Logging configuration updated"); + } + + /// + // Sets up the combined resource manager so that the strings from the logging + // exceptions and configuration work. + protected override SecureConfigurationManager GetConfigurationManager() + { + var configurationManager = base.GetConfigurationManager(); + + // Set the resource manager for the configuration manager. + var combinedResourceManager = new CombinedResourceManager(true, configurationManager.ResourceManager); + + // Set the resource manager for the configuration. + configurationManager.ResourceManager = combinedResourceManager; + return configurationManager; + } + + /// + protected override IEnumerable CustomValidation(Vault vault, Configuration config) + { + // Return any base validation errors. + foreach (var finding in base.CustomValidation(vault, config) ?? new ValidationFinding[0]) + yield return finding; + + // Add in the logging validation errors. + foreach (var finding in config?.LoggingConfiguration?.GetValidationFindings() ?? new ValidationFinding[0]) + yield return finding; + } + + #endregion + } +} \ No newline at end of file diff --git a/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/WithoutVAFExtensionsLibrary.csproj b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/WithoutVAFExtensionsLibrary.csproj new file mode 100644 index 0000000..8e485e8 --- /dev/null +++ b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/WithoutVAFExtensionsLibrary.csproj @@ -0,0 +1,85 @@ + + + net45 + WithoutVAFExtensionsLibrary + WithoutVAFExtensionsLibrary + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;DONOTDEPLOY + prompt + 4 + + + true + false + bin\Debug\ + TRACE;DEBUG;DONOTDEPLOY + full + AnyCPU + prompt + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/appdef.xml b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/appdef.xml new file mode 100644 index 0000000..988002d --- /dev/null +++ b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/appdef.xml @@ -0,0 +1,26 @@ + + + 7653b064-8618-44ae-95a0-ddfa6cb20c07 + WithoutVAFExtensionsLibrary + Example of how to use the logging library without the VAF Extensions library. + + 0.1 + + 20.5.0.0 + false + + + WithoutVAFExtensionsLibrary + WithoutVAFExtensionsLibrary.dll + WithoutVAFExtensionsLibrary.VaultApplication + Install + Uninstall + Initialize + Uninitialize + StartOperations + + + diff --git a/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/install-application.ps1 b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/install-application.ps1 new file mode 100644 index 0000000..3546217 --- /dev/null +++ b/Samples/VAF/Logging/WithoutVAFExtensionsLibrary/install-application.ps1 @@ -0,0 +1,143 @@ +param( + + [Parameter(Mandatory=$False)] + [string[]] $InstallGroups=@() + +) + +# Load M-Files API. +$null = [System.Reflection.Assembly]::LoadWithPartialName("Interop.MFilesAPI") + +# Load the version from the appdef file. +$version = ""; +try{ + [xml]$appDef = Get-Content "appdef.xml"; + $version = Select-Xml -Xml $appDef -XPath "//version" +} +catch{} + +# Application details +$appFilePath = "bin\Debug\WithoutVAFExtensionsLibrary-" + $version + ".mfappx" +$appGuid = "7653b064-8618-44ae-95a0-ddfa6cb20c07" + +# Target vault +$vaultName = "Sample Vault" + +# Connection details +$authType = [MFilesAPI.MFAuthType]::MFAuthTypeLoggedOnWindowsUser +$userName = "" +$password = "" +$domain = "" +$spn = "" +$protocolSequence = "ncacn_ip_tcp" +$networkAddress = "localhost" +$endpoint = 2266 +$encryptedConnection = $false +$localComputerName = "" + +# Default to reporting an error if the script fails. +$ErrorActionPreference = 'Stop' + +# Append the current path so we have the full location (required in some situations). +$currentDir = Get-Location +$appFilePath = Join-Path $currentDir $appFilePath + +# If we are using install-application.user.json then parse the vault connections. +$doesInstallApplicationUserFileExist = $false +$vaultConnections = @() +try { + Write-Output " Parsing install-application.user.json (if available)..." + $jsonInput = Get-Content -Path install-application.user.json | ConvertFrom-Json + if($InstallGroups.Count -eq 0) { + Write-Output " No install groups given, proceeding with default." + $InstallGroups += "default" + } + ForEach($jsonConnection in $jsonInput.VaultConnections) { + $doesInstallApplicationUserFileExist = $true + + ForEach($ig in $InstallGroups) { + # if no groups, include to default + if(-not $jsonConnection.installGroups) { + if($InstallGroups -contains "default") { + $vaultConnections += $jsonConnection + Write-Output " Will deploy to $($jsonConnection.vaultName) on $($jsonConnection.networkAddress), as the declaration has no groups defined (included in default)." + } + break; # The connection has no groups, no further looping is needed + } + if($jsonConnection.InstallGroups -contains $ig) { + $vaultConnections += $jsonConnection + Write-Output " Will deploy to $($jsonConnection.vaultName) on $($jsonConnection.networkAddress), as the declaration has group $($ig) defined." + break; + } + } + } +} +catch [System.IO.FileNotFoundException], [System.Management.Automation.ItemNotFoundException] +{ + # This is fine; the user is probably not using this approach for deployment. + Write-Output " install-application.user.json file not found; using data from install-application.ps1." +} +catch { + # Write the exception out and throw so that we stop execution. + Write-Error -Exception $error[0].Exception + throw; +} +finally +{ + $error.clear(); +} +# If we are not using an external JSON file +# then use the connection/authentication information defined at the top of the file. +if(-not $doesInstallApplicationUserFileExist) { + $vaultConnections += [PSCustomObject]@{ + vaultName = $vaultName + authType = $authType + userName = $userName + password = $password + domain = $domain + spn = $spn + protocolSequence = $protocolSequence + networkAddress = $networkAddress + endpoint = $endpoint + encryptedConnection = $encryptedConnection + localComputerName = $localComputerName + } +} + +ForEach($vc in $vaultConnections) { + # Connect to M-Files Server. + Write-Host " Connecting to '$($vc.vaultName)' on $($vc.networkAddress)..." + $server = new-object MFilesAPI.MFilesServerApplicationClass + $tzi = new-object MFilesAPI.TimeZoneInformationClass + $tzi.LoadWithCurrentTimeZone() + $null = $server.ConnectAdministrativeEx( $tzi, $vc.authType, $vc.userName, $vc.password, $vc.domain, $vc.spn, $vc.protocolSequence, $vc.networkAddress, $vc.endpoint, $vc.encryptedConnection, $vc.localComputerName ) + # Get the target vault. + $vaultOnServer = $server.GetOnlineVaults().GetVaultByName( $vc.vaultName ) + # Login to vault. + $vault = $vaultOnServer.LogIn() + # Install application. + Write-Host " Installing application..." + try { + $vault.CustomApplicationManagementOperations.InstallCustomApplication( $appFilePath ) + # Restart vault. + Write-Host " Restarting vault..." + $server.VaultManagementOperations.TakeVaultOffline( $vaultOnServer.GUID, $true ) + $server.VaultManagementOperations.BringVaultOnline( $vaultOnServer.GUID ) + # Short sleep to prevent SQL errors on logging in. + Start-Sleep -Milliseconds 500 + # Login to vault again. + $vault = $vaultOnServer.LogIn() + } catch { + # Already exists + if($_.Exception -Match "0x80040031") { + Write-Host " This application version already exists on the vault, installation skipped" + } + else { + if($_.Exception -Match "0x8004091E") { + Write-Host " A newer version of this application is already installed on the vault, installation skipped" + } else { + throw + } + } + } +} \ No newline at end of file