Monday, December 27, 2010

Client-side scripting example for RetrieveMultiple

Goal:
When a new case is created generate a case number, instead of using the "auto-numbering", so that you can put it in any format you want. I wanted our case number to be all numeric, and be sequential. In other words, I wanted to create new cases with case number = last case number + 1.

Client-side code
In the Case form OnLoad event (under form properties)  add the following javascript:
Note: This client-side code is the almost equivalent to the SQL statement: SELECT TOP 1 ticketnumber + 1 FROM IncidentBase ORDER BY createdon DESC


var CRM_FORM_TYPE_CREATE = 1;
if(crmForm.FormType == CRM_FORM_TYPE_CREATE)
{
// Prepare variables to retrieve the contacts.
var msg = "";
var authenticationHeader = GenerateAuthenticationHeader();
// Prepare the SOAP message.
var xml = "<?xml version='1.0' encoding='utf-8'?>"+
"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'"+
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'"+
" xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"+
authenticationHeader+
"<soap:Body>"+
"<RetrieveMultiple xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+
"<query xmlns:q1='http://schemas.microsoft.com/crm/2006/Query'"+
" xsi:type='q1:QueryExpression'>"+
"<q1:EntityName>incident</q1:EntityName>"+
"<q1:ColumnSet xsi:type='q1:ColumnSet'>"+
"<q1:Attributes>"+
"<q1:Attribute>ticketnumber</q1:Attribute>"+
"</q1:Attributes>"+
"</q1:ColumnSet>"+
"<q1:Orders>" +
"<q1:Order>" +
"<q1:AttributeName>createdon</q1:AttributeName>" +
"<q1:OrderType>Descending</q1:OrderType>" +
"</q1:Order>" +
"</q1:Orders>" +
"<q1:PageInfo>" +
"<q1:PageNumber>1</q1:PageNumber>"+
"<q1:Count>1</q1:Count>"+
"</q1:PageInfo>"+
"</query>"+
"</RetrieveMultiple>"+
"</soap:Body>"+
"</soap:Envelope>";
// Prepare the xmlHttpObject and send the request.
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
// Capture the result.
var resultXml = xHReq.responseXML;
// Check for errors.
var errorCount = resultXml.selectNodes('//error').length;
if (errorCount !== 0)
{
var msg = resultXml.selectSingleNode('//description').nodeTypedValue;
alert(msg);
}
// Parse and display the results.
else
{
var results = resultXml.getElementsByTagName('BusinessEntity');
var msg = "";
if (results.length === 0)
{
msg = "Unable to generate case number, please fill in the Case Number field manually";
crmForm.all.ticketnumber.disabled = false;
alert(msg);
return;
}
else
{
var ticketnumber= results[0].selectSingleNode('./q1:ticketnumber').nodeTypedValue;
var strArr = ticketnumber.split('-');
var index = 0;
if(strArr.length > 1)
index = 1;
var tickNum = new Number(strArr[index]);
if(!isNaN(tickNum))
{
crmForm.all.ticketnumber.value = new Number(tickNum + 1);
}
else
{
msg = "Case number found was not a number, please fill in the Case Number field manually";
crmForm.all.ticketnumber.disabled = false;
alert(msg);
return;
}
}
}
}


References:
1. Server-side translation into client-side JavaScript
http://community.dynamics.com/product/crm/crmtechnical/b/crminogic/archive/2009/08/28/how-to-convert-a-retrievemultiple-query-written-server-side-to-soap-message-to-be-used-in-javascripts.aspx
2. Example of attributes for an entity (incident): http://msdn.microsoft.com/en-us/library/dd903985.aspx

Tuesday, December 21, 2010

Unable to publish workflow - Dynamics CRM 4.0

Problem:
You cannot publish Workflows in Dynamics CRM 4.0, and you get the following message in the event viewer: "Exception has been thrown by the target of an invocation."

Solution:
1. Open the CRM website's web.config. (typically located in C:\Inetpub\wwwroot)

2. Locate section <authorizedTypes>

3. Add the following to this section:
<authorizedType Assembly="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Namespace="System.Globalization" TypeName="CultureInfo" Authorized="True"/>

Friday, December 10, 2010

Two very useful tools for rebuilding a computer

DriverMax - Allows you to quickly see all of the drivers on your system, and then export them to a folder. This is useful because you can then slipstream the drivers into the OS installation, instead of having to download them all and add them from scratch.


