Showing posts with label FSI. Show all posts
Showing posts with label FSI. Show all posts

Thursday, September 20, 2012

Adding NuGet Support to F# Interactive in VS2012

About a year ago, I posted an approach for adding basic NuGet support to VS2010. This post provides an updated script for adding this support in VS2012.

There may be times when you wish to use NuGet from the F# Interactive, such as when you are creating F# scripts. Since NuGet focuses on Visual Studio projects, this functionality is not supported out-of-the-box; however, it’s fairly simple to get things up and running.

The first step that we’ll need to do is create an F# script that is able to interact with the official NuGet package source. The script found here does the trick. I won’t spend too much time explaining the code in this script, but at a high level this allows you to use the F# Interactive window to talk to the NuGet package source, pull down packages, and automatically add a reference to the F# script file that has focus. 

The last step to accomplish our goal, is to tell F# Interactive to run our script each time that it launches. This is pretty easy to do thanks to the functionality provided by Visual Studio for adding F# Interactive options. To set the applicable option, go to Tools | Options | F# Tools | F# Interactive. You can then add the following information to the F# Interactive options setting.

--use:C:\temp\fsiext.fsx

 The F# Interactive options window looks like the following after making this change:


Once this is in place you can do something like this:

- Create a new F# Library project and build it. 
- Open the Script.fsx file.
- Navigate to the F# Interactive window.
- Execute InstallPackage “FSPowerPack.Core.Community”;; in the F# Interactive.

This will cause the package to be pulled down from the official NuGet repository and will automatically add the appropriate references to the Script.fsx file. 

Here's what the screen should look like after completing these steps.


Disclaimer: There are a few known issues with this approach.

Thursday, August 25, 2011

Adding NuGet Support to F# Interactive

A little over a week ago, Rick Minerich and I had a brief conversation about how cool it would be to install NuGet packages via the F# Interactive (FSI). After some research, there seems to be 3 options for accomplishing this:

1. Write a script that is loaded when the FSI starts.
2. Modify the source of FSI.exe (which can be found at http://fsharppowerpack.codeplex.com/).
3. Create an alternate F# Interactive Window VSIX that starts the FSI.exe as a new process as well as provides new commands.

In this post, I'll explore the first of these options.

Building the Script:

There are 3 steps to accomplishing the desired goal with option 1.

1. Create a F# script that has the ability to retrieve packages from NuGet and interact with Visual Studio. The script that I used to accomplish this can be found here.

Note: NuGet must be installed on the machine. Additionally, you will need to change the path to the NuGet.Core.dll reference if running a 32-bit version of Windows. This will be evident if you receive an error like the following when starting the F# Interactive Window - "error FS0084: Assembly reference 'C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies\NuGet.Core.dll' was not found or is invalid".

2. Update the FSI command line options in Visual Studio by going to Tools | Options | F# Tools | F# Interactive. Add "--use:<Path>\FsiExtension.fsx" to the "F# Interactive Options" value (see example below). Note: A full list of available FSI options can be found at http://msdn.microsoft.com/en-us/library/dd233172.aspx.


3. Open the F# Interactive Window (or reset the session if the window is already opened).

Taking it for a Test Drive:

Now that you are setup, it's time to try out the new functionality.

1. Create a new F# project and add a F# Script File (if one doesn't currently exist).

2.  Add some code (such as the following example from the Getting Started with F# PowerPack - Part 2 blog post) to the F# Script File:
open Microsoft.FSharp.Control  
  
let rec job = async {     
        for i in 1 .. 20 do    
            printfn "doing some work"  
            do! Async.Sleep 300  
            worker.ReportProgress i  
    }  
    and worker : AsyncWorker<_> = AsyncWorker(job)  
  
worker.ProgressChanged.Add(fun jobNumber -> printfn "job %d completed" jobNumber)   
worker.Error.Add(fun err -> printfn "Error: %A" err.Message)  
worker.Completed.Add(fun _ -> printfn "All jobs have completed")  
worker.Canceled.Add(fun _ -> printfn "Jobs have been canceled")  
  
worker.RunAsync() |> ignore  

3. In the F# Interactive Window, type InstallPackage "FSPowerPack.Core.Community";; and execute it. This will fire off the process to retrieve the FSPowerPack.Core.Community NuGet package from NuGet Gallery. The F# Interactive Window should look like the following once the process is complete:


This does two things:

1. It retrieves the specified NuGet package.
2. It adds any appropriate references to the fsx file. Your code will now look something like this:
#r @"C:\git\TestFsDte\packages\FSPowerPack.Core.Community.2.0.0.0\Lib\Net40\FSharp.PowerPack.dll"
open Microsoft.FSharp.Control  
  
let rec job = async {     
        for i in 1 .. 20 do    
            printfn "doing some work"  
            do! Async.Sleep 300  
            worker.ReportProgress i  
    }  
    and worker : AsyncWorker<_> = AsyncWorker(job)  
  
worker.ProgressChanged.Add(fun jobNumber -> printfn "job %d completed" jobNumber)   
worker.Error.Add(fun err -> printfn "Error: %A" err.Message)  
worker.Completed.Add(fun _ -> printfn "All jobs have completed")  
worker.Canceled.Add(fun _ -> printfn "Jobs have been canceled")  
  
worker.RunAsync() |> ignore  
4. You can also see what packages are installed by typing ShowInstalledPackages();;

Conclusion:

While this is hardly a perfect solution, hopefully it will at least spawn a few ideas. This implementation has several known issues (and probably several that are unknown). Let me know if you have ideas on better approaches or improvements.