SharePoint Server 2010 Configure People Picker

When the People Picker control is used, a user’s name is resolved when the Check Name icon is clicked or a list of users is displayed when the Browse icon is clicked.

If the Web application is using Windows authentication and the site user directory path is not set, the People Picker control searches the entire Active Directory to resolve users’ names or find users, instead of searching only users within a particular organizational unit (OU). The setsiteuseraccountdirectorypath operation allows the user’s directory path to be set to a specific OU in the same domain. After the directory path is set to a site collection, the People Picker control will only search under that particular OU.

If a site collection is new and an administrator uses the setsiteuseraccountdirectorypath operation to specify a target OU, only users under the specified path can be added to the site collection and no one else can be added to the site collection.

If users have already been added to a site collection and the setsiteuseraccountdirectorypath operation is run, only users under the specified path will be able to be added going forward.

To set a list of users to a specific OU (for example, Sales) in the Contoso Corp domain, use the following syntax:

stsadm -o setsiteuseraccountdirectorypath -path “CN=Sales,DC=ContosoCorp,DC=local” –url http://server_name

http://technet.microsoft.com/en-us/library/cc263328(office.12).aspx

http://technet.microsoft.com/en-us/library/gg602075(v=office.14).aspx#section5

 

Advertisements

Full on ASP.Net C# Web Application to upload a PPTX, convert to PPSX and JPGs and copy to file shares and SharePoint library

In addition to the pages and code below, you will need an impersonation class. Please see this C# Impersonation Class post.

You will need to install PowerPoint on the server and run it once as your service account to clear out setup prompts.

On the server run Component Services, DCOM Config, choose Microsoft Office Powerpoint Slides, Properties, Identity Tab and choose “Logon as This User” and enter the service account username and password. (The Interactive User will work if you are always logged onto the server hosting this application.)

 

If the site that will host this web application runs SSL, open your IIS Manager go to your web application’s Configuration Editor, under system.webServer, serverRuntime, Properties change the uploadReadAheadSize to a little over the size of your PowerPoint presentations.

Set IIS Authentication to Windows Authentication Enabled. All others disabled.

Set IIS SSL Settings to Ignore Client Certificates

Default.aspx:

<%@ Page trace="false" Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" StylesheetTheme="SkinFile" MasterPageFile="~/Site.master"  %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="PageTitle" runat="server" ContentPlaceHolderID="PageTitle">
    <h1>EBB Management</h1>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">

    <asp:Panel ID="pnlHeader" CssClass="pnlHeader" runat="server">
        <p>The Bulletin Board Management application assists with upload and distribution of PowerPoint presentations to various electronic displays located on the network.</p>
        <p>
            <asp:Label runat="server" ID="lblError" /></p>
            </asp:Panel>
    <asp:Panel ID="pnlUpload" CssClass="pnlUpload" runat="server" Visible="true">
        <asp:FileUpload ID="fileupload1" runat="server" />
        <asp:Button ID="Button1" runat="server" Text="  Upload  " OnClick="UploadPPTX" Height="22px" />
    </asp:Panel>
    <asp:Panel ID="pnlSLEBBs" CssClass="pnlSLEBBs" runat="server" Visible="false">
        <p>You may choose to update the SharePoint Portal and the following EBBs located on this network.</p>
        <asp:CheckBoxList ID="cbxDirStat" runat="server" Visible="false" RepeatDirection="Horizontal" OnDataBound="CheckAllBoxes">
        </asp:CheckBoxList>
        <br />
        <asp:Button ID="btnFileProcessing" runat="server" Text="Update selected EBBs and SharePoint Library" OnClick="UpdateBBs_OnClick" />
        <asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClick="Cancel_OnClick" />

    </asp:Panel>
    <asp:Panel ID="pnlImages" CssClass="pnlImages" runat="server" ScrollBars="Vertical" Height="600px" Visible="false">
        <p>The following slides were created from your upload.</p>
        <asp:DataList ID="dlImages" runat="server" RepeatColumns="4" CellPadding="3" Visible="false">
            <SelectedItemStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />

            <ItemTemplate>
                <asp:Image ID="ibImage" runat="server" ImageUrl='<%# Eval("Name", "jpg/{0}") %>' Width="165px" Height="155px" />
            </ItemTemplate>
            <FooterStyle />
            <ItemStyle />
        </asp:DataList>
    </asp:Panel>
</asp:Content>

Default.aspx.cs:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Runtime.InteropServices;
using System.Net.Mail;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using AjaxControlToolkit;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
using System.Threading;

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Packaging;

using System.Security;

public partial class _Default : System.Web.UI.Page
{
    private static string smtpServer,
                              sendToUser,
                              sendToAdmin,
                              sendFrom,
                              sharepointlibrary,
                              slebbfolder,
                              uploadfolder,
                              jpgfolder,
                              ppsxfolder,
                              spdomain,
                              spname,
                              sppassword,
                              sharedomain,
                              sharename,
                              sharepassword,
                              thispptx,
                              thisppsx,
                              thispptxfullpath,
                              thisppsxfullpath;