nLite - Use it to build slipstreamed OS bootable ISO with customizations, such as adding drivers, creating an unattended installation, and more.

Boot and Nuke - This is used to completely erase data from hard drives.

Tuesday, November 30, 2010

How to run Windows 98 on Windows Virtual PC

Why and overview of how
So I decided I wanted to play an old game ('96) called Heroes of Might and Magic 2. I tried like hell to get it to work on my Windows 7 64-bit computer but it just wouldn't. Then I discovered Windows Virtual PC. This is the Windows 7 version of Virtual PC 2007 (etc...). So I got Win98 up and running, but it didn't have the "integration components", which makes the virtual utterly annoying to use. So then I discovered you can simply get "Additions" (Virtual PC version of integration components), because Win98 was supported in the previous versions of Virtual PC! So here's a neat little list on how to do this:

How in details
1. Install Windows Virtual PC http://www.microsoft.com/windows/virtual-pc/
2. Have a Win98 iso or installation disk ready (you can easily find a torrent for the iso)
3. Install win98 on virtual machine:
http://www.essjae.com/virtualization/WinVPC-InstallingWin98.pdf
4. To get "Additions" from an older version of VPC follow these steps:
http://blogs.msdn.com/b/virtual_pc_guy/archive/2010/05/27/installing-windows-98-on-windows-virtual-pc.aspx

Finally
So I got Win98 fully working. It's pretty sweet seeing it again. I haven't used it in something like 8 years or so. The game (HoMM2) works, except I can't resize it and it's stuck at something like 400x400 or so. I haven't been able to find a solution to this, but I don't care at this point, because at least I get to the play the game :)

Wednesday, October 27, 2010

The report data source object must be of the type System.Data.DataTable, System.Collections.IEnumerable, System.Windows.Forms.BindingSource, or System.Type.

Problem:
"The report data source object must be of the type System.Data.DataTable, System.Collections.IEnumerable, System.Windows.Forms.BindingSource, or System.Type." when you add an object to ReportDataSource.value

Solution:
If you are adding a business object then you should create a BindingList collection class, and then put the single business object into the collection and set that as the data source.

For example, lets say you have business class Product. Create a class public class ProductCollection : BindingList {}
note: BindingList is part of the System.ComponentModel namespace.

"Index was out of range" error when clicking on a column header in DataGridView

Problem
Clicking on a DataGridView column results in the error message "Index was out of range. Must be non-negative and less than the size of the collection."


Solution 
Make sure you are handling the CellContentClick (and other click events if appropriate) properly. Below is what I had
        private void gvBatches_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 0) //then they clicked on the link
            {
                //code that uses e.RowIndex
            }
        }

What this does is when the user clicks on the first column it proceeds to use e.RowIndex regardless of the value, because I assumed that a Column Header would not fire this event, but that's not the case. The e.RowIndex for a column header is -1, so make sure to check if e.RowIndex == -1. For example, i fixed mine and it looks like this now:
        private void gvBatches_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 0 && e.RowIndex != -1) //then they clicked on the link
            {
                //code that uses e.RowIndex
            }
        }

References
1. http://www.eggheadcafe.com/community/aspnet/14/10173997/index-out-of-range-error-when-clicking-the-column-header-in-datagridview.aspx 

Monday, October 25, 2010

Deep Copy in C#

Problem
If a modifiable object is ever accessed by multiple users, then you need to do a deep copy to make sure they aren't using the same object.

For example, if you cache an object.

Solution
Use this DeepCopy method:
public object DeepCopy(object obj)
{
    MemoryStream ms = new MemoryStream();
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(ms, obj);    

    object retval;
    ms.Seek(0, SeekOrigin.Begin);
    retval = bf.Deserialize(ms);
    ms.Close();
    return retval;
}


Note: You'll need to add 
"using System.IO;
using System.Runtime.Serialization.Formatters.Binary;"

to whatever file you put this in.
 


Reference  
1. http://weblogs.asp.net/gunnarpeipman/archive/2007/10/07/net-and-deep-copy.aspx 

You know you're on a software project [comic]

http://geekandpoke.typepad.com/geekandpoke/2010/10/advanced-yiw-ommiw.html

Wednesday, October 20, 2010

