Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, November 22, 2010

Use C# to generate sample Word and PDF files on the fly!

While doing SharePoint development, I constantly run into a task where I need to add a bunch of random sample files in order to see how content looks when it is populates. I try to keep some sample files handy, but I tend to misplace these, need to target a different type of content, or need a different naming convention. In this example, I wanted to create a handful of HR policies and procedures documents.

Steps:
1. Create a console application in Visual Studio 2010. Make sure it is .NET 4.0.
2. A
dd a reference to “Microsoft Word 14.0 Object Library”. It is likely this will work with 12.0, but I haven’t tested it.
3. Copy and paste the code below. Make sure to update your namespace if necessary.
4. Make sure the variables are setup correctly. You may need to update the SAVE_DIRECTORY constant or use prompt the user with a FolderBrowserDialog. You can also set the CreateMode enum for creating only Word, only PDF, or both. You can also update the list. I tend to add a bunch of values in Excel and then create a simple formula to get them in the format I want. For example: ="docList.Add(" &char(34) & A1 & char(34) & ");"
5. Hit F5!

Note: .NET 4.0 makes working with COM objects much easier and I take advantage of this new functionality in this example. If you plan on using an earlier version, you will have to make a few minor changes. (See references below.) Keep in mind, all of these documents are blank too. You will need to do a little more work to add text.

References
MSDN - Saving Word 2007 Documents to PDF and XPS Formats
COM Interop Gets Much Better in C# 4.0
Sample Human Resources Policies, Checklists, Forms, and Procedures

using
System;
using System.Collections.Generic;
using System.IO;
using Word = Microsoft.Office.Interop.Word;

namespace CreateSampleHRFiles
{
classProgram
{
private enum CreateMode { WordOnly, PdfOnly, Both };
private const string SAVE_DIRECTORY = "c:\\temp\\";
private static Word.Application wordApp = null;
private static Word.Document wordDoc = null;

private static void Main(string[] args)
{
CreateSampleDocuments(FileNames, CreateMode.Both);
}

private static void CreateSampleDocuments(List<string> fileNames, CreateMode createMode)
{
foreach (string fileName in fileNames)
{
string wordFileName = SAVE_DIRECTORY + fileName + ".docx"; ;
string pdfFileName = SAVE_DIRECTORY + fileName + ".pdf";
switch(createMode)
{
caseCreateMode.Both:
CreateWordDoc(wordFileName);
ConvertWordToPdf(wordFileName, pdfFileName);
break;
caseCreateMode.PdfOnly:
CreateWordDoc(wordFileName);
ConvertWordToPdf(wordFileName, pdfFileName);
File.Delete(wordFileName);
break;
caseCreateMode.WordOnly:
CreateWordDoc(wordFileName);
break;
}
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}

private static void CreateWordDoc(string fileName)
{
wordApp = newWord.Application();
object paramMissing = System.Reflection.Missing.Value;
wordDoc = wordApp.Documents.Add(paramMissing, paramMissing, paramMissing, paramMissing);
wordDoc.Activate();
wordApp.Selection.TypeText(fileName.Replace(".docx", "").Replace(SAVE_DIRECTORY, ""));
try
{
wordDoc.SaveAs(fileName, ReadOnlyRecommended: false);
}
catch(Exceptionex)
{
//TODO:
}
finally
{
if(wordDoc != null)
{
wordDoc.Close(SaveChanges: true);
wordDoc = null;
}
if(wordApp != null)
{
wordApp.Quit(SaveChanges: true);
wordApp = null;
}

}
}

private static void ConvertWordToPdf(object paramSourceDocPath, string paramExportFilePath)
{
wordApp = newWord.Application();
object paramMissing = Type.Missing;
Word.WdExportFormat paramExportFormat = Word.WdExportFormat.wdExportFormatPDF;
bool paramOpenAfterExport = false;
Word.WdExportOptimizeFor paramExportOptimizeFor = Word.WdExportOptimizeFor.wdExportOptimizeForPrint;
Word.WdExportRange paramExportRange = Word.WdExportRange.wdExportAllDocument;
int paramStartPage = 0;
int paramEndPage = 0;
Word.WdExportItem paramExportItem = Word.WdExportItem.wdExportDocumentContent;
bool paramIncludeDocProps = true;
bool paramKeepIRM = true;
Word.WdExportCreateBookmarks paramCreateBookmarks = Word.WdExportCreateBookmarks.wdExportCreateWordBookmarks;
bool paramDocStructureTags = true;
bool paramBitmapMissingFonts = true;
bool paramUseISO19005_1 = false;
try
{
wordDoc = wordApp.Documents.Open(ref paramSourceDocPath, ConfirmConversions: true);
if (wordDoc != null)
wordDoc.ExportAsFixedFormat(paramExportFilePath, paramExportFormat, paramOpenAfterExport,
paramExportOptimizeFor, paramExportRange, paramStartPage, paramEndPage, paramExportItem,
paramIncludeDocProps, paramKeepIRM, paramCreateBookmarks, paramDocStructureTags,
paramBitmapMissingFonts, paramUseISO19005_1, ref paramMissing);
}
catch (Exception ex)
{
//TODO:
}
finally
{
if (wordDoc != null)
{
wordDoc.Close(SaveChanges: true);
wordDoc = null;
}
if (wordApp != null)
{
wordApp.Quit(SaveChanges: true);
wordApp = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}

public static List<string> FileNames
{
get
{
List<string> docList = new List<string>();
#region docList
docList.Add("Absenteeism and Tardiness Policy");
docList.Add("Access to Personnel Records");
docList.Add("Amendments to Handbook Policy Sample");
docList.Add("Applicant for Jobs - Evaluation Form");
docList.Add("Applicant Self Identification Form - Race Ethnicity");
docList.Add("Application for Internal Job Opportunities");
docList.Add("Armed Services Leave Policy");
docList.Add("At Will Employment Sample Policy");
docList.Add("Attendance Policy Samples");
docList.Add("Benefits Options");
docList.Add("Bereavement Leave");
docList.Add("Blogging and Social Media Policy Sample");
docList.Add("Breaks and Lunch Requirements");
docList.Add("Breast Feeding Accommodation Policy");
docList.Add("Business Casual Dress Code");
docList.Add("Business Casual Dress Code - Manufacturing and Office");
docList.Add("Candidate Evaluation Form");
docList.Add("Candidate Job Offer Letter - Early Career");
docList.Add("Candidate Job Offer Letter - Executive");
docList.Add("Candidate Job Offer Letter - Mid- career");
docList.Add("Candidate Job Offer Letter - Sales Representative");
docList.Add("Candidate Job Offer Letter - Standard");
docList.Add("Candidate Rejection Letter");
docList.Add("Casual Dress Code - Manufacturing and Office");
docList.Add("Cell Phone Policy");
docList.Add("Code of Conduct Outline");
docList.Add("Concealed Weapons Policy");
docList.Add("Confidentiality Agreement");
docList.Add("Counseling Record for Disciplinary Warning Form");
docList.Add("Cover Letter Sample for Review");
docList.Add("Discipline");
docList.Add("Discipline Warning Form- Counseling Record for Disciplinary Warning");
docList.Add("Dress Code - Business Casual");
docList.Add("Dress Code - Casual- Manufacturing and Office");
docList.Add("Dress Code - Customer Interaction and Trade Shows");
docList.Add("Dress Code - Formal, Professional");
docList.Add("Dress Code - Relaxed, Casual");
docList.Add("Dress Code- Letter of Introduction");
docList.Add("Drug Testing - Screening Policy Development");
docList.Add("Drug- free Workplace (Policy Components)");
docList.Add("Email and Internet Sample Policy");
docList.Add("Employee Handbook - Table of Contents");
docList.Add("Employee Handbook Acknowledgement of Receipt");
docList.Add("Employee Handbook Introduction and Purpose");
docList.Add("Employment at Will Sample Policy");
docList.Add("Employment Discrimination Guidelines");
docList.Add("Employment Ending Checklist and Form");
docList.Add("Ethics Code Outline");
docList.Add("Exempt Classification - Non-exempt Classification");
docList.Add("Exit Interviews- Questions for Exit Interviews");
docList.Add("Fair Labor Standards Act (FLSA)");
docList.Add("Family and Medical Leave Act (FMLA)");
docList.Add("Funeral Leave");
docList.Add("Gift Policy");
docList.Add("Glossary of Terms - Dictionary");
docList.Add("Handbook Acknowledgement of Receipt");
docList.Add("Handbook Introduction");
docList.Add("Handbook Table of Contents");
docList.Add("Handbooks");
docList.Add("Harassment - Aids - HIV");
docList.Add("Harassment Investigation Steps");
docList.Add("Health and Safety and Environmental");
docList.Add("Hiring Checklist");
docList.Add("Hiring Forms");
docList.Add("HR Records Access by Employees");
docList.Add("Human Resource Director Job Description");
docList.Add("Human Resources Generalist Job Description");
docList.Add("Human Resources Letters (Samples)");
docList.Add("I- 9 Form- Employment Eligibility for Employers");
docList.Add("Initial Phone Screen");
docList.Add("Internal Job Application");
docList.Add("Internet and Email Acceptable Use Policies");
docList.Add("Internet and Email Policy");
docList.Add("Interview Questions Samples");
docList.Add("Investigation Steps");
docList.Add("Investigation Steps");
docList.Add("Job Application - Internal Transfer");
docList.Add("Job Offer Letter- Early Career");
docList.Add("Job Offer Letter- Executive Job Offer");
docList.Add("Job Offer Letter- Generic");
docList.Add("Job Offer Letter- Mid- career Job Offer");
docList.Add("Job Offer Letter- Sales Representative");
docList.Add("Letter of Resignation Sample");
docList.Add("No Smoking Policy");
docList.Add("Non-exempt Classification - Exempt Classification");
docList.Add("Paid Sick Days Policy");
docList.Add("Paid Time Off (PTO) Policy Sample");
docList.Add("Paid Vacation Days Policy");
docList.Add("Performance Development Plan Form");
docList.Add("Performance Improvement Plan");
docList.Add("Performance Management Process Checklist");
docList.Add("Personnel File Access Policy");
docList.Add("Personnel File Policy");
docList.Add("Phone (Cell) Policy Sample for Workplaces");
docList.Add("Phone Screening - Initial Telephone Interview");
docList.Add("Policy Receipt Acknowledgement Sample");
docList.Add("Progressive Discipline Steps");
docList.Add("Progressive Discipline Warning Form");
docList.Add("Race - Applicant Self Identification Form");
docList.Add("Records - Employee Access to Personnel Records");
docList.Add("Reference Checking Format");
docList.Add("Rejection of Candidate Letter Sample");
docList.Add("Resignation Letter Sample");
docList.Add("Resume Cover Letter Sample");
docList.Add("Resume Sample - Why This Resume Rocks");
docList.Add("Screening Telephone Interview");
docList.Add("Sexual Harassment Complaint - How to Address");
docList.Add("Sick Leave Policy");
docList.Add("Smoke Free Workplace Policy");
docList.Add("Social Media and Blogging Policy Sample");
docList.Add("Space Planning Feedback");
docList.Add("Tardiness and Absenteeism Policy");
docList.Add("Team Norms Sample");
docList.Add("Telephone Screening Format");
docList.Add("Telephone Use Policy - Manufacturing Facility");
docList.Add("Termination Checklist and Form");
docList.Add("The Americans With Disabilities Act Requirements");
docList.Add("Uniformed Services Leave Policy (USERRA)");
docList.Add("Vacation Days Policy");
docList.Add("Weapons (Concealed) Sample Policy");
#endregiondocList
returndocList;
}
}
}
}

Friday, February 19, 2010

Create a sample text generator system tray tool with C#

There are a ton of great websites that allow you to generate sample text, but I’ve always wanted one that I can access quickly and easily, especially when I am doing some testing. Here is one that can be easily created and runs in your system tray. The code is simple enough that you can add more options like DBCS text generator.

image

Steps
1. Open Visual Studio and create a Windows Forms Application.
2. Add a new or existing Icon File to be shown in your system tray.
3. Add a ContextMenuStrip control the the form and rename it “contextMenuStrip”.
4. Add a NotifyIcon control to your form and rename it “notifyIcon”.
i. Change the Text to “TextGenerator”.
ii. Change the Icon to the one you added in Step 2.
iii. Change the ContextMenuStrip to the one in Step 3.
5. Add the following code to the Form code behind. (Alternatively you can use the designer to some of this code, but I find it more scalable if I do it in code.)

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace TextGenerator
{
public partial class Form1 : Form
{
public bool ShowTooltips { get; set; }
public int DefaultCharLength { get; set; }
public string SampleText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec consequat " +
"dolor auctor tortor tincidunt tristique sit amet et arcu. Vivamus dui risus, hendrerit quis rhoncus" +
"vel, consequat ut augue. Quisque congue nisi id enim lobortis vitae pellentesque nulla euismod." +
"Aenean ante risus, feugiat vel facilisis non, iaculis ac augue. Phasellus in mollis est. Suspendisse" +
"potenti. Vestibulum gravida sem enim. Vestibulum vel dui id odio vulputate fringilla. Curabitur " +
"bibendum lorem a nisi posuere sit amet tincidunt diam condimentum. Fusce in tellus urna. Suspendisse" +
"condimentum tortor et mi luctus facilisis. Fusce tincidunt augue vitae odio luctus posuere. Phasellus" +
"ac turpis metus, pharetra tempor lectus. Sed eget massa sit amet lacus faucibus blandit in a risus." +
"Phasellus dui dolor, pulvinar vitae cursus pharetra, porttitor in augue. Donec tristique dignissim " +
"diam in sollicitudin. Integer luctus elit a orci tristique sit amet pulvinar erat tempor. Maecenas " +
"sit amet aliquam libero. Sed tincidunt justo at velit sollicitudin vel vehicula turpis ultrices. " +
"Etiam erat nulla, vehicula non viverra non, porta eu elit. Proin commodo adipiscing nisl nec pretium." +
"Nam lacinia posuere varius. Cras mollis rutrum felis, venenatis lobortis mi imperdiet non. Lorem ipsum" +
"dolor sit amet, consectetur adipiscing elit. Nam id nisi lorem, non pulvinar erat. Donec sit amet velit" +
"eu velit varius imperdiet sit amet vitae leo. Nulla malesuada, dolor sit amet tincidunt fermentum, " +
"mauris nisl posuere nisi, a consequat leo risus ut nibh. In a sapien eu lectus lobortis lacinia. " +
"Pellentesque sit amet lacus sem, non molestie sapien. Duis at enim magna. Integer vitae mi purus, id " +
"rutrum neque. Mauris vitae sem nulla, at accumsan odio. Quisque pulvinar, urna ut aliquam tristique, " +
"magna magna ornare tortor, ut adipiscing nunc nisi et ipsum. Nam porttitor sodales porta. Cras " +
"ullamcorper libero ut sem dapibus ac dapibus tellus scelerisque. Mauris a nisi nec odio varius " +
"iaculis. Integer vel massa eget nunco volutpati.";
public Form1()
{
InitializeComponent();
this.WindowState = FormWindowState.Minimized;
}

private void Form1_Load(object sender, EventArgs e)
{
ShowTooltips = false;
DefaultCharLength = 100;
this.Visible = false;
this.WindowState = FormWindowState.Minimized;

if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
MessageBox.Show("An instance of TextGenerator is already running.\r\nCheck your system tray.");
System.Threading.Thread.Sleep(3000);
this.Close();
}

ToolStripMenuItem defaultText = new ToolStripMenuItem("Default Character Length");
ToolStripMenuItem defaultText50 = new ToolStripMenuItem("50");
defaultText50.Click += new EventHandler(defaultText_Click);
ToolStripMenuItem defaultText100 = new ToolStripMenuItem("100");
defaultText100.Checked = true;
defaultText100.Click += new EventHandler(defaultText_Click);
ToolStripMenuItem defaultText250 = new ToolStripMenuItem("250");
defaultText250.Click += new EventHandler(defaultText_Click);
ToolStripMenuItem defaultText500 = new ToolStripMenuItem("500");
defaultText500.Click += new EventHandler(defaultText_Click);
ToolStripMenuItem defaultText1000 = new ToolStripMenuItem("1000");
defaultText1000.Click += new EventHandler(defaultText_Click);
ToolStripMenuItem defaultText2000 = new ToolStripMenuItem("2000");
defaultText2000.Click += new EventHandler(defaultText_Click);
defaultText.DropDownItems.Add(defaultText50);
defaultText.DropDownItems.Add(defaultText100);
defaultText.DropDownItems.Add(defaultText250);
defaultText.DropDownItems.Add(defaultText500);
defaultText.DropDownItems.Add(defaultText1000);
defaultText.DropDownItems.Add(defaultText2000);

ToolStripMenuItem copy50 = new ToolStripMenuItem("Copy 50") { Tag = 50 };
copy50.Click += new EventHandler(copy_Click);
ToolStripMenuItem copy100 = new ToolStripMenuItem("Copy 100") { Tag = 100 };
copy100.Click += new EventHandler(copy_Click);
ToolStripMenuItem copy250 = new ToolStripMenuItem("Copy 250") { Tag = 250 };
copy250.Click += new EventHandler(copy_Click);
ToolStripMenuItem copy500 = new ToolStripMenuItem("Copy 500") { Tag = 500 };
copy500.Click += new EventHandler(copy_Click);
ToolStripMenuItem copy1000 = new ToolStripMenuItem("Copy 1000") { Tag = 1000 };
copy1000.Click += new EventHandler(copy_Click);
ToolStripMenuItem copy2000 = new ToolStripMenuItem("Copy 2000") { Tag = 2000 };
copy2000.Click += new EventHandler(copy_Click);

ToolStripMenuItem exit = new ToolStripMenuItem("Exit");
exit.Click += new EventHandler(exit_Click);

ToolStripMenuItem options = new ToolStripMenuItem("Options");
ToolStripMenuItem showToolTipItem = new ToolStripMenuItem("Show Tooltips");
showToolTipItem.Click += new EventHandler(showToolTipItem_Click);
options.DropDownItems.Add(showToolTipItem);

contextMenuStrip.Items.Add(defaultText);
contextMenuStrip.Items.Add(copy50);
contextMenuStrip.Items.Add(copy100);
contextMenuStrip.Items.Add(copy250);
contextMenuStrip.Items.Add(copy500);
contextMenuStrip.Items.Add(copy1000);
contextMenuStrip.Items.Add(copy2000);

contextMenuStrip.Items.Add(new ToolStripSeparator());

contextMenuStrip.Items.Add(options);
contextMenuStrip.Items.Add(exit);
}

void showToolTipItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem showToolTipItem = sender as ToolStripMenuItem;
ShowTooltips = !showToolTipItem.Checked;
showToolTipItem.Checked = !showToolTipItem.Checked;
}


void exit_Click(object sender, EventArgs e)
{
this.Close();
}

void defaultText_Click(object sender, EventArgs e)
{
foreach (ToolStripMenuItem childItem in ((ToolStripMenuItem)((ToolStripMenuItem)sender).OwnerItem).DropDownItems)
{
childItem.Checked = false;
}
((ToolStripMenuItem)sender).Checked = true;
DefaultCharLength = Convert.ToInt32(((ToolStripMenuItem)sender).Text);
CopyToClipboard(DefaultCharLength);
}

void copy_Click(object sender, EventArgs e)
{
CopyToClipboard(Convert.ToInt32(((ToolStripMenuItem)sender).Tag));
}

private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
CopyToClipboard(DefaultCharLength);
}
}

private void CopyToClipboard(int characters)
{
try
{
Clipboard.SetText(SampleText.Substring(0, characters));
if (ShowTooltips)
{
notifyIcon.ShowBalloonTip(50, "TextGenerator", "Copied " + characters.ToString() + " characters to the clipboard.", ToolTipIcon.Info);
}
}
catch (Exception ex)
{
notifyIcon.ShowBalloonTip(10, "TextGenerator", "Unknown Error: " + ex.ToString(), ToolTipIcon.Error);
}
}
}
}
6. Hit F5 and run!


Instructions
1. Left-Click to copy default characters.
2. Right-click to copy a different amount of characters or set the default character link.
References
Sample text taken from LoremIpsum.

Thursday, February 4, 2010

Submit a new InfoPath form to a SharePoint Form Library Programmatically

Let me first start out by saying that if anyone has a better way to do this I am all ears. As far as I’m concerned this isn’t an ideal solution, but after scouring the web I simply could not find a different approach.

Requirements
The ability to programmatically add a new InfoPath form to a SharePoint Form Library using one of the content type templates that have been defined in the same Form Library.

Summary
The reason I need this functionality is because I have developed a very complicated and interactive Silverlight form that will have a number of dependent InfoPath forms. I needed a way to generate these on the fly whenever a new record was created and then to be able to reference them. Adding a file to a Form Library is pretty trivial, but getting an InfoPath template from a Form Library is not out of the box. This part was critical as the template has the ability to be updated at any time and I wanted to make sure I was always using a valid one.

A special thanks to Mike Hodnick for providing the code for retrieving the InfoPath template.
Programmatically create an InfoPath form instance from XSN template

UPDATE: It turns out this solution will only work with the root site and not other site collections in the same farm. Fortunately, there is a work around. Keep these steps in mind when following these instructions.
1. Encapsulate the code from GetInfoPathTemplate.aspx into a web part and deploy it to SharePoint.
2. Install the web part on a web part page in the same site collection where the forms will be located.
3. Update the web service to include a parameter for the web part page url.

Create Web Service Project
1. Create an “ASP.NET Web Service Application” project in Visual Studio 2008.
2. Make sure that the assembly is signed with a strongly named key. (Project –> Properties –> Signing –> Sign the assembly)
3. Add a reference to Microsoft.SharePoint (C:\Program Files\Common Files\microsoft shared\web server extensions\12\ISAPI\Microsoft.SharePoint.dll)
4. Add a reference to Microsoft.Office.InfoPath and Microsoft.InfoPath.Server (c:\Program Files\Microsoft Office Servers\12.0\Bin)
5. Add Web Form to the project. I have called mine GetInfoPathTemplate.aspx.
6. Add a single PlaceHolder control to the page in design view. This will be used to instantiate an InfoPath form and will allow us to retrieve the template xml.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetInfoPathTemplate.aspx.cs" Inherits="Acme.Services.InfoPath.GetInfoPathTemplate" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<
html xmlns="http://www.w3.org/1999/xhtml">
<
head runat="server">
<
title></title>
</
head>
<
body>
<
form id="form1" runat="server">
<
div>
<
asp:PlaceHolder ID="formHostPlaceholder" runat="server" />
</
div>
</
form>
</
body>
</
html>

7. Add the code behind for the page. You will see that it takes a query string called “templateUrl”. (Note: I haven’t add exception handling yet.)

