Finding/counting Keywords out of a Text Document

A quick program to find keywords out of a document - great for a knowledge base or .txt file repository

I wrote this a while back and it became relevant again today.  All this does is take in a text file, go through it making a Dictionary of all the words and counting them (ignoring the words in the exclusion list) and then sorts and outputs them.  The logic is pretty straightforward and looks like this:

[code:c#]

public partial class keywords : System.Web.UI.Page
{
    Dictionary<string, int> _keywords = new Dictionary<string, int>();
    char[] delimiter = {' '}; // whatever you want to delimit the text with, I just use spaces
    string[] DEFAULT_EXCLUDE = { "a", "the", "is", "and" };//things you want excluded even if the user does not specify (you can leave it blank too)

    protected void Page_Load(object sender, EventArgs e)
    {
        lblExcluded.Text = string.Empty;
        for(int i=0;i<DEFAULT_EXCLUDE.Length;i++)
            lblExcluded.Text += i == DEFAULT_EXCLUDE.Length - 1 ? DEFAULT_EXCLUDE[i] + " " : DEFAULT_EXCLUDE[i] + ", ";
    }
    protected void submit_Click(object sender, EventArgs e)
    {
        string[] words_to_exclude = txtExclude.Text.Length<1 ? new string[] {" "} : txtExclude.Text.Split(new char[] {','});
        for (int i = 0; i < words_to_exclude.Length; i++) words_to_exclude[i] = words_to_exclude[i].Trim(); //cut off all empty space
        List<string> excluded = new List<string>();
        foreach (string s in DEFAULT_EXCLUDE)
            if (!excluded.Contains(s)) excluded.Add(s);
        foreach (string s in words_to_exclude)
            if (!excluded.Contains(s)) excluded.Add(s);

        int keyword_threshhold = Int32.Parse(txtThreshhold.Text);
        if (fu.HasFile)
        {
            try
            {
                //Save the file here
                StreamReader sr = new StreamReader(fu.FileContent);//this pulls from the user, or you can pull it from where you saved it to now
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    string[] splitString = line.Split(delimiter);
                    foreach (string s in splitString)
                    {
                        if (!excluded.Contains(s))
                        {
                            try { _keywords[s] = _keywords[s] + 1; }
                            catch { _keywords.Add(s, 1); }
                        }
                    }
                }
                bool switcher = false;
                phKeywords.Controls.Add(new LiteralControl("<div id=\"keys\" class=\"main_area\"><h2>Keywords</h2>"));

                var query = from p in _keywords orderby p.Value descending select p;

                foreach (KeyValuePair<string, int> d in query)
                {
                    if ((int)d.Value >= keyword_threshhold)
                    {
                        string color = switcher?"blue": "white";
                        phKeywords.Controls.Add(new LiteralControl("<div class=\""+ color +"\">"+ d.Value + " - " + d.Key + "</div>"));
                        switcher = !switcher;
                    }
                }
                phKeywords.Controls.Add(new LiteralControl("</div>"));
            }

            catch (Exception ex)
            { phError.Controls.Add(new LiteralControl("<div id=\"error\" class=\"main_area\"><b>Error:</b>" + ex.Message + "</div>")); }
        }
        else
            phError.Controls.Add(new LiteralControl("<div id=\"error\" class=\"main_area\"><b>Error:</b> Can't process what you don't give me...</div>"));

    }

[/code]

 

The inputs are fu, which is a FileUpload control that holds the file you are parsing, txtExclude which is a TextBox of the words to exclude (added to default exclusions), and txtThreshhold which is a TextBox where you enter the number of words to consider before it is counted as a keyword.

 

 

 

 

 

 

Amazing jQuery Color Picker

This is by far the smoothest, most compact color picker I have found

 

Looking for a new color picker today, and I cam across this beauty!  The 'Farbtastic' color picker... what a name!  It requires jQuery, but is easily the best of it's kind I have ever found.  It is extremely easy to implement and looks/works great (I really like the fact that it is mroe compact than most). 

 

I just finished making a style customizer for one of our intranet applications that uses this to re-write our css and hence change the theme based on the user input.  This tool was super easy to work with and cut my development time down by a huge margin.  I can't say enough about this plugin!  Hopefully I can get a post up about the online css customizer pretty soon.

 

DOWNLOAD: http://acko.net/dev/farbtastic

Running a 'For' Loop in MS SQL

There really isn't a 'for' loop in MS SQL, but you can do basically the same thing

First of all, I am far from a SQL master; I would even go as far to say I would be lucky to be an amatuer at best.  But I did stumble upon a convenient way for populating a lot of new rows using a simple technique that is not using a bulk insert.  It is actually pretty basic stuff, but nice to know if you were Googling for it like I was.

 

DECLARE @count INT

SET @count = 0

WHILE (@count < 40)

BEGIN

   INSERT INTO some_table ([columnA], [columnB]) VALUES ('val1', 'val2')

   SET @count = (@count + 1)

END

 

All that was really done is a manual 'For' loop using the SQL WHILE loop.  Just set the number in WHILE (@count < 40) to however many times you want the loop to run.

"Object reference not set to an instance of an object." when running stsadm backup or enumsites

I ran across this strange error while trying to backup a site collection

I noticed that while running automated SharePoint backups that a certain site collection was not being backed up.  This was a site collection one level down from the root site collection.  For example, if the root site was http://mySharePoint, this was a sub-site collection (sub-SC): http://mySharePoint/sites/subSiteCollection (this was running MOSS 2007 Enterprise).

 

I logged on to the machine and ran the script in a command prompt and it worked fine, it just skipped over the sub-SC.  This got me thinking as to why this was happening, as the script is supposed to enumerate down through all site collections.  First I tried to run a manual backup by running:

 

stsadm -o backup -url http://mySharePoint/sites/subSiteCollection -filename \\backups\subSC.bak

 

And it gave me the error:

 

Object reference not set to an instance of an object.

 

I then tried to enumerate through the sites:

 

stsadm -o enumsites -url http://mySharePoint

 

And all of the other sub site collections showed up fine, but I got this error:

 

<Sites Count="2">

  <Site Url="http://mySharePoint" Owner="DOMAIN\naspinski" SecondaryOwner="DOMAIN\stan" ContentDatabase="WSS_Content_Root" StorageUsedMB="500" StorageWarningMB="0" StorageMaxMB="0" />

  <Site Error="Object reference not set to an instance of an object." />

 

As you can see, the first site shows up, but it is followed by the vague error message where the second site report should be.  This is an incredibly non-descript SharePoint error that leaves you scratching your head.  I knew the site collection was there; I could navigate to it, I could find it in my Central Administration and everything worked fine.  I was able to back up other site collections and everything, just not this one.

 

Turns out after scouring the internet and checking every setting I could find without any help at all, I fell back on one of my List of 5 Simple SharePoint 2007 Fixes (which I should have done first) and number two on the list fixed it.  I ran SharePoint Technologies and Configuration Wizard and magically the problem had stopped.  Once again, not sure exactly why SharePoint did what it did, but this seemed to work out.

List of 5 Simple SharePoint 2007 Fixes

Low-hanging fruit is the easiest to gather; always look for the easy solutions before you move on

I have been a SharePoint 2007 admin/developer for about a year now, and I have learned a LOT.  I have also spent countless hours tracking down strange and seemingly causeless errors in SharePoint only to find out that 50% of my problems required a simple 5 minute (or less) fix.

 

Here is my list, hopefully this will save you time. 

ALWAYS try these before you go on to crazy or overly involved solutions.

 

1. Run an IIS Reset

This is the simplest and often reflects changes that were made that might not show up right away.  Simply open the command prompt on your SharePoint machine and type iisreset.  This will cause momentary downtime (a few seconds) if you are running a single WFE.

 

2. Run 'SharePoint Technologies and Configuration Wizard'

Only #2 on the list because it takes slightly more time than #1.  On the other hand, this has fixed more problems for me than any other on the list.  This does automatic IIS resets, so you will have temporary downtime on a single WFE environment.

 

3. Reboot your machine(s)

This seems obvious, but for some reason is often overlooked.  This holds as true for SharePoint as any other Windows OS/application; the only problem is potential downtime for your users, but if you have more than one WFE, it shouldn't be a problem.

 

4. Make sure account has proper rights

This one is more for stsadm operations and scripts, but most of the time I have found if a command is giving you some strange failurethat it shouldn't, it is more often the account you are using doesn't have the specific right you need for that operation.  The command line runat command is your friend for testing this.

 

5. Install most recent Service Pack/Update

Be sure to check with Microsoft for any updates.  SharePoint is one of their most premier products at the moment, and they are spending a lot of time and money developing for it.

Automatically clean up/kill Orphaned Processes

A nice easy way to patrol and eliminate orphaned processes 

I have several web applications on our local intranet that require Excel to be called to make documents for my users.  That brings up a problem:If you add the impatient tendancies of users (hey, I just clicked that button, I want my spreadsheet NOW!) to the statelessness of html on top of the stubornnessof the Excel process you get orphans, those pesky orphans that sit around, use your resources and do nothing.  Now programatically, I have done all I can to kill these bastards but I can't seem to stop the persistant jerks 100% of the time.

 

So, what I decided to do was to make an 'enforcer' on the web server that makes his rounds every five minutes and kills any of these little pricks that are still hanging out in my otherwise peaceful system.  This enforcer is not only effective, he is also efficient (tiny script, executes instantly) and keeps track of his work (log file).

 

The code for my vbs file can be seen here:

 

[code:js]

Option Explicit
Dim objWMIService, objProcess, colProcess, intCount
Dim strComputer, strProcessKill, logPath
strComputer = "."
strProcessKill = "'EXCEL.EXE'" 'process to kill
logPath = "C:\scripts\killExcel.log" 'path to log file
intCount = 0

Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")

Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = " & strProcessKill )
For Each objProcess in colProcess
objProcess.Terminate()
intCount = intCount + 1
Next

If intCount > 0 Then
    Dim fso, txtFile
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set txtFile = fso.OpenTextFile(logPath, 8)
    txtFile.WriteLine(Date & " - " & Time & " Killed " _
    & intCount & " processe(s)")
    txtFile.Close
End If

WScript.Quit

[/code]

 

As you can see, it's very simple, and you can change it to eliminate any kind of process you want.  Here it is if you want to check it out, included is an empty log file, the vbs file, and the bat file used to schedule it (assuming you place this in c:\scripts\), enjoy.

 

 

Packaging and Deploying a SharePoint 2007 Web Part

You know how to make a web part, but do you know how to get it to your production environment in the proper way?

In a past post, I did a WSS 3.0/MOSS 2007 Web Part Tutorial that showed how to make a web part.  That's all great and grand, but I did not cover how to actually get it to your production environment (truth is I didn't know how at the time).  Technically, you could install VS 2008 and the extension package on your production farm, but that isn't necessarily a good idea or 'best practice' by a long shot.  What you want is one nice neat file that you can take to your server and upload as a feature, that is what this tutorial is all about (most of this info was deciphered from the SharePoint 2007 SDK.)

 