Copying a file to an external hard drive error "too large for the destination file"

Problem
If your hard drive's file system is not NTFS then your files have size limits and you'll receive a "too large for the destination file" error message.

Solution
Convert your hard drive file system to NTFS.  See this Microsoft article on how to do that: http://windows.microsoft.com/en-US/windows-vista/Convert-a-hard-disk-or-partition-to-NTFS-format

Note: When you follow these instructions it will ask you for your "volume label". To quickly retrieve this type "vol " into the command line. For example: if the hard drive you are converting is C: then type vol c:

References
1. http://forums.techguy.org/windows-vista/704717-too-large-destination-file-system.html
2. http://forums.cnet.com/7723-6122_102-217982.html

Monday, October 18, 2010

How to execute a batch from the current directory even when you run as admin

Problem
When you want a batch file to execute from the same directory that it's located and have to "Run as admin" you'll have a problem because it defaults to "%Windows%system32" instead of the current directory.

Solution
Add these two lines to the top of your batch file
@setlocal enableextensions
@cd /d "%~dp0

Tuesday, October 5, 2010

Type exists in both App_Web_type.#.dll and App_Web_#.dll

Error:
The type ''type" exists in both 'c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\26676eb7\92c7e946\App_Web_type.cdcab7d2.7qilrjrp.dll' and 'c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\26676eb7\92c7e946\App_Web_a0xipze6.dll'

Solution:
Add batch="false" to web.config node compilation, i.e.
<system.web>...
<compilation batch="false">

References:
http://forums.asp.net/t/1249970.aspx

Friday, October 1, 2010

SQL Server instance not showing up in GP utlities list

Solution:
We created the ODBC manually and pointed to "SQL Server" instead of "SQL Native Client" in the driver list. We fixed this by removing the ODBC with this and recreating one and pointing to SQL Native Client instead of SQL Server.

References:
1. https://community.dynamics.com/forums/t/35862.aspx

Monday, September 13, 2010

Mafia 2 black screen

 Mafia 2 has been crashing for me a lot. It crashes randomly and always results in a black screen and weird sound coming from the computer. Luckily I found the solution to this here:


Mafia 2 Blackscreen Fix
When you start the game, it gives you a constant black screen, one reason for that can your monitor being out of range. Simple solution is:
Go to
C:\Users\yourAccountUserName\AppData\Local\2K Games\Mafia II\Saves
and open file “videoconfig” with notepad and change video resolution to your native desktop resolution.
Thanks to http://segmentnext.com/2010/08/24/mafia-2-errors-crashes-ati-fix-physx-fix-graphics-bugs/

Thursday, August 26, 2010

Insert a backup table back into the original table

1. Get the column list
SELECT COLUMN_NAME + ', ' from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '(table name)'

2. Copy the results of this query, and remove the comma from the last record.

3. Run the query:

SET IDENTITY_INSERT originalTableName ON

INSERT INTO originalTableName
(paste column list here)
SELECT
(paste column list here)
FROM (backup table)

SET IDENTITY_INSERT  originalTableName OFF

Note: If your table doesn't have an identity column you can safely disregard the first and last lines of this query.


Reference: http://blog.sqlauthority.com/2007/03/28/sql-server-fix-error-8101-an-explicit-value-for-the-identity-column-in-table-can-only-be-specified-when-a-column-list-is-used-and-identity_insert-is-on/

Wednesday, August 18, 2010

InstallShield error: fatal error -1014: Cannot rename directory to \folder.Bak

I ran into this problem when I was debugging and accidentally left a "pause" at the end of a batch file that was run at the end of installation, which I made execute silently. Thus you see the problem, it was waiting for the user to end the execution by pressing a button, which could not be done since it was not visible.

Solution:
1. The current InstallShield owner's KB article is here (new window).
2. None of their proposed solutions helped, so I figured the installer was still running but I couldn't find it in the process list. So what fixed it was restarting my computer.
3. A less "hammer to kill an ant" approach is to download and use the MSI clean up utility, found here (new window).

Tuesday, July 13, 2010

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type




I got this error when trying to dynamically set the WebServiceNamespace attribute, from a value from the web.config. If you're trying to do this, don't do it. See this thread for reasons why not to: http://forums.asp.net/p/1171781/1963223.aspx

