Friday, November 13, 2009

C/C++ pointers 101

If you're gonna be using pointers you should know what they are and why they are useful instead of just learning the syntax. So here's a brief little introduction followed by how to use them.

What are pointers

Pointers are very useful. Why? Because instead of passing large data structures (class, struct, arrays) into functions you simply pass in the address. The pointer's size is very small, it's just the size of the integer representation of the memory of it's pointing to. So using pointers effectively will make your code more efficient.

Why do only C/C++ use pointers?
They don't. Higher level languages hide the fact that they are using pointers. For example in Java, it's completely object oriented, which means every object is really a reference. The reason they abstract the idea of a pointer away from you is because it's a difficult concept to try to learn.

How to use pointers (using simple examples)
int a = 3; //first you create something to be pointed to
int *ptr; //then you create the pointer, using the * syntax
ptr = &a; //assign the pointer to the address of (&) of a

let's say a's address in memory is 0x123 for the following examples:

cout << *ptr << "=" << 3="3" 0x123="0x123" style="font-style: italic;">Pointers as arrays
function caller()
{
int *a;
for(int i = 0; i < 5; i++)
{
(a+ i) = &i; //set a[i] to i
}
printArray(a, 5);

}

function printArray(int *a, int size)
{
for(int j = 0; j < size; j++)
cout << a[i] << endl;
}

printArray will print out
0
1
2
3
4

Now you know the basic essentials of pointers. Now apply that to larger objects (like structs) and it works the same way.

Friday, October 16, 2009

How to use backspace in emacs from remote terminal

For classes i have to use linux for development. So I have to use SSH to connect to the linux servers. The problem I always run into is using EMACS to edit C++ source files. The problem is whenever I hit "backspace" to delete something it does some crazy shit and I have to exit emacs and start over.

Note: This is for SSH Secure Shell. Other remote terminal programs should have a similar setting.

The way to solve this is to:

1. Go to "Edit"
2. Go to "Settings" at the bottom
3. expand "Profile Settings" and in "Keyboard"
4. Check "Backspace sends delete" and OK

Wednesday, September 2, 2009

Cannot find template file for the new query

1. Navigate to C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\SsmseeTemplates\Sql

2. Create file called SQLFile.sql

References:
1. http://sqlug.be/blogs/steves_sql_blog/archive/2009/03/19/sqlfile-sql.aspx

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


Friday, July 24, 2009

How to use PingBack on your blog

What is PingBack?
If you link to a site in your blog and then run a PingBack utility it will post a link in the comments of that site to your own site.

Example:
Look at this --
link to pingback test page
I posted a link to this website which has PingBack enabled, and then ran a PingBack utility and now there is a comment from my blog with a link back to this post.

Why is this useful?
If your blog is topical readers may be interested in reading what you have to say about the subject, so they'll click on your link. Simply put, it will increase your traffic. It is widely accepted because you are linking to them, so they return the favor by linking to you. You are both helping each other, so it's a mutually beneficial relationship.

Read here for more information on why it's useful.

How to PingBack
I learned how to do this from this site: logofarchiver

Get all the programs/files required
1. Download the latest Python
2. Install Python
3. Download Trackback 'em All. It's the ZIP under Downloads section
4. Extract Trackback 'em All files
4. Download FeedParser. Get the ZIP file
5. Extract FeedParser files to the Trackback 'em All folder where you see "tball.py"

Setup a command prompt to point to TrackBack 'em All
1. Get a shortcut for Command Prompt (Start->Program Files->Accessories->Drag Command Prompt to the desktop)
2. Change the Start Folder to the TrackBack 'em All folder where "tball.py" is located (Right-click->Properties)

Commands
1. Now open up that Command Prompt shortcut. It should be pointed to your TrackBack 'em All folder
Add: tball.py -a /rss.xml
Send PingBacks: tball.py
It will say all the links it's attempting to process. A lot of sites will not have PingBack enabled. If they do have it enabled it will say "Sending PingBack to..."

