简体   繁体   English

从fsx脚本编译时的F#管理引用

[英]F# managing references when compiling from fsx script

I need to interact with SharePoint (on premise) and decided to give a try to F#. 我需要与SharePoint交互(在前提下),并决定尝试F#。 It is or should be simple enough that I did it with CLI tools only. 仅使用CLI工具就可以做到这一点,或者应该足够简单。

I managed to interact with a site and get the info I needed. 我设法与一个网站进行交互并获得了所需的信息。 I struggled with the required DLL, but in the end 我为所需的DLL苦苦挣扎,但最后

#if INTERACTIVE
#r @"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
#r @"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

// seems to be required
#r @"[...]\Microsoft.Online.SharePoint.Client.Tenant.dll.15.0.4615.1001\Microsoft.Online.SharePoint.Client.Tenant.dll"

#r @"[...]\SharePointPnPCoreOnline.3.8.1904\lib\net45\OfficeDevPnP.Core.dll"

#endif

worked out with Fsi REPL or Fsi script.fsx , but I cannot make it compile, wether as a fs file or with the fsx script. 使用Fsi REPLFsi script.fsx ,但无论是fs文件还是fsx脚本,都无法编译。

My code is, say: 我的代码是:

open Microsoft.SharePoint.Client;;

let main () = 
    let authnManager = OfficeDevPnP.Core.AuthenticationManager()
    printfn "%A" authnManager
    0

main()

Running with fsi: 使用fsi运行:

PS> fsi script.fsx
OfficeDevPnP.Core.AuthenticationManager #OK!

Trying to compile: 尝试编译:

PowerShell>  fsc --warn:5 -r "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" `
>>      -r "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" `
>>      -r "absolute\path\to\Microsoft.Online.SharePoint.Client.Tenant.dll.15.0.4615.1001\Microsoft.Online.SharePoint.Client.Tenant.dll" `
>>      -r "absolute\path\to\SharePointPnPCoreOnline.3.8.1904\lib\net45\OfficeDevPnP.Core.dll"  .\script.fsx
Microsoft (R) F# Compiler version 10.4.0 for F# 4.6
Copyright (c) Microsoft Corporation. All Rights Reserved.

> .\script.exe

Exception non gérée (unmanaged exception) : System.IO.FileNotFoundException: 
Impossible de charger le fichier ou l'assembly 'OfficeDevPnP.Core,
Version=3.8.1904.0, Culture=neutral, PublicKeyToken=5e633289e95c321a'
ou une de ses dépendances. Le fichier spécifié est introuvable.
   à Script.main()
   à <StartupCode$script>.$Script$fsx.main@()

Why this difference? 为什么会有这种差异? What am I missing? 我想念什么? How to load references with fsc (as nuget installed quite a few transitive dependencies) ? 如何使用fsc加载引用(因为nuget安装了很多传递依赖项)? They must be managed as well with fsc as with fsi, for sure! 当然,必须同时使用fsc和fsi对它们进行管理! (Unless there's a specific issue with OfficeDevPnP.Core.dll ...) (除非OfficeDevPnP.Core.dll出现特定问题……)

I think the DLLs referenced via #r in F# Interactive need to be in dependency-order. 我认为在F#Interactive中通过#r引用的DLL必须处于依赖顺序。 So, if the SharePoint DLLs depend on the OfficeDevPnp DLL, then the OfficeDevPnp DLL needs to be referenced first (it's #r line needs to come before the SharePoint #r lines). 所以,如果在SharePoint的DLL取决于OfficeDevPnp DLL,然后OfficeDevPnp DLL需要先引用(这是#r行需要来将SharePoint前#r线)。 You will have to reset the interactive session once you've loaded the DLLs to re-load them in the correct order. 一旦您加载了DLL,就必须以正确的顺序重新设置交互式会话。

In general, loading package dependencies in F# interactive is quite tricky. 通常,在F#交互中加载程序包依赖项非常棘手。 There are some F# tools like Paket you can take a look at that might make your life a little easier. 您可以查看一些F#工具(例如Paket) ,这可能会使您的生活更轻松一些。 Another option, if you already have a Visual Studio project with the references you need, is to use that to generate the package references for your script file. 如果您已经有了一个带有所需引用的Visual Studio项目,则另一个选择是使用该项目为脚本文件生成程序包引用。 You can read the .fsproj file and generate the #r statements from the references used by the project. 您可以阅读.fsproj文件并生成#r的项目使用的引用语句。 Something like this might work: 这样的事情可能会起作用:

#r "System.Xml"
#r "System.Xml.Linq"

open System
open System.IO
open System.Linq
open System.Xml.Linq

let inline isNotNull o = o |> isNull |> not

let private getProject path =
    Directory.EnumerateFiles(path, "*.*proj") |> Seq.head |> XDocument.Load    

let generateDlls path =
    let projectFile = getProject path
    let references =
        projectFile.Descendants <| XName.Get("HintPath", "http://schemas.microsoft.com/developer/msbuild/2003")
        |> Seq.filter (fun reference -> reference.Value.ToLower().EndsWith(".dll"))
        |> Seq.filter (fun reference -> reference.Value.StartsWith("$") |> not)
        |> Seq.map (fun reference -> reference.Value)
    let projects =
        projectFile.Descendants <| XName.Get("ProjectReference", "http://schemas.microsoft.com/developer/msbuild/2003")
        |> Seq.map (fun reference -> reference.Elements(XName.Get("Name", "http://schemas.microsoft.com/developer/msbuild/2003")).SingleOrDefault())
        |> Seq.filter (fun nameElement -> nameElement |> isNotNull)
        |> Seq.map (fun nameElement -> nameElement.Value)
        |> Seq.map (fun reference -> sprintf "../%s/bin/debug/%s.dll" reference reference)

    references 
    |> Seq.append projects
    |> Seq.iter (fun reference -> printfn "#r @\"%s\"" reference)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM