Monday, August 31, 2009

Creating a PDF with ReportViewer and emailing it

This code will render a report as a PDF file and then add it as an email attachment and send it. This is assuming you have a ReportViewer and it's all linked to a data source.

Source
Simply change fields that have in it to match your settings.

string mimeType;
string encoding;
string fileNameExtension;
Warning[] warnings;
string[] streamids;
byte[] bytes =
reportViewer1.LocalReport.Render("PDF",
null, out mimeType, out encoding, out fileNameExtension
, out streamids, out warnings);
Stream s = new MemoryStream(bytes);
SmtpClient sc = new SmtpClient("", );
MailMessage mm = new MailMessage(new MailAddress(""),
new MailAddress(""));
mm.Subject = "REPORT";
mm.Attachments.Add(new Attachment(s, "report" + "." + fileNameExtension));
mm.Body = "Report from report viewer is attached";
sc.Send(mm);

Visual Studio freezes when switching to Design mode in Website projects

My computer BSOD'd while installing something last week and then i started getting VS2008 errors, where the Design mode would not switch, it would just freeze!

All the Event viewer says is Application Hang with description = "Fault bucket 881396771."

Solution
-Try to reinstall Web Authoring Component. The easiest way to do this is to just do a repair on your VS2008 installation. Just open up Control Panel and do a "Change" on VS, then do a repair.

This fixed my problem.

Here's an official source on all the ways to solve this problem. Follow each step to make sure you have all the bases covered.
http://blogs.msdn.com/webdevtools/archive/2008/10/03/troubleshooting-visual-studion-2008-design-view-hangs-issues.aspx

Saturday, August 29, 2009

Calculate the next time a job scheduled for multiple days should be processed

This is my research for a component in a real world project.

Scenario:
User creates a new job to process at 3 pm on Monday and Friday. *Note: I'm using System.Threads.Timers for async job scheduling, so multiple jobs can be configured.

Solution:
First here's the UI I created for my research:

Current Date: it defaults to DateTime.Now, but can be changed. This is so I could create several different testing scenarios
Time of Day: The poorly named field is actually "TimeToExecute". This defaults to the current time and can be changed to any time.

Source notes:

btnWeekly_Click method is what you would call when you call Timer.Change(TimeSpan, TimeSpan). In a real job scheduler when you create the Timer you would want to call the "btnWeekly_Click" method (obviously not an event handler in real code) to calculate the first parameter of Timer.Change() function.