To test it out create a new blog post and link to this:
http://ebestagent.com/trackback-tester/2009/02/24/wwwbabblrde-trackpack-pingback-testpage
Then run the TrackBack 'em All program. Finally go to that website you just linked to and check if theres a comment at the bottom from your site.

Monday, July 20, 2009

Unable to configure CRM for Outlook because of Authentication error

Step 1: Create a managed password
1. On the client computer open the control panel.
2. Open the User Accounts icon.
3. Click the Advanced tab. (click here if you don't see an Advanced tab)
4. Click Manage Passwords.
5. Click Add.
6. Enter the server name of the CRM server
7. Enter the username as domain\username
8. Enter the password.
9. Click OK, then click Close and then click OK.
NOTE: These steps will only work for client physically connected to the LAN or over a VPN connection.

Step 2: Add CRM website to Trusted Sites
1. On the client open IE, click the Tools menu and then click Internet Options.
2. Click the Security tab.
3. Click the Local Intranet icon.
4. Click the Sites button.
5. Click the Advanced button.
6. Enter the website (add intranet and external address) for access Microsoft CRM and then click the Add button.
7. Click OK 3 times.
8. Close any open IE sessions

Step 3: Map CRM website to the server's IP address
1. Navigate to your host file: (On Win XP) :\WINDOWS\system32\drivers\etc
2. Open file 'hosts' with Notepad
3. Enter in the IP address of your CRM web server, tab, and then the name of the server.
i.e. if your server is on 10.1.1.2, and the name is CRMServer, put 10.1.1.2 CRMServer


note: These steps were found in various locations from various sources

How to access the Advanced tab of User Account

I was trying to figure out where the Advanced tab in User Accounts (Control Panel -> User Accounts) was. It was missing! I'm on Windows XP Pro logged in as the Admin, so that's a bit odd.

All you need to get to the Advanced tab is the following:
1. Start->Run, type cmd
2. Type 'control userpasswords2'

Now you can see a way more useful user management thing than the standard User Accounts.

How to use GROUP BY and HAVING clause to aggregate rows

The number 1 problem for newbies using SQL is the requirement to think in terms of sets. For someone who primarily uses programming languages, such as Java or C++, they are used to thinking in terms of individual operations.

Example: If you have a list of objects that you need to process you will do this by using a loop, and go through each object in the list.

However in SQL the way to do a loop is by using a cursor. This literally goes through all rows, one row at a time. Problem is SQL is not designed to be used like this, so it's totally inefficient!

In SQL whenever you need to aggregate rows and perform calculations on them as a whole you can use the GROUP BY and HAVING clauses.

So what are these?

GROUP BY: You group by all columns that are not aggregate list. For example, lets say you want to calculate the average age of all people with the same last name.
You would use this:
SELECT LastName, AVG(Age) as [Average Age]
FROM People
GROUP BY LastName

And the results would be like:
LastName Average Age
Smith 20
Obama 40
Bush 50

Here's a good guide for additional help: http://www.w3schools.com/sql/sql_groupby.asp

HAVING: This is used for when you want to only get groups that fit a certain criteria. For example, you want to get a list of all last name's for which the average age is > 20. You would use the following:

SELECT LastName, AVG(Age) as [Average Age] FROM People
GROUP BY LastName
HAVING AVG(Age) > 20

Using the previous example's query, the results would be:
LastName Average Age
Obama 40
Bush 50

*Notice how Smith 20 is missing? :)

Access denied to folder when using FileUpload dialog

I had this problem when i was creating a video management system.

Problem: Access denied to a folder that you are trying upload a file to, using FileUpload.

Solution:
FileUpload has a posted file. When a postback occurs the posted file stream is removed. I had a button called [Upload Video] that was meant to validate the upload. The actual upload operation is done after all the information is input and the [Save] button is hit. So because of this problem i decided to make the [Upload Video] do the upload operation.

Put simply: You need to perform the saving of the file prior to any postback, otherwise the file stream is not there anymore!

How to dynamically retrieve a company's name in Dynamics GP

So I had to build reports for a company and then make it generic so we could resell it to anybody. Well a big problem we had was how to get the company's name on the report without asking them for it. Well here's the trick:

