Developing for SharePoint I found myself in situation when I had an access
the the server (direct or remote desktop) and need to run some ad-hoc code on it
but the server did not have Visual Studio or any other development environment
installed. I think this is familiar to some of us. These are some possible
options:
- install Visual Studio or any other development environment (very
unlikely that administrator will allow you to do it for test or production
environment)
- develop the code on the other machine and run on the server (good
approach but you loose code flexibility especially if you want to write and
test your code interactively)
- use
SnippetCompiler. This is a very good tool and I would choose it if
it supported command line execution of C# files.
- use Windows Scripting Host (WSH) to create and run scripts (good
approach but you need to use JScript of VBScript)
- use
Dot Net Script (good tool, but it uses its own file format and does not
have IDE)
I wanted to have some kind of a combination of
SnippetCompiler and
Dot
Net Script where I could create some scripts and maybe execute them
automatically in future.
So meet MyScriptHost.

This is a console application with a windowed code editor. It works with one
file at a time which can be executed with or without code editor. It can
associate .mysh files to itself (I have taken this idea from
Dot
Net Script project).
Command line usage:
MyScriptHost.exe <filename> <command>
where <filename> is a name of a file and <command> is one of the following:
/open |
open the file for editing. This is a default behavior if no other
command is specified. |
/compile |
compile the file without execution |
/run |
compile and execute the file |
/runandwait |
compile and execute the file and keep the console window open after
execution |
Code file should be a C# class containing public static void Main()
as entry point.
The only addition to pure C# code is a metatag <@ Reference Name="assembly name
or path" %>
in order to define external references. Code file can
have any number of these tags at the beginning of the file.
MyScriptHost contains internal static class MyshDebug which has some methods
useful for debugging:
static void Watch(params object[] values) |
Opens a watch window for specified values |
static void Print(object obj) static void Print(object obj, int levels)
|
Prints object properties to console. It also allows to specify a
number of levels to print out. |
Watch window is a modal window and allows you to see and change properties in
PropertyGrid. Invoke tab allows you to print property value with a specified
level of details.


This is an example of a script I used with MOSS to import news items from xml
file to SharePoint document library.
<%@ Reference Name="C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI\Microsoft.SharePoint.dll" %>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.IO;
using System.Xml;
public class Class1
{
private const string m_destNewsItemsFolder = @"C:\My Projects\Sharepoint Scripts\ImportNews\Items\";
private const string m_destNewsAttachmentsFolder = @"C:\My Projects\Sharepoint Scripts\ImportNews\Attachments\";
private const string m_siteUrl = @"http://localhost:1003/";
private const string m_prefix = "newPage_";
private const string m_pageTemplateName = "page1.aspx";
public static void Main()
{
SPSite site = new SPSite(m_siteUrl);
SPWeb web = site.OpenWeb("News");
SPFolder pages = web.Folders["Pages"];
SPFile pageTemplate = pages.Files[m_pageTemplateName];
Console.WriteLine("Deleting previous files...");
List<SPFile> filesToDelete = new List<SPFile>();
foreach(SPFile file in pages.Files)
{
Console.WriteLine(String.Format("{0}", file.Name));
if(file.Name.StartsWith(m_prefix))
{
filesToDelete.Add(file);
}
}
foreach(SPFile file in filesToDelete)
{
Console.WriteLine("Deleting " + file.Name);
file.Delete();
}
string[] fileNames = Directory.GetFiles(m_destNewsItemsFolder);
for (int i = 0; i < fileNames.Length; i++)
{
string fileName = Path.GetFileNameWithoutExtension(fileNames[i]);
fileName = m_prefix + fileName;
Console.WriteLine("Creating " + fileName);
pageTemplate.CopyTo(pages.Url + "/" + fileName + ".aspx", true);
}
pages = web.Folders["Pages"];
for (int i = 0; i < fileNames.Length; i++)
{
string fileName = Path.GetFileNameWithoutExtension(fileNames[i]);
fileName = m_prefix + fileName;
Console.WriteLine("Uploading " + fileName);
XmlDocument doc = new XmlDocument();
doc.Load(fileNames[i]);
string body = GetNodeText(doc, "//body");
string date = GetNodeText(doc, "//date");
string sourceName = GetNodeText(doc, "//sourceName");
string newsType = GetNodeText(doc, "//newsType");
string title = GetNodeText(doc, "//title");
string[] attachments = GetNodeTextArray(doc, "//attachment");
string creator = GetNodeText(doc, "//creator");
string creatorName = GetNodeText(doc, "//creatorName");
string author = GetNodeText(doc, "//author");
string entity = GetNodeText(doc, "//Entity"); //????
SPFile newPage = pages.Files[fileName + ".aspx"];
body = "<p>" + body.Replace("\r\n", "</p><p>") + "</p>";
newPage.CheckOut();
SPListItem item = newPage.Item;
item["Page Content"] = body;
item["Article Date"] = date;
item["Title"] = title;
item["Contact Name"] = author;
item.Update();
newPage.CheckIn("");
newPage.Publish("");
}
}
private static string GetNodeText(XmlNode root, string xpath)
{
XmlNode node = root.SelectSingleNode(xpath);
if (node == null)
{
return "";
}
return node.InnerText;
}
private static string[] GetNodeTextArray(XmlNode root, string xpath)
{
XmlNodeList nodes = root.SelectNodes(xpath);
List<string> values = new List<string>();
foreach (XmlNode node in nodes)
{
values.Add(node.InnerText);
}
return values.ToArray();
}
}
I am not going to
explain how this script works. It just demonstrates the power and flexibility I
gained in development for SharePoint in restricted environment.
I started this project for fun and now it becomes a very useful tool for me.