using System;
using System.IO;
using Microsoft.Office.InfoPath.Server.Controls;

namespace Acme.Services.InfoPath
{
public partial class GetInfoPathTemplate : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["templateUrl"] != null)
{
XmlFormView formView = new XmlFormView();
formView.Initialize += new EventHandler<InitializeEventArgs>(formView_Initialize);
string url = Request.QueryString["templateUrl"].ToString();
this.formHostPlaceholder.Controls.Add(formView);
formView.XsnLocation = url;
}
}

void formView_Initialize(object sender, InitializeEventArgs e)
{
XmlFormView formView = sender as XmlFormView;
Stream stream = formView.XmlForm.Template.OpenFileFromPackage("template.xml");
StreamReader reader = new StreamReader(stream);
string xml = reader.ReadToEnd();
this.Response.Clear();
this.Response.ContentType = "text/xml";
this.Response.Write(xml);
this.Response.End();
}
}
}

8. Open up the code behind for the web service and add code for retrieving template names, updating the template xml, and submitting to a SharePoint Form Library.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Xml.Linq;
using Microsoft.SharePoint;

namespace Acme.Services.InfoPath
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service : System.Web.Services.WebService
{
[WebMethod]
public bool SubmitInfoPathForm(string templateUrl, string formItemUrl)
{
bool submitted = false;
string infoPathTemplateUrl = string.Empty;
try
{
WebClient client = new WebClient();
client.Credentials = CredentialCache.DefaultCredentials;
infoPathTemplateUrl = GetInfoPathTemplateUrl() + "?templateUrl=" + templateUrl;
Stream stream = client.OpenRead(infoPathTemplateUrl);
StreamReader reader = new StreamReader(stream);
string formXml = UpdateTemplate(templateUrl, reader.ReadToEnd());
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes(formXml);
using (SPSite site = new SPSite(templateUrl))
{
using (SPWeb web = site.OpenWeb())
{
web.Files.Add(formItemUrl, bytes);
submitted = true;
}
}
}
catch (Exception ex)
{
throw ex;
}
return submitted;
}

[WebMethod]
public string[] GetInfoPathTemplates(string webUrl, string listName)
{
List<string> templates = new List<string>();
using (SPSite site = new SPSite(webUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[listName];
SPContentTypeCollection contentTypes = list.ContentTypes;
foreach (SPContentType contentType in contentTypes)
{
if (contentType.DocumentTemplate.EndsWith(".xsn"))
{
templates.Add(contentType.DocumentTemplate);
}
}
}
}
return templates.ToArray();
}

private string GetInfoPathTemplateUrl()
{
return HttpContext.Current.Request.Url.ToString().Replace("Service.asmx", "GetInfoPathTemplate.aspx");
}

private string UpdateTemplate(string templateUrl, string templateXml)
{
XDocument xDocRoot = XDocument.Parse(templateXml);
IEnumerable<XNode> nodes = xDocRoot.Nodes();
foreach (XNode node in nodes)
{
if (node.ToString().Contains("mso-infoPathSolution")) //Lame, but couldn't find any other way.
{
if (!((XProcessingInstruction)node).Data.Contains("href="))
{
((XProcessingInstruction)node).Data = ((XProcessingInstruction)node).Data + " href=\"" + templateUrl + "\"";
}
break;
}
}
return xDocRoot.Declaration + xDocRoot.ToString();
}
}
}

9. Create a folder called “InfoPathServices” at the level of your SharePoint bin directory and add your web service “Service.asmx” and web form “GetInfoPathTemplate.aspx”. (C:\inetpub\wwwroot\wss\VirtualDirectories\80)

image

10. Register your web service assembly in the GAC and take note of the Public Key Token. (Start –> Run –> assembly)
11. Open the web.config and add a new SafeControl and assembly tag with the Public Key Token in the previous step. (C:\inetpub\wwwroot\wss\VirtualDirectories\80)
<configuration>
<SharePoint>
<SafeControls>
<SafeControl Assembly="Acme.Services.InfoPath, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxx" Namespace="Acme.Services.InfoPath" TypeName="*" Safe="True" />
</SafeControls>
</SharePoint>
<system.web>
<compilation>
<add assembly="Acme.Services.InfoPath, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxx" />
</compilation>
</system.web>
</configuration>