Note: My DayOfWeek enum is a bit flag (marked with [Flags], which means you can use bit operations and have multiple days selected. System.DayOfWeek is not a bit flagged enum. I'll create a separate blog post about this subject.

Any questions about implementation or about the code comment or email me.

Source:

private void btnWeekly_Click(object sender, EventArgs e) {
    DayOfWeek days = new DayOfWeek();
    //this is from the schedule object

    DateTime now = DateTime.Parse(txtCurrentDateTime.Text);
    TimeSpan target = DateTime.Parse(txtTimeOfDay.Text).TimeOfDay;
    TimeSpan currentBest = new TimeSpan(20, 0, 0, 0);
    //set a random amount of time that can't possibly be
    //reached in a legitmite configuration, to initalize comparison
    //this will not be necessary in the real code, just for simulation

    //This is just for the simulator, Remove when moved
    for (int i = 0; i < daysOfWeek.CheckedItems.Count; i++) {
        switch (daysOfWeek.CheckedItems[i].ToString()) {
            case "Sunday":
                days = days | DayOfWeek.Sunday;
                break;
            case "Monday":
                days = days | DayOfWeek.Monday;
                break;
            case "Tuesday":
                days = days | DayOfWeek.Tuesday;
                break;
            case "Wednesday":
                days = days | DayOfWeek.Wednesday;
                break;
            case "Thursday":
                days = days | DayOfWeek.Thursday;
                break;
            case "Friday":
                days = days | DayOfWeek.Friday;
                break;
            case "Saturday":
                days = days | DayOfWeek.Saturday;
                break;
        }
    }
    //end of remove



    for (int j = 0; j < 7; j++) {
        if (daySelected(days, now)) {
            TimeSpan tmp = getNextOccurence(now.TimeOfDay, target, j, false);
            if (TimeSpan.Compare(tmp, currentBest) < 0)
                currentBest = tmp;
        }
        now = now.AddDays(1);
    }
    //DEBUGGING
    txtResults.Text += "Best time = " + currentBest.TotalMinutes.ToString() + Environment.NewLine;
}
private TimeSpan getNextOccurence(TimeSpan checkTime, TimeSpan targetTime, int dayCount, bool isDaily) {
    TimeSpan ts = new TimeSpan();
    if (TimeSpan.Compare(checkTime, targetTime) < 0) {
        //checkTime is earlier than targetTime
        if (isDaily)
            dayCount = 0;
        ts = targetTime.Subtract(checkTime);
        ts = ts.Add(new TimeSpan(dayCount, 0, 0, 0));
        //DEBUGGING
        txtResults.Text += "dayCount = " + dayCount.ToString() +
            " difference in minutes = " + ts.TotalMinutes.ToString() + Environment.NewLine;

    } else {
        //checkTime is later than targetTime
        if (isDaily)
            dayCount = 6;
        ts = new TimeSpan(6 - dayCount, 0, 0, 0);
        ts = ts.Add(new TimeSpan(24, 0, 0).Subtract(checkTime.Subtract(targetTime)));
        //DEBUGGING
        txtResults.Text += "dayCount = " + dayCount.ToString() +
            " difference in minutes = " + ts.TotalMinutes.ToString() + Environment.NewLine;

    }
    return ts;
}
private bool daySelected(DayOfWeek daysSelected, DateTime toTest) {
    DayOfWeek dayOfWeekToTest = mapDayToDayOfWeekEnum(toTest);
    return (daysSelected & dayOfWeekToTest) == dayOfWeekToTest;
}
private DayOfWeek mapDayToDayOfWeekEnum(DateTime test) {
    switch (test.DayOfWeek) {
        case System.DayOfWeek.Friday:
            return DayOfWeek.Friday;
            break;
        case System.DayOfWeek.Monday:
            return DayOfWeek.Monday;
            break;
        case System.DayOfWeek.Saturday:
            return DayOfWeek.Saturday;
            break;
        case System.DayOfWeek.Sunday:
            return DayOfWeek.Sunday;
            break;
        case System.DayOfWeek.Thursday:
            return DayOfWeek.Thursday;
            break;
        case System.DayOfWeek.Tuesday:
            return DayOfWeek.Tuesday;
            break;
        case System.DayOfWeek.Wednesday:
            return DayOfWeek.Wednesday;
            break;
    }
    return DayOfWeek.Wednesday; //this will not be reached
}#
endregion
}
[Flags]
public enum DayOfWeek {
    Sunday = 1,
        Monday = 2,
        Tuesday = 4,
        Wednesday = 8,
        Thursday = 16,
        Friday = 32,
        Saturday = 64
}


Wednesday, August 26, 2009

VS2008 crashes when exiting a VSS project

Event Viewer problem:
Faulting application devenv.exe, version 9.0.30729.1, stamp 488f2b50, faulting module tdnamespaceextension.dll, version 8.0.50727.901, stamp 468b6495, debug? 0, fault address 0x0002fcdf.

The important thing is "faulting tdnamespaceextension.dll"

Luckily Microsoft knows about this and put out a workaround,

Start->Run->Copy and paste the following
regsvr32 "C:\Program Files\Microsoft Visual SourceSafe\tdnamespaceextension.dll"

References:
1. http://blogs.msdn.com/richardb/archive/2007/11/19/vs-2008-users-remember-to-download-the-sourcesafe-ctp.aspx

Package failed to load in VS2008

Try this list: http://blogs.msdn.com/astebner/archive/2005/12/16/504906.aspx

This is for VS2005 but do the same things for VS2008.

What worked for me is doing a repair on .NET 3.5 SP1

Monday, August 24, 2009

