Subodh Personal and Programming tips(C#)

Thursday, October 19, 2006

HP Printer hack display message

namespace hphack
{
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
public class PrnHack
{
public static int Main(string[] args)
{
if(!ParseArgs(args))
{
return -1;
}

Console.WriteLine("\nHP Display Hack");
Console.WriteLine("Host: {0}", args[0]);
Console.WriteLine("Message: {0}\n", message);

IPEndPoint ipEndPoint;
ipEndPoint = new IPEndPoint( Dns.Resolve(args[0]).AddressList[0], PJL_PORT);

Console.WriteLine("Host is {0}", ipEndPoint.ToString());

Socket socket;
socket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp
);

socket.Connect(ipEndPoint);

byte [] sendData;
string sendString;

sendString = String.Format(
"\x1B%-12345X@PJL RDYMSG DISPLAY = \"{0}\"\r\n\x1B%-12345X\r\n",
message
);
//PJL RDYMSG DISPLAY and not PJLRDYMSG DISPLAY. The latter makes it print the message.

sendData = Encoding.ASCII.GetBytes(sendString);

int result;
result = socket.Send(sendData, sendData.Length, 0);

if(result == 0)
{
Console.WriteLine("Could not send on socket");
}

socket.Close();

Console.WriteLine("Finished\n\n");
return 0;
}



protected static bool ParseArgs(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine(
"HP Display Hack: " +
"hphack printername \"message\" "
);
return false;
}

if(args[1].Length > 16)
{
Console.WriteLine("Message must be <= 16 characters");
return false;
}

if(args[1].CompareTo("random") == 0)
{
message = GetRandomMessage();
}
else
{
message = args[1];
}

return true;
}


public static string GetRandomMessage()
{
string [] Messages = {
"BUZZ OFF",
"TOUCH ME",
"STEP AWAY",
"SET TO STUN",
"SCORE = 3413",
"PAT EATS MICE",
"FEED ME",
"GO AWAY",
"NEED MORE SPACE",
"POUR ME A DRINK",
"IN DISTRESS",
"NICE SHIRT",
"GO AWAY",
"NO PRINT FOR YOU",
"RADIATION LEAK",
"HANDS UP",
"PRESS MY BUTTON",
"TAKE ME HOME",
"LOOKS LIKE RAIN",
"HELLO WORLD",
"NICE HAIR",
"NEED A MINT?",
"BE GENTLE",
"BE KIND",
"INSERT DISK",
"BUY ME LUNCH",
"DONT STOP",
"COME CLOSER",
"TAKE A BREAK",
"INSERT QUARTER",
"BLACK SABBATH"
};


Random r = new Random();
return Messages[r.Next() % Messages.Length];
}

protected const int PJL_PORT = 9100;
protected static string message = "NO MESSAGE";

}
}

Tuesday, May 02, 2006

Add and impersonation in Web.config

configuration
appSettings
add key="DbString" value="integrated security=SSPI;data source=SUBODHP;persist security info=true;initial catalog=Northwind" /
/appSettings


system.web

identity impersonate="true" userName="domian\login" password="pwd" /

Thursday, December 29, 2005

 
 Posted by Picasa

Wednesday, July 13, 2005

Dynamically creating C# and VB code from CodeDOM

using System;
using System.IO;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;

namespace Demo.CodeDOM
{

public class DynamicDOM
{
public DynamicDOM(){}
static void Main(string[] args)
{
CodeCompileUnit compileUnit = new CodeCompileUnit();

CodeNamespace samples = new CodeNamespace("Samples");
samples.Imports.Add( new CodeNamespaceImport("System") );

compileUnit.Namespaces.Add( samples );
CodeTypeDeclaration class1 = new CodeTypeDeclaration("MyClass");
samples.Types.Add(class1);

CodeEntryPointMethod start = new CodeEntryPointMethod();
CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("System.Console"),
"WriteLine", new CodePrimitiveExpression("Hello World! This code is dymnamically created and compiled") );
start.Statements.Add(cs1);

CodeMethodInvokeExpression cs2 = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"),
"ReadLine");
start.Statements.Add(cs2);
class1.Members.Add( start );

Console.WriteLine("Cs File Generated ----- {0}",GenerateCSharpCode(compileUnit));
Console.WriteLine(CompileCSharpCode("HelloWorldcs.cs","HelloWorldcs.exe" ));

Console.WriteLine("VB.Net File Generated ----- {0}",GenerateVBCode(compileUnit));
Console.WriteLine(CompileVBCode("HelloWorldvb.vb","HelloWorldvb.exe" ));
Console.ReadLine();

}
public static String GenerateCSharpCode(CodeCompileUnit compileunit)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeGenerator gen = provider.CreateGenerator();
String sourceFile;
if (provider.FileExtension[0] == '.')
{
sourceFile = "HelloWorldcs" + provider.FileExtension;
}
else
{
sourceFile = "HelloWorldcs." + provider.FileExtension;
}
IndentedTextWriter tw = new IndentedTextWriter( new StreamWriter(sourceFile, false), " ");
gen.GenerateCodeFromCompileUnit(compileunit, tw,new CodeGeneratorOptions());
tw.Close();
return sourceFile;
}
public static bool CompileCSharpCode(String sourceFile, String exeFile)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeCompiler compiler = provider.CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add( "System.dll" );