SELECT DYNAMICS..Sy01500.CMPNYNAM FROM DYNAMICS..Sy01500
WHERE Dynamics..Sy01500.INTERID = (SELECT db_name())

This works because Dynamics stores the company's database name, which you can reference to get to the company's formal name.

An item disappears from radio button group

I have a radio button group with 4 choices, and I need to add another one. So i went to the RBG's properties and clicked on "Collection" and added
the new choice. I then built and debugged it, and noticed that the choice was NOT there!

So I looked in the behind code (ASP.NET markup) and noticed that the choice was not actually put in the list, but it was appearing in Design Mode.

Whats up with that? Well I couldn't find any explanation for why it happens but all you need to do to fix it is manually add the new item into the RBG:
like this

<asp:RadioButtonList ID="Choices" runat="server">
<asp:ListItem Value="OldChoice">Old Choice</asp:ListItem>
<asp:ListItem Value="NewChoice">New Choice</asp:ListItem>
</asp:RadioButtonList>

Sunday, July 19, 2009

How to create dynamic links in a gridview

Whenever you are displaying results for a query you need to allow the user to click on a link that will bring them to an appropriate page. Put this in a GridView and customize to get the results you want:

<asp:TemplateField HeaderText="Subject">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl='<%# Eval("ID", "~/Page.aspx?id={0}") %>'
Text='<%# Eval("Subject") %>'></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>

How to create a multivalue array in SQL

I had to figure this out when I was creating reports. The report had to be based on different document types depending on the choices of the individual. So lets say theres 5 different document types. Well a simple query to check all 5 document types would be

SELECT * FROM Table WHERE DocType IN (1, 2, 3, 4, 5). Well now you have a very complicated query to deal with when you have to exclude document types. The simplest way is to save the "IN" string as a multivalue array. I.e. you would use the string "1, 2, 3, 4, 5".

Well here's how you do this:

  

1. First create a function that's used to parse the parameters can turn it into a
multivalued array
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID(’UF_CSVToTable’))
DROP FUNCTION UF_CSVToTable
GO

CREATE FUNCTION UF_CSVToTable
(
@psCSString VARCHAR(8000)
)
RETURNS @otTemp TABLE(sID VARCHAR(20))
AS
BEGIN
DECLARE @sTemp VARCHAR(10)

WHILE LEN(@psCSString) > 0
BEGIN
SET @sTemp = LEFT(@psCSString, ISNULL(NULLIF(CHARINDEX(',', @psCSString) - 1, -1),
LEN(@psCSString)))
SET @psCSString = SUBSTRING(@psCSString,ISNULL(NULLIF(CHARINDEX(',', @psCSString), 0),
LEN(@psCSString)) + 1, LEN(@psCSString))
INSERT INTO @otTemp VALUES (@sTemp)
END

RETURN
END
Go

2. Create the stored procedure that will use the function from step 1.
CREATE
PROCEDURE TEMP_SP_RETRIVE_JOBS
@sCategoryID VARCHAR(5000)
AS
BEGIN
SELECT * FROM TblJobs WHERE iCategoryID IN (SELECT * FROM UF_CSVToTable(@sCategoryID))
END
GO

How to upload and play a video (ASP.NET)

So I was given the task of creating a video management system on my work's website. This simply means employees can upload a video, and then allow anybody to view the video.

Notice: This is way more simple than a final version would be, this is just to show the basics of getting it to work.

1. Add the ability to upload video:
public partial class WebUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void Button1_Click(object sender, EventArgs e)
{
if (!fileUploadDialog.HasFile) //Check if user has specified file
{
lblStatus.Text = "Must select a video file to upload";
return;
}
string virtualFilePath = "~/VideoDirectory/" + fileUploadDialog.FileName;

string physicalFilePath = Path.Combine(Server.MapPath("VideoDirectory"), fileUploadDialog.FileName);
fileUploadDialog.SaveAs(physicalFilePath);

SqlCommand cmd = new SqlCommand();
try
{
Guid vidId = Guid.NewGuid();
cmd.CommandText = "INSERT INTO Videos(VideoID, VideoPath) VALUES(@VideoID, @VideoPath)";
cmd.Parameters.AddWithValue("@VideoID", vidId);
cmd.Parameters.AddWithValue("@VideoPath", virtualFilePath);
cmd.Connection = new SqlConnection(YourConnectionString);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
lblStatus.Text = "File has been uploaded!";

}
catch(SqlException se)
{
//SQL error occured, so delete file in the file system
File.Delete(physicalFilePath);
lblStatus.Text = "A SQL error occured, file has not been uploaded.";
}
finally
{
cmd.Connection.Close();
}
}
}