How to create an async Server/Client sockets program


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace SocketsLearning
{

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void SetTextEventLog(string text)
{
txtEventLog.Text += text + Environment.NewLine;
}
void acceptCallback(IAsyncResult ar)
{
if (txtEventLog.InvokeRequired)
{
txtEventLog.Invoke(new SetTextCallback(SetTextEventLog), new object[] { "Server is reading sent data (Invoke)" });
}
else
SetTextEventLog("Server is reading sent data (Not Invoke)");
// Add the callback code here.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
listener.BeginAccept(new AsyncCallback(acceptCallback), listener);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(readCallback), state);


}
void readCallback(IAsyncResult ar)
{

StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;

// Read data from the client socket.
int read = handler.EndReceive(ar);

// Data was read from the client socket.
if (read > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,read));
handler.BeginReceive(state.buffer,0,StateObject.BufferSize, 0,
new AsyncCallback(readCallback), state);

}
else
{
if (state.sb.Length > 1) {
// All the data has been read from the client;
// display it on the console.
string content = state.sb.ToString();
if (txtRecieve.InvokeRequired)
{
txtRecieve.Invoke(
new SetTextCallback(SetText), new object[] { content + " (Invoke)" });
}
else
SetText(content + " (not Invoke)");
}
handler.Close();
}
}

private void SetText(string text)
{
txtRecieve.Text += text + Environment.NewLine;
}
delegate void SetTextCallback(string text);
private void txtStartListening_Click(object sender, EventArgs e)
{
try
{
IPAddress ip = IPAddress.Parse(txtIP.Text);
IPEndPoint ipen = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
soc.Bind(ipen);
soc.Listen(1000);
txtEventLog.Text += "Server listening to (" + ip.ToString() + ":" + txtPort.Text + ")" + Environment.NewLine;
soc.BeginAccept(new AsyncCallback(acceptCallback), soc);

}
catch
{
txtEventLog.Text += "Error while trying to listen to IP/port" + Environment.NewLine;
}

}

private void button2_Click(object sender, EventArgs e)
{
IPAddress ip = IPAddress.Parse(txtClientIP.Text);
IPEndPoint ipen = new IPEndPoint(ip, Convert.ToInt32(txtClientPort.Text));
Socket sendsoc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sendsoc.BeginConnect(ipen, new AsyncCallback(connectCallback), sendsoc);

}
void connectCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;

// Complete the connection.
client.EndConnect(ar);
if (txtEventLog.InvokeRequired)
{
txtEventLog.Invoke(new SetTextCallback(SetTextEventLog), new object[] { "Client connected to server (Invoke)" });
}
else
SetTextEventLog("Client connected to server (not Invoke)");

// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(txtSend.Text);

// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None,
new AsyncCallback(sendCallBack), client);


}
void sendCallBack(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
if (txtEventLog.InvokeRequired)
{
txtEventLog.Invoke(new SetTextCallback(SetTextEventLog), new object[] { "Client sent " + bytesSent.ToString() + " bytes to client (Invoke)" });
}
else
SetTextEventLog("Client sent " + bytesSent.ToString() + " bytes to client (Invoke)");
client.Close();
}

}

public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
}

Appendum:
The server can send a message back to the client very easily. At first I thought this required creating a client socket, but no; All you need to do is use Send with the worker Socket in the "BeginRecieve" callback: workersocket.Send(stuff). Thanks to reference #4 for that.

References:
1. http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c7695
2. http://msdn.microsoft.com/en-us/library/dz10xcwh.aspx
3. http://msdn.microsoft.com/en-us/library/6aes97be.aspx
4. http://blog.xploiter.com/c-and-aspnet/socket-programming-in-c-using-the-built-in-libraries-a-fully-working-production-example-part-1/

Sunday, August 23, 2009

Timer for Windows Service

Windows Services can only use System.Timers.Timer class, not the System.Windows.Forms.Timer control. So make sure you are using the correct class.

There are five members/events/methods in Timer that you care about:
.Elapsed - this is an event that fires every specified interval of time. You need to wire it up to a event handler like this:
testTimer.Elapsed += new ElapsedEventHandler(testTimer_Elapsed);

then create the testTimer_Elapsed function like this:

private void testTimer_Elapsed(object sender, ElapsedEventArgs e)
{
//do stuff
}

.Interval - this is how often you want the Elapsed event to fire and it's in milliseconds. To make things easier you may want to create some functions that convert milliseconds to more useful time periods, like seconds.
1 second = 1000 milliseconds
1 minute = 60 seconds
so 1 minute = 60 * 1000
etc...

.Enabled - set this true if you want the Timer to work. Make it false when the timer isn't needed.

.Start()- Call this to make the Timer start counting down.
.Stop() - Call this when you no longer want the Timer to count down

Full Example:
using System.Timers;