We are going to assume that you already made your web part, and I am going to use the one from my past tutorial as the example for simplicity's sake.

 

Setup your Solution Structure

In order for this to compile correctly, your web part and cab projects must be inside the same solution.

 

  • Here we go: Open Visual Studio and Choose File > New Project, once in that dialogue, click on Other Project Types > Visual Studio Solutions and choose Blank Solution. Name it something, I am going to use TestSolution for mine.
  • This is a tricky part, but it is to keep the solution folder open and not go to a smaller project when we import one: In the Solution Explorer, right click on the solution and choose Add > New Solution Folder and name it dummy -- we will delete this later, but we need it for a moment.
  • In the Solution Explorer, right click on the solution and choose Add > Existing Project now navigate to your existing csproj (in my case, WPs.csproj) and click OK.
  • Now, in the Solution Explorer, right click on the solution and choose Add > New Project click on Other Project Types > Setup and Deployment and choose CAB Project name it and click OK (I named mine TestCab).
  • Now go back and delete the dummy folder.

 

Now you have the proper setup and structure to your folder.  Only a couple more steps and we will have a nice portable web part.  Your Solution Explorer should now look like this:

 

Prepare your Manifast and dwp files

These are required in order for your cab to be properly set up and used by SharePoint.

 

  • Right click on the Web Part Project inside the Solution and add an XML File, name it Manifest.xml, insert the following text into the file (notice the noly changes you might need to make are to the Namespace, which is used in your .cs file of the webpart, and FileName attributes):

