My First ScriptCS

Posted by Shawn Wildermuth on Jan 09, 2017 on 21:27PM

I’ve known Glenn Block for a long time now and I’ve heard about the ScriptCS project he’s worked on for a long time. I’ve never had time to dig in until now.

For the uninitiated, ScriptCS is a scriptable environment that uses .NET and C# for it’s platform. It makes writing simple scripts easier if you know C# already. It has support in several different editors, but I’ll talk about how I used it with Visual Studio Code since that’s my new favorite toy.

Before I can learn something interesting I have to have a job to do. In this case I had a simple problem: I needed to clean up Visual Studio projects. I create a *lot* of projects. Whether they are examples for courses, talks, or for my own investigations, I end up with projects lying around everywhere. Before I could share them, I want to clean them of temporary data (e.g. bin and obj directories, et al). Now that I use GitHub for many of these projects, cleaning isn’t that important but even in that case I still have a lot of disk space devoted to these files, so I still want to clean them up.

My goals were simple, I’ll give you a list of file masks or directory names and you find them and delete them. For extra credit, tell me what space I saved to make me feel better.

There are a bunch of tools that do these, but many of them didn’t work for me (or were no longer maintained), so a few months ago I crufted up this Powershell version:

Get-ChildItem .\ -include bin,obj,bld,Backup,_UpgradeReport_Files,Debug,Release,ipch,*.mdf,*.ldf,*.suo,Packages,bower_components,node_modules,lib,.vs,artifacts -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse }

This works, but is hard to make sense of what it is doing and I couldn’t make it pretty or do some of the calculations I wanted. I am sure a couple of you Powershell guys are screaming at the screen about how I’d do it, but this was a good excuse to learn ScriptCS.

For me, I use Chocolatey to install most of my apps, so adding ScriptCS was as simple as opening an Admin prompt and typing in:

C:\Users\Shawn>choco install scriptcs

Once I had that, I created a new file called CleanVS.csx. That extension is the convention for ScriptCS files. I opened this in Visual Studio Code and had color coding immediately:


(click to enlarge)

This was a good start, but I wasn’t getting any real intellisense. After some searching I found that you could get pretty good intellisense by dropping an empty project.json file (just an empty object tag: {}) inside and OmniSharp would start doing it’s magic and giving me some good intellisense!

So I had a job to do, so let’s start. Unlike a standard C# file, you just write code (though you can create an use classes). In my case that started with just using my list of directories and files to delete so I wrote:

Console.WriteLine("Cleaning current folder and subfolders");

var toDelete = new [] { "bin","obj","bld","Backup","_UpgradeReport_Files","Debug","Release,ipch","*.mdf","*.ldf","*.suo","Packages","bower_components","node_modules","lib",".vs","artifacts" };

foreach (var srch in toDelete)


No ceremony or anything, I just wrote code in C# like I love to do. Since this is essentially going to be a console app, I could use the Console class just like anywhere in C#. Now that I wanted to go through each of these names to find out what to delete, I wrote:

var candidates = Directory.GetFileSystemEntries(

This is the same code I’ve written a bunch of times to find files and directories. But the Directory class and the SearchOption enumeration weren’t recognized. Ah, I needed a using statement:

using System.IO;

Just like old times, I’m writing C#. You get the idea, now I could write code the way I wanted. Certainly longer winded than Powershell, but feeling empowered by using the entire breadth of the .NET Framework feels natural. Even in some of my tests I was able to use Win32 calls (PInvoke) and shell out to other scripts. It feels natural and familiar and I like it. You can see the entire script here in a gist:

What do you think?

Application Name WilderBlog Environment Name Production
Application Ver Runtime Framework .NETCoreApp,Version=v1.1
App Path D:\home\site\wwwroot Runtime Version .NET Core 4.6.24628.01
Operating System Microsoft Windows 6.2.9200 Runtime Arch X86