cp.GenerateExecutable = true;
cp.OutputAssembly = exeFile;
cp.GenerateInMemory = false;
CompilerResults cr = compiler.CompileAssemblyFromFile(cp, sourceFile);
if(cr.Errors.Count > 0)
{
Console.WriteLine("Errors building {0} into {1}",
sourceFile, cr.PathToAssembly);
foreach(CompilerError ce in cr.Errors)
{
Console.WriteLine(" {0}", ce.ToString());
Console.WriteLine();
}
}
else
{
Console.WriteLine("Source {0} built into {1} successfully.",
sourceFile, cr.PathToAssembly);
}
if (cr.Errors.Count > 0)
{
return false;
}
else
{
return true;
}
}
public static String GenerateVBCode(CodeCompileUnit compileunit)
{
VBCodeProvider provider = new VBCodeProvider();
ICodeGenerator gen = provider.CreateGenerator();
String sourceFile;
if (provider.FileExtension[0] == '.')
{
sourceFile = "HelloWorldvb" + provider.FileExtension;
}
else
{
sourceFile = "HelloWorldvb." + provider.FileExtension;
}
IndentedTextWriter tw = new IndentedTextWriter( new StreamWriter(sourceFile, false), " ");
gen.GenerateCodeFromCompileUnit(compileunit, tw,new CodeGeneratorOptions());
tw.Close();
return sourceFile;
}
public static bool CompileVBCode(String sourceFile, String exeFile)
{
VBCodeProvider provider = new VBCodeProvider();
ICodeCompiler compiler = provider.CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add( "System.dll" );

cp.GenerateExecutable = true;
cp.OutputAssembly = exeFile;
cp.GenerateInMemory = false;
CompilerResults cr = compiler.CompileAssemblyFromFile(cp, sourceFile);
if(cr.Errors.Count > 0)
{
Console.WriteLine("Errors building {0} into {1}",
sourceFile, cr.PathToAssembly);
foreach(CompilerError ce in cr.Errors)
{
Console.WriteLine(" {0}", ce.ToString());
Console.WriteLine();
}
}
else
{
Console.WriteLine("Source {0} built into {1} successfully.",
sourceFile, cr.PathToAssembly);
}
if (cr.Errors.Count > 0)
{
return false;
}
else
{
return true;
}
}
}
}

Tuesday, July 12, 2005

System.CodeDom

The System.CodeDom namespace contains classes that can be used to represent the elements and structure of a source code document. The classes in this namespace can be used to model the structure of a source code document that can be output as source code in a supported language using the functionality provided by the System.CodeDom.Compiler namespace.

You just wonder why somebody wants to generate assemblies dynamically at runtime and execute. Take ASP.NET for example, it uses the CodeDOM to create object graphs that it compiles into assemblies that can render HTML pages and controls.

using System;
using System.IO;
using Microsoft.CSharp;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections;

namespace Demo.CodeDOM
{
class ClsMyDOM
{
[STAThread]
static void Main(string[] args)
{
StreamWriter sw = File.CreateText("RunTimeGen.cs");
sw.WriteLine("using System;");
sw.WriteLine("class ClsDynamicGen{");
sw.WriteLine("public static void Main(){");
sw.WriteLine(@"System.Console.WriteLine(""This code is generated Dynamically"");");
sw.WriteLine("Console.ReadLine();");
sw.WriteLine("}}");
sw.Close();

CSharpCodeProvider csCompiler = new CSharpCodeProvider();
ICodeCompiler iCodeCompiler= csCompiler.CreateCompiler();
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.OutputAssembly = "RuntimeGen.exe";
compilerParams.ReferencedAssemblies.Add("System.dll");
compilerParams.GenerateExecutable = true;

CompilerResults compilerResults= iCodeCompiler.CompileAssemblyFromFile(compilerParams,"RunTimeGen.cs");
DisplayCompilerResults(compilerResults);
Console.ReadLine();
}
public static void DisplayCompilerResults(System.CodeDom.Compiler.CompilerResults cr)
{
// If errors occurred during compilation, output the compiler output and errors.
if( cr.Errors.Count > 0 )
{
for( int i=0; i<cr.Output.Count; i++ )
Console.WriteLine( cr.Output[i] );
for( int i=0; i<cr.Errors.Count; i++ )
Console.WriteLine( i.ToString() + ": " + cr.Errors[i].ToString() );

}
else
{
// Display information about the compiler's exit code and the generated assembly.
Console.WriteLine( "Compiler returned with result code: " + cr.NativeCompilerReturnValue.ToString() );
Console.WriteLine( "Generated assembly name: " + cr.CompiledAssembly.FullName );
if( cr.PathToAssembly == null )
Console.WriteLine( "The assembly has been generated in memory." );
else
Console.WriteLine( "Path to assembly: " + cr.PathToAssembly );

// Display temporary files information.
if( !cr.TempFiles.KeepFiles )
Console.WriteLine( "Temporary build files were deleted." );
else
{
Console.WriteLine( "Temporary build files were not deleted." );
// Display a list of the temporary build files
IEnumerator enu = cr.TempFiles.GetEnumerator();
for( int i=0; enu.MoveNext(); i++ )
Console.WriteLine( "TempFile " + i.ToString() + ": " + (string)enu.Current );
}
}
}

}
}

Monday, July 11, 2005

Size of a .NET object

Each instance of a reference type has two fields maintained by the runtime - a method table pointer and a sync block. These are 4 bytes each on a 32-bit system, making a total of 8 bytes per object overhead. Obviously the instance data for the type must be added to this to get the overall size of the object. So, for example, instances of the following class are 12 bytes each: class MyInt
{
...
private int x;
}
However, note that with the current implementation of the CLR there seems to be a minimum object size of 12 bytes, even for classes with no data (e.g. System.Object).
Values types have no equivalent overhead.

Difference between an event and a delegate

An event is just a wrapper for a multicast delegate. Adding a public event to a class is almost the same as adding a public multicast delegate field. In both cases, subscriber objects can register for notifications, and in both cases the publisher object can send notifications to the subscribers. However, a public multicast delegate has the undesirable property that external objects can invoke the delegate, something we'd normally want to restrict to the publisher. Hence events - an event adds public methods to the containing class to add and remove receivers, but does not make the invocation mechanism public.

Calling Win32 API from a .NET program

Use P/Invoke. This uses similar technology to COM Interop, but is used to access static DLL entry points instead of COM objects. Here is an example of C# calling the Win32 MessageBox
function:

using System;
using System.Runtime.InteropServices;
class MainApp
{
[DllImport("user32.dll", EntryPoint="MessageBox", SetLastError=true, CharSet=CharSet.Auto)]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);

public static void Main()
{
MessageBox( 0, "Hello, this is PInvoke in operation!", ".NET", 0 );
}
}

.NET remoting -- Quick Look

.NET remoting involves sending messages along channels. Two of the standard channels are HTTP and TCP. TCP is intended for LANs only - HTTP can be used for LANs or WANs (internet).

Support is provided for multiple message serializarion formats. Examples are SOAP (XML-based) and binary. By default, the HTTP channel uses SOAP (via the .NET runtime Serialization SOAP Formatter), and the TCP channel uses binary (via the .NET runtime Serialization Binary Formatter). But either channel can use either serialization format.

There are a number of styles of remote access:
SingleCall. Each incoming request from a client is serviced by a new object. The object is thrown away when the request has finished.
Singleton. All incoming requests from clients are processed by a single server object.
Client-activated object. This is the old stateful (D)COM model whereby the client receives a reference to the remote object and holds that reference (thus keeping the remote object alive) until it is finished with it.
Distributed garbage collection of objects is managed by a system called 'leased based lifetime'. Each object has a lease time, and when that time expires the object is disconnected from the .NET runtime remoting infrastructure. Objects have a default renew time - the lease is renewed when a successful call is made from the client to the object. The client can also explicitly renew the lease.

COM Callable Wrapper (CCW)

Dll in .Net and callable in vbscript..

1) CCW.cs
using System;
using System.Runtime.InteropServices;
namespace NMyCCW
{
[ClassInterface(ClassInterfaceType.AutoDual)]
public class ClsCOMServer
{
private string m_strName;
public ClsCOMServer(){}
public void SetName(string strName){m_strName = strName;}
public string GetName(){return m_strName ;}
}
}

2) csc /target:library CCW.cs --- Make a dll

3) regasm ccw.dll /tlb:ccwtlb.tlb /codebase --- Create a tlb.

4) use tlb in vbs---

Dim dotNetObj
Set dotNetObj = CreateObject("NMyCCW.ClsCOMServer")
dotNetObj.SetName ("Subodh")
MsgBox "Name is " & dotNetObj.GetName()

run as --- wscript comclient.vbs

Runtime Callable Wrapper (RCW)

This wrapper turns the COM interfaces exposed by the COM component into .NET-compatible interfaces. For oleautomation interfaces, the RCW can be generated automatically from a type library. For non-oleautomation interfaces, it may be necessary to develop a custom RCW which manually maps the types exposed by the COM interface to .NET-compatible types.
1. create an ATL component which implements the following IDL
2. tlbimp cppcomserver.tlb
3.
using System;
using CPPCOMSERVERLib;
public class MainApp
{
static public void Main()
{
CppName cppname = new CppName();
cppname.SetName( "bob" );
Console.WriteLine( "Name is " + cppname.GetName() );
}
}

4. csc /r:cppcomserverlib.dll csharpcomclient.cs

eg of TLB file:
http://www.andymcm.com/dotnetfaq.htm#1.

import "oaidl.idl";
import "ocidl.idl";
[ object, uuid(EA013F93-487A-4403-86EC-FD9FEE5E6206), helpstring("ICppName Interface"), pointer_default(unique), oleautomation ]
interface ICppName : IUnknown { [helpstring("method SetName")] HRESULT SetName([in] BSTR name); [helpstring("method GetName")] HRESULT GetName([out,retval] BSTR *pName ); }; [ uuid(F5E4C61D-D93A-4295-A4B4-2453D4A4484D), version(1.0), helpstring("cppcomserver 1.0 Type Library") ] library CPPCOMSERVERLib { importlib("stdole32.tlb"); importlib("stdole2.tlb"); [ uuid(600CE6D9-5ED7-4B4D-BB49-E8D5D5096F70), helpstring("CppName Class") ] coclass CppName { [default] interface ICppName; }; };

Things that I can't be done in C#

1) Can throw exceptions that are not derived from System.Exception. (in IL its possible)
2) can have non-zero-based arrays, in IL.

ilasm and ildasm

.assembly MyAssembly {}
.class MyApp {
.method static void Main() {
.entrypoint ldstr "Hello, this code is genarated directly from IL..." call void [mscorlib]System.Console::WriteLine(string)
ret
}
}

caspol options

1 ) caspol -lg :- To see the code groups defined on your system
2) caspol -ag 1.3 -site www.mydomain.com FullTrust :- define my own code group
3) caspol -ap samplepermset.xml :-
samplepermset.xml
-
-










-


-


-


-


-


-


-


SamplePermSet
By default this sample permission set is the same as the standard 'Everything' permission set - just edit to suit your needs.

caspol -lg Code Access Security

the code groups defined on your system, run 'caspol -lg' from the command-line

create my own metadata attributes

[AttributeUsage(AttributeTargets.Class)]
public class InspiredByAttribute : System.Attribute
{ public string InspiredBy;
public InspiredByAttribute( string inspiredBy )
{
InspiredBy = inspiredBy;
}
}
[InspiredBy("Andy Mc's brilliant .NET FAQ")]
class CTest { }

class CApp {
public static void Main()
{
object[] atts = typeof(CTest).GetCustomAttributes(true);
foreach( object att in atts )
if( att is InspiredByAttribute )
Console.WriteLine( "Class CTest was inspired by {0}", ((InspiredByAttribute)att).InspiredBy );
}
}

Serialization Issues

1) XmlSerializer is slow --- There is a once-per-process-per-type overhead with XmlSerializer. So the first time you serialize or deserialize an object of a given type in an application, there is a significant delay.