[code:xml]

<?xml version="1.0"?>
<!-- You need only one manifest per CAB project for Web Part Deployment.-->
<!-- This manifest file can have multiple assembly nodes.-->
<WebPartManifest xmlns="http://schemas.microsoft.com/WebPart/v2/Manifest">
    <Assemblies>
        <Assembly FileName="WPs.dll">
            <!-- Use the <ClassResource> tag to specify resources like image files or Microsoft JScript files that your Web Parts use. -->
            <!-- Note that you must use relative paths when specifying resource files. -->

            <ClassResources></ClassResources>

            <SafeControls>
                <SafeControl
                  Namespace="WPs"
                  TypeName="*"
                />
            </SafeControls>
        </Assembly>
    </Assemblies>
    <DwpFiles>
        <DwpFile FileName="WPs.dwp"/>
    </DwpFiles>
</WebPartManifest>

[/code]

 

  •  Now right click on the sameProject and add another xml file, name this one your_web_part_name.dwp, for my example I am using WPs.dwp.  Notice that it is the same as specified in the FileName attribute in the xml file above -- add this text to your dwp file:

[code:xml]

<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2" >
    <Title>Title goes here</Title>
    <Description>Put your description here.</Description>
    <Assembly>WPs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5</Assembly>
    <TypeName>WPs.Test</TypeName>
    <!-- Specify initial values for any additional base class or custom properties here. -->
</WebPart>

[/code]

 

The only part that may be a snag for some people is populating the <Assembly>'s PublicKeyToken and  <TypeName> tags in the above XML file.  Let me try and explain what and how to get these values:

  • To get the <Assembly>'s PublicKeyToken you need to go to your test machine, where the code was compiled and get the PublicKeyToken - that is the value you enter there.
  • As for the <TypeName> that is simply the Namespace.WebPartName of the web part itself.
  • Now right-click on your CAB Project and choose Add > Project Output once in that dialogue, choose Primary Output and Content Files, Click OK.
  • Right-click again on the CAB Project and Choose Add > File then browse you your dwp file you just made (mine is WPs.dwp), click Open and save your Solution.

 

You should now have everything set up correctly, your Solution Explorer should look like this:

 

Build and Deploy

All the hard work is done, now just build and deploy.

 

  • Right click on the solution and choose Build Solution - this makes your portable web part, just look in your solution folder, in my example it is located at TestSolution\TestCab\Debug\TestCab.CAB - if you will notice, that is just: Solution_Name\Cab_Project_Name\Debug\CabFile.CAB.
  • Now that you have your file, copy it to your production environment to the folder: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin\
  • Then run the command (from that directory):

     

    stsadm -o addwppack -filename Time_Zones.CAB -url http://your_url_here -globalinstall -force

     

  • And run an iisreset.


You are all done.  You should have your web part available to all of your users on the farm now.  And you can pass out the .CAB file to whoever wants it without any messy code to worry about!

SharePoint 2007 Web Part: Time Zones

Displays 6 Time Zones of your choosing, fully customizable