Testing

1. Template Retrieval Testing - Test the web application by opening the URL with the query string to a valid template url.

http://[portalname]/InfoPathService/GetInfoPathTemplate.aspx?templateUrl=http://[portalname]/[form libraryname]/Forms/[reporttemplatename].xsn

It should look something like this:


image


2. For the rest, you can simply create a Console Application that references the web service. Here is an example I have provided. You will need four parameters:

Web Url – Base URL where your list is located.
List Name – Name of your form library.
Content Type Name – The name of your report template.
List Item Name – This is the name that you will be giving your report.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.SharePoint;
using Acme.Services.InfoPath.Tester.InfoPathService;

namespace Acme.Services.InfoPath.Tester
{
class Program
{
static void Main(string[] args)
{
string webUrl = @"http://[portalname]/[teamsitename]/";
string listName = "[formlibraryname]";
string contentTypeName = "[reportname]";
string listItemName = Guid.NewGuid().ToString();
try
{
SubmitInfoPath(webUrl, listName, contentTypeName, listItemName);
}
catch (Exception ex)
{
//todo: handle exception
}
}

static void SubmitInfoPath(string webUrl, string listName, string contentTypeName, string listItemName)
{
string templateUrl = GetTemplateUrl(webUrl, listName, contentTypeName);
string itemUrl = string.Format(webUrl + listName + "/" + listItemName + ".xml");
if (!string.IsNullOrEmpty(templateUrl))
{
Service sc = new Service();
sc.Credentials = CredentialCache.DefaultNetworkCredentials;
sc.SubmitInfoPathForm(templateUrl, itemUrl);
}
else
{
throw new Exception("Content type does not exist.");
}
}

static string GetTemplateUrl(string listUrl, string listName, string contentTypeName)
{
string templateUrl = string.Empty;
Service sc = new Service();
sc.Credentials = CredentialCache.DefaultNetworkCredentials;
string[] templates = sc.GetInfoPathTemplates(listUrl, listName);
templateUrl = (from t in templates where t.Contains(contentTypeName) select t).Single();
return templateUrl;
}

public static string[] GetInfoPathTemplates(string webUrl, string listName)
{
List<string> templates = new List<string>();
using (SPSite site = new SPSite(webUrl))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[listName];
SPContentTypeCollection contentTypes = list.ContentTypes;
foreach (SPContentType contentType in contentTypes)
{
if (contentType.DocumentTemplate.EndsWith(".xsn"))
{
templates.Add(contentType.DocumentTemplate);
}
}
}
}
return templates.ToArray();
}
}
}
Assuming you did everything right, you should start seeing items in your form library!
image

Thursday, August 6, 2009

Compare the content of two files

Use the following snippet:

using System.IO;

. . .


private static bool FileCompare(string filePath1, string filePath2)
{
    int file1byte;
    int file2byte;
    FileStream fileStream1;
    FileStream fileStream2;
    if (filePath1 == filePath2)
    {
        return true;
    }
    FileInfo fileInfo = new FileInfo(filePath1);
    fileInfo.IsReadOnly = false;
    fileInfo = new FileInfo(filePath2);
    fileInfo.IsReadOnly = false;
    fileStream1 = new FileStream(filePath1, FileMode.Open);
    fileStream2 = new FileStream(filePath2, FileMode.Open);
    if (fileStream1.Length != fileStream2.Length)
    {
        fileStream1.Close();
        fileStream2.Close();
        return false;
    }
    do
   
{
        file1byte = fileStream1.ReadByte();
        file2byte = fileStream2.ReadByte();
    }
    while ((file1byte == file2byte) && (file1byte != -1));
    fileStream1.Close();
    fileStream2.Close();
    return ((file1byte - file2byte) == 0);
}

 

Kill a Windows Service or Process Thread

Use one of the following code snippets:

using System.Diagnostics;

. . .

private static void KillProcessThread(string processName)
{
    Process[] processes;
    processes = Process.GetProcessesByName(processName);
    foreach(Process proc in processes)
    {
        proc.Kill();
    }
}

 

using System.ServiceProcess;

. . .

private static void KillWindowsService(string serviceName)
{
        ServiceController sc = new ServiceController();
        sc.ServiceName = serviceName;
        sc.Stop();
}

Get a recursive list of files in a given directory

Here is a simple code snippet:

using System.Collections.Generic;
usingSystem.IO;
usingSystem.Text;

. . .