2) XmlSerializer will refuse to serialize instances of any class that implements IDictionary, e.g. Hashtable. SoapFormatter and BinaryFormatter do not have this restriction.

3)
XmlSerializer needs to know in advance what type of objects it will find in an ArrayList. To specify the type, use the XmlArrayItem attibute like this: public class Person
{
public string Name;
public int Age;
}
public class Population
{
[XmlArrayItem(typeof(Person))] public ArrayList People;
}

Else InvalidOperationException is thrown

Should I use XmlSerializer, SoapFormatter or BinaryFormatter?

It depends. XmlSerializer has severe limitations such as the requirement that the target class has a parameterless constructor, and only public read/write properties and fields can be serialized.
However, on the plus side, XmlSerializer has good support for customising the XML document that is produced or consumed. XmlSerializer's features mean that it is most suitable for cross-platform work, or for constructing objects from existing XML documents.

SoapFormatter and BinaryFormatter have fewer limitations than XmlSerializer. They can serialize private fields, for example. However they both require that the target class be marked with the [Serializable] attribute, so like XmlSerializer the class needs to be written with serialization in mind.
Also there are some quirks to watch out for - for example on deserialization the constructor of the new object is not invoked.
The choice between SoapFormatter and BinaryFormatter depends on the application. BinaryFormatter makes sense where both serialization and deserialization will be performed on the .NET platform and where performance is important. SoapFormatter generally makes more sense in all other cases, for ease of debugging if nothing else.

customise the serialization process
XmlSerializer supports a range of attributes that can be used to configure serialization for a particular class. For example, a field or property can be marked with the [XmlIgnore] attribute to exclude it from serialization.
Another example is the [XmlElement] attribute, which can be used to specify the XML element name to be used for a particular property or field.
Serialization via SoapFormatter/BinaryFormatter can also be controlled to some extent by attributes. For example, the [NonSerialized] attribute is the equivalent of XmlSerializer's [XmlIgnore] attribute.
Ultimate control of the serialization process can be acheived by implementing the the ISerializable interface on the class whose instances are to be serialized.

What is the lapsed listener problem?

The lapsed listener problem is one of the primary causes of leaks in .NET applications. It occurs when a subscriber (or 'listener') signs up for a publisher's event, but fails to unsubscribe.
The failure to unsubscribe means that the publisher maintains a reference to the subscriber as long as the publisher is alive.
For some publishers, this may be the duration of the application.

This situation causes two problems. The obvious problem is the leakage of the subscriber object. The other problem is the performance degredation due to the publisher sending redundant notifications to 'zombie' subscribers.

There are at least a couple of solutions to the problem.
The simplest is to make sure the subscriber is unsubscribed from the publisher, typically by adding an Unsubscribe() method to the subscriber. Another solution, documented here by Shawn Van Ness, is to change the publisher to use weak references in its subscriber list.

creating Application Domain

AppDomains are usually created by hosts. Examples of hosts are the Windows Shell, ASP.NET and IE. When you run a .NET application from the command-line, the host is the Shell. The Shell creates a new AppDomain for every application.
AppDomains can also be explicitly created by .NET applications. Here is a C# sample which creates an AppDomain, creates an instance of an object inside it, and then executes one of the object's methods:

using System;
using System.Runtime.Remoting;
using System.Reflection;
public class CAppDomainInfo : MarshalByRefObject
{ public string GetName()
{
return AppDomain.CurrentDomain.FriendlyName;
}
}
public class App
{ public static int Main()
{
AppDomain ad = AppDomain.CreateDomain( "Andy's new domain" );
CAppDomainInfo adInfo = (CAppDomainInfo)ad.CreateInstanceAndUnwrap Assembly.GetCallingAssembly().GetName().Name, "CAppDomainInfo" );
Console.WriteLine( "Created AppDomain name = " + adInfo.GetName() );
return 0;
}
}

Tuesday, July 05, 2005

Interface Rules

1) All method declarations are public within an interface. This is the default access modifier, which means you can omit the modifier in the declaration. As a matter of fact, if you code a modifier like protected, private, or even public, you will get a compiler error.
2)
An interface cannot contain data declarations. However, you can declare properties:int amountOfFood
{
get;
set;
}
3)
An interface can inherit from another interface. You may wish to add more functionality to the interface and keep the original less-specific interface as it is
interface ISnakeFeedable: IFeedable
{
void FeedSnake();
}