Reputation: 1284
I need to interact with SharePoint (on premise) and decided to give a try to F#. It is or should be simple enough that I did it with CLI tools only.
I managed to interact with a site and get the info I needed. I struggled with the required DLL, but in the end
#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.
My code is, say:
open Microsoft.SharePoint.Client;;
let main () =
let authnManager = OfficeDevPnP.Core.AuthenticationManager()
printfn "%A" authnManager
0
main()
Running with 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) ? They must be managed as well with fsc as with fsi, for sure! (Unless there's a specific issue with OfficeDevPnP.Core.dll
...)
Upvotes: 0
Views: 180
Reputation: 6510
I think the DLLs referenced via #r
in F# Interactive need to be in dependency-order. 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). You will have to reset the interactive session once you've loaded the DLLs to re-load them in the correct order.
In general, loading package dependencies in F# interactive is quite tricky. There are some F# tools like Paket you can take a look at that might make your life a little easier. 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. You can read the .fsproj file and generate the #r
statements from the references used by the project. 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)
Upvotes: 1