Programmatic Execution of an Excel Macro on Remote Machine from a website

I tried searching everywhere for a solution on this issue but found nothing. To give you an idea what I want to achieve here is the scenario.

We have a website where users generate and Excel report using a macro, when I try to run it in my local machine it generates perfectly and runs the macro inside the excel. When I publish it into the server and at the same time I am logged in there (RDP open session) and try to run it from a browser outside that server it is also running as expected. The problem occurs when I am logged off in the server (RDP) then run it in a browser outside the server (ie from my machine) the macro does not run but creates my Excel.

This is the code that I am using

public class Report
{
    protected Workbook Workbook { getset; }
    protected Application Excel { getset; }

    public void RunReport()
    {
        // Launch Excel on the server
        Excel = new Application
        {
            DisplayAlerts = false,
            ScreenUpdating = false,
            Visible = false
        };

        // Load the workbook template  
        Workbook = Excel.Workbooks.Open(@"C:\{YourTemplateName}.xlt");

        // You your stuff here
        DoStuff();

        // Execute macros 
        ExecuteMacros();

        Workbook.SaveAs(@"C:\{YourExportedFileName}.xls"XlFileFormat.xlExcel8);

        // Properly Close Excel
        QuitExcel();

    }

    private void QuitExcel()
    {
        if (Workbook != null)
        {
            Workbook.Close(false);
            Marshal.ReleaseComObject(Workbook);
        }

        if (Excel != null)
        {
            Excel.Quit();
            Marshal.ReleaseComObject(Excel);
        }
    }    

    private void ExecuteMacros()
    {
        const string moduleName = "{YourModuleName}";
        const string macroName = "{YourMacroName}";

        bool macroExists = false;
        try
        {
            var macroModule = Workbook.VBProject.VBComponents.Item(moduleName);
            if (macroModule != null)
            {
                int macroStartLine = macroModule.CodeModule.ProcStartLine[macroName, Microsoft.Vbe.Interop.vbext_ProcKind.vbext_pk_Proc];
                macroExists = macroStartLine > 0;
            }
        }
        catch (Exception)
        {
            //no macro found
            macroExists = false;
        }

        if (!macroExists)
        {
            return;
        }

        // VBA code for the dynamic macro that calls 
        var moduleCode = new StringBuilder();
        moduleCode.AppendLine("Public Sub LaunchMacro()");
        moduleCode.AppendLine(string.Format("{0}.{1}", moduleName, macroName));
        moduleCode.AppendLine("End Sub");

        // Add the dynamic macro 
        var workbookMainModule = Workbook.VBProject.VBComponents.Item("ThisWorkbook");
        workbookMainModule.CodeModule.AddFromString(moduleCode.ToString());

        // Execute the dynamic macro
        Microsoft.VisualBasic.Interaction.CallByName(Workbook, "LaunchMacro", Microsoft.VisualBasic.CallType.Method, new object[] { });
    }
}

as explained everything works properly until you log off to the server.  Now after some investigation we notice that the Trust access to the VBA project object model is turned off when you log out of the server which makes your macro useless as it would not run.

It was a bit of a search to come up with this conclusion but nice to know there was a solution and here it is.

Since we know that is being turned off when a user logs out we have to create a method on our application to turn that on so we can run our macro happily and that is done through a registry setting like such.

private static void ModifyExcelSecuritySettings()
{
    // Make sure we have programmatic access to the project to run macros
    using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\14.0\Excel\Security"true))
    {
        if (key != null)
        {
            if ((int)key.GetValue("AccessVBOM", 0) != 1)
            {
                key.SetValue("AccessVBOM", 1);
            }
            key.Close();
        }
    }
}

Just change the path depending on the Excel version you are using.

This is then used before you launch Excel on the server like such.

public void RunReport()
{
    ModifyExcelSecuritySettings();

    // Launch Excel on the server
    Excel = new Application
    {
        DisplayAlerts = false,
        ScreenUpdating = false,
        Visible = false
    };

    // Load the workbook template  
    Workbook = Excel.Workbooks.Open(@"C:\{YourTemplateName}.xlt");

    // You your stuff here
    DoStuff();

    // Execute macros 
    ExecuteMacros();

    Workbook.SaveAs(@"C:\{YourExportedFileName}.xls"XlFileFormat.xlExcel8);

    // Properly Close Excel
    QuitExcel();

}

BTW for those interested the site is deployed in IIS7 using Integrated Application Pool Identity and Passtrough Authentication / Identity Impersonation.

Top 3 Free IIS Based Wiki

Have you ever wondered what are the top 3 IIS based Wiki Applications, well here is my list not sure if it will be you top 3 but this is mine.

So what are my criteria?  It should be free, you can easily modify it (opensource), the backend database should be SQL Server and it should be Microsoft Based Application which means it should run in IIS.  So what is my top 3 then.

3. DNN (DotNetNuke)

DNN Wiki

The most popular .Net Open Source CMS is my third in the list.  And eventhough it is a CMS application it has as Wiki Module, though not extensive as the open source wiki’s it does it job.  To give you an idea here are the main things that you can only do.

