james.paul.p
Home
June 9th, 2010 — James

DisconnectedContext was detected

Message: Context 0x33567b8′ is disconnected.  Releasing the interfaces from the current context (context 0×3356648).This may cause corruption or data loss. To avoid this problem, please ensure that all contexts/apartments stay alive until the applicationis completely done with the RuntimeCallableWrappers that represent COM components that liveinside them.

One way to avoid this error seems to build the project in release configuration without any debug information.
I will update this post when I have a reproducible generic code.
May 25th, 2010 — James

The code in this post works fine if you compile using Visual Studio .NET 2003 with .NET Framework 1.1.

If you compile the same code in .NET Framework 2.0+ it fails. Something is broken in my opinion.

You will get an error: Min (number) must be less than or equal to max (-1) in a Range object.

The error occurs when you don’t specify the data type of the column. A strongly typed data set will not get this error.

I got this error when loaded up some Excel spreadsheet in to a data set and did some search on a column I knew would have integer values. The rest of the columns contain user data that may contain unexpected type.

I cannot comment on why it is failing when the type is the default string type and only on certain values. I haven’t looked at the framework code yet. May never look at it.

Here is one place where a similar problem is discussed.

Here is a code to reproduce the problem. Program.cs


using System;
using System.Data;

class Program
{
    static void Main(string[] args)
    {
        DataSet ds = GetDSNoType();
        LoadData(ds);
        SearchData(ds);
        ds = GetDSWithType();
        LoadData(ds);
        SearchData(ds);
    }
    static void SearchData(DataSet ds)
    {
        Console.WriteLine("Searching data with type: {0}", ds.Tables[0].Columns[0].DataType);
        foreach (DataRow row in ds.Tables[0].Rows)
        {
            string Query = string.Format("some_number={0}", row["some_number"]);
            try
            {
                DataRow[] rows = ds.Tables[1].Select(Query);
            }
            catch (Exception e)
            {
                Console.WriteLine("Query: {0}", e.Message);
            }
        }
    }
    static DataSet GetDSNoType()
    {
        DataSet ds = new DataSet("NewDataSet");
        ds.Tables.Add("T1");
        ds.Tables["T1"].Columns.Add("some_number");
        ds.Tables.Add("T2");
        ds.Tables["T2"].Columns.Add("some_number");
        return ds;
    }
    static DataSet GetDSWithType()
    {
        DataSet ds = new DataSet("NewDataSet");
        ds.Tables.Add("T1");
        ds.Tables["T1"].Columns.Add("some_number", typeof(int));
        ds.Tables.Add("T2");
        ds.Tables["T2"].Columns.Add("some_number", typeof(int));
        return ds;
    }
    static void LoadData(DataSet ds)
    {
        foreach (int index in T1)
            ds.Tables[0].Rows.Add(new object[] { index });
        foreach (int index in T2)
            ds.Tables[1].Rows.Add(new object[] { index });
    }
    static int[] T1 =
    {
        2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
        70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
        92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
        111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
        129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
        147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
        165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
        183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
        201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
        219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
        237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
        255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
        273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
        291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
        309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
        327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
        345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
        363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380,
        381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398,
        399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416,
        417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434,
        435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452,
        453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470,
        471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488,
        489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506,
        507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524,
        525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542,
        543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
        561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578,
        579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596,
        597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614,
        615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632,
        633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650,
        651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668,
        669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686,
        687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704,
        705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722,
        723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740,
        741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758,
        759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776,
        777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794,
        795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
        813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830,
        831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848,
        849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866,
        867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884,
        885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902,
        903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920,
        921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939 };
    static int[] T2 =
    {
        77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
        100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
        118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
        136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
        154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
        172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
        190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
        208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
        226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
        244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
        262, 263, 264, 265, 266, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
        281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
        299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 312, 313, 314, 315, 316, 317,
        318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
        336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353,
        354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 368, 369, 370, 371, 372,
        373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390,
        391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408,
        409, 410, 411, 412, 413, 414, 415, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427,
        428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445,
        446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463,
        464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481,
        482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499,
        500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517,
        518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535,
        536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553,
        554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571,
        572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
        590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607,
        608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625,
        626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643,
        644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661,
        662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679,
        680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697,
        698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715,
        716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733,
        734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751,
        752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769,
        770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787,
        788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805,
        806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823,
        824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841,
        842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859,
        860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877,
        878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895,
        896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913,
        914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931,
        932, 933, 934, 935, 936, 937, 938, 939 };
}
May 14th, 2010 — James