If you actually need to dynamically update an attribute then follow this article: http://geekswithblogs.net/abhijeetp/archive/2009/01/10/dynamic-attributes-in-c.aspx


Wednesday, June 2, 2010

How to delete all checked items in CheckedListBox

Remove all checked items from a CheckedListBox
for (int i = checkListDays.Items.Count - 1; i >= 0; i--)
{
if (checkListDays.GetItemChecked(i))
checkListDays.Items.RemoveAt(i);
}



Another solution is to save all the items in a List by iterating through CheckedListBox.CheckedItems, and then iterating through the resulting List and CheckedListBox.Items.Remove(object from List<>).


These solutions differ slightly in efficiency. The first solution iterates through the CheckedListBox only once, thanks to on-the-fly item removal, thus O(n). The second solution could iterate through the CheckedItems list, which could contain all items, and then iterate through the List<>, thus O(2n). But, O(2n) == O(n), because the 2 is dropped, thus the difference in efficiency is insignificant. I do like the first solution more however, because of its elegance.


References
1.
Delete all checked items in CheckedListBox | debugging:

Tuesday, June 1, 2010

Read-only ComboBox in Windows Form

Problem:
You are using a ComboBox as a drop down list and want to disallow the user from typing in the box.

Solution:
Set the ComboBox's DropDownStyle to "DropDownList"

References
1.
Make combobox readonly - C# / C Sharp answers

Wednesday, May 26, 2010

"Specified cast is not valid" when converting to variable from SqlDataReader

Problem:
"Specified cast is not valid." exception thrown from converting data from a SqlDataReader, i.e. short shortVar = (short)reader["shortField"];


Solution:
If your types are actually the same, then this error implies that you must use a Convert.To method.


Example:
buggy: 
short shortVar = (short)reader["shortField"];
fixed:
short shortVar = Convert.ToInt16(reader["shortField"]);

How to add resources to subprojects in Project Server 2010

If you have a master project with many subprojects then the answer is crappy. You must add the resources to each subproject individually. Unfortunately the resources do not appear to trickle down from the master project.

Friday, May 21, 2010

SharePoint People Picker Returns No Results

Problem:
In SharePoint Server 2010 in Central Admin you try to look up a user, but it returns no results.

Solution:

1. Open up SharePoint Management Shell
2. Run these two commands
  • stsadm -o setapppassword -password password 
  • stsadm -o setproperty -pn peoplepicker-searchadforests -pv "domain:domaintosearch.com,username,password" -url http://centraladminurl

References:

Jonny Trees Online: SharePoint People Picker Returns No Results

http://www.sharepointdevwiki.com/display/spadmin2010/15+-+Configure+User+Profile+Synchronization+Service

Wednesday, April 14, 2010

Assembly Uses 'Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' which has a higher version than referenced assembly 'Microsoft.ReportViewer.WinForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'




Problem:
Build a project that uses ReportViewer and you get the following error:
Assembly Uses 'Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' which has a higher version than referenced assembly 'Microsoft.ReportViewer.WinForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Solution:
Before you start, make sure the project is actually referencing Microsoft.ReportViewer.WinForms version 9.0. For some reason re-adding this in the references does not change the number in the project file. So after you are sure you're using version 9.0 do the following steps...

1. Open up the location of your project file. If you're using C# this is ProjectName.csproj
2. Open the project file with Notepad
3. Find the node containing Microsoft.ReportViewer.WinForms
4. Change the version number from 8.0.0.0 to 9.0.0.0 like the following picture:

References
1. http://davidsandor.com/blogs/tipsandtricks/archive/2008/07/16/solved-the-base-class-includes-the-field-reportviewer1-but-its-type-microsoft-reporting-webforms-reportviewer-is-not-compatible-with-the-type-of-control-microsoft-reporting-webforms-reportviewer.aspx  


 

Tuesday, April 6, 2010

How to select multiple values in an enum

Lets say you have an enum called DaysOfWeek, because you need to keep track of multiple days a user may select, because they may select different combos of days. The most efficient to store this is by using an enum with [Flag] attribute.

Like this:













Notice the values are are 2^x. This is because this is actually an 8-bit field.
We have [0000000], with a bit for each day.

So lets say you have Monday and Saturday chosen. This would be:
[1000010] = 64 + 2 = 66

Ok so how do you use this value?