Home – Brings you to the  default page of the Wiki, not the default page of the site.
Search – Searches the Wiki.
Recent Changes – Review the history of changes.
Index – Some sort of a table of contents where it shows you all Wiki Pages.
Add – Adds a new wiki page.
Edit – Edits a wiki page.
View Topic History – Review the history of changes on the specific Wiki Page.

Some additional settings:
Use DotNetNuke Security for edit content permissions – As it says use DNN Security otherwise you can manually override the permissions.
Allow Pages Comments – Allows visitors to leave comments on the wiki pages (individually or globally)
Allow Pages Ratings – Allows the visitor to rank the page (individually or globally).

And thats about it, thats all you can do.  I’m not saying that its not good but DNN’s main focus is CMS not a Wiki.  The wiki part is just a bonus.  DNN can be freely downloaded here.

Pro

  • Open Source which means you can customize whatever you want.
  • Have Active Directory Providers.
  • Can do more than just a Wiki site.
  • Can easily port to the internet.

Cons

  • Need a bit of learning if you want to customize stuff.
  • Not a full blown wiki application.

2. Microsoft Sharepoint

Sharepoint Wiki

Yes, youve seen it right its Sharepoint and its another CMS Application.  Eventhough Sharepoint is a content management system it can be utilized as a Wiki tool and it comes free with a Windows Server which you can download here.

Pro

  • Integrates with Microsoft Office.
  • Can do more than just a Wiki site.
  • Highly Customizable.
  • Integrated natively with Active Directory.
  • Install and use.

Cons

  • Performance is based on the Server Hardware.
  • You need to use Microsoft Sharepoint Designer to customize.
  • Making it available on the Internet it not simple.

1. ScrewTurn Wiki

ScrewTurn Wiki

And the number one is ScrewTurn Wiki!

It is a dedicated Wiki engine developed in C# which can use SQL Server or just file system for its database.  Since its a dedicated wiki engine it means it have all of the wiki functionalities you are looking for like change control, discussions, ratings, attachments just to name some.  Definitely its free and can be downloaded here

Pro

  • Open Source
  • Blazing fast (High performance)
  • Low Bandwidth usage (ViewState Compression and HTTP Compression)
  • Install and use
  • Simple usage and administration
  • RSS

Cons

  • I cannot use key strokes in the editor (such as CTRL+B, CTRL+U,etc)

How to List all Websites in IIS

Its been a while since I had posted something that is because my Laptop gave up on me.  Anyways I’m back in action but still no laptop…  Anyways I was tasked to get to list all websites that we had on the organization as we are implementing an Enterprise Architecture tool which need to be populated (the EA tool is called Troux).  Now my dilemma is that I dont have anything on the desktop I have now, just a standard installation of OS and thats it so whats the best way to achieve the solution?

Aha!!!! Use the old school style vbs scripting.

So how do I achieve that? First is that you should know what are your servers and list them on a spreadsheet, In my case its good as we have it already pre-populated on the EA tool that we have so Ill just export it.  So I have to create a code that will loop though that Spreadsheet and check what Websites are in there.  Here is how I do it.

Set oExcel = CreateObject("Excel.Application")
If (Err.Number <> 0) Then
 On Error GoTo 0
 Wscript.Echo "You need to install an Excel Application"
 Wscript.Quit
End If
On Error GoTo 0

sExcelPath = "C:\Scripts\SERVERS-new.xls"

' Open Spreadsheet and Use First Worksheet.
oExcel.WorkBooks.Open sExcelPath
Set objSheet = oExcel.ActiveWorkbook.Worksheets(1)

' Loop through all the items in Speadsheet, 1st row is a Header Row
intRow = 2
Do While objSheet.Cells(intRow, 1).Value <> ""
 strServerName = objSheet.Cells(intRow, 1).Value
 On Error Resume Next
 ' This takes care if you dont have IIS installed on the server
 
 Dim oW3SVC, oWebSite

 'Get the IIS Server Object 
 Set oW3SVC = GetObject("IIS://" & strServerName & "/W3SVC")
 If (Err <> 0) Then
 
 Else
 For Each oWebSite In oW3SVC
 If oWebSite.class = "IIsWebServer" Then

 Set oFile = CreateObject("Scripting.FileSystemObject")
 Set oTextFile = oFile.OpenTextFile("C:\Scripts\IIS.txt", 8, True)
 'Get the Name of the Website
 oTextFile.WriteLine(strServerName & "," & oWebSite.ServerComment)
 oTextFile.Close
 
 Set oTextFile = Nothing
 Set oFile = Nothing


 End If
 Next
 End If
 intRow = intRow + 1
Loop

' Close Workbook and Excel.
oExcel.ActiveWorkbook.Close
oExcel.Application.Quit

' Clean up.
Set oExcel = Nothing
Set objSheet = Nothing
Set objUser = Nothing
Set oW3SVC = Nothing
Set oWebSite = Nothing
Wscript.Echo "Done"

Save it as [Filename].vbs and click the File then get your results. Simple yet effective specially when you have more than 200 websites on your organization, it saves your time jotting them down and you dont know you might discover new websites.

Follow

Get every new post delivered to your Inbox.

Join 773 other followers