namespace TestingTimer
{
public partial class MyNewService : ServiceBase
{
int count = 0;
public MyNewService()
{
InitializeComponent();

}

protected override void OnStart(string[] args)
{
Timer testTimer = new Timer();
testTimer.Elapsed += new ElapsedEventHandler(testTimer_Elapsed);
testTimer.Interval = getMS(10);
testTimer.Enabled = true;
testTimer.Start();


}
private int getMS(int Seconds)
{
return Seconds * 1000;
}

protected override void OnStop()
{
}

private void testTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
System.Windows.Forms.MessageBox.Show("Event #" + (++count).ToString());
}
catch (Exception a)
{
EventLog.WriteEntry(a.ToString());
}
}
}
}

References:
1. http://www.codeguru.com/columns/dotnet/article.php/c6919
2. http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

Installing a Windows Service project for debugging

You cannot just hit "Debug" project for Windows Service projects in Visual Studio. You need to install the service on the system and then use various debugging techniques (like writing to event log)

1. Add Installer in VS:
  • In the Service [Design] right-click anywhere
  • Click on "Add Installer"
2. Configure "Installer"
  • Click on the ProjectInstaller [Design] and click on serviceProcessInstaller1, choose Properties tab
  • Choose an Account (otherwise you get prompted). Most likely you'll want LocalSystem
  • Click on serviceInstaller1 and choose Properties tab
  • Verify that ServiceName is the correct value (i.e. the name of your service)
3. Create some batch files to automatically install/uninstall it
  • @ECHO Installing
    @SET PATH=%PATH%;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\
    @InstallUtil "path to your service.exe"
    @ECHO Install Done.
    @pause
  • For deleting the service: sc delete MyNewName
4. Now Start it
  • Control Panel -> Administrative Tools -> Services
  • Right-click on your service and Start
Troubleshooting:
1. After you install the service you cannot Build the project. You need to Delete the service first. Luckily you have batch files to rapidly do this for you :)

2. If you are trying to use pop up a message box for debugging purposes you'll get an error. Check your error log to make sure. Click here to read about this

3. Service fails to install. If you previously installed it you'll need to Delete it before you try reinstalling.

References:
1. http://www.dotheweb.net/articles/dotnet/services3.aspx
2. Trial and error

Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation

I am writing a Windows Service that pops up a message box for debugging purposes. This does not work because services are not configured automatically to interact with the desktop.

All you need to do to fix this is:
1. Control Panel -> Administrative Tools -> Services
2. Right click on your service -> Properties -> Logon tab
3. Then make it look like this:
References:
1. http://www.dotnet247.com/247reference/msgs/36/184244.aspx

Friday, August 21, 2009

Hosts file

Location in XP: C:/Windows/system32/drivers/etc/
Edit with Notepad

Cannot access SharePoint website outside of LAN

1. Go to Central admin
2. Click on operations
3. On the upper right choose Alternate access mappings
4. edit public URL
5. provide the ip address in the default zone.
6. Add internal URL
7. add your company.com to the default zone.

IIS password keeps popping up

Disable Loopback Checking

  1. start->run->regedit
  2. Find HKLM\System\CurrentControlSet\Control\Lsa
  3. Create a new DWORD value called DisableLoopbackCheck and give it a value of 1
  4. Restart the computer

Monday, August 10, 2009

Could not create type exception in Web Service




Description:
An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: Could not create type ''.
Source Error:
Line 1: <%@ WebService Language="C#" CodeBehind="<filename>.asmx.cs" Class="<classname>" %>

Solution:
1. Put this in web.config within :
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>

2. If your web service description is in a DLL then make sure this DLL is in the bin folder of your website.

3. Be sure to be calling the Web Service from the correct folder. Our customer was attempting to call the web service from ~/B/WebServiceName.asmx, instead of ~/A/B/WebServiceName.asmx. So be sure to check for this very simple error.


Saturday, August 8, 2009

Font's are very small (Firefox)

This is a very annoying problem I've ran into. I'll be looking at a page on Firefox and the font is so small I can barely read it. I'm talking size 4 and 6, very unreadable.
Here's how to fix this problem














Tools->Options
Choose Advanced tab next to Fonts & Colors

Choose the minimum font size. Warning: if you choose a large number, like 13, it will make fonts look distorted on most pages. 9 should be sufficient to prevent unreadable font size


There was an error in this gadget