Previously I showed how to build a web part from scratch.  This is my first fully-featured web part.  The javascript was mostly stolen from some unknown source that had been wandering around my shop for years.  Other than that, the web part is all me.  The javascript I was given was just the 6 time zones we use over here (I am working in the Middle East right now) and I got tired of every different division wanting a different set of time zones, so I just made it so they could modify it themselves; now everyone is happy.

 

To install, place the Time_Zones.CAB file into the magical directory of:

 

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin\

 

Then run the command (from the same directory):

 

stsadm -o addwppack -filename Time_Zones.CAB -url http://your_url_here -globalinstall -force

 

Then simply run an iisreset and your web part is ready to use.  The full zip file includes the CAB as well as all the original code so you can modify it if you want.  Otherwise, just download the CAB if you want to simply use the part, enjoy!

 

 

 
 
 
 
 

 

Extracting a Public Key Token from an Assembly in Visual Studio

How to get that mythical number/letter combination

It is not an extremely common need to get your public key token from a dll, but when the problem arises (custom SharePoint development) it is nice to be able to figure it out.  Turns out it is very simple; once you actually figure out how to get it that is.

 

All you need to do is go into your VS command prompt: 


Start->All Program->Visual Studio 2008->Visual Studio Tools->Visual Studio 2008 Command Prompt

-or-

Start->All Program->Visual Studio 2008->Visual Studio Tools->Visual Studio 2008 x64 Cross Tools Command Prompt 

 

Once you are in there, just type the command:


sn -T <location of dll>

 

and it will spit out your Private Key Token.

 

Javascript page modifiers

Simple way for your users to modify how a page looks

I have been asked more than once on how to make javascript (or as everyone asks now, 'AJAX') methods to modify a page.  It is very simple and easy to implement.

 

In the supplied example, I show modifiers for both single areas, and the whole page.  I know I chose hideous colors, but live with it, it's just an example...

 

First, what you need to do is some simple JS that allows you to change the style attributes of your html, here are both sets of functions; ones that apply to the whole page, others that apply to specific parts:

 

[code:js]

//apply to the whole page
function fontSize(number)
{ document.body.style.fontSize = number + "em"; }
function fontColor(color)
{ document.body.style.color = color; }
function backgroundColor(color)
{ document.body.style.backgroundColor = color; }

//apply to a specific part of the page
function divFontSize(number, div)
{ document.getElementById(div).style.fontSize = number + "em"; }
function divFontColor(color, div)
{ document.getElementById(div).style.color = color; }
function divBackgroundColor(color, div)
{ document.getElementById(div).style.backgroundColor = color; }

[/code]

 

As you can see,that is about as simple and straight-forward as you get, then simple call them like this:

 

[code:html]

<div>
    Single Div Modifiers:
    <a href="javascript:divFontSize('0.8', 'div1')" style="font-size:0.8em;" >small</a> |
    <a href="javascript:divFontSize('1', 'div1')" >medium</a> |
    <a href="javascript:divFontSize('1.2', 'div1')" style="font-size:1.2em;">large</a> |
    <a href="javascript:divFontColor('black', 'div1')" style="color:Black;">black</a> |
    <a href="javascript:divFontColor('navy', 'div1')" style="color:Navy;">navy</a> |
    <a href="javascript:divFontColor('green', 'div1')" style="color:Green;">green</a> |
    <a href="javascript:divBackgroundColor('white', 'div1')" style="background:white;">White</a> |
    <a href="javascript:divBackgroundColor('grey', 'div1')" style="background:grey;">Grey</a> |
    <a href="javascript:divBackgroundColor('yellow', 'div1')" style="background:yellow;">Yellow</a>
</div>

<div id="div1">
    Lorem ipsum dolor sit amet.
    Mauris nunc odio, molestie quis.
    Sed ac orci eu diam dapibus scelerisque. 
    Phasellus in nulla a justo dignissim suscipit.
    Class aptent taciti inceptos himenaeos.
</div>

[/code]

 

In the code shown above, the modifiers will only affect whatever is in div1.  And there you have it.