Microsoft PlayGround

A Playground for Microsoft Technologies

Deploying multiple wsp packages with one installation file

Today the public beta of SharePoint 2010 is released and everyone started blogging about SharePoint 2010. I am still preparing a Virtual Machine because the beta does not fully works on a Windows Server 2008 R2 installation and I had prepared a virtual machine with this operating system. But know back to deploying multiple wsp packages.

At the moment I’m working for a client that want to install multiple wsp packages and keep it simple for administrators to change the deployment. To accomplish this I created a sample configuration file for a custom installation.

<?xml version="1.0" encoding="utf-8" ?>
<Solution>
    <Package file="Solutions\CustomPackage2.wsp" deployment="Globally"></Package>
    <Package file="Solutions\CustomPackage1.wsp" deployment="WebApplication">
       <WebApplication url="http://myportal.com" />
    </Package>
</Solution>

In the configuration file you can see that there are two packages. One of the packages has to be deployed globally and 1 of them for several web applicatiosn that is why the second packages has child elements.

Know that we have a sample configuration file we want we to start building a application to install those packages. First of all we will try to read out the xml file in a console application.

class Program
 {
    public const string SolutionElement = "Solution";
    public const string PackageElement = "Package";
    public const string FileAttribute = "file";
    public const string DeploymentAttribute = "deployment";

    public static void Main()
    {

       try
       {
          if (File.Exists("Installation.config"))
          {
             //get the installation document
             WriteSectionLine("Loading installation configuration file.....");
             var config = XDocument.Load("Installation.config");

             var packages = from XElement package in config.Element(SolutionElement).Elements(PackageElement)
                            select package;

             foreach (XElement element in packages)
             {
                ProcessPackage(element);
             }
          }
          else
          {
             Console.WriteLine("Configuration file 'Installation.config' is nog in the same directory as the solution installer.");
          }
       }
    catch (Exception exception)
    {
       Console.WriteLine("An exception ocurred during the installation");
       Console.WriteLine("-------------------------------------------------------------------");
       Console.WriteLine(exception.Message);
       Console.WriteLine("-------------------------------------------------------------------");
    }
    WriteSectionLine("Press any key to close.");
    Console.ReadKey();
 }

In the ‘Main’ of the console application we check if the configuration file exists and when it exists we load the file and run a linq query for the package elements. When we have package elements within the configuration file we run the method ProcessPackage for each package element.

private static void ProcessPackage(XElement element)
{
    var deployment = element.Attribute(DeploymentAttribute).Value;
    if (deployment.ToUpperInvariant() == "GLOBALLY")
    {
       DeploymentGlobally(element);
    }
    else
    {
       DeploymenWebApplication(element);
    }
}

In the process package we check the deployment attribute to check how to deploy the package, globally or for web applications.

private static void DeploymenWebApplication(XElement element)
 {
    var file = element.Attribute(FileAttribute).Value;
    var fileName = Path.GetFileName(file);

    WriteSectionLine(string.Format(CultureInfo.InvariantCulture, "Processing Global Solution: {0}", fileName));
    var query = from childElement in element.Elements("WebApplication")
                select childElement;

    //delete / retract solution
    foreach (XElement el in query)
    {
      var url = el.Attribute("url").Value;
      Console.WriteLine(Processes.RunStsAdmProcces("retractsolution", string.Format(CultureInfo.InvariantCulture, "-name {0} -url {1} -immediate", fileName, url)));
      Console.WriteLine(Processes.RunStsAdmProcces("execadmsvcjobs", string.Empty));
    }

    Console.WriteLine(Processes.RunStsAdmProcces("deletesolution", string.Format(CultureInfo.InvariantCulture, "-name {0} -override", fileName)));
    Console.WriteLine(Processes.RunStsAdmProcces("addsolution", string.Format(CultureInfo.InvariantCulture, "-filename {0}", file)));

    foreach (XElement el in query)
    {
       var url = el.Attribute("url").Value;
       Console.WriteLine(Processes.RunStsAdmProcces("deploysolution", string.Format(CultureInfo.InvariantCulture, "-name {0} -url {1} -allowgacdeployment -immediate", fileName, url)));
       Console.WriteLine(Processes.RunStsAdmProcces("execadmsvcjobs", string.Empty));
    }
 }

private static void DeploymentGlobally(XElement element)
{
    var file = element.Attribute(FileAttribute).Value;
    var fileName = Path.GetFileName(file);

    WriteSectionLine(string.Format(CultureInfo.InvariantCulture, "Processing Global Solution: {0}", fileName));

    //preform processes
    Console.WriteLine(Processes.RunStsAdmProcces("retractsolution", string.Format(CultureInfo.InvariantCulture, "-name {0} -immediate", fileName)));
    Console.WriteLine(Processes.RunStsAdmProcces("execadmsvcjobs", string.Empty));
    Console.WriteLine(Processes.RunStsAdmProcces("deletesolution", string.Format(CultureInfo.InvariantCulture, "-name {0} -override", fileName)));
    Console.WriteLine(Processes.RunStsAdmProcces("addsolution", string.Format(CultureInfo.InvariantCulture, "-filename {0}", file)));
    Console.WriteLine(Processes.RunStsAdmProcces("deploysolution", string.Format(CultureInfo.InvariantCulture, "-name {0} -allowgacdeployment -immediate", fileName)));
    Console.WriteLine(Processes.RunStsAdmProcces("execadmsvcjobs", string.Empty));
 }

In the methods we read out additional information from the package element. In the ‘DeploymentWebApplication’ we read out the child elements and retract and delete the solution for each web application before we start installing the solution. Each time we retract or deploy a package we also run the execadmsvcjobs because we have to make sure no action for a package is running at the moment we start a new action.

The actions we do are started by the method RunStsAdmProcess this methods starts a new process that runs the stsadm tool of SharePoint. The methods needs two parameters the command and the argument.

internal static string RunStsAdmProcces(string command, string arguments)
 {
    var retVal = string.Empty;
    var commonFilesPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonProgramFiles);

    using (var process = new Process())
    {
       //create the start info of the project
       var processStartInfo = new ProcessStartInfo(command);
       processStartInfo.UseShellExecute = false;
       processStartInfo.RedirectStandardOutput = true;
       processStartInfo.FileName = commonFilesPath + @"\Microsoft Shared\web server extensions\12\BIN\stsadm.exe";
       processStartInfo.Arguments = string.Format(CultureInfo.InvariantCulture, " -o {0} {1}", command, arguments);

       //initialize the process
       process.StartInfo = processStartInfo;
       process.Start();

       //read the output stream of the process
       StreamReader myStreamReader = process.StandardOutput;
       retVal = myStreamReader.ReadToEnd();

       process.Close();
    }
    return retVal;

 }