2. Use a GridView to display the list of videos. Dynamically generate links to the video viewing page:
<asp:gridview id="gvVid" runat="server" autogeneratecolumns="False">
<columns>
<asp:templatefield headertext="Name">
<itemtemplate>
<%# getFileName(Eval("VideoPath").ToString()) %>
</itemtemplate>

</asp:templatefield>

<asp:templatefield headertext="Video Link">
<itemtemplate>
<asp:hyperlink navigateurl="" vid="{0}&quot;)">">
ID="HyperLink1" runat="server">[View Video]</asp:hyperlink>
</itemtemplate>
</asp:templatefield>
</columns>
</asp:gridview>

protected void Page_Load(object sender, EventArgs e)
{

}
protected string getFileName(string path)
{
return System.IO.Path.GetFileNameWithoutExtension(path);
}
protected void btnRefresh_Click(object sender, EventArgs e)
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = new SqlConnection(YourConnectionString);
cmd.CommandText = "SELECT VideoID, VideoPath FROM Videos";
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
try
{
da.Fill(dt);
gvVid.DataSource = dt;
gvVid.DataBind();
}
catch
{ }

}

3. Setup the behind code for the video viewer page

string vpath = "";

if (Request.QueryString["vid"] != null && new Guid(Request.QueryString["vid"]) != Guid.Empty)
{
SqlCommand cmd = new SqlCommand("SELECT VideoPath FROM Videos WHERE VideoID = @VideoID");

cmd.Connection = new SqlConnection(YourConnectionString);
cmd.Parameters.AddWithValue("@VideoID", Request.QueryString["vid"]);
try
{
cmd.Connection.Open();
vpath = cmd.ExecuteScalar().ToString();
cmd.Connection.Close();

}
catch { }
finally
{
if (cmd.Connection.State == ConnectionState.Open)
cmd.Connection.Close();
}

}
Label1.Text = vpath;
MediaPlayer1.MediaSource = vpath;
}

**MediaPlayer1 is from Silverlight. You'll need to download this and include it in your project. Get silverlight here: silverlight sdk download

Now you have the basic setup that will allow you to create your own video management system. Good luck.

A healthy information source

Recently I became interested in getting physically fit and being healthy. Well, where to begin? I started combing websites for useful information that would allow me to get started with my quest for a healthy lifestyle.

I ran into many sites that suggested information that I didn't find that useful. And then I found this site: health blog, which dispenses tips for being healthy, the natural way (aka natural health)! This is quite interesting and different from other sites because 1) The blogger is a genuinely trying to help people out, and 2) the information helps you solve practical health problems using natural remedies, instead of prescription drugs.

So yeah, from now on I'm going to be using this site. After all, I can't keep computers healthy if I can't keep myself healthy :)

How to center your web page content using a div

Go to google.com and try resizing the page. Notice how everything remains centered? Well the trick to using that is by using <div>'s. The way you do this is the following:

1. Insert the following code into a CSS file:
body
{
text-align: center;
}

div.content
{
text-align: left;
}

2. On your content page insert a <div class="content">

Voila! Your div will now be centered and all it's content will be left aligned :)

How to get XML File Changes to work in InstallShield 10.5

Problem: XML File Changes feature is not properly updating an element's content to a [PROPERTYNAME] changed value. This can be found by navigating to "XML File Changes" -> Click on a node -> click on "Advanced tab"

Workaround: First set the content to "[PROPERTYNAME]" (with qutoation marks), build it, and then remove the quotation marks, and build again.