    private static FileInfo[] files, jpgfiles;
    private static string[] slebbs;

    public _Default()
    {
        smtpServer = safeGetAppSetting("smtpServer");
        sendToUser = safeGetAppSetting("sendToUser");
        sendToAdmin = safeGetAppSetting("sendToAdmin");
        sendFrom = safeGetAppSetting("sendFrom");
        sharepointlibrary = safeGetAppSetting("SharePointLibrary");
        slebbfolder = safeGetAppSetting("SLEBBFolder");
        uploadfolder = safeGetAppSetting("UploadFolder");
        jpgfolder = safeGetAppSetting("JPGFolder");
        ppsxfolder = safeGetAppSetting("PPSXFolder");
        spdomain = safeGetAppSetting("spDomain");
        spname = safeGetAppSetting("spName");
        sppassword = safeGetAppSetting("spPwd");
        sharedomain = safeGetAppSetting("shareDomain");
        sharename = safeGetAppSetting("shareName");
        sharepassword = safeGetAppSetting("sharePwd");
        slebbs = safeGetAppSetting("SLEBBs").Split(new Char[] { ',' });
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            CleanUpFolders();
            lblError.Text = "Click 'Browse', select your PowerPoint presentation (.pptx) then 'Upload'.";
        }
    }

    protected void CleanUpFolders()
    {
        CleanUpFolder(Server.MapPath("~/" + uploadfolder));
        CleanUpFolder(Server.MapPath("~/" + jpgfolder));
        CleanUpFolder(Server.MapPath("~/" + ppsxfolder));
    }

    protected void CleanUpFolder(string folder)
    {
        string[] path = Directory.GetFiles(folder);
        if (path != null)
        {
            try
            {
                foreach (string deadfile in path){File.Delete(deadfile);}
            }
            catch (Exception ex6)
            {
                lblError.Text = "Cleanup Error: " + ex6.Message;
            }
        }
    }

    private void ShowDisplays()
    {
        //DirectoryInfo dir = new DirectoryInfo(slebbfolder);
        //slebbs = dir.GetFiles("*.ppsx");
        ArrayList list = new ArrayList();
        list.Add("CISF Portal");
        foreach (string ebb in slebbs)
        {
            list.Add("Rm. " + ebb);
        }
        cbxDirStat.Visible = true;
        cbxDirStat.DataSource = list;
        cbxDirStat.DataBind();

        btnFileProcessing.Visible = true;
        lblError.Visible = true;
    }

    protected void CheckAllBoxes(object sender, EventArgs e)
    {
        foreach (ListItem li in cbxDirStat.Items)
        {
            li.Selected = true;
        }
    }

    protected void UploadPPTX(object sender, EventArgs e)
    {
        if (!fileupload1.PostedFile.FileName.ToLower().EndsWith(".pptx"))
        { lblError.Text = "That file is not a PowerPoint presentation.<br/>I'm looking for any file that ends in .pptx"; }
        else
        {
            // Checks if there is a file present for uploading.
            if ((fileupload1.PostedFile != null) && (fileupload1.PostedFile.ContentLength > 0))
            {
                lblError.Text = string.Empty;
                lblError.Text = string.Empty;
                thispptx = System.IO.Path.GetFileName(fileupload1.PostedFile.FileName);
                thispptxfullpath = Server.MapPath("~/upload/") + thispptx;
                try
                {
                    // Saving to Files folder
                    fileupload1.PostedFile.SaveAs(thispptxfullpath);
                }
                catch (Exception ex)
                {
                    lblError.Text = "File upload error.<br />";
                }
            }
            else
            {
                lblError.Text += "Please select a file to upload.";
            }
            // Deletes hidden sides
            DeleteHiddenSlides(thispptxfullpath);

            // Used for displaying slides to uploaded to sharepoint
            ExtractJPGs(thispptxfullpath);

            // convert to ppsx
            SavePresentationAsSlideshow(thispptxfullpath);

            ShowDisplays();

            // Displays images for review
            ListImages();

            lblError.Text = fileupload1.PostedFile.FileName + " was uploaded and hidden slides were removed.";
            pnlImages.Visible = true;
            pnlSLEBBs.Visible = true;
            pnlUpload.Visible = false;
        }

    }

    public void DeleteHiddenSlides(string pppath)
    {
        int slideCount = -1;

        slideCount = CountSlides(pppath);
        lblError.Text += slideCount + " slides processed.<br />";

        for (int i = 0; i <= slideCount; i++)
        {
            DeleteSlide(pppath);
        }
    }

    public static void DeleteSlide(string presentationFile)
    {
        if (presentationFile == null)
        {
            throw new ArgumentNullException("presentationDocument");
        }

        using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
        {
            // Get the presentation part from the presentation document.
            PresentationPart presentationPart = presentationDocument.PresentationPart;

            // Get the presentation from the presentation part.
            DocumentFormat.OpenXml.Presentation.Presentation presentation = presentationPart.Presentation;

            // Get the list of slide IDs in the presentation.
            SlideIdList slideIdList = presentation.SlideIdList;

            int slideIdx = -1;
            foreach (SlideId _slideId in presentation.SlideIdList)
            {
                slideIdx++;

                // Get the slide ID of the specified slide
                SlideId slideId = slideIdList.ChildElements[slideIdx] as SlideId;

                // Get the relationship ID of the slide.
                string slideRelId = slideId.RelationshipId;

                // Get the slide part for the specified slide.
                SlidePart slidePart = presentationPart.GetPartById(slideRelId) as SlidePart;

                if (slidePart.Slide.Show != null)
                {
                    if (slidePart.Slide.Show.HasValue != null)
                    {
                        // Remove the slide from the slide list.
                        slideIdList.RemoveChild(slideId);

                        // Remove references to the slide from all custom shows.
                        if (presentation.CustomShowList != null)
                        {
                            // Iterate through the list of custom shows.
                            foreach (var customShow in presentation.CustomShowList.Elements<CustomShow>())
                            {
                                if (customShow.SlideList != null)
                                {
                                    // Declare a link list of slide list entries.
                                    LinkedList<SlideListEntry> slideListEntries = new LinkedList<SlideListEntry>();
                                    foreach (SlideListEntry slideListEntry in customShow.SlideList.Elements())
                                    {
                                        // Find the slide reference to remove from the custom show.
                                        if (slideListEntry.Id != null && slideListEntry.Id == slideRelId)
                                        {
                                            slideListEntries.AddLast(slideListEntry);
                                        }
                                    }

                                    // Remove all references to the slide from the custom show.
                                    foreach (SlideListEntry slideListEntry in slideListEntries)
                                    {
                                        customShow.SlideList.RemoveChild(slideListEntry);
                                    }
                                }
                            }
                        }

                        // Save the modified presentation.
                        presentation.Save();

                        // Remove the slide part.
                        presentationPart.DeletePart(slidePart);
                        break;
                    }
                }
            }

        }
    }

    public static int CountSlides(string presentationFile)
    {
        // Open the presentation as read-only.
        using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, false))
        {
            // Pass the presentation to the next CountSlide method
            // and return the slide count.
            return CountSlides(presentationDocument);
        }
    }

    public static int CountSlides(PresentationDocument presentationDocument)
    {
        // Check for a null document object.
        if (presentationDocument == null)
        {
            throw new ArgumentNullException("presentationDocument");
        }

        int slidesCount = 0;

        // Get the presentation part of document.
        PresentationPart presentationPart = presentationDocument.PresentationPart;

        // Get the slide count from the SlideParts.
        if (presentationPart != null)
        {
            slidesCount = presentationPart.SlideParts.Count();
        }

        // Return the slide count to the previous method.
        return slidesCount;
    }

    public void SavePresentationAsSlideshow(string presentationFile)
    {
        using (PresentationDocument presentationDocument = PresentationDocument.Open(presentationFile, true))
        {
            try
            {
                presentationDocument.ChangeDocumentType(PresentationDocumentType.Slideshow);
                presentationDocument.Close();
                File.Copy(Server.MapPath("~/upload/default.pptx"), Server.MapPath("~/ppsx/default.ppsx"));
            }
            catch (Exception ey)
            {
                lblError.Text = "Save Presentation As Slideshow Error: " + ey.Message;
            }
        }
    }

    protected void ExtractJPGs(string pppath)
    {
        using (new Impersonate.Impersonation(sharedomain, sharename, sharepassword))
        {
                 Microsoft.Office.Interop.PowerPoint.Application ppApplication = new Microsoft.Office.Interop.PowerPoint.Application();
                Microsoft.Office.Interop.PowerPoint.Presentation ppPresentation = ppApplication.Presentations.Open(Server.MapPath("~/upload/Default.pptx"), MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
           try
            {
                ppPresentation.SaveAs(Server.MapPath("~/jpg"), PpSaveAsFileType.ppSaveAsJPG, MsoTriState.msoFalse);
                Thread.Sleep(500);

            }
            catch (Exception ex2)
            {
                lblError.Text = "ExtractJPGs Error: " + ex2.Message;
            }
            finally
            {
                ppPresentation.Close();
            }
        }
    }

    private void ListImages()
    {
        DirectoryInfo dir = new DirectoryInfo(MapPath("~/jpg"));
        files = dir.GetFiles();
        ArrayList list = new ArrayList();
        foreach (FileInfo file in files)
        {
            if (file.Extension == ".JPG")
            {
                list.Add(file);
            }
        }
        dlImages.Visible = true;
        dlImages.DataSource = list;
        dlImages.DataBind();
    }

    protected void UpdateBBs_OnClick(object sender, EventArgs e)
    {
        string msg = "";
        foreach (ListItem li in cbxDirStat.Items)
        {
            if (li.Selected == true)
            {
                if (li.Text == "CISF Portal")
                {
                    CopyToSharePointLibrary();
                    msg += "<br />CISF Portal was updated.";
                }else{
                    thisppsx = li.Text.Replace("Rm. ", "Default") + ".ppsx";
                    File.Copy(Server.MapPath("~/" + ppsxfolder) + @"\\default.ppsx", Path.Combine(slebbfolder, thisppsx), true);
                    msg += "<br />" + li.Text + " was updated.";
                }
            }
        }
        lblError.Text = msg;
        CleanUpFolders();
        pnlImages.Visible = false;
        pnlSLEBBs.Visible = false;
        pnlUpload.Visible = true;
    }

    public void CopyToSharePointLibrary()
    {
        using (new Impersonate.Impersonation(spdomain, spname, sppassword))
        {
            try
            {
                Array.ForEach(Directory.GetFiles(sharepointlibrary), File.Delete);

                DirectoryInfo dir = new DirectoryInfo(MapPath("~/jpg"));
                jpgfiles = dir.GetFiles();
                foreach (FileInfo jpgfile in jpgfiles)
                {
                    File.Copy(jpgfile.FullName, Path.Combine(sharepointlibrary, jpgfile.Name), true);
                }
            }
            catch (Exception ex6_5)
            {
                lblError.Text = "Copy To SharePoint Library Error: "+ ex6_5.Message;
            }
        }
    }

    protected void Cancel_OnClick(object sender, EventArgs e)
    {
        Response.Redirect("default.aspx");
    }

    private string safeGetAppSetting(string key)
    {
        try
        {
            return ConfigurationManager.AppSettings[key];
        }
        catch (ConfigurationErrorsException ex)
        {
            lblError.Text = "Web.Config Error: " + key + " " + ex.Message;
            return "Key is missing " + key;
        }
    }
}