In the method a new stsadm process is started with the parameters. With a streamreader the output of the process is captured and returned to the console application.

I hope this can help you guys with creating solutions to deploy multiple wsp packages from one installation.

SharePoint 2010: Getting Started with Development – Part 2

More and more resources are coming available for starting development with SharePoint 2010. Today I received a link from MSDN Flash with some cool new developer resources. After watching the presentations you can even test your skill by answering a question. Besides that their are also code samples available for each module.


Get Started Developing on SharePoint 2010



Besides the getting started modules Microsoft also released resources to get started working with Visual Studio 2010 and SharePoint 2010:


SharePoint Development in Visual Studio 2010


You should also take a look at http://channel9.msdn.com/learn/courses/SharePoint2010Developer/. On this site there are severela great movies to learn how to develop for SharePoint 2010.

SharePoint 2010: Getting Started with Development

When I was reading and searching information about SharePoint 2010 on the internet I found I really helpful page in the Microsoft download  to get started with development for SharePoint 2010.

On the page a 10 Hands on Labs for you to try out in C# and Visual Basic.

Overview
HOL01 – Developing a Visual Web Part in Visual Studio 2010
This hands-on lab introduces the Visual Studio 2010 SharePoint development environment. It shows how to build a Visual Web Part using LINQ to SharePoint, and how to connect one Web Part to another Web Part on the page.

HOL02 – Developing a List Definition and Event Receiver in Visual Studio 2010
This hands-on lab walks you through building a list definition for SharePoint 2010 in Visual Studio 2010. It also shows how to build an event receiver for the list in Visual Studio 2010 and deploy it to SharePoint. After the list and event receiver are deployed, you can use the developer dashboard to evaluate the performance of the event receiver.

HOL03 – Developing Advanced Web Parts for SharePoint 2010 with Visual Studio 2010
This hands-on lab shows how to build a Web Part using several SharePoint-specific controls in Visual Studio 2010. Investigate advanced built-in Web Parts, including the Data View Web Part.

HOL04 – Developing with LINQ to SharePoint in Visual Studio 2010
This hands-on lab explores a variety of LINQ queries on SharePoint 2010, going into more depth than the introductory hands-on lab. It also walks you through an exercise of creating a custom content type in Visual Studio 2010.

HOL05 – Developing for SharePoint 2010 with the Client OM and REST in Visual Studio 2010
This hands-on lab introduces the Client object model for use in calling SharePoint 2010 APIs from a client machine. It also shows the use of ADO.NET Data Services to call REST services in SharePoint 2010.

HOL06 – Developing a BCS External Content Type with Visual Studio 2010
This hands-on lab walks you through building an external content type for Business Connectivity Services using Visual Studio 2010. It also builds a form for Microsoft Outlook and shows the data being edited offline in Outlook.

HOL07 – Developing a SharePoint 2010 Workflow with Initiation Form in Visual Studio 2010
This hands-on lab walks you through building a workflow in Visual Studio 2010 for SharePoint 2010. You add an initiation form to the workflow and use an external data exchange activity in the workflow.

HOL08 – Developing SharePoint 2010 User Interface with Silverlight in Visual Studio 2010
This hands-on lab walks you through building Microsoft Silverlight applications for use in SharePoint 2010. You will access SharePoint 2010 data in Silverlight using the Client object model.

HOL09 – Developing SharePoint 2010 Sandboxed Solutions in Visual Studio 2010
This hands-on lab walks you through building a Sandboxed Solution Web Part for SharePoint 2010. It will also add code to the Web Part that overloads the limits placed by the sandboxed solution, and you will review how the solution is shut down.

HOL10 – Developing SharePoint 2010 User Interface Ribbon and Dialog Customizations
This hands-on lab walks you through adding a custom action to the SharePoint 2010 ribbon, and creating a Web Part that uses the Dialog Framework.

You can download them here.

Besides that I subscribed myself for one of the MSDN Get Ready sessions that will be given in November and December of this year. I will be attending the SharePoint 2010 Development session. Let me know if you will be attending one of those sessions.

Sitemap Provider for Community Server 2.1

For my new blog I had to create a sitemap provider to provide my content to several search engines.


Because I did not find any solution on the internet I thought I would share my solution with you guys:


You can download the source here:
MSFTPlayground.Sitemap.zip

The provider is meant for one blog. In the definitions file within the solution you can change the properties for you blog. You only have to add a httphandler to your web.config just like it is done in the file “web.config(extension)” within the solution.


Let me know what you guys think of this provider.

So long "Blog About SharePoint" and Hello "Microsoft Playground"

Almost two years ago I started “Blog About SharePoint” to blog about SharePoint related subjects.

The last couple of months my focus has changed to more Microsoft products so I have created a new blog called “Microsoft Playground“. Microsoft Playground will be a blog for articles regarding all kind of Microsoft technologies.

I hope you guys will enjoy “Microsoft Playground” as much as you have enjoyed “Blog About SharePoint”.

RSS feed : Microsoft Playground