First we need to STORE the values. We do this by using a bitwise OR.
Example: if we chose Monday and Wednesday we have Monday = [10] and Wednesday = [1000]. ORing these together 10 | 1000 = 1010, which in decimal is 10.

Next we need to LOAD the values. We do this by using a bitwise AND.
Example: To see if Monday was chosen we would do the total bit representation [1010] AND Monday [10] so 1010 & 10, which will return [10], which in this case is Monday.

How to programmatically check items in CheckedListBox

You can simply use CheckedItemBox.SetItemChecked(int index, bool value).

If you need to set the value based on the values from an enum with the [Flag] attribute you can do this:

cbDays.SetItemChecked(0, (curSchedule.DaysOfWeek & DaysOfWeek.Monday) == DaysOfWeek.Monday);
Where cbDays is a CheckedItemBox.
0 means we are looking at the first item in the CheckedItemBox. In this case it's "Monday".

The next part, curSchedule.DaysOfWeek & DaysOfWeek.Monday) == DaysOfWeek.Monday is doing a bitwise AND to see if Monday is a selected value.


References:
1. http://msdn.microsoft.com/en-us/library/t0zxd5z5%28vs.71%29.aspx

How to get CheckedListBox selected values

Problem:
You want to get the selected checkbox values from a CheckedListBox in a Winform project.

Solution:
Here's a simple application to illustrate how to get the values from a CheckedListBox.

1. UI pre-select

















2. UI post-select


3. Here's the simple C# source for the Process button, which gets the values from the CheckedListBox and puts them in the "You selected" part



























So all you need to get the value is "CheckedItems".

If you want to store these values in a database you'll need to use an enum with the [Flags] attribute. See my other post for more details on this:
http://makguidetosoft.blogspot.com/2009/08/calculate-next-time-job-scheduled-for.html

Saturday, February 20, 2010

Could not load file or assembly 'AntiXssLibrary, Version=3.1.3524.16873, Culture=neutral, PublicKeyToken=d127efab8a9c114f' or one of its dependencies.




Exception:
Could not load file or assembly 'AntiXssLibrary, Version=3.1.3524.16873, Culture=neutral, PublicKeyToken=d127efab8a9c114f' or one of its dependencies.

Required permissions cannot be acquired.

Cause:
The hosting environment is configured for Medium Trust and AntiXssLibrary is compiled using the "unsafe code" flag by default.

Solution:
1. In order to test this on your development comp you'll need to go into your web.config file and add a node
<trust level="Medium"> somewhere between <system.web></system.web>

2. Download the source code for AntiXSSLibrary, located here: http://antixss.codeplex.com/SourceControl/changeset/view/28744# and click on Download button

3. Open up the project in Visual Studio and right-click on the AntiXSSLibrary project.

4. Build tab, uncheck "Allow unsafe code" as seen below. NOTE: This cant be done in version 3.1, so only try it in version 3.0



5. Add [assembly: System.Security.AllowPartiallyTrustedCallers()] to AntiXssLibrary project AssemblyInfo.cs (located under Properties folder), as seen below










6. Recompile the project, and then add the reference to your project and test.


References:
1. http://msdn.microsoft.com/en-us/library/ms998341.aspx
2. http://forums.iis.net/t/1164637.aspx
3. http://antixss.codeplex.com/Thread/View.aspx?ThreadId=44517



Wednesday, February 3, 2010

Please configure the Windows SharePoint Services Timer service to run as a domain account



1. Start->Control Panel->Administrative Tools

2. Click on Services

3. Navigate to "Windows SharePoint Services Timer"

4. Right-click on it and choose "Properties"

5. Click on the "Log On" tab

6. Choose "This Account" and specify an account on your company's domain.

Note:
Preferably this account should be specially setup only for the purpose of running this timer, but you can use any account that's already setup if you choose to do so.

Thursday, January 14, 2010

How to hide an HTML table row in ASP.NET

1. In your ASP.NET (.aspx) page in your table row () tag do the following:


Notice: The id is what you normally access controls with, and should be named something that will be easier for you to remember and not conflict with other controls. Therefore by convention it should be named rowID, where ID is some unique identifier for that row.

2. In your page behind code (.aspx.cs or .vb) you can now reference your row control by it's id. Do the following:
rowID.Visible = false;

Reference:
1. http://scottelkin.com/programming/csharp/hiding-a-row-in-aspnet/
There was an error in this gadget