http://stackoverflow.com/questions/2836960/why-does-trimstart-trims-a-char-more-when-asked-to-trim-prn-nul

Now to the history:

From .NET Framework 1.0, I had a need to trim out specific strings from the beginning or end of an input. TrimStart always sounded the logical option except it would trim more than I wanted in many cases. Replace would replace every instance. The only option I found was to use Remove which requires more than one step. Now I had to do the same thing in 3.5 and found that there still doesn’t exist a way to trim out a string from the beginning or end of a string with a single method call. It was the number of times I needed that functionality in the last ~10 years. It may not be obvious to developers who write code at library level but if you need to manipulate strings for user facing applications, string manipulation functions of any kind is so useful.

I wanted to ask this as a trick question, that is why I came up with PRN, NUL and AUX to get the attention. But looks like someone ignored that part right away and went straight to my intent. Sarcasm probably requires a better handle on English. I should stick to plain and simple complaining which I am getting better, I think.

March 30th, 2010 — James

Here is the sample code to read the app settings from the web.config file in an application specific folder. You can use this in ASP.NET applications, WCF services and so on.

using System.Web;
using System.Web.Configuration;
using System.Configuration;

public class SomeClass
{
    public void SomeMethod()
    {
            AppSettingsSection section = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath).AppSettings;
            string mysetting1 = section.Settings["mysetting1"].Value;
            string mysetting2 = section.Settings["mysetting2"].Value;
    }
}
March 13th, 2010 — James

I don’t know where you will use it but here is a code that can convert an integer to say for example, HEX string. I needed a base 32 string converter and wrote this one up. This one is about 4 years old.

public class BaseXString
{
	private int maxStringLength = 16;
	private readonly string BaseCharacters;
	private readonly int BaseCharactersLength;

	public BaseXString(string baseCharacters) {
		// Example of a baseCharacter "0123456789ABCDEF" for HEX.
		this.BaseCharacters = baseCharacters;
		this.BaseCharactersLength = baseCharacters.Length;
	}

	public int MaxStringLength { get { return maxStringLength; } set { maxStringLength=value; } }

	public string ConvertToBaseXString(long NumericValue, int totalWidth, char paddingChar) {
		return ConvertToBaseXString(NumericValue).PadLeft(totalWidth, paddingChar);
	}

	public string ConvertToBaseXString(long NumericValue) {
		StringBuilder sb = new StringBuilder();
		int ModVal;
		long OriginalValue = NumericValue;
		char BaseXDig;
		while (NumericValue >= this.BaseCharactersLength) {
			ModVal       = (int) (NumericValue % this.BaseCharactersLength);
			NumericValue = NumericValue / this.BaseCharactersLength;
			BaseXDig     = BaseCharacters[ModVal];
			sb.Insert(0, BaseXDig);
		}
		BaseXDig = BaseCharacters[(int)NumericValue];
		sb.Insert(0, BaseXDig);
		if (sb.Length > this.MaxStringLength)
			throw new ApplicationException(string.Format("{0} - {1}: Converted string exceeds maximum allowed length of {2}.", OriginalValue, sb.ToString(), this.MaxStringLength));
		return sb.ToString().Trim();
	}
}

zipped source of basexstring.cs

March 13th, 2010 — James

This is a wrapper I created 8 years ago for FTP from WinInet and thought I will share. It was written for .NET Framework 1.1, so your mileage may vary. If you need real production quality FTP, you should get a third party component. But for playing around and for simple projects, this will do.

public class FTP
{
	private int InternetHandle = 0;
	private int ConnectHandle = 0;
	private int Context;
	private bool mBinary = false;
	private string __lastErrorMsg;
	public string LastErrorMsg { get { return this.__lastErrorMsg; } }

	public enum FTP_TRANSFER_TYPE : int
	{
		FTP_TRANSFER_TYPE_UNKNOWN = 0x00000000,
		FTP_TRANSFER_TYPE_ASCII = 0x00000001,
		FTP_TRANSFER_TYPE_BINARY = 0x00000002
	}

	public bool Binary
	{
		get
		{
			return mBinary;
		}
		set
		{
			mBinary = value;
		}
	}

	private void SetLastErrorMessage(int Error)
	{
		if (Error < 12000)
			this.__lastErrorMsg = this.GetWin32ErrorMessage(Error);
		else
			this.__lastErrorMsg = this.GetWinInetErrorMessage(Error);
	}

	[DllImport("KERNEL32.DLL", EntryPoint="GetModuleHandleW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern int GetModuleHandle(string ModuleName);
	[DllImport("KERNEL32.DLL", EntryPoint="FormatMessageW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern int FormatMessage(int Flags, int Handle, int Error, int Language, [In][Out] StringBuilder Buffer, int BufferSize, ref int ArgList);
	private string GetWin32ErrorMessage(int Error)
	{
		StringBuilder outBuffer = new StringBuilder(1024);
		int Handle = GetModuleHandle("kernel32.dll");
		int ArgList = 0;
		FormatMessage(0x00000800, Handle, Error,0, outBuffer, 1023, ref ArgList);
		return outBuffer.ToString();
	}

	[DllImport("wininet.dll", EntryPoint="InternetGetLastResponseInfoW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool InternetGetLastResponseInfo(out int Error, [In][Out] StringBuilder Buffer, ref int BufferLength);
	private string GetWinInetErrorMessage(int Error)
	{
		StringBuilder outBuffer = new StringBuilder(1024);
		if (Error == 12003)
		{
			int BufferLength = 1023;
			InternetGetLastResponseInfo(out Error, outBuffer, ref BufferLength);
		}
		else
		{
			int Handle = GetModuleHandle("wininet.dll");
			int ArgList = 0;
			FormatMessage(0x00000800, Handle, Error,0, outBuffer, 1023, ref ArgList);
		}
		return outBuffer.ToString();
	}

	[DllImport("wininet.dll", EntryPoint="InternetOpenW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern int InternetOpen(string Agent, int AccessType, string ProxyName, string ProxyBypass, int Flags);
	[DllImport("wininet.dll", EntryPoint="InternetConnectW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern int InternetConnect(int InternetHandle, string ServerName, int ServerPort, string Username, string Password, int Service, int Flags, out int Context);
	public bool Open(string ServerName, string UserName, string Password)
	{
		int Error;
		// InternetOpen: Pass a "1" for the 2nd param to indicate to skip the proxy for
		// host name look ups due to some rare timeouts with the proxy/dns lookups.
		if (0 == (InternetHandle = InternetOpen("MyApp", 1, null, null, 0)))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		if (0 == (ConnectHandle = InternetConnect(InternetHandle, ServerName, 21, UserName, Password, 1, 0, out Context)))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			InternetCloseHandle(InternetHandle);
			InternetHandle = 0;
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpSetCurrentDirectoryW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpSetCurrentDirectory(int ConnectHandle, string NewDirectory);
	public bool SetCurrentDirectory(string NewDirectory)
	{
		if (!FtpSetCurrentDirectory(ConnectHandle, NewDirectory))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpCreateDirectoryW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpCreateDirectory(int ConnectHandle, string NewDirectory);
	public bool CreateDirectory(string NewDirectory)
	{
		if (!FtpCreateDirectory(ConnectHandle, NewDirectory))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpRemoveDirectoryW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpRemoveDirectory(int ConnectHandle, string RemoteDirectory);
	public bool RemoveDirectory(string RemoteDirectory)
	{
		if (!FtpRemoveDirectory(ConnectHandle, RemoteDirectory))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpGetCurrentDirectoryW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpGetCurrentDirectory(int ConnectHandle, [In][Out] StringBuilder CurrentDirectory, ref int LenCurrentDirectory);
	public bool GetCurrentDirectory(out string CurrentDirectory)
	{
		StringBuilder CurrentDir = new StringBuilder(260);
		int LenCurrentDirectory = 260;
		if (!FtpGetCurrentDirectory(ConnectHandle, CurrentDir, ref LenCurrentDirectory))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		CurrentDirectory = CurrentDir.ToString();
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpPutFileW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpPutFile(int ConnectHandle, string LocalFile, string RemoteFile, int Flags, ref int Context);
	public bool PutFile(string LocalFile, string RemoteFile)
	{
		int Flags = (int)(mBinary ? FTP_TRANSFER_TYPE.FTP_TRANSFER_TYPE_BINARY : FTP_TRANSFER_TYPE.FTP_TRANSFER_TYPE_ASCII);
		if (!FtpPutFile(ConnectHandle, LocalFile, RemoteFile, Flags, ref Context))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpGetFileW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpGetFile(int ConnectHandle, string RemoteFile, string LocalFile, bool FailOnExisting, int FlagsAndAttributes, int Flags, ref int Context);
	public bool GetFile(string RemoteFile, string LocalFile, bool FailOnExisting)
	{
		if (!FtpGetFile(ConnectHandle, RemoteFile, LocalFile, FailOnExisting, 0, 0, ref Context))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="FtpDeleteFileW", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool FtpDeleteFile(int ConnectHandle, string FileName);
	public bool DeleteFile(string RemoteFile)
	{
		if (!FtpDeleteFile(ConnectHandle, RemoteFile))
		{
			this.SetLastErrorMessage(Marshal.GetLastWin32Error());
			return false;
		}
		return true;
	}

	[DllImport("wininet.dll", EntryPoint="InternetCloseHandle", CharSet=CharSet.Auto, SetLastError=true)]
	private static extern bool InternetCloseHandle(int Handle);
	public void Close()
	{
		if (0 != InternetHandle)
		{
			InternetCloseHandle(InternetHandle);
			InternetHandle = 0;
		}
		if (0 != ConnectHandle)
		{
			InternetCloseHandle(ConnectHandle);
			ConnectHandle = 0;
		}
	}

	~FTP()
	{
		Close();
	}
}

zipped source ftp.cs

March 6th, 2010 — James

Here is a slightly dark color setting that can be imported to Visual Studio 2010.

Color setting for XML.

Color setting for HTML

Color setting for C#

CSS coloring

Download the slate-v-01 here.

Download the slate-v-011 here.

Here is a completely black one for VS2008.

Updated black setting for VS2008.

Black color settings for VS2010

February 24th, 2010 — James

There seems to be a bug in the way Dns.GetHostEntry is implemented.

Assume that your server is in a Windows domain but the top DNS suffixis different from the domain name. There are many reasons you may want this.

When you call Dns.GetHostEntry with IP address and host name as the input, you get various outputs depending on where you made the call from.

Case 1: You are on a computer that has domain name as the dns suffix. You call Dns.GetHostEntry with the IP address and host name of a computer with different dns suffix than the domain name.

IPAddress input ->hostname.dns.suffix

Hostname input ->hostname.domain.name

Case 2: You are on a computer that has different dns suffix and domain name. You call Dns.GetHostEntry with the IP address and host name of a computer with different dns suffix than the domain name.

IPAddress input ->hostname.dns.suffix

Hostname input ->hostname.dns.suffix

Case 3: You are on a computer that has different dns suffix and domain name. You call Dns.GetHostEntry with the IP address and host name of the local host. You may also use 127.0.0.1 and localhost.

IPAddress input ->hostname.domain.name

Hostname input ->hostname.domain.name

Bottom line: That host name attribute is not reliable. nslookup always returned the hostname.dns.suffix no matter where the call came from or how I specified the input, IP Address or host name.

Here is a comment from MS Support here: “looking up a host name based on IPAddress is not reliable and in Ipv6 it is not supported”.

A discussion at work with DNS guys suggests that this call may be going to AD (Active Directory) for name resolution. In some cases it may be going to AD first. In those cases it may only be going to AD and never to DNS.

Here is the code to test it:

using System;
using System.Net;

namespace DnsQuery
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (1 != args.Length)
                {
                    Console.WriteLine("Usage:");
                    Console.WriteLine("DnsQuery <IP Address>");
                    Console.WriteLine("        OR");
                    Console.WriteLine("DnsQuery <Host Name>");
                    return;
                }
                Console.WriteLine(Dns.GetHostEntry(args[0]).HostName);
            }
            catch (Exception Ex)
            {
                Console.WriteLine(Ex.Message);
            }
        }
    }
}

Please post in comments if you are trying to resolve a specific problem.

September 17th, 2009 — James

There are times when you have a limited space to display something inside a grid or list box but needed to display a large text. Like when the user clicks a button to submit data but forgot to enter some input in a list box column.

Here is how to do it from the data template:

<DataTemplate x:Key=...>
<TextBox Text="{Binding FirstName}".../>
<ToolTipService.ToolTip>
<ToolTip Content="{Binding message, Mode=OneWay}"/>
</ToolTipService.ToolTip>
</TextBox>
</DataTemplate>

Now when the user leaves the first name empty, you can just set the message field in the data source and the item will show tool tip.