Note: This is a bug and it's not known why this workaround actually works, but it does.

Calling a function when button is clicked in datagrid

So you have a datagrid that's automatically populated by your data, including dynamically generated links.

For example, you allow people to search for books, and you want them to be able to click on a link to the books that are returned in the search...well you need to dynamically generate the links based on the books ID. www.YourSite.com/books.aspx?id=1234 etc...

Well sometimes you also need to be able to call a function to do some additional processing when the list is generated. Here's the code necessary to do this:

ASP.NET Code:
<asp:TemplateField HeaderText="Video Links" >
<ItemTemplate>
<asp:LinkButton OnCommand="lbEdit_Click" ID="lbEdit" CommandName="Edit" CommandArgument='<%# Eval("VideoID").ToString() %>)' runat="server" Text="Edit Video">
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>


In the C# behind code file:
protected void lbEdit_Click(object sender, CommandEventArgs e)
{
//Pass the contextual info to the next function
ProcessInfoFunction(e.CommandArgument.ToString());
}

How to get your deleted records back in CRM

Have you ever accidentally deactivated or deleted something in CRM that you wish you could get back? well, my coworkers have, so you're in luck :)

First of all, records aren't really deleted right away like you think would happen. They are MARKED for deletion, and then bulk deleted (this is ideal for performance).

Here's what to do:
1. Login to the SQL Server containing your CRM database
2. Find the table that holds your record of interest. For example, if you deleted an Account, you'll want to use the AccountBase table
3. Execute a query to find your record of interest, and then confirm that this is the appropriate record. For example, if you deleted an Account with the name of "Oops Enterprises", search for that
4. Execute the following update:
UPDATE SET DeletionStateCode = 0

Yay! Now if you go into CRM you'll see that your deleted object is still in there!

Disclaimer: Your records are eventually deleted, so you need to act as quickly as possible before they are actually deleted.

How to setup a network printer

If you are using a printer that is capable of network printing, follow these steps to set it up:

1. Plug network cable to Ethernet plug
2. Go to Printers and Faxes
3. Add a printer
4. Local printer, uncheck Plug and Play
5. Add port
6. Add TCP/IP type port and type in the IP of the printer (you should be able to find this within the display screen on the printer, use Menu/Setup and then find network settings)
7. Point to this port
8. Add the appropriate drivers and print a test page

How to speed up CRM for Outlook

Most of my coworkers use the CRM for Outlook client, which basically integrates CRM and Outlook, allowing you to attach emails to entities (i.e. Cases, Accounts) in CRM without having to use CRM itself.

A major problem they were having is that using CRM for Outlook caused their Outlook's performance to decrease. Well here are methods i found that actually helped to increase the speed issues...Good luck!

1
. Close Outlook
2. Go to:
If XP: C:\Documents and Settings\\Application Data\Microsoft\Outlook
If Vista: C:\\AppData\Roaming\Microsoft\Outlook
Note: These may be hidden so go to any folder and select Tools > Folders Options > View. Check "Show hidden files and folders".
3. Rename outcmd.dat to outcmd.dat.old, and the same thing for outlprnt. (outlprnt may be missing)
4. Start->Run
5. Type regsvr32 OLE32.DLL, hit OK
6. Type regsvr32 INETCOMM.DLL, hit OK
7. Restart Outlook

How to determine if object from database is null (C#)

When you are getting data out of your database you may need to do some type checking. This is important if the field allows null.

For example, if you have an nvarchar(#) that allows Null, you'll want to check if you are getting a Null string so that you can safely set it to "" (empty string) or whatever value you want. This prevents exceptions from being thrown.

Code (ADO.NET C#):

Using one line:
string columnName = reader["columnName"].GetType() == Type.GetType("System.DBNull") ? "" : reader["columnName"].ToString();

Using if, then:
if(reader["columnName"].GetType() == Type.GetType("System.DBNull"))
columnNameVariable = ""; //or whatever value you want to set it to
else
columnNameVariable = reader["columnName"].ToString();
There was an error in this gadget