在使用 F# Interactive 时,我需要捕获 F# 函数的输入和输出.当程序在 Visual Studio 下使用 F5 或 Ctrl-F5 运行时,我能够让 NLog 正常工作.同样,包含要输出到日志的语句的相同方法也能正常工作,并且在通过 F# Interactive 调用时会被调用;日志文件中什么都没有.
我还尝试使用 F# Interactive 执行以下操作以设置对 NLog 的引用,但从 F# Interactive 运行时,日志中仍然没有任何内容.
#I @"..packagesNLog.2.0.0.2000lib et40"#r @"NLog.dll"我什至发现了
为所有三个项目安装 NLog.
2.a.手动创建 NLog.config注意:要使这些示例在 __SOURCE_DIRECTORY__;; 从 F# Interactive 运行时起作用,它应该报告作为项目一部分的目录,并且不是临时 目录.
注意:此答案中的所有路径都相对于解决方案目录.当您看到 替换为您实际的解决方案目录时.
路径:NLog.config
<目标><target xsi:type="文件"名称=文件"fileName="log.txt"自动冲洗=真"/></目标><规则><记录器名称="*"最小级别=跟踪"写入=文件"/></规则></nlog>注意:记得把改为实际路径并设置autoFlush="true"
注意:将 NLog.config 添加到解决方案中可以更轻松地查看/修改文件.
2.b.从正在运行的项目中访问 NLog.config在 Log.Library1.fs 中
命名空间日志模块 MyLog =让 configureNLog() =让 projectPath = __SOURCE_DIRECTORY__让 soulutionPath = projectPath + ".."让 configPath = soulutionPath + @"NLog.config"让 xmlConfig = new NLog.Config.XmlLoggingConfiguration(configPath)NLog.LogManager.Configuration out + (sprintf "%A " target)) out targets让规则 = NLog.LogManager.Configuration.LoggingRuleslet out = Seq.fold (fun out rule -> out + (sprintf "%A " rule)) out rules出去让 printNLogConfig() =printf.printfn "%s" (NLogConfigToString())并为 Log 项目添加对 System.XML
的引用在 Main.Program.fs 中
打开日志[]让主 argv =MyLog.configureNLog()MyLog.printNLogConfig()0//返回一个整数退出代码并为 Main 项目添加对 Log 项目的引用,并将 Main 项目设置为启动项目.
运行时应该输出到控制台:
文件目标[文件]logNamePattern: (:All) 级别:[跟踪调试信息警告错误致命] appendTo:[文件]2.c.将消息记录到文件中
在 Log.Library1.fs 中
命名空间日志打开 NLog模块 MyLog =让 configureNLog() =让 projectPath = __SOURCE_DIRECTORY__让 soulutionPath = projectPath + ".."让 configPath = soulutionPath + @"NLog.config"让 xmlConfig = new NLog.Config.XmlLoggingConfiguration(configPath)NLog.LogManager.Configuration out + (sprintf "%A " target)) out targets让规则 = NLog.LogManager.Configuration.LoggingRuleslet out = Seq.fold (fun out rule -> out + (sprintf "%A " rule)) out rules出去让 printNLogConfig() =printf.printfn "%s" (NLogConfigToString())让 evalTracer = LogManager.GetLogger("file")在 Main.Program.fs 中
打开日志打开图书馆1[]让主 argv =MyLog.configureNLog()MyLog.printNLogConfig()//根据需要添加尽可能多的这些MyLog.evalTracer.Trace("在主@1.")MyFunctions.test001()0//返回一个整数退出代码并为 Main 项目添加对 MyLibrary 项目的引用.
在 MyLibrary.Library1.fs 中
namespace Library1打开日志模块 MyFunctions =让 test001 () =MyLog.evalTracer.Trace("在图书馆@1.")并为 MyLibrary 项目添加对 Log 项目的引用.
运行时日志文件log.txt应该包含类似的内容:
2016-03-28 11:03:52.4963|TRACE|file|In Main @1.2016-03-28 11:03:52.5263|TRACE|文件|在图书馆@13.a.以编程方式创建配置
如果存在 NLog.config 文件,请删除它以验证代码创建了新配置但没有创建文件.
要使用 F# 以编程方式设置配置,您需要知道:
到 Log.Library1.fs 添加
让 configureNLogPrgramatically () =让 config = new NLog.Config.LoggingConfiguration()让 fileTarget = new NLog.Targets.FileTarget()让 projectPath = __SOURCE_DIRECTORY__让 soulutionPath = projectPath + ".."让 filePath = soulutionPath + @"log.txt"让布局 = 新 NLog.Layouts.SimpleLayout(filePath)fileTarget.Name <-文件"fileTarget.FileName <- 布局fileTarget.AutoFlush <- 真config.AddTarget("file", fileTarget)let rule1 = new NLog.Config.LoggingRule("*",NLog.LogLevel.Trace,fileTarget)config.LoggingRules.Add(rule1)NLog.LogManager.Configuration <- 配置3.b.为正在运行的项目创建配置并将消息记录到文件中
在 Main.Program.fs 中
打开日志打开图书馆1[]让主 argv =MyLog.configureNLogPrgramatically ()MyLog.printNLogConfig()//根据需要添加尽可能多的这些MyLog.evalTracer.Trace("在主@1.")MyFunctions.test001()0//返回一个整数退出代码运行时日志文件log.txt应该包含类似的内容:
2016-03-28 11:16:07.2901|TRACE|file|In Main @1.2016-03-28 11:16:07.3181|TRACE|文件|在图书馆@1.并注意 NLog.config 文件是未创建的.
4.使用 F# Interactive 创建配置并将消息记录到文件中在 MyLibrary.Script.fsx 中
//打印出 __SOURCE_DIRECTORY__ 以确保我们没有使用 Temp 目录printfn __SOURCE_DIRECTORY__#我 __SOURCE_DIRECTORY__//通知 F# Interactive 在哪里可以找到日志模块中的函数#I "../Log/bin/Debug/"#r "Log.dll"打开日志//现在可以运行日志模块中的函数.MyLog.configureNLogPrgramatically ()MyLog.printNLogConfig()//通知 F# Interactive 在哪里可以找到 MyLibrary 模块中的函数#I "../MyLibrary/bin/Debug/"#r "MyLibrary.dll"打开图书馆1//现在可以运行 MyLibrary 模块中的函数.MyFunctions.test001()使用 F# Interactive 执行脚本时
Microsoft (R) F# Interactive version 14.0.23413.0版权所有 (c) 微软公司.版权所有.如需帮助,请输入 #help;;><解决方案目录>MyLibrary验证它:单位 = ()-->将 <Solution directory>MyLibrary' 添加到库包含路径-->将 <Solution directory>MyLibrary../Log/bin/Debug/' 添加到库包含路径-->引用MyLibrary../Log/bin/Debug/Log.dll'文件目标[文件]logNamePattern: (:All) 级别:[跟踪调试信息警告错误致命] appendTo:[文件]-->将 <Solution directory>MyLibrary../MyLibrary/bin/Debug/' 添加到库包含路径-->引用MyLibrary../MyLibrary/bin/Debug/MyLibrary.dll'验证它:单位 = ()>日志文件 log.txt 应该包含类似于:
2016-03-28 11:42:41.5417|TRACE|file|在图书馆@1.此外,这将在您仍有活动的 F# Interactive 会话时记录,因此您可以在执行命令之间查看日志.
I have a need to capture the input and output of F# functions when using F# Interactive. I am able to get NLog to work just fine when the program is run under Visual Studio using F5 or Ctrl-F5. Also the same methods that contain statements to output to the log work just fine and are called when invoked via F# Interactive; just nothing in the log file.
I also tried the following with F# Interactive to setup references to NLog and still nothing in the log when run from F# Interactive.
#I @"..packagesNLog.2.0.0.2000lib et40" #r @"NLog.dll"And I even found this which led me to try each of these
NLog.Config.SimpleConfigurator.ConfigureForConsoleLogging() NLog.Config.SimpleConfigurator.ConfigureForFileLogging(<full file name>)and still nothing in the log file.
Anyone know if Nlog can be used with F# Interactive? If so, how is it done?
EDIT
I was able to get NLog to work with fsi.exe when run as a stand alone. So now the problem appears to be getting NLog to find the config file because NLog cannot find the config file starting from the location of fsi.exe for Visual Studio. Looking at using NLog.dll.nlog in the NLog.dll directory.
解决方案The Problem
The problem with using NLog from F# Interactive is that NLog thinks that the Temp directory is where to find NLog.config and never succeeds. The way around this is to programmatically locate NLog.config for NLog.
Things to know to solve this problem:When you run F# Interactive from within Visual Studio, it sets the current working directory to a temp file.
> System.Environment.CurrentDirectory;; val it : string = "C:UsersEricAppDataLocalTemp"NLog logging requires three components: a. reference to NLog.dll. b. configuration file. c. calls to a logger method from code.
Instead of jumping right into the F# Interactive solution, the following progression will be used because a DLL will need to be created to setup and hold the functions for use with NLog from F# Interactive.
Create a solution with three projects and install NLog. Solution Name: NLogExample Project 1 - Library, Name: Log - holds extension functions that call NLog Project 2 - Library, Name: MyLibrary - used to generate a demo DLL that uses Log functions. Project 3 - Console Application, Name: Main - used to generate a demo EXE that uses Log functions.
a. Manually create NLog.config b. Access NLog.config from as a running project c. Log a message to the file
a. Programmatically create a configuration b. Create a configuration for a running project and log a message to the file
Create a configuration and log a message to the file using F# Interactive
1. Create a solution with three projects and install NLog
Using Visual Studio create the three projects.
Install NLog for all three projects.
2.a. Manually create NLog.configNote: For these examples to work when __SOURCE_DIRECTORY__;; is run from F# Interactive it should report a directory that is part of the project and NOT the Temp directory.
Note: All the paths in this answer are relative to the solution directory. When you see <Solution directory> substitute in your actual solution directory.
Path: <Solution director>NLog.config
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="www.nlog-project/schemas/NLog.xsd" xmlns:xsi="www.w3/2001/XMLSchema-instance" throwExceptions="true"> <targets> <target xsi:type="File" name="file" fileName="<Solution directory>log.txt" autoFlush="true" /> </targets> <rules> <logger name="*" minlevel="Trace" writeTo="file" /> </rules> </nlog>Note: Remember to change <Solution directory> to an actual path and set autoFlush="true"
Note: Adding NLog.config to the solution makes it easier to view/modify the file.
2.b. Access NLog.config from as a running projectIn Log.Library1.fs
namespace Log module MyLog = let configureNLog () = let projectPath = __SOURCE_DIRECTORY__ let soulutionPath = projectPath + ".." let configPath = soulutionPath + @"NLog.config" let xmlConfig = new NLog.Config.XmlLoggingConfiguration(configPath) NLog.LogManager.Configuration <- xmlConfig let NLogConfigToString () = let targets = NLog.LogManager.Configuration.AllTargets let out = "" let out = Seq.fold (fun out target -> out + (sprintf "%A " target)) out targets let rules = NLog.LogManager.Configuration.LoggingRules let out = Seq.fold (fun out rule -> out + (sprintf "%A " rule)) out rules out let printNLogConfig () = Printf.printfn "%s" (NLogConfigToString ())and for the Log project add a reference to System.XML
In Main.Program.fs
open Log [<EntryPoint>] let main argv = MyLog.configureNLog () MyLog.printNLogConfig () 0 // return an integer exit codeand for the Main project add a reference to the Log project and set the Main project as the startup project.
When run this should output to the console:
File Target[file] logNamePattern: (:All) levels: [ Trace Debug Info Warn Error Fatal ] appendTo: [ file ]2.c. Log a message to the file
In Log.Library1.fs
namespace Log open NLog module MyLog = let configureNLog () = let projectPath = __SOURCE_DIRECTORY__ let soulutionPath = projectPath + ".." let configPath = soulutionPath + @"NLog.config" let xmlConfig = new NLog.Config.XmlLoggingConfiguration(configPath) NLog.LogManager.Configuration <- xmlConfig let NLogConfigToString () = let targets = NLog.LogManager.Configuration.AllTargets let out = "" let out = Seq.fold (fun out target -> out + (sprintf "%A " target)) out targets let rules = NLog.LogManager.Configuration.LoggingRules let out = Seq.fold (fun out rule -> out + (sprintf "%A " rule)) out rules out let printNLogConfig () = Printf.printfn "%s" (NLogConfigToString ()) let evalTracer = LogManager.GetLogger("file")In Main.Program.fs
open Log open Library1 [<EntryPoint>] let main argv = MyLog.configureNLog () MyLog.printNLogConfig () // Add as many of these as needed MyLog.evalTracer.Trace("In Main @1.") MyFunctions.test001 () 0 // return an integer exit codeand for the Main project add a reference to the MyLibrary project.
In MyLibrary.Library1.fs
namespace Library1 open Log module MyFunctions = let test001 () = MyLog.evalTracer.Trace("In Library @1.")and for the MyLibrary project add a reference to the Log project.
When run the log file log.txt should contain something similar to:
2016-03-28 11:03:52.4963|TRACE|file|In Main @1. 2016-03-28 11:03:52.5263|TRACE|file|In Library @13.a. Programmatically create a configuration
If a NLog.config file exist delete it to verify that the code created a new configuration but did not create a file.
To set the configuration programmatically using F# you need to know:
To Log.Library1.fs add
let configureNLogPrgramatically () = let config = new NLog.Config.LoggingConfiguration() let fileTarget = new NLog.Targets.FileTarget() let projectPath = __SOURCE_DIRECTORY__ let soulutionPath = projectPath + ".." let filePath = soulutionPath + @"log.txt" let layout = new NLog.Layouts.SimpleLayout(filePath) fileTarget.Name <- "file" fileTarget.FileName <- layout fileTarget.AutoFlush <- true config.AddTarget("file", fileTarget) let rule1 = new NLog.Config.LoggingRule("*",NLog.LogLevel.Trace,fileTarget) config.LoggingRules.Add(rule1) NLog.LogManager.Configuration <- config3.b. Create a configuration for a running project and log a message to the file
In Main.Program.fs
open Log open Library1 [<EntryPoint>] let main argv = MyLog.configureNLogPrgramatically () MyLog.printNLogConfig () // Add as many of these as needed MyLog.evalTracer.Trace("In Main @1.") MyFunctions.test001 () 0 // return an integer exit codeWhen run the log file log.txt should contain something similar to:
2016-03-28 11:16:07.2901|TRACE|file|In Main @1. 2016-03-28 11:16:07.3181|TRACE|file|In Library @1.and note that a NLog.config file was NOT created.
4. Create a configuration and log a message to the file using F# InteractiveIn MyLibrary.Script.fsx
// print out __SOURCE_DIRECTORY__ to make sure we are not using the Temp directory printfn __SOURCE_DIRECTORY__ #I __SOURCE_DIRECTORY__ // Inform F# Interactive where to find functions in Log module #I "../Log/bin/Debug/" #r "Log.dll" open Log // Functions in Log module can now be run. MyLog.configureNLogPrgramatically () MyLog.printNLogConfig () // Inform F# Interactive where to find functions in MyLibrary module #I "../MyLibrary/bin/Debug/" #r "MyLibrary.dll" open Library1 // Functions in MyLibrary module can now be run. MyFunctions.test001 ()When the script is executed with F# Interactive
Microsoft (R) F# Interactive version 14.0.23413.0 Copyright (c) Microsoft Corporation. All Rights Reserved. For help type #help;; > <Solution directory>MyLibrary val it : unit = () --> Added <Solution directory>MyLibrary' to library include path --> Added <Solution directory>MyLibrary../Log/bin/Debug/' to library include path --> Referenced <Solution directory>MyLibrary../Log/bin/Debug/Log.dll' File Target[file] logNamePattern: (:All) levels: [ Trace Debug Info Warn Error Fatal ] appendTo: [ file ] --> Added <Solution directory>MyLibrary../MyLibrary/bin/Debug/' to library include path --> Referenced <Solution directory>MyLibrary../MyLibrary/bin/Debug/MyLibrary.dll' val it : unit = () >The log file log.txt should contain something similar to:
2016-03-28 11:42:41.5417|TRACE|file|In Library @1.Also, this will log while you still have an active F# Interactive session, so you can peek at the log between executing commands.
更多推荐
在 Visual Studio 中使用 NLog 和 F# Interactive
发布评论