If you are playing with XML using .NET libraries, then you might be familiar with below mentioned exception:
System.Xml.XPath.XPathException: ‘objOfXmlDocument[@attribute={value containing single-quote}]’ has an invalid token.
If you are looking for a patch for the above mentioned problem, then you are at the right place.
Sample xml text: //test.xml
<?xml version=”1.0″ encoding=”utf-8″ ?>
<
root>
<
emp fname=”Vaibhav” lname=”Gaikwad” />
<
emp fname=”Lavina” lname=”D’cunha” />
</
root>
//code to access the test.xml
class
Program
{
static void Main(string[] args) {
XmlDocument doc = new XmlDocument();
doc.Load(
“test.xml”);
string ln =
“D’cunha”;
// This fails :((  resulting in XPath exception.
XmlNode n = doc.SelectSingleNode(“/root/emp[@lname=’ “+ ln +” ‘]”);
}
}  
So, the issue is due the single-quote inside the XPath expression.
We try to resolve it using the “concat” function of XSL, and this is the helper function:
public static string GetXPathString(string input) {
string[] fragments = input.Split(new char[] { ‘\” });
string result = “”;
result += “concat(””;
for (int i = 0; i < fragments.Length; i++)
{
result += “, ‘” + fragments[i] + “‘”;
if (i < fragments.Length – 1)
{
result += “, \”‘\””;
}
}
result += “)”;
return result;
}
And here is how you modify the above code so as to use our new function:
// remember to remove the single-quotes after = and ]
 
XmlNode n = doc.SelectSingleNode(“/root/emp[@lname=” + GetXPathString(ln) + “]”);
So its all done and the day is saved.

 -Bugs!

Advertisements

Recently I got a comment on my last post that it was throwing up exceptions. I realised the bad things in the code. Here is the revised version of the same

// CLSID_CorRuntimeHost from MSCOREE.DLL

[ Guid(“CB2F6723-AB3A-11D2-9C40-00C04FA30A3E”), ComImport]
class CorRuntimeHost {}

// IID_IcorThreadPool  

[ Guid(“84680D3A-B2C1-46e8-ACC2-DBC0A359159A”),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ICorThreadpool {
// Note that IUnknown Interface members are NOT listed here:
void RegisterWaitForSingleObject();
void UnregisterWait(); 

void QueueUserWorkItem();
void CreateTimer(); 
void ChangeTimer(); 
void DeleteTimer(); 
void BindIoCompletionCallback(); 
void CallOrQueueUserWorkItem();
void SetMaxThreads(uint MaxWorkerThreads, uint MaxIOCompletionThreads);
void GetMaxThreads(out uint MaxWorkerThreads, out uint MaxIOCompletionThreads);
void GetAvailableThreads(out uint AvailableWorkerThreads, out uint AvailableIOCompletionThreads);}

//Here is the sample code for the consumption of these types. CorRuntimeHost runtimeMgr = new CorRuntimeHost();
// QueryInterface for the ICorThreadPool interface
ICorThreadpool coreThreadPool = (ICorThreadpool)runtimeMgr;
uint maxWorkerThreads;
uint maxIOThreads;
coreThreadPool.GetMaxThreads(
out maxWorkerThreads, out maxIOThreads); // this returned me 50, 1000
coreThreadPool.SetMaxThreads(25,1000); //setting max of 25 threads

//end code

This code is tested on .NET 2.0, and if you face any issues for 1.0 or 1.1 please let me know.-Bugs!

.NET ThreadPool has a default maximum number of threads in pool which is 25 as documented. There might be a need to increase it, but there is no proper documented API to achieve this goal. This might be a requirement for many of us.

Here’s what you can do:

The Mscoree.h has the definitions for MAX limit of thread pool, and there are APIs for getting/setting it.

What is Mscoree.dll?
Mscoree.dll is the .NET Runtime Execution Engine.

So how can you change the default size of ThreadPool?
Using the definitions in Mscoree.h we can define a COM interop dll, as mentioned below
using System;
using System.Runtime.InteropServices;
[Guid(“CB2F6723-AB3A-11D2-9C40-00C04FA30A3E”), ComImport]
class CorRuntimeHost {}

[Guid(“84680D3A-B2C1-46e8-ACC2-DBC0A359159A”),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ICorThreadPool
{
void slot0(); // max threadpool settings
void slot1();
void slot2();
void slot3();
void slot4();
void slot5();
void slot6();
void CorSetMaxThreads( uint MaxWorkerThreads, uint MaxIOCompletionThreads );
void CorGetMaxThreads( out uint MaxWorkerThreads, out uint MaxIOCompletionThreads );
void CorGetAvailableThreads( out uint AvailableWorkerThreads, out uint AvailableIOCompletionThreads );
}
// Ok you are done with the COM interop, now build this into a class library (e.g. ThreadPool.dll )

Then you must consume the dll into you application, and using the APIs of this managed dll you can now change the default ThreadPool size. Here how you go about doing it.

uint maxWorkerThreads;
uint availWorkerThreads;
uint maxIOThreads;
uint availIOThreads;

ICorThreadPool iThreadPool ;
iThreadPool = (ICorThreadPool)new CorRuntimeHost();
iThreadPool.CorGetMaxThreads(out maxWorkerThreads, out maxIOThreads);
iThreadPool.CorGetAvailableThreads(out availWorkerThreads, out availIOThreads);
System.Console.Writeline(“Available worker threads : ” + availWorkerThreads);
System.Console.Writeline(“Available IO threads : ” + availIOThreads);
iThreadPool.CorSetMaxThreads(30,availIOThreads); // changing worker threadpool size from 25 to 30

Hmm! so we are done 🙂

-Bugs!

There might be several possible secenarios where you might need to forcefully impersonate a user which is valid on some domain but without using identity impersonation.

Looking back in time of the Win32 apis, here is how it can be achieved:

The Win32 api called as LogonUser(string user, string domain, string password, LogonSessionType type, LogonProvider provider, out IntPtr token) is the question to our answer. This is a exported from advapi32.dll.

//code
using System.Security;
using System.Security.Principal; 

[DllImport(“advapi32.dll”, SetLastError = true)]
static extern bool LogonUser( string user, string domain, string password, LogonSessionType logonType, LogonProvider logonProvider, out IntPtr token);

enum LogonSessionType : uint{Interactive = 2, Network, Batch, Service, NetworkCleartext = 8, NewCredentials}enum LogonProvider : uint{
Default = 0,
// default for platform (use this!)
WinNT35, // sends smoke signals to authority
WinNT40, // uses NTLM
WinNT50 // negotiates Kerb or NTLM
}

public void ImpersonateCurrentRequest(HttpContext ctxt)
{
IntPtr token = IntPtr.Zero;
bool result = LogonUser(“someusername”, “somedomain”, “somepassword”,LogonSessionType.Network,LogonProvider.Default,out token);
if (result)
{
WindowsIdentity iden = new WindowsIdentity(token);
WindowsPrincipal principal = new WindowsPrincipal(iden);
IPrincipal p = (IPrincipal)principal;
ctxt
.User = p;
CloseHandle(token);
}
}

//end code

Note this has to be done before the request is processed, so it better to call this function from a httpmodule:BeginRequest()

-Bugs!

Generally no one notices that the StreamReader in .NET has a problem with ReadLine() function. The function is expected to read a line which has “\r\n” at the end, but it reads up to “\r”.  Carriage returns are are treated as new-line characters in .NET StreamReader.

Here is a possible implemention of good “ReadLine()” function using the StreamReader itself.

public string ReadLine(){

StreamReader sr = new StreamReader(“some_test_file.csv”);

StringBuilder sb = new StringBuilder();char[] ch = new char[1];

int state = -1;//FSM code for parsing the \r\n

while (true){

int i = sr.Read();switch (i){

case 13 :

state = 1;

break;case 10:

if (state == 1){ state = 2; }

else

{ state = 0; }

break;case -1: state = 2;

break;

default:state = 0;

sb.Append((char)i);break;}

if (state == 2) break;}

return sb.ToString();}

In this code the care is taken for taking “\r\n” as new-line and not “\r”.

 -Bugs!

This article discusses how web services are generated on the fly. The code is generated and compiled at runtime. The code file  (i.e. “.cs”), service file (i.e. “.asmx” ) and compiled library (i.e. “.dll”) are generated dynamically.

After this code generation the third party applications can directly add a web-reference to the respective web-service and start using it.

class extenstions
    {
        public const string asmx = “.asmx”;
        public const string cs = “.cs”;
        public const string dll = “.dll”;
    }  #region WebService on Fly
string binPath = @”D:\StudioProjects\wwwroot\bin\”;
string codePath = @”D:\StudioProjects\wwwroot\code\”;
string asmxPath = @”D:\StudioProjects\wwwroot\webservices\”;
string code = “[WebService(Namespace = \”http://tempuri.org/\”)] “ +
              “[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]” +
              “public class dyna : System.Web.Services.WebService “ +
              “{ “ +
              “public dyna () {} “ +
              “[WebMethod]” +
              “public string HelloWorld() { “ +
              “return \”Hello World\”; “ +
              “}” +
              “}”;
string classname = “dyna”;
string[] assemblies = new string[] {
     “System”,“System.Web”,“System.Web.Services”,“System.Web.Services.Protocols”
};
 
//CS file generation
string codeFile =  codePath + classname + extenstions.cs;
StreamWriter writer = new StreamWriter(codeFile ,false);
foreach(string assembly in assemblies)
writer.WriteLine(“using “ + assembly + “;”);
writer.WriteLine();  
writer.Write(code);
 
writer.Close();
// ASMX  file generation
string asmxCode = “<%@ WebService Language=\”C#\” CodeBehind=\”~\\code\\”
+ classname + extenstions.cs +
“\” Class=\”” + classname + “\” %> “;
writer = new StreamWriter(asmxPath + classname + extenstions.asmx,false);
writer.WriteLine(asmxCode);
writer.Close(); 
Microsoft.CSharp.CSharpCodeProvider provider = new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler compiler = provider.CreateCompiler(); 
CompilerParameters param = new CompilerParameters();
param.CompilerOptions = @”/optimize”;
param.GenerateInMemory = false;
param.GenerateExecutable = false;
param.IncludeDebugInformation = false;
param.TreatWarningsAsErrors = false;
param.ReferencedAssemblies.Add(“System.dll”);
param.ReferencedAssemblies.Add(“System.Web.dll”);
param.ReferencedAssemblies.Add(“System.Web.Services.dll”);
param.OutputAssembly = binPath + classname + extenstions.dll;
CompilerResults results = compiler.CompileAssemblyFromFile(param, codeFile);
if (results.Errors.Count > 0)
{
StringBuilder err = new StringBuilder(); 
int i=1;
           
foreach (CompilerError error in results.Errors)
{
err.AppendLine(i + ” : “ + error.ErrorText);
err.AppendLine();
}
 
throw new Exception(err.ToString());
}
#endregion 

Now you can test your web-service directly on the local machine using a url. And the client application can directly include a web-reference to your web-service dll in the “webservices” directory of my application.

Incase you get a error saying “401 Access Denied” then just enable “Anonymous access” & “Intergrated Windows aunthentication” on the “webservices” folder.

 

-Bugs!

Have your ever felt the need to attach a Console window to your winform application?  If this is what you want, here is a article just for you.

I have not come across any possible way to show the Console window for a Windows application. So I tried my way with the help of Win32 API calls. Here is the list of APIs which will be needed:

[DllImport(“kernel32.dll”)]
public static extern Boolean AllocConsole();

[DllImport(“kernel32.dll”)]
public static extern Boolean FreeConsole();

[DllImport(“kernel32.dll”)]
public static extern IntPtr GetStdHandle(int nStdHandle);

[DllImport(“kernel32.dll”)]
public static extern bool SetConsoleTitle(String lpConsoleTitle);

[DllImport(“kernel32.dll”, SetLastError = true)]
public static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, CharacterAttributes wAttributes);

//And here is the enumeration CharacterAttributes

public enum CharacterAttributes
{
FOREGROUND_BLUE = 0x0001,
FOREGROUND_GREEN = 0x0002,
FOREGROUND_RED = 0x0004,
FOREGROUND_INTENSITY = 0x0008,
BACKGROUND_BLUE = 0x0010,
BACKGROUND_GREEN = 0x0020,
BACKGROUND_RED = 0x0040,
BACKGROUND_INTENSITY = 0x0080,
COMMON_LVB_LEADING_BYTE = 0x0100,
COMMON_LVB_TRAILING_BYTE = 0x0200,
COMMON_LVB_GRID_HORIZONTAL = 0x0400,
COMMON_LVB_GRID_LVERTICAL = 0x0800,
COMMON_LVB_GRID_RVERTICAL = 0x1000,
COMMON_LVB_REVERSE_VIDEO = 0x4000,
COMMON_LVB_UNDERSCORE = 0x8000
}

private void Form1_Load(object sender, EventArgs e)
{
    bool flag = AllocConsole();
}

private void Form1_FormClosing(object sender, CancelEventArgs e)

    bool flag = FreeConsole();
}

//Put a button on the form and write the following code in to the Click event handler of the button.

private void button1_Click(object sender, EventArgs e)
{
    IntPtr hStdWin = GetStdHandle(-11);
   SetConsoleTitle(“My Console :)”);
   SetConsoleTextAttribute(hStdWin,CharacterAttributes.FOREGROUND_GREEN);
   Console.WriteLine(“Hi from Window application.”);

}

//code ends here

Check this out, and if this is not you expected, then put your comments.

-Bugs!