static void Main(string[] args)
{
List<FileSystemInfo> fileInfo = GetDirectoryInfo(@"c:\temp", true);
StringBuilder directoryCsv = new StringBuilder();
directoryCsv.Append("Name,Full Name,Parent Folder,Creation Time,Last Access Time,Last Write Time,Length, Extension,Attributes\r\n");
foreach (FileSystemInfo di in fileInfo)
{
if (di.GetType() == typeof(FileInfo))
{
directoryCsv.Append(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8}\r\n", di.Name, di.FullName, di.FullName.Replace(di.Name, ""), di.CreationTime, di.LastAccessTime, di.LastWriteTime, ((FileInfo)di).Length.ToString(), di.Extension, di.Attributes.ToString()));
}
else
{
directoryCsv.Append(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8}\r\n", di.Name, di.FullName, di.FullName.Replace(di.Name, ""), di.CreationTime, di.LastAccessTime, di.LastWriteTime, "", "", di.Attributes.ToString()));
}
}
SaveCsvFile(directoryCsv.ToString(), @"c:\temp\test.csv");
}
public List<FileSystemInfo> GetDirectoryInfo(string directoryPath, bool includeDirectoryInfo)
{
List<FileSystemInfo> directoryList = new List<FileSystemInfo>();
DirectoryInfo di = new DirectoryInfo(directoryPath);
foreach (DirectoryInfo childDi in di.GetDirectories())
{
directoryList.AddRange(GetDirectoryInfo(childDi.FullName, includeDirectoryInfo));
}
if (includeDirectoryInfo)
{
directoryList.Add(di);
}
directoryList.AddRange(GetFileInfo(directoryPath));
return directoryList;
}

