/// <summary> /// Helper to create the location of a file /// </summary> private void ScanFiles(LanguageConfig languageConfig) { var directories = new List <string>(); if (languageConfig.SpecifiedDirectories != null) { directories.AddRange(languageConfig.SpecifiedDirectories); } if (languageConfig.CheckStartupDirectory) { var startupDirectory = FileLocations.StartupDirectory; if (startupDirectory != null) { directories.Add(Path.Combine(startupDirectory, "languages")); } } if (languageConfig.CheckAppDataDirectory) { var appDataDirectory = FileLocations.RoamingAppDataDirectory(languageConfig.ApplicationName); if (appDataDirectory != null) { directories.Add(Path.Combine(appDataDirectory, "languages")); } } if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Scanning directories: {0}", string.Join(",", directories)); } Files = FileLocations.Scan(directories, _filePattern) .GroupBy(x => x.Item2.Groups["IETF"].Value) .ToDictionary(group => group.Key, group => group.Select(x => x.Item1) .ToList()); if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Detected language ietfs: {0}", string.Join(",", Files.Keys)); } var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures) .ToLookup(e => e.IetfLanguageTag, StringComparer.OrdinalIgnoreCase).ToDictionary(x => x.Key, x => x.First()); // TODO: Create custom culture for all not available, see: https://msdn.microsoft.com/en-us/library/ms172469(v=vs.90).aspx // TODO: Add Embedded resources, especially for the assemblies to which ILanguage interfaces belong AvailableLanguages = (from ietf in Files.Keys where allCultures.ContainsKey(ietf) select ietf).Distinct().ToDictionary(ietf => ietf, ietf => allCultures[ietf].NativeName); if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Languages found: {0}", string.Join(",", AvailableLanguages.Keys)); } }
/// <summary> /// Ends session. No additional authorization required. /// </summary> /// <param name="jiraClient">ISessionDomain to bind the extension method to</param> /// <param name="cancellationToken">CancellationToken</param> public static async Task EndAsync(this ISessionDomain jiraClient, CancellationToken cancellationToken = default(CancellationToken)) { // Find the cookie to expire var sessionCookies = jiraClient.Behaviour.CookieContainer.GetCookies(jiraClient.JiraBaseUri).Cast <Cookie>().ToList(); Log.Debug().WriteLine("Ending session"); // check if a cookie was found, if not skip the end session if (sessionCookies.Any()) { if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Found {0} cookies to invalidate", sessionCookies.Count); foreach (var sessionCookie in sessionCookies) { Log.Debug().WriteLine("Found cookie {0} for domain {1} which expires on {2}", sessionCookie.Name, sessionCookie.Domain, sessionCookie.Expires); } } var sessionUri = jiraClient.JiraAuthUri.AppendSegments("session"); jiraClient.Behaviour.MakeCurrent(); var response = await sessionUri.DeleteAsync <HttpResponseMessage>(cancellationToken).ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.NoContent) { Log.Warn().WriteLine("Failed to close jira session. Status code: {0} ", response.StatusCode); } // Expire the cookie, no mather what the return code was. foreach (var sessionCookie in sessionCookies) { sessionCookie.Expired = true; } } }
/// <summary> /// Create a IWebProxy Object which can be used to access the Internet /// This method will check the configuration if the proxy is allowed to be used. /// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins /// </summary> /// <param name="uri"></param> /// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns> public static IWebProxy CreateProxy(Uri uri) { if (!Config.UseProxy) { return(null); } IWebProxy proxyToUse = WebRequest.DefaultWebProxy; if (proxyToUse != null) { proxyToUse.Credentials = CredentialCache.DefaultCredentials; if (!Log.IsDebugEnabled()) { return(proxyToUse); } // check the proxy for the Uri if (!proxyToUse.IsBypassed(uri)) { var proxyUri = proxyToUse.GetProxy(uri); if (proxyUri != null) { Log.Debug().WriteLine("Using proxy: " + proxyUri + " for " + uri); } else { Log.Debug().WriteLine("No proxy found!"); } } else { Log.Debug().WriteLine("Proxy bypass for: " + uri); } } else { Log.Debug().WriteLine("No proxy found!"); } return(proxyToUse); }
/// <summary> /// Get server information /// See: https://docs.atlassian.com/jira/REST/latest/#d2e3828 /// </summary> /// <param name="jiraClient">IServerDomain to bind the extension method to</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>ServerInfo</returns> public static async Task <ServerInfo> GetInfoAsync(this IServerDomain jiraClient, CancellationToken cancellationToken = default) { Log.Debug().WriteLine("Retrieving server information"); var serverInfoUri = jiraClient.JiraRestUri.AppendSegments("serverInfo"); jiraClient.Behaviour.MakeCurrent(); var response = await serverInfoUri.GetAsAsync <HttpResponse <ServerInfo, Error> >(cancellationToken).ConfigureAwait(false); if (Log.IsDebugEnabled() && !response.HasError) { var serverInfo = response.Response; Log.Debug().WriteLine("Server title {0}, version {1}, uri {2}, build date {3}, build number {4}, scm info {5}", serverInfo.ServerTitle, serverInfo.Version, serverInfo.BaseUrl, serverInfo.BuildDate, serverInfo.BuildNumber, serverInfo.ScmInfo); } return(response.HandleErrors()); }
/// <summary> /// This creates the capture form /// </summary> /// <param name="coreConfiguration">ICoreConfiguration</param> /// <param name="capture">ICapture</param> /// <param name="windows">IList of IInteropWindow</param> public CaptureForm(ICoreConfiguration coreConfiguration, ICapture capture, IList <IInteropWindow> windows) : base(coreConfiguration, null) { _coreConfiguration = coreConfiguration; _isZoomerTransparent = _coreConfiguration.ZoomerOpacity < 1; ManualLanguageApply = true; ManualStoreFields = true; // Enable the AnimatingForm EnableAnimation = true; _capture = capture; _windows = windows; UsedCaptureMode = capture.CaptureDetails.CaptureMode; // // The InitializeComponent() call is required for Windows Forms designer support. // InitializeComponent(); Text = "Greenshot capture form"; // Log at close if (Log.IsDebugEnabled()) { FormClosing += (s, e) => Log.Debug().WriteLine("Closing captureform"); } // set cursor location _cursorPos = _mouseMovePos = WindowCapture.GetCursorLocationRelativeToScreenBounds(); // Initialize the animations, the window capture zooms out from the cursor to the window under the cursor if (UsedCaptureMode == CaptureMode.Window) { _windowAnimator = new RectangleAnimator(new NativeRect(_cursorPos, NativeSize.Empty), _captureRect, FramesForMillis(700), EasingTypes.Quintic, EasingModes.EaseOut); } // Set the zoomer animation InitializeZoomer(_coreConfiguration.ZoomerEnabled); Bounds = capture.ScreenBounds; // Fix missing focus ToFront = true; TopMost = true; }
public static async Task <int> Main(string[] args) { LogSettings.RegisterDefaultLogger <DebugLogger>(LogLevels.Verbose); var applicationConfig = ApplicationConfigBuilder.Create() .WithApplicationName("DemoConsoleApp") .WithScanDirectories( #if DEBUG @"..\..\..\..\Dapplo.Addons.TestAddonWithCostura\bin\Debug\netstandard2.0", #else @"..\..\..\..\Dapplo.Addons.TestAddonWithCostura\bin\Release\netstandard2.0", #endif FileLocations.StartupDirectory, @"MyOtherLibs" ) .WithAssemblyNames("Dapplo.HttpExtensions", "Dapplo.Addons.TestAddonWithCostura").BuildApplicationConfig(); using (var bootstrapper = new ApplicationBootstrapper(applicationConfig)) { #if DEBUG bootstrapper.EnableActivationLogging = true; #endif bootstrapper.Configure(); await bootstrapper.InitializeAsync().ConfigureAwait(false); bootstrapper.Container.Resolve <ServiceStartupShutdown>(); // Find all, currently, available assemblies if (Log.IsDebugEnabled()) { foreach (var resource in bootstrapper.Resolver.EmbeddedAssemblyNames()) { Log.Debug().WriteLine("Available embedded assembly {0}", resource); } } Assembly.Load("Dapplo.HttpExtensions"); } return(0); }
/// <summary> /// Process the commandline arguments /// </summary> /// <param name="isAlreadyRunning">bool which specifies if the application is already running</param> /// <param name="arguments">string array with the arguments</param> public void Process(bool isAlreadyRunning, string[] arguments) { var filesToOpen = new List <string>(); if (arguments.Length > 0 && Log.IsDebugEnabled()) { Log.Debug().WriteLine("Greenshot arguments: " + string.Join(",", arguments.Select(s => $"\"{s}\""))); } for (var argumentNr = 0; argumentNr < arguments.Length; argumentNr++) { var argument = arguments[argumentNr]; switch (argument) { case "/help": case "/h": case "/?": break; } // Help if (argument.ToLower().Equals("/help") || argument.ToLower().Equals("/h") || argument.ToLower().Equals("/?")) { // Try to attach to the console var attachedToConsole = Kernel32Api.AttachConsole(Kernel32Api.ATTACHCONSOLE_ATTACHPARENTPROCESS); // If attach didn't work, open a console if (!attachedToConsole) { Kernel32Api.AllocConsole(); } var helpOutput = new StringBuilder(); helpOutput.AppendLine(); helpOutput.AppendLine("Greenshot commandline options:"); helpOutput.AppendLine().AppendLine(); helpOutput.AppendLine("\t/help"); helpOutput.AppendLine("\t\tThis help."); helpOutput.AppendLine().AppendLine(); helpOutput.AppendLine("\t/exit"); helpOutput.AppendLine("\t\tTries to close all running instances."); helpOutput.AppendLine().AppendLine(); helpOutput.AppendLine("\t/reload"); helpOutput.AppendLine("\t\tReload the configuration of Greenshot."); helpOutput.AppendLine().AppendLine(); helpOutput.AppendLine("\t/language [language code]"); helpOutput.AppendLine("\t\tSet the language of Greenshot, e.g. greenshot /language en-US."); helpOutput.AppendLine().AppendLine(); helpOutput.AppendLine("\t/inidirectory [directory]"); helpOutput.AppendLine("\t\tSet the directory where the greenshot.ini should be stored & read."); helpOutput.AppendLine().AppendLine(); helpOutput.AppendLine("\t[filename]"); helpOutput.AppendLine("\t\tOpen the bitmap files in the running Greenshot instance or start a new instance"); helpOutput.AppendLine(); helpOutput.AppendLine(); helpOutput.AppendLine("\t/capture <region|window|fullscreen>[,Destination]"); helpOutput.AppendLine("\t\tStart capture from command line. Use /capture without arguments for more info. Greenshot must be running"); Console.WriteLine(helpOutput.ToString()); // If attach didn't work, wait for key otherwise the console will close to quickly if (!attachedToConsole) { Console.ReadKey(); } // TODO: //FreeMutex(); return; } if (argument.ToLower().Equals("/exit")) { // unregister application on uninstall (allow uninstall) try { Log.Info().WriteLine("Sending all instances the exit command."); // Pass Exit to running instance, if any GreenshotClient.Exit(); } catch (Exception e) { Log.Warn().WriteLine(e, "Exception by exit."); } // TODO: //FreeMutex(); return; } // Reload the configuration if (argument.ToLower().Equals("/reload")) { // Modify configuration Log.Info().WriteLine("Reloading configuration!"); try { // Update running instances GreenshotClient.ReloadConfig(); } catch (Exception ex) { Log.Error().WriteLine(ex, "Couldn't reload configuration."); } // TODO: /* * finally * { * FreeMutex(); * } */ return; } // Stop running if (argument.ToLower().Equals("/norun")) { // Make an exit possible // TODO: //FreeMutex(); return; } // Language if (argument.ToLower().Equals("/language")) { _coreConfiguration.Language = arguments[++argumentNr]; continue; } // Setting the INI-directory if (argument.ToLower().Equals("/inidirectory")) { // Change the ini config location //IniConfig.Current.IniDirectory = arguments[++argumentNr]; continue; } // Capture from command line, only accept as first argument if (arguments.Length > 0 && arguments[0].ToLower().Equals("/capture")) { // Try to attach to the console bool attachedToConsole = Kernel32Api.AttachConsole(Kernel32Api.ATTACHCONSOLE_ATTACHPARENTPROCESS); // If attach didn't work, open a console if (!attachedToConsole) { Kernel32Api.AllocConsole(); } // Display help for /capture command if not enough arguments if (arguments.Length < 2) { var helpOutput = new StringBuilder(); helpOutput.AppendLine(); helpOutput.AppendLine(); helpOutput.AppendLine("Usage for /capture:"); helpOutput.AppendLine("\t/capture <region|window|fullscreen>[,Destination]"); helpOutput.AppendLine(); helpOutput.AppendLine("\tDestinations: (CaseSensitive!)"); helpOutput.AppendFormat( "\t\t{0,-16}\t==>\t{1}{2}", "\"External CmdName\"", "External Command like MS Paint", Environment.NewLine ); foreach (var destination in ServiceLocator.Current.GetAllInstances <IDestination>()) { helpOutput.AppendFormat( "\t\t{0,-16}\t==>\t{1}{2}", destination.Designation, destination.Description, Environment.NewLine ); } helpOutput.AppendLine(); helpOutput.AppendLine(); helpOutput.AppendLine("\tUsage examples:"); helpOutput.AppendLine("\t\t/capture window,FileNoDialog\t\t(capture window, save in default screenshot folder)"); helpOutput.AppendLine("\t\t/capture fullscreen\t\t\t(capture fullscreen, use destination from settings)"); helpOutput.AppendLine("\t\t/capture region,Clipboard\t\t(capture region directly to clipboard)"); helpOutput.AppendLine("\t\t/capture fullscreen,Picker\t\t(capture fullscreen, ask what to do)"); helpOutput.AppendLine("\t\t/capture region,\"External MS Paint\"\t(capture region and send to external command 'MS Paint')"); helpOutput.AppendLine(); helpOutput.AppendLine("\tShortcut path examples for Windows:"); helpOutput.AppendLine("\t\t\"C:\\Program Files\\Greenshot\\Greenshot.exe\" /capture region,\"External MS Paint\""); helpOutput.AppendLine("\t\tD:\\Programme\\Greenshot\\Greenshot.exe /capture fullscreen,FileNoDialog"); helpOutput.AppendLine(); Console.WriteLine(helpOutput.ToString()); // If attach didn't work, wait for key otherwise the console will close to quickly if (!attachedToConsole) { Console.ReadKey(); } } else if (!isAlreadyRunning) { Console.WriteLine("{0}{0}Please start Greenshot first", Environment.NewLine); // If attach didn't work, wait for key otherwise the console will close to quickly if (!attachedToConsole) { Console.ReadKey(); } } else { GreenshotClient.Capture(arguments[1]); } // TODO: //FreeMutex(); return; } // Files to open filesToOpen.Add(argument); } if (isAlreadyRunning) { // We didn't initialize the language yet, do it here just for the message box if (filesToOpen.Count > 0) { GreenshotClient.OpenFiles(filesToOpen); } else { //ShowInstances(); } // TODO: //FreeMutex(); //Application.Exit(); return; } }
/// <summary> /// This will assert that the log levels work /// </summary> private static void AssertLogLevels(LogSource logSource, ILogger loggerUnderTest) { var initialLevel = loggerUnderTest.LogLevel; try { // Assert the log levels loggerUnderTest.LogLevel = LogLevels.None; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.False(logSource.IsWarnEnabled()); Assert.False(logSource.IsErrorEnabled()); Assert.False(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Verbose; Assert.True(logSource.IsVerboseEnabled()); Assert.True(logSource.IsDebugEnabled()); Assert.True(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Debug; Assert.False(logSource.IsVerboseEnabled()); Assert.True(logSource.IsDebugEnabled()); Assert.True(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Info; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.True(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Warn; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Error; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.False(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Fatal; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.False(logSource.IsWarnEnabled()); Assert.False(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); } finally { loggerUnderTest.LogLevel = initialLevel; } }
/// <summary> /// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the /// targetStream /// </summary> /// <param name="imageToProcess">Image to pass to the external process</param> /// <param name="targetStream">stream to write the processed image to</param> /// <returns></returns> private static bool ProcessPngImageExternally(Image imageToProcess, Stream targetStream) { if (string.IsNullOrEmpty(CoreConfig.OptimizePNGCommand)) { return(false); } if (!File.Exists(CoreConfig.OptimizePNGCommand)) { Log.Warn().WriteLine("Can't find 'OptimizePNGCommand' {0}", CoreConfig.OptimizePNGCommand); return(false); } var tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png"); try { using (var tmpStream = File.Create(tmpFileName)) { Log.Debug().WriteLine("Writing png to tmp file: {0}", tmpFileName); imageToProcess.Save(tmpStream, ImageFormat.Png); if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("File size before processing {0}", new FileInfo(tmpFileName).Length); } } if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Starting : {0}", CoreConfig.OptimizePNGCommand); } var processStartInfo = new ProcessStartInfo(CoreConfig.OptimizePNGCommand) { Arguments = string.Format(CoreConfig.OptimizePNGCommandArguments, tmpFileName), CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false }; using (var process = Process.Start(processStartInfo)) { if (process != null) { process.WaitForExit(); if (process.ExitCode == 0) { if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("File size after processing {0}", new FileInfo(tmpFileName).Length); Log.Debug().WriteLine("Reading back tmp file: {0}", tmpFileName); } var processedImage = File.ReadAllBytes(tmpFileName); targetStream.Write(processedImage, 0, processedImage.Length); return(true); } Log.Error().WriteLine("Error while processing PNG image: {0}", process.ExitCode); Log.Error().WriteLine("Output: {0}", process.StandardOutput.ReadToEnd()); Log.Error().WriteLine("Error: {0}", process.StandardError.ReadToEnd()); } } } catch (Exception e) { Log.Error().WriteLine(e, "Error while processing PNG image: "); } finally { if (File.Exists(tmpFileName)) { Log.Debug().WriteLine("Cleaning up tmp file: {0}", tmpFileName); File.Delete(tmpFileName); } } return(false); }
/// <summary> /// Initialize the bootstrapper /// </summary> public virtual async Task <bool> InitializeAsync(CancellationToken cancellationToken = default) { if (Container != null) { throw new NotSupportedException("Initialize can only be called once."); } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Initializing"); } await LoadAssemblies(cancellationToken).ConfigureAwait(false); Configure(); _builder.Properties[nameof(EnableActivationLogging)] = EnableActivationLogging.ToString(); // Process all assemblies, while doing this more might be loaded, so process those again var processedAssemblies = new HashSet <string>(); int countBefore; do { countBefore = Resolver.LoadedAssemblies.Count; var assembliesToProcess = Resolver.LoadedAssemblies.ToList() // Skip dynamic assemblies .Where(pair => !pair.Value.IsDynamic) // Ignore well know assemblies we don't care about .Where(pair => !Resolver.AssembliesToIgnore.IsMatch(pair.Key)) // Only scan the assemblies which reference Dapplo.Addons .Where(pair => pair.Value.GetReferencedAssemblies() .Any(assemblyName => string.Equals("Dapplo.Addons", assemblyName.Name, StringComparison.OrdinalIgnoreCase))) .Where(pair => processedAssemblies.Add(pair.Key)); foreach (var assemblyToProcess in assembliesToProcess) { try { if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Processing assembly {0}", assemblyToProcess.Key); } _builder.RegisterAssemblyModules(assemblyToProcess.Value); } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't read modules in {0}", assemblyToProcess.Key); } } } while (Resolver.LoadedAssemblies.Count > countBefore); // Now build the container try { Container = _builder.Build(); } catch (Exception ex) { Log.Error().WriteLine(ex, "Coudn't create the container."); throw; } // Inform that the container was created OnContainerCreated?.Invoke(Container); // And the scope Scope = Container.BeginLifetimeScope(); return(true); }
/// <summary> /// Load an assembly via a file, this used via Assembly.Load or Assembly.LoadFrom depending on where the file is or can be stored /// </summary> /// <param name="additionalInformation">AssemblyLocationInformation used for some decisions</param> /// <returns>Assembly</returns> private Assembly LoadFromFile(AssemblyLocationInformation additionalInformation) { // Get the assembly name from the file var assemblyName = AssemblyName.GetAssemblyName(additionalInformation.Filename); // Check the cache again, this time with the "real" name if (LoadedAssemblies.TryGetValue(assemblyName.Name, out var assembly)) { if (Log.IsInfoEnabled()) { Log.Info().WriteLine("Returned {0} from cache.", assemblyName.Name); } return(assembly); } var destination = $@"{FileLocations.AddonsLocation}\{assemblyName.Name}.dll"; var destinationIsNotSource = !destination.Equals(additionalInformation.Filename, StringComparison.OrdinalIgnoreCase); if (Log.IsDebugEnabled() && !destinationIsNotSource) { Log.Debug().WriteLine("Skipping copy, as destination and source would be the same."); } if (_applicationConfig.CopyAssembliesToProbingPath && FileLocations.AddonsLocation != null && destinationIsNotSource) { try { if (ShouldWrite(additionalInformation, destination)) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Creating a copy of {0} to {1}, solving potential context loading issues.", additionalInformation.Filename, destination); } File.Copy(additionalInformation.Filename, destination); // Register delete on exit, this is done by calling a command _assembliesToDeleteAtExit.Add(destination); } // Load via the assembly name, it's not inside the probing path assembly = Assembly.Load(assemblyName); if (assembly != null) { return(assembly); } } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't create a copy of {0} to {1}.", additionalInformation.Filename, destination); } } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Loading {0} from {1}.", additionalInformation.Name, additionalInformation.Filename); } try { return(Assembly.LoadFrom(additionalInformation.Filename)); } catch (Exception ex) { Log.Error().WriteLine(ex, "Couldn't load assembly from file {0}", additionalInformation.Filename); } return(null); }