Web.Config:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="SharePointLibrary" value="\\SharePointServer@SSL\DavWWWRoot\Library\"/>
    <add key="SLEBBFolder" value="\\Server\fileshare"/>
    <add key="SLEBBs" value="101,109,214,255"/>

    <add key="UploadFolder" value="upload"/>
    <add key="JPGFolder" value="jpg"/>
    <add key="PPSXFolder" value="ppsx"/>

    <add key="shareDomain" value="Domain"/>
    <add key="shareName" value="ServiceAccount"/>
    <add key="sharePwd" value="Password"/>

    <add key="spDomain" value="Domain"/>
    <add key="spName" value="ServiceAccount2"/>
    <add key="spPwd" value="Password"/>

    <add key="ClientSettingsProvider.ServiceUri" value=""/>
  </appSettings>
  <system.web>

    <identity impersonate="true" userName="Domain\ServiceAccount" password="Password"/>
      <compilation debug="true" targetFramework="4.0" tempDirectory="C:\temp">
      <assemblies>
        <add assembly="office, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C"/>
        <add assembly="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
        <add assembly="DocumentFormat.OpenXml, Version=2.0.5022.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="Microsoft.Office.Interop.PowerPoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71E9BCE111E9429C"/>
      </assemblies>
    </compilation>
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
    <httpRuntime maxRequestLength="100000"/>
  </system.web>
</configuration>

How to Copy Files from a Server Share to a SharePoint 2010 Library – ASP.Net C# and Command Line

SharePoint Libraries you can “Open with Windows Explorer” I spent some time trying to figure out how to automate file management that I could do using drag and drop. Trouble was, to use the SharePoint libraries you have to develop and run your application on a SharePoint server, which I didn’t want to do. After dorking around on the command line I found that you could assign a drive letter to the SharePoint library via “net use”.

Command Line:

net use r: /delete
net use s: /delete
net use r: \\Server\Share
net use s: https://SharePointServer/Library
del s:. /F/Q
copy r:. s:
net use s: /delete
net use r: /delete

That share shows up in Windows Explorer as a drive mapping that looks like this:

MyLibrary (\\SharePointServer@SSL\DavWWWRoot\)

Well, heck! If that’s the case then the following aught to work – and does!

ASP.Net C#:

string mysharepointlibrary = @"\\SharePointServer@SSL\DavWWWRoot\MyLibrary\";
Array.ForEach(Directory.GetFiles(mysharepointlibrary), File.Delete);
DirectoryInfo dir = new DirectoryInfo(MapPath("~/uploadfolder"));
files = dir.GetFiles();
foreach (FileInfo file in files)
{
  File.Copy(file.FullName, Path.Combine(mysharepointlibrary , file.Name), true);
}

More information:

http://www.iis.net/learn/publish/using-webdav/using-the-webdav-redirector

WebClient Service uses the Local Service account by default.

Recovering from a corrupted SharePoint 2010 Installation that would not create a Search Service Application

After a perfect storm of urgent and ill implemented security measures during a series of updates to SharePoint Server 2010 we were left with a corrupted production SharePoint 2010 installation. The symptoms were that some Web Application databases reported that some components were still updating and we could not create a search service application. These are the steps we went through to repair the installation.

Login as service account used for sptimerv4.
Make sure service account is dbo for all sp dbs plus the master.
Make sure service account is in administrators group, and all iis created groups.
Rerun sharepoint products configuration wizard from start.

psconfig.exe -cmd upgrade -inplace b2b -wait -force

Delete everything in C:\ProgramData\Microsoft\SharePoint\Config\ EXCEPT the cache.ini
Edit cache.ini change number to 1

Stop sptimerv4

stsadm -o setproperty -pn command-line-upgrade-running -pv No

Start sptimerv4

psconfig.exe -cmd upgrade -inplace b2b -wait -force

Rerun sharepoint products configuration wizard as admin from start.
Check version of C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\*.dll

psconfig -cmd installfeatures
psconfig -cmd secureresources
psconfig -cmd services -install
psconfig -cmd upgrade -inplace b2b -wait -force
iisreset /noforce
Upgrade-SPContentDatabase wss_content_sitecollectiondb
Upgrade-SPContentDatabase wss_content_othersitecollectiondb

Deleted unupgradeable datatases:
wss_content_sitecollectiondb
wss_content_othersitecollectiondb

Tell SharePoint that the databases are gone

Get-SPDatabase | where {$_.exists -eq $false}
Get-SPDatabase | where {$_.exists -eq $false} | foreach {$_.delete()}

Rerun sharepoint products configuration wizard as admin from start.

Go to add or remove programs, right click on sharepoint 2010 server and select repair.

Run the SharePoint 2010 configuration wizard, this time remove SharePoint server from farm then add sharepoint server back to the farm.

Run the SharePoint 2010 configuration wizard, this time remove SharePoint server from farm then create new SharePoint farm.

After we created a new SharePoint farm, all of the errors went away and were are again able to create search service applications. It appears to me that the corruption happened in the SharePoint_Config and the Web Application / Root Site Collection database.

In CA, Recover Data from an Unattached Content Database, chose the wss_content_sitecollectiondb, and exported site.

import-spweb -identity https://SharePointServer -path c:\temp\recoverexport.cmp

Load control template file /_controltemplates/TaxonomyPicker.ascx failed

Load control template file /_controltemplates/TaxonomyPicker.ascx failed: Could not load type ‘Microsoft.SharePoint.Portal.WebControls.TaxonomyPicker’ from assembly ‘Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c’.

  1. Navigate to /14/TEMPLATE/ControlTemplates/TaxonomyPicker.ascx user control
  2. Open the user control in a text editor and locate the first line
  3. Find the character string , and replace with a comma ‘,’ (without quotes).
  4. Save the user control

http://support.microsoft.com/kb/2481844

Sometimes, the error does not go away even after following the steps listed above. In such cases, the fix is to rename the ‘TaxonomyPicker.ascx’ to  something like ‘TaxonomyPicker.ascx_broken’ so that we do not try to recompile it each time the AppPool is started. The user control is never used  within SharePoint and therefore serves no real purpose.

http://blogs.technet.com/b/praveenh/archive/2010/12/16/sharepoint-2010-gt-gt-taxonomy-picker-ascx-failed-error.aspx

 

Rebuilding a Windows Service that converts PPTX to JPG on a remote share then updates an Image Library in SharePoint 2010

A friend of mine, Eric Mikuska built a windows service that converts PPTX to JPG on a remote share and updates an Image Library in SharePoint 2007.  Here are steps I took to rebuild it to work with SharePoint 2010 on 64 bit hardware.

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;

using System.Windows.Forms;
//using ServiceDebuggerHelper; //for ServiceDebuggerHelper

namespace Conversion-Service
{
static class Program
{
/// <summary>
/// Uncomment this for deployment.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Conversion-Service()
};
ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// This is for debugging.  //for ServiceDebuggerHelper
/// </summary>
//static void Main(string[] args)
//{
//    if (args.Length > 0 && args[0].ToLower().Equals("/debug"))
//    {
//        Application.Run(new ServiceRunner(new Conversion-Service()));
//    }
//    else
//    {
//        System.ServiceProcess.ServiceBase[] ServicesToRun = new System.ServiceProcess.ServiceBase[]
//            {
//                new Conversion-Service(),
//            };

//        System.ServiceProcess.ServiceBase.Run(ServicesToRun);
//    }
//}
}
}

Conversion-Service.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;

using System.Configuration;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Net.Mail;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Packaging;
using Microsoft.SharePoint;

//using ServiceDebuggerHelper;  //for ServiceDebuggerHelper

namespace Conversion-Service
{
partial class Conversion-Service : ServiceBase//, IDebuggableService   //for ServiceDebuggerHelper
{
public Conversion-Service()
{
InitializeComponent();
CanPauseAndContinue = true;
}

protected override void OnStart(string[] args)
{
WatchForUploadedFiles();
}

protected override void OnStop()
{
UnmapDriveLetter(ConfigurationManager.AppSettings["remoteDriveLetter"]);
}

protected override void OnPause()
{
}

protected override void OnContinue()
{
}

#region IDebuggableService Members

public void Start(string[] args)
{
OnStart(args);
}

public void StopService()
{
OnStop();
}

public void Pause()
{
OnPause();
}

public void Continue()
{
OnContinue();
}

#endregion

#region Functions

private void WatchForUploadedFiles()
{
FileSystemWatcher fsWatcher = new FileSystemWatcher();
try
{
MapDriveLetter();
fsWatcher.Created += new FileSystemEventHandler(OnFileCreated);
FolderCleanUp("Directory ready for operation.");                                      // Parameter used for debugging only
fsWatcher.Path = ConfigurationManager.AppSettings["remoteFolder"];             // @"Z:\";
fsWatcher.Filter = ConfigurationManager.AppSettings["sourceFileName"];         // "Default.pptx";
fsWatcher.EnableRaisingEvents = true;
}
catch (Exception ex1)
{
WriteException(ex1, "Ex1");
}
}

public static void MapDriveLetter()
{
try
{
if (System.IO.Directory.Exists(ConfigurationManager.AppSettings["remoteFolder1"]))           //"Z" + ":\\"
{
UnmapDriveLetter(ConfigurationManager.AppSettings["remoteDriveLetter"]);                //"Z:"
}
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "net.exe";
p.StartInfo.Arguments = @" use " + ConfigurationManager.AppSettings["remoteDriveLetter"]
+ " " + ConfigurationManager.AppSettings["remoteShareName"]
+ " " + ConfigurationManager.AppSettings["userPwd"]
+ " /user:" + ConfigurationManager.AppSettings["userName"];

//EventLog.WriteEntry("Conversion Service", "Remote drive mapped successfully", EventLogEntryType.Information);

p.Start();
p.WaitForExit();
}
catch (Exception ex6_5)
{
WriteException(ex6_5, "Ex6.5");
}
}

protected static void UnmapDriveLetter(string DriveLetter)
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
try
{
p.StartInfo.FileName = "net.exe";
p.StartInfo.Arguments = " use " + ConfigurationManager.AppSettings["remoteDriveLetter"] + " /DELETE";
p.Start();
}
catch (Exception ex7)
{
WriteException(ex7, "Ex7");
}
finally
{
p.WaitForExit();
}
}

static void OnFileCreated(object sender, FileSystemEventArgs e)
{
SavePPTXasJPGs();
DeleteSharePointSlides();
UploadJPGsToSharePoint();
//FolderCleanUp("Files deleted from temporary directory.");                        // Parameter used for debugging only
//UnmapDriveLetter(ConfigurationManager.AppSettings["remoteDriveLetter"]);        //"Z:"
}

protected static void SavePPTXasJPGs()
{
Microsoft.Office.Interop.PowerPoint.Application app = new Microsoft.Office.Interop.PowerPoint.Application();
Microsoft.Office.Interop.PowerPoint.Presentation pptPresentation = null;
try
{
pptPresentation = app.Presentations.Open(ConfigurationManager.AppSettings["remoteFolder"] + ConfigurationManager.AppSettings["sourceFileName"], MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
pptPresentation.SaveAs(ConfigurationManager.AppSettings["remoteFolder"] + ".", PpSaveAsFileType.ppSaveAsJPG, MsoTriState.msoFalse);
Thread.Sleep(500);
}
catch (Exception ex2)
{
WriteException(ex2, "Ex2");
}
finally
{
pptPresentation.Close();
}
}

public static void ProcessPresentation()
{
string fileNamePath = ConfigurationManager.AppSettings["remoteFolder"] + ConfigurationManager.AppSettings["sourceFileName"];
int slideCount = -1;
slideCount = CountSlides(fileNamePath);
for (int i = 0; i <= slideCount; i++)
{
DeleteSlide(fileNamePath);
}
}

public static void DeleteSlide(string presentationFile)
{
if (presentationFile == null)
{
throw new ArgumentNullException("presentationDocument");
}
using (DocumentFormat.OpenXml.Packaging.PresentationDocument presentationDocument =
DocumentFormat.OpenXml.Packaging.PresentationDocument.Open(presentationFile, true))
{
// Get the presentation part from the presentation document.
DocumentFormat.OpenXml.Packaging.PresentationPart presentationPart = presentationDocument.PresentationPart;
// Get the presentation from the presentation part.
DocumentFormat.OpenXml.Presentation.Presentation presentation = presentationPart.Presentation;
// Get the list of slide IDs in the presentation.
DocumentFormat.OpenXml.Presentation.SlideIdList slideIdList = presentation.SlideIdList;
int slideIdx = -1;
foreach (DocumentFormat.OpenXml.Presentation.SlideId _slideId in presentation.SlideIdList)
{
slideIdx++;
// Get the slide ID of the specified slide
DocumentFormat.OpenXml.Presentation.SlideId slideId = slideIdList.ChildElements[slideIdx] as DocumentFormat.OpenXml.Presentation.SlideId;
// Get the relationship ID of the slide.
string slideRelId = slideId.RelationshipId;
// Get the slide part for the specified slide.
DocumentFormat.OpenXml.Packaging.SlidePart slidePart = presentationPart.GetPartById(slideRelId) as DocumentFormat.OpenXml.Packaging.SlidePart;
if (slidePart.Slide.Show != null)
{
if (slidePart.Slide.Show.HasValue != null)
{
// Remove the slide from the slide list.
slideIdList.RemoveChild(slideId);
// Save the modified presentation.
presentation.Save();
// Remove the slide part.
presentationPart.DeletePart(slidePart);
break;
}
}
}
}
}

public static int CountSlides(string presentationFile)
{
// Open the presentation as read-only.
using (DocumentFormat.OpenXml.Packaging.PresentationDocument presentationDocument = DocumentFormat.OpenXml.Packaging.PresentationDocument.Open(presentationFile, false))
{
// Pass the presentation to the next CountSlide method
// and return the slide count.
return CountSlides(presentationDocument);
}
}

public static int CountSlides(DocumentFormat.OpenXml.Packaging.PresentationDocument presentationDocument)
{
// Check for a null document object.
if (presentationDocument == null)
{
throw new ArgumentNullException("presentationDocument");
}
int slidesCount = 0;
// Get the presentation part of document.
DocumentFormat.OpenXml.Packaging.PresentationPart presentationPart = presentationDocument.PresentationPart;

// Get the slide count from the SlideParts.
if (presentationPart != null)
{
slidesCount = presentationPart.SlideParts.Count();
}
// Return the slide count to the previous method.
return slidesCount;
}

public static int PPTGetSlideCount(string fileName, bool includeHidden = true)
{
int slidesCount = 0;
using (PresentationDocument doc = PresentationDocument.Open(fileName, false))
{
PresentationPart presentationPart = doc.PresentationPart;
if (presentationPart != null)
{
if (includeHidden)
{
slidesCount = presentationPart.SlideParts.Count();
}
else
{
var slides = presentationPart.SlideParts.Where(
(s) => (s.Slide != null) &&
((s.Slide.Show == null) ||
(s.Slide.Show.HasValue && s.Slide.Show.Value)));
slidesCount = slides.Count();
}
}
}
return slidesCount;
}

protected static void DeleteSharePointSlides()
{
SPWeb SharePoint2010Site = new SPSite(ConfigurationManager.AppSettings["portalURL"]).OpenWeb();
SPList imagesLibrary = SharePoint2010Site.Lists[ConfigurationManager.AppSettings["imageListFolder"]];
SharePoint2010Site.AllowUnsafeUpdates = true;
try
{
while (imagesLibrary.Items.Count > 1)
{
imagesLibrary.Items[imagesLibrary.Items.Count - 1].File.Delete();
}
}
catch (Exception ex4)
{
WriteException(ex4, "Ex4");
}
finally
{
}
}

protected static void UploadJPGsToSharePoint()
{
bool success = false;
string[] files;
files = null;
files = Directory.GetFiles(ConfigurationManager.AppSettings["remoteFolder1"], ConfigurationManager.AppSettings["imageFileExtension"]);
SPWeb SharePoint2010Site = new SPSite(ConfigurationManager.AppSettings["portalURL"]).OpenWeb();
SharePoint2010Site.AllowUnsafeUpdates = true;
FileStream fs = null;
string fileName = string.Empty;
if (files.Length > 1)
{
try
{
foreach (string file in files)
{
fileName = file.Split(@"\".ToCharArray())[1].ToLower();
fs = File.Open(file, FileMode.Open);
SharePoint2010Site.Files.Add(ConfigurationManager.AppSettings["imageListFolder"] + "/" + fileName, fs, true);
Thread.Sleep(500);
fileName = string.Empty;
fs.Close();
}
success = true;
}
catch (Exception ex5)
{
WriteException(ex5, fileName);
}
finally
{
SharePoint2010Site.AllowUnsafeUpdates = false;
if (success) { SendEmail(success); }
FolderCleanUp("Clean up the mess.");
}
}
}

protected static void FolderCleanUp(string _message)
{
string[] filesToDelete = Directory.GetFiles(ConfigurationManager.AppSettings["remoteFolder"]);
try
{
foreach (string file in filesToDelete)
{
File.Delete(file);
}
}catch (Exception ex6)
{
WriteException(ex6, "Ex6");
}
}

public static void WriteException(Exception ex, string source)
{
string err = "Conversion-Service Error" +
"\n\nError Message from method " + source + ": " + ex.Message.ToString() +
"\n\nStack Trace: " + ex.StackTrace.ToString() + "\n";
EventLog.WriteEntry("Conversion-Service", err, EventLogEntryType.Error);
SendEmail(false);
}

public static void SendEmail(bool success)
{
System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
message.To.Add(ConfigurationManager.AppSettings["sendToAdmin"]);
message.Subject = "Conversion-Service " + (success == true ? "Successful" : "Failed");
message.From = new System.Net.Mail.MailAddress(ConfigurationManager.AppSettings["sendFrom"]);
message.Body = (success == true ? "Image Library updated successfully." : "Conversion-Service update failed. Please see server logs on " + ConfigurationManager.AppSettings["portalURL"] + ".");
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient(ConfigurationManager.AppSettings["smtpServer"]);
smtp.Send(message);
}
#endregion
}
}

App.Config

<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="smtpServer" value="my.smtp.server"/>
<add key="sendToAdmin" value="admin@email.com"/>
<add key="sendToUser" value="user@email.com"/>
<add key="sendFrom" value="from@email.com"/>
<add key="portalURL" value="https://MySharePoint2010Server/"/>
<add key="imageListFolder" value="MyImageLibrary"/>
<add key="remoteFolder" value="Z:\\"/>
<add key="remoteFolder1" value="Z:\"/>
<add key="sourceFileName" value="MyPowerPoint.pptx"/>
<add key="remoteDriveLetter" value="Z:"/>
<add key="remoteShareName" value="\\MyOtherServer\UploadFolder"/>
<add key="userName" value="MyServiceAccount"/>
<add key="userPwd" value="Password"/>
<add key="imageFileExtension" value="*.jpg"/>
<add key="otherFileExtension" value="*.pptx"/>
<add key="emailBodyContent" value="Conversion Service operation was successfully completed. You can view uploaded slides at https://MySharePoint2010Server/MyImageLibrary/Forms/AllItems.aspx. Note: This is an automated email generated by the Conversion Service application.\nIt is to inform you that a presentation was processed. Should an issue developed, there \nwould be a separate email sent out unless there was a unrelated SMTP server failure; in \nany case the event log will have detailed information on the nature of the issue."/>
<add key="ClientSettingsProvider.ServiceUri" value=""/>
</appSettings>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf1111ad364e35" serviceUri=""/>
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400"/>
</providers>
</roleManager>
</system.web>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

Set the Project Properties, Build, Platform Target to x64

Get Eric De Carufel’s ServiceDebuggerHelper from http://www.codeproject.com/Articles/21887/Debugging-Windows-Service-Without-Deploying-It

To debug your service set your Project Properties, Debug, Command line arguments: /debug

Comment in the ServiceDebuggerHelper code in program.cs and service1.cs to debug and test the service as an application.

After you’ve confirmed that it works, comment out the ServiceDebuggerHelper project code in program.cs and service1.cs.

Create a new deployment project and in the Solution Explorer, select the deployment project. In the Properties window, make sure that the TargetPlatform property is set to x64. On the View menu, point to Editor, and then click File System. In the File System editor, select the File System on Target Machine node. On the Action menu, choose Add Special Folder, and then choose Common Files (64-bit), Program Files (64-bit), or System (64-bit). Add the your service project output to the new folder.

Build your project and installer.

When you build the Windows Installer project in Visual Studio it embeds the 32-bit version of InstallUtilLib.dll into the Binary Table as InstallUtil. Since the native InstallUtilLib.dll is 32-bit it loads the 32-bit Framework which will throw a BadImageFormatException when you install your service since your managed class library is 64-bit.

To fix this you will need to install the Windows SDK from the Download Center ( http://www.microsoft.com/en-us/download/details.aspx?id=8279 or http://www.microsoft.com/en-us/download/details.aspx?id=3138 ). Then in the “bin” folder of the installation directory (ex: %ProgramFiles%\Microosft SDKs\Windows\v7.0A\bin) there is Orca.msi. Double-click to install that. After installing, you can right-click on your MSI and select Edit with Orca.

Then either replace the 32-bit InstallUtilLib.dll with the 64-bit bitness: Open the resulting .msi in Orca from the Windows Installer SDK, Select the Binary table, Double click the cell [Binary Data] for the record InstallUtil, Make sure “Read binary from filename” is selected and click the Browse button, Browse to %WINDIR%\Microsoft.NET\Framework64\v4.0.30319, Select InstallUtilLib.dll, Click the Open button, Click the OK button

Or if you already have or anticipate having 32-bit custom actions in future patches – and I recommend this approach because the future is difficult to predict – you should add a new record: Open the resulting .msi in Orca from the Windows Installer SDK, Select the Binary table, Click the Tables menu and then Add Row,  Enter InstallUtil64 for the Name, Select the Data row and click the Browse button, Browse to %WINDIR%\Microsoft.NET\Framework64\v4.0.30319, Select InstallUtilLib.dll, Click the Open button, Click the OK button, Select the CustomAction table, For each custom action where the Source column is InstallUtil and only those custom actions that are 64-bit managed custom actions (or that were built with /platform:anycpu, the default, where you want to run as 64-bit custom actions), change InstallUtil to InstallUtil64

Install your service.

Install Office Standard 2010 x64 on the server that you installed your service.

On the server running your service, go into the Component Services, Computer, My Computer, DCOM Config. Then go to the ‘Microsoft PowerPoint Slide’ DCOM and select properties On the identity tab and change the user from being inherited to be a specific user with Network Service/access privileges.

Finally you will need to add the service account and the server that your service is running on to the security on the remote server’s folder with full control.

Thanks to:

http://social.msdn.microsoft.com/profile/heath%20stewart/

http://blogs.msdn.com/b/heaths/archive/2006/02/01/64-bit-managed-custom-actions-with-visual-studio.aspx

http://blogs.technet.com/b/stefan_gossner/

http://blogs.technet.com/b/stefan_gossner/archive/2011/09/19/common-issue-new-spsite-returns-quot-the-web-application-at-http-server-port-could-not-be-found-quot.aspx

http://www.codeproject.com/Members/Eric-De-Carufel

http://www.codeproject.com/Articles/21887/Debugging-Windows-Service-Without-Deploying-It