public List<FileSystemInfo> GetFileInfo(string filePath)
{
DirectoryInfo di = new DirectoryInfo(filePath);
FileInfo[] rgFiles = di.GetFiles("*.*");
List<FileSystemInfo> fileList = new List<FileSystemInfo>();
foreach (FileInfo fi in rgFiles)
{
fileList.Add(fi);
}
return fileList;
}
private void SaveCsvFile(string fileText, string fileName)
{
try
{
Stream myStream;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "CSV Files (*.csv)|*.csv";
saveFileDialog1.FileName = fileName + ".csv";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if ((myStream = saveFileDialog1.OpenFile()) != null)
{
StreamWriter wText = new StreamWriter(myStream);
wText.Write(fileText);
wText.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
 

Update:  I found a nice solution using LINQ for filtering on multiple file extensions.

http://msdn.microsoft.com/en-us/library/wz42302f.aspx

using System.Linq;

string folder = @"C:\Projects";

IEnumerable<string> fileNames =  Directory.GetFiles(folder).Where(f => f.EndsWith( ".vb" ) || f.EndsWith( ".xml" ) || f.EndsWith( ".aspx" ));

I have a whopping 693 programs on my XP development machine. How many do you have?

You can simply find out by creating a C# console application, cutting the following, and hitting F5.

using System;
using System.Collections.Generic;
using Microsoft.Win32;


. . .


static void Main(string[] args)
{
List<string> programs = GetInstalledPrograms();
foreach (string program in programs)
{
Console.WriteLine(program);
}
Console.WriteLine("Total - " + programs.Count.ToString());
Console.Read();
}

private static List<string> GetInstalledPrograms()
{
string installKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
List<string> displayNames = new List<string>();
string[] subkeyNames = Registry.LocalMachine.OpenSubKey(installKey).GetSubKeyNames();
foreach (string subkeyName in subkeyNames)
{
string displayName = (string)Registry.LocalMachine.OpenSubKey(installKey + "\\" + subkeyName).GetValue("DisplayName");
if (!string.IsNullOrEmpty(displayName))
{
displayName += "\t" + subkeyName;
}
else
{
displayName = subkeyName;
}
displayNames.Add(displayName);
}
displayNames.Sort();
return displayNames;
}

Monday, June 29, 2009

Create Windows startup shortcut for ClickOnce application

ClickOnce does not provide an option for adding the application to start automatically when starting Windows. You can use the concepts in the following method to add or remove this option. You will need to make sure “Allow URL parameters to be passed to the application” is checked. This if found within Project Properties –> Publish tab –> Options –> Manifests.

using System;
using System.Deployment.Application; //Requires System.Deployment assembly
using System.IO;
using System.Text;
using System.Windows.Forms;
...
private void CreateWindowsStartup(bool create)
{
string startupFileName = Environment.GetFolderPath(System.Environment.SpecialFolder.Startup) + "\\" + Application.ProductName + ".appref-ms";
string applicationShortcut = ApplicationDeployment.CurrentDeployment.ActivationUri.ToString();
if (create)
{
if (!File.Exists(startupFileName))
{
using (FileStream fs = new FileStream(startupFileName, FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.Unicode))
{
sw.WriteLine(applicationShortcut);
}
}
}
}
else
{
if (File.Exists(startupFileName))
{
File.Delete(startupFileName);
}
}
}



 




Friday, June 26, 2009

C# SMTP Snippet

I recently provided this simple snippet to a colleague and thought I’d share it out. It includes a way to attach a local file or attach one generated on the fly.
using System;
using System.IO;
using System.Net.Mail;
using System.Text;
...
public static void SendEmail()
{
try
{
bool createFile = true;
string fileName = @"c:\boot.ini";
MailMessage mail = new MailMessage();
mail.IsBodyHtml = true;
mail.From = new MailAddress("you@domain.com");
mail.To.Add(new MailAddress("you@domain.com"));
mail.Subject = "Subject";
mail.Body = "Body";
if (createFile)
{
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes("File Content Blah Blah Blah");
MemoryStream ms = new MemoryStream(bytes);
mail.Attachments.Add(new Attachment(ms, "FileTitle" + ".txt", "text/plain"));
}
else
{
mail.Attachments.Add(new Attachment(fileName));
}
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = "SMTPSERVERNAME";
smtpClient.Send(mail);
}
catch (Exception ex)
{

}
}

Thursday, November 13, 2008

Build StringBuilder Code from C#

With a little quick and dirty code, you can generate StringBuilder code from C# code. To use it, all you need is a WinForms project with two TextBoxes and a Button. This is very useful for creating code generation tools. My reason is that I am in the process of creating a dynamic form generation tool for SharePoint Lists and Document Libraries.

Form Example Screenshot:

C# Code (Not Optimized):

public string GetStringBuilderCodeFromCSharp(string[] lines)
{
    StringBuilder stringBuilder = new StringBuilder();
    string line = string.Empty;
    foreach (string s in lines)
    {
        line = s.Replace("    ", "\\t").TrimEnd();    //Replace four spaces with tabs. VS cs uses spaces
        if (line.StartsWith("\\t\\t"))                      //Eliminate double tabs. VS cs defaults with tab
            line = line.Substring(4, line.Length - 4);
        line = line.Replace("\"", "\\\"");               //Replace double quotes with escaped double quotes
        line = "stringBuilder.Append(\"" + line + "\\r\\n\");\r\n";   //StringBuilder Append Code
        stringBuilder.Append(line);
    }
    stringBuilder.Insert(0, "StringBuilder stringBuilder = new StringBuilder();\r\n");
    return stringBuilder.ToString();
}

Wednesday, July 16, 2008

.NET 3.5 - Extension Methods Magic!

One of my favorite new features about .NET 3.5 is the ability to create Extension Methods. Essentially this provides you with the ability to extend a given type with your own custom methods. Let's think about what you would need to do to retrieve a control value from a ASP.NET FormView. First you need to use the Controls collection or FindControl method to return the control. Then, you need to cast the control to the specific control in question. Finally, you have to cast it to the type you need returned. The following is an example of this:

int woodchucksTotal = Convert.ToInt32(((Label)WoodChuckerForm.FindControl("WoodchucksTotal")).Text);

This syntax is very error prone, tedious, and hard to debug if you are doing it with a large number of controls. Alternatively, and with very little work, you can use extension methods and have syntax like this instead:

int? woodchucksTotal = WoodChuckerForm.ControlToInt32("WoodchucksTotal");

This allows me to simplify my syntax and almost cut it in half and decrease the number of parentheses from 8 to 2. I have also provided means to return a nullable typed integer. This can be helpful if, for example, you'd prefer to insert a null instead of a zero in a database. To be able to implement extension methods, you simply need to use the following two simple steps:

Implement an Extension Method

  1. Create a non-nested static class.
  2. Add static methods that have first parameters use the this modifier with the type being extended.

Sample C# Code

public static class WebControlUtil
{
    public static string ControlToString(this FormView formView, string controlName)
    {
        WebControl ctrl = (WebControl)formView.FindControl(controlName);
        switch (ctrl.GetType().ToString())
        {
            case "System.Web.UI.WebControls.TextBox":
                ctrlText = ((TextBox)ctrl).Text;
                break;
            case "System.Web.UI.WebControls.CheckBox":
                ctrlText = ((CheckBox)ctrl).Checked.ToString();
                break;
            case "System.Web.UI.WebControls.DropDownList":
                ctrlText = ((DropDownList)ctrl).Text;
                break;
        }
        return ctrlText;
    }

    public static bool ControlToBool(this FormView formView, string controlName)
    {
        WebControl ctrl = (WebControl)formView.FindControl(controlName);
        bool ctrlBool = false;
        switch (ctrl.GetType().ToString())
        {
            case "System.Web.UI.WebControls.CheckBox":
                ctrlBool = ((CheckBox)ctrl).Checked;
                break;
        }
        return ctrlBool;
    }

    public static int? ControlToInt32(this FormView formView, string controlName)
    {
        WebControl ctrl = (WebControl)formView.FindControl(controlName);
        int? ctrlInt32 = null;
        switch (ctrl.GetType().ToString())
        {
            case "System.Web.UI.WebControls.TextBox":
                if (((TextBox)ctrl).Text != "")
                {
                    ctrlInt32 = Convert.ToInt32(((TextBox)ctrl).Text);
                }
                break;
            case "System.Web.UI.WebControls.DropDownList":
                ctrlInt32 = Convert.ToInt32(((DropDownList)ctrl).SelectedValue);
                break;
        }
        return ctrlInt32;
    }

    public static DateTime? ControlToDate(this FormView formView, string controlName)
    {
        WebControl ctrl = (WebControl)formView.FindControl(controlName);
        DateTime? ctrlDate = null;
        switch (ctrl.GetType().ToString())
        {
            case "System.Web.UI.WebControls.TextBox":
                if (((TextBox)ctrl).Text != "")
                {
                    ctrlDate = Convert.ToDateTime(((TextBox)ctrl).Text);
                }
                break;
        }
        return ctrlDate;
    }
}

Tuesday, June 17, 2008

Simple LINQ Projection Example

Here is a simple example using LINQ projection. It takes a List<string> that include space-delimited strings, queries them and then project into an IEnumerable<Person>. I then loop through the output sequence and write the results to the console.

class Program
    {
        static void Main(string[] args)
        {
            List<string> people = new List<string>
                { "Joe Smith 20", "Jim Jackson 30", "Jason Suzuki 40" };
            IEnumerable<Person> query =
                from p in people
                select new Person
                {
                    FirstName = p.Split(' ')[0],
                    LastName = p.Split(' ')[1],
                    Age = Convert.ToInt32(p.Split(' ')[2])
                };
            foreach (Person p in query)
            {
                Console.WriteLine("First Name:\t{0}\r\nLastName:\t{1}\r\nAge:\t\t{2}",
                    p.FirstName, p.LastName, p.Age);
            }
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }