Sunday, December 11, 2005

Reading ini-file from C#




Here comes small utility class to read settings from old-fashioned-style .ini files
(general sketch only - it reparses file to read each setting):



using System;
using System.IO;
using System.Text.RegularExpressions;

namespace CommonUtilities
{
/// <summary>
/// Parse settings from ini-like files
/// </summary>
public class IniFile
{
static IniFile()
{
_iniKeyValuePatternRegex = new Regex(
@"((\s)*(?<Key>([^\=^\s^\n]+))[\s^\n]*
# key part (surrounding whitespace stripped)
\=
(\s)*(?<Value>([^\n^\s]+(\n){0,1})))
# value part (surrounding whitespace stripped)
"
,
RegexOptions.IgnorePatternWhitespace |
RegexOptions.Compiled |
RegexOptions.CultureInvariant );
}
static private Regex _iniKeyValuePatternRegex;

public IniFile(string iniFileName)
{
_iniFileName = iniFileName;
}

public string ParseFileReadValue(string key)
{
using( StreamReader reader =
new StreamReader(_iniFileName) )
{
do
{
string line = reader.ReadLine();
Match match =
_iniKeyValuePatternRegex.Match(line);
if( match.Success )
{
string currentKey =
match.Groups["Key"].Value as string;
if( currentKey != null &&
currentKey.Trim().CompareTo(key) == 0 )
{
string value =
match.Groups["Value"].Value as string;
return value;
}
}

}
while(reader.Peek() != -1);
}
return null;
}

public string IniFileName
{
get{ return _iniFileName; }
} private string _iniFileName;
}
}





[Listening to: Sax For Lovers - How Many Dreams]



DropMyRights - running applications with restricted rights from your administrative account




Two useful command line utilities (both with source-code) allowing to run process with restricted rights from administrative account: DropMyRights and it's .NET clone DropMyRights.NET.
Very useful to prevent viruses/spyware in your IE, FireFox, MSN Messenger, Outlook etc while running them from your administrative account. Just run them through shortcuts like:
"D:\Program Files\DropMyRights\DropMyRights.exe" "D:\Program Files\FireFox\firefox.exe" C



Thursday, December 08, 2005

G2G Share - service allowing to use your GMail account for file sharing





G2G Share - service allowing to use your GMail account for file sharing. The general idea is that you open your account data for the service and then people may download files from your GMail account without having your login data.

Two more interesting services allowing to upload files to your GMail as if it was flash-disk:
RoamDrive and GMail Drive .




[Listening to: Manu Chao - Infinita Tristeza]


Regular expression to parse .ini files




Regular expression to fetch <key-value> pairs from the old-fashioned .ini files:

((\s)*(?<Key>([^\=^\s^\n]+))[\s^\n]* # key part (surrounding whitespace stripped)
\=
(\s)*(?<Value>([^\n^\s]+(\n){0,1}))) # value part (surrounding whitespace stripped)

Would fetch patterns in form of:



webProxyPort=8080
   webProxyPort  =   8080 
webProxyPort =
8080

Key and Value appears in form of named captures with whitespaces stripped on both ends.



Monday, September 12, 2005

The PocketMod - free PDA





Cool & free organizer replacement - creates PDA style pages in style of TODO list, Calendar, Shopping List, etc, etc that are printed and then easily folded in a pocket book: The PocketMod .













P.S. - see also DIY Planer



Wednesday, August 31, 2005

Free tools to manage MSDE





Here Microsoft maintains list of non-MS tools used to manage MSDE.
My addition is Aqua Data Studio from aquafold.





Monday, August 29, 2005

Turn your GMail account into a virtual file storage










Here is an interesting utility that I've occasionally found - it enables to use your GMail account as a virtual files drive (it just appears as an additional drive in explorer). You can use your 2Gb mail-account to store files, synchronize between home & work, etc.



Monday, August 22, 2005

How interception affects performance in .NET




Recently I prepared a lecture on AOP & interception in .NET for my collegues.
As part of a lecture I created a small demo to demonstrate how interception could affect
the performance of the intercepted code. My original estimation was to obtain result
similar to one, obtained in that nice article (slowdown upto 300%
with ~~0,022 microsecond per call).
My test shows a quite different numbers - slowdown by 1099 times with timing of
about ~~19 microsecond per call. The only difference is that I created a complete simple
AOP scenario with context attribute, context property and a message sink (all of a no-op style).

Full test code is below ...



using System;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting;
using System.Diagnostics;
using System.Threading;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Services;
using System.Runtime.Remoting.Contexts;

namespace InteropTimingDemo
{
public class NoOpProperty
: IContextProperty
, IContributeServerContextSink
{
internal NoOpProperty(){}

// IContributeServerContextSink members
public IMessageSink GetServerContextSink(IMessageSink next)
{
return new NoOpSink( next);
}

// IContextProperty members
public string Name { get { return "NoOpProperty"; } }
public bool IsNewContextOK(Context ctx)
{
return true;
}
public void Freeze(Context ctx) { }
}

public class NoOpSink : IMessageSink
{
[ ContextStatic ]
readonly IMessageSink _next;

public NoOpSink(IMessageSink next)
{ this._next = next; }

public IMessage SyncProcessMessage(IMessage r)
{
return _next.SyncProcessMessage(r);
}

public IMessageSink NextSink
{
get{return _next;}
}

public IMessageCtrl AsyncProcessMessage(
IMessage msg, IMessageSink replySink)
{
return null;
}
}

// Define our context-attrbute
[ AttributeUsage(AttributeTargets.Class) ]
public class NoOpAttribute : Attribute, IContextAttribute
{
internal NoOpAttribute(){}

// IContextProperty members
public bool IsContextOK(
Context current, IConstructionCallMessage ctor)
{
object property = current.GetProperty("NoOpProperty");
return (property != null);
}

public void GetPropertiesForNewContext(
IConstructionCallMessage ctor )
{
IContextProperty prop = new NoOpProperty();
ctor.ContextProperties.Add(prop);
}
}


interface ITestClassInterface
{
double DoSomething(double paramA, double paramB);
}

[ NoOp ]
public class InterceptedClass
: ContextBoundObject, ITestClassInterface
{
public double DoSomething(double paramA, double paramB)
{
return paramA * paramB;
}
}

public class OrdinaryClass : ITestClassInterface
{
public double DoSomething(double paramA, double paramB)
{
return paramA * paramB;
}
}


class MainClass
{
[STAThread]
static void Main(string[] args)
{
InterceptedClass interceptedObj = new InterceptedClass();
OrdinaryClass ordinaryObj = new OrdinaryClass();

const int numIterations = 100000;

CTimeMeasurement measure1 = new CTimeMeasurement();
measure1.Start();
//int start = Environment.TickCount;
for( int i=0; i<numIterations; i++ )
{
interceptedObj.DoSomething(i,i+1);
}
//int stop = Environment.TickCount;
measure1.Stop();
Console.WriteLine(
"{0} operations with intercepted object took {1}",
numIterations, measure1.Duration()/*, stop-start*/ );

CTimeMeasurement measure2 = new CTimeMeasurement();
measure2.Start();
//double d = 0.0;
for( int j=0; j<numIterations; j++ )
{
/*d += */ordinaryObj.DoSomething(j,j+1);
}
measure2.Stop();
Console.WriteLine(
"{0} operations with simple object took {1}",
numIterations, measure2.Duration() );

Console.WriteLine(
"Interception slows things down {0} times",
measure1.Duration()/measure2.Duration() );
Console.WriteLine(
"It's about {0} microseconds per call",
measure1.Duration()*1000000/numIterations );

Console.ReadLine();
}
}
}




Plugin to publish blog posts at blogspot.com from Word






You can get it here ...
(Seems not to work when Word is defined as your default editor in Outlook.)




Tuesday, July 12, 2005

Blog geo-location updated




Finally I found some time to update the geo-location of my blog at Feedmap.

I took my coordinates initially from Google Maps and was need to make few iterations of updating location and looking at how it's being reflected at Feedmap, since there is some difference between coordinates mapping between those engines.
Here is my example if any blogger nearby is interested:




<meta name="geo.position" content="31.96;34.81" />

<meta name="geo.region" content="IL-M" />

<meta name="geo.placename" content="Rishon LeZiyyon" />







Monday, May 09, 2005

Against software patents




There is an in-process legislation initiative in European parliament to adopt software patents.
In my opinion, if adopted - it could adverse private initiative, freedom and future of open-source software projects.
Here is description of current situation with software patents and petition against it.


Wednesday, May 04, 2005

Closing Internet Explorer window in ASP.NET




Here is how you can close IE window (e.g. upon some button-clicked event):


  Line  1:  Response.Write("<
script language='javascript'>parentwin = window.self;
parentwin.opener = window.self;
parentwin.close(); </script>"
);





Sunday, April 17, 2005

Restraining your stress at work





If your job requires long hours in front of computer, whether you're a hi-tech veteran covered by scars of past industry bubble or a callow novice making your first overwork hours - you've either faced the consequences already or are aware of them (being honest to yourself).
Glasses, stress, wrist pains - those are just harmless door bells ringing in front of invited guests - heart attacks, rheumatism, social and family problems.
While I can't order you a recipe to working day of eight hours (being working for something like eleven last months) - here are two RSI-antidote tips.

  • The first one is my favorite stress-reliever for the few last years - Aire Freshner. It's small tray-icon application that can play sounds giving you an atmosphere of various nature environments.


  • The second one is Workrave - it's must-have organizer/reminder for your stress-recovery activity during the workday.

Both are free (Aire is donationware) and useful like a water in Sahara Dezert…


Wednesday, April 13, 2005

Random link - online workshop/tutorial on ASP.NET






Good online book covering work with ASP.NET:

ASPXtreme ASP.NET Web WorkShop



[Listening to: The Memory Of Trees (Instrumental - Enya - The Memory Of Trees (4:20)]



Monday, April 04, 2005


Regular expression to find potential SEDOL's





(?<Sedol>[B-Db-dF-Hf-hJ-Nj-nP-Tp-tV-Xv-xYyZz\d]{6}\d)



This regular expression accepts SEDOL (Stock Exchange Daily Official List number, a code used by the London Stock Exchange to identify foreign stocks).
To be more exact - it accepts potential SEDOL's, since the last, 7th digit of a sedol is a kind of check-sum digit and this reg-ex doesn't check's its correctness. Also, despite following to the formal SEDOL definition - its first character should be a consonant character - there are actual sedol's with the first character, which is a number (e.g. 0067340 for BAA) and they are accepted by this reg-ex.

[Listening to: Bongo Bong - Manu Chao - Clandestino (2:38)]

Sunday, April 03, 2005

Useful resource for international meetings planning

If you need to setup a meeting for participants in multiple timezones - there is a useful resource at
http://www.timeanddate.com/worldclock/meeting.html . It not only shows time differences between locations and converts local times to UTC but also visually represents daytime time-table, so that you can easily pick-up the most appropriate hour...

Tuesday, March 22, 2005

How to read a file that's in use by another process.


Recently I was needed to read context of some log file that's in use by another process when I trying to read from it.

It seems that there is no way to do it with System.IO.StreamReader. The stuff like:

using( System.IO.StreamReader logReader = new System.IO.StreamReader(logPath) )
{
System.String errorFileContext = updateErrorFileReader.ReadToEnd();
}


will cause System.IO.IOException with Message saying "The process cannot access the file ... because it is being used by another process."
My obvious guess was that System.IO.StreamReader doesn't have a constructor specifying the file sharing mode, so I switched to System.IO.FileStream:


using( System.IO.FileStream logReader = new System.IO.FileStream(
logFilePath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read ) )
{
// In my case it always the case, o/w you can read file line-by-line
const int maxFileSize = 10*1024;
byte[] fileBytes = new byte[maxFileSize];

int amountOfBytes = updateErrorFileReader.Read(fileBytes, 0, maxFileSize);

System.Text.UTF7Encoding utf7 = new System.Text.UTF7Encoding();

System.String errorFileContext = utf7.GetString(fileBytes, 0, amountOfBytes);
}



MSDN documentation states that setting last parameter of System.IO.FileStream constructor to System.IO.FileShare.Read:



"Allows subsequent opening of the file for reading.
If this flag is not specified, any request to open the file
for reading (by this process or another process) will fail
until the file is closed. However, if this flag is specified
additional permissions might still be needed to access the file."




Well, that's was exactly what I was going to do and ... imagine my surprise when I got the same thing again:
System.IO.IOException with "The process cannot access the file ... because it is being used by another process.".

Solution came after playing a bit around. What you need to do - is to put last parameter to
System.IO.FileShare.ReadWrite

It was quite surprising and took me some time to found it, since MSDN says that it "Allows subsequent opening of the file for reading or writing." while I was need reading only. Any way it just works...

Wednesday, March 09, 2005

Notepad++ : cool replacement for windows Notepad

Some time ago I started to use Notepad++ - freeware multi-document WYSIWYG editor with a lot of cool features (reg-ex find & replace, syntax highlighting for recognized languages, etc).
The good thing is that it has built-in files associations manager (Setting->Files Associations Manager), so you don't need to deal with replacement of standard Windows Notepad and associated problems as with Notepad2.

Sunday, March 06, 2005

Agile Project Management tools

Few days ago I was looking for some Agile PM tool to try.
After considering few options I've stopped on
XP StoryStudio . It seems that few other popular choices are TargetProcess and VersionOne .

While installation came smooth and usage is easy - here are few things that could be useful:

  • I succeeded to run it only with SQL running in Mixed Mode rather than Windows Authentication Mode (I'm using Desktop SQL engine).
    To install your SQL in Mixed Mode - use the following command line: setup SAPWD="MyPassword" SECURITYMODE=SQL .
  • If you want to check or change current SQL mode - here is how:
    "How to Determine or Change Your Authentication Mode -
    http://support.microsoft.com/?kbid=322336 "
  • If something gone wrong during the installation (one of post-installation tests failed) or you just want to reinstall it - you'll need manually eliminate XPStoryStudio link from the Default Web Page in IIS and delete C:\Program Files\Microsoft SQL Server\MSSQL\Data\StoryStudio.* files.

Does anyone have any suggestions/using experience regarding a PM tool you use?

Thursday, February 24, 2005

A better way to check whether another instance of your application is already running

Do you needed to restrict your C# Win Forms application to a single instance? - I did.

And what do you do these days when you need to create a piece of code? Right, you're opening Google and typing something like "C# single instance application".

Wow - big bunch of answers right at your service. And all looks pretty similar (how could? :0) ) - thanks to our day’s information plague.

But even if there is too much information – there is never too much knowledge, right?

So, putting aside all mine pathetic – what do we have?

All solutions I've found are offering to check whether a process with the same name already exists:

http://weblogs.asp.net/tgraham/archive/2004/05/28/143907.aspx

http://www.dotnet247.com/247reference/msgs/11/56519.aspx

private static bool ExistsPreviousInstance()
{
System.String myProcessName =
System.Diagnostics.Process.GetCurrentProcess().ProcessName;
return System.Diagnostics.Process.GetProcessesByName( myProcessName ).Length > 1;
}

This worked like a charm on my developer computer, but when we started to test my application on other machines – zbang – on SOME computers System.InvalidOperationException computers was thrown from System.Diagnostics.Process.GetCurrentProcess().

I’ve spent quite a while, trying to understand what makes those few computers so different and finally – the problem is that they have performance counters disabled!
Go to
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfProc\Performance,
change it from 0 to 1 and it works like a charm again.
(Thanks to
http://blogs.pingpoet.com/overflow/archive/2004/07/27/673.aspx ).

But do you really want to deal with registry here? Do you want to deal with adding security permissions to be able to access System.Diagnostics.Process stuff?

If not – plain old named mutex solution seems to be a better way:

private
static bool ExistsPreviousInstance()
{
bool
mutexWasCreated=false;
_existanceCheckMutex = new System.Threading.Mutex( false, "MyFirm.MyApplication", out mutexWasCreated );
return mutexWasCreated==false;
} private static System.Threading.Mutex _existanceCheckMutex;

So easy? Misfortunately - we are not done yet.
What if by occasion you running your application from different user accounts? For example, one - from SYSTEM and the second one - from ADMINISTRATOR? It happens that above simple solution wouldn't work. All because you need to set such security attributes for our named mutex that they would enable to 'query' it from different accounts. In my case - I've run in to that problem, since my application is executed by 3rd party scheduler, which is a system service (SYSTEM), while I want to prevent user from running occasionally it's 2nd instance from, say, ADMINISTRATOR account. If you are not involved in such a weird situation you're done with the above code.

Otherwise - you have two choises:

  1. Check that you getting ApplicationException and the problem is "Access denied":
    exception.Message == "Access is denied.\r\n"
  2. Use the following sniplet, using PINVOKE'd WIN32 API calls (I didn't found any way to do it directly through the .NET 1.1 API. Any one did? Is there any way at all to manipulate ACE's SID's, DACL's in it? Btw, there is an API to set security attributes directly in mutex constructor in WinFX).

{{{To be continued}}}.

Hope it could keep a pellet of Advil Liqui-gel for some one.

My first blog posting ...




Well, friends, I guess my blog-time has come and this is my first blog posting.
Not sure yet how far I will come that way, whether it would be mine permanent host, etc.
For a while I'm going to start with few development issues I want to share.