tag:blogger.com,1999:blog-58947057159450785562024-03-19T05:16:05.272-05:00Polish Cowboy's Random ThoughtsDarek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.comBlogger32125tag:blogger.com,1999:blog-5894705715945078556.post-40603630027970513222019-06-26T12:40:00.002-05:002019-06-26T12:40:34.888-05:00Don't lose your marbles with Talend<span style="font-family: Arial, Helvetica, sans-serif;">I kind of like Talend. I mean I really want to like it. But the documentation I have found so far is poor and often incomplete. So if you find yourself in a situation like mine, when after installing additional JDKs 11 and 12 your Talend application on macOS stops working, remember this: it is a java app with an ini file. </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Open it up, usually from /Applications/TOSDI-7.1.1/studio/TOS_DI-macosx-cocoa.ini, and add these two lines on top: </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-vm </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/bin </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"> Your entire file might end up looking like this: </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-vm </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/bin </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-vmargs </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-Xms2048m </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-Xmx4096m </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-Xdock:icon=../Resources/talend.icns </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-XstartOnFirstThread </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-Dorg.eclipse.swt.internal.carbon.smallFonts </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-Dosgi.instance.area.default=../../../workspace
-Dfile.encoding=UTF-8 </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-Dosgi.requiredJavaVersion=1.8 </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-XX:+UseG1GC </span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">-XX:+UseStringDeduplication</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Enjoy/</span>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-45553462532813709102018-07-24T06:49:00.004-05:002018-08-13T07:52:19.028-05:00IBM Cognos Analytics Linux services<span style="font-family: "arial" , "helvetica" , sans-serif;">I've been recently asked to deploy IBM Cognos Analytics 11.0.11 on a bunch of Linux servers. To meet the pre-requisites of an installation, you must </span><span style="font-family: "arial" , "helvetica" , sans-serif;">first </span><span style="font-family: "arial" , "helvetica" , sans-serif;">install a number of packages:</span><br />
<br />
<pre>
sudo yum -y install glibc.i686 glibc.x86_64 libstdc++.i686 \
libstdc++.x86_64 nspr.i686 nss.i686 nspr.x86_64 \
nss.x86_64 xorg-x11-xauth xorg-x11-fonts-* \
xorg-x11-font-utils xorg-x11-fonts-Type1 \
xorg-x11-apps libX11 libXmu.i686 motif.i686 \
motif.x86_64 unixODBC.i686 unixODBC.x86_64 \
libcom_err.i686 libcom_err.x86_64
</pre>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Proceed with the installation and configuration as usual. Then create a file called </span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b>cognos</b></span><span style="font-family: "arial" , "helvetica" , sans-serif;"> in the </span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b>/etc/init.d</b></span><span style="font-family: "arial" , "helvetica" , sans-serif;"> directory with this content:</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<pre>
#!/bin/bash
#
# cognos Start/Stop Cognos Analytics
#
# chkconfig: 2345 90 60
# description: Cognos services auto start-stop script.
#
# Save script in: /etc/init.d as "cognos"
# Perform next steps to make it autostart on powerup:
# chmod a+x cognos
# chkconfig --add cognos
# chkconfig cognos on
#
COGNOS_OWNER=cogadmin
RETVAL=0
prog="Cognos Services"
start() {
echo -n $"Starting $prog: "
# Start the Cognos services
runuser -l $COGNOS_OWNER bash -c '/cognos/analytics/bin64/cogconfig.sh -s'
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/cognos
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
# Stop the Cognos services
runuser -l $COGNOS_OWNER bash -c '/cognos/analytics/bin64/cogconfig.sh -stop'
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -r /var/lock/subsys/cognos
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
</pre>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">This will start IBM Cognos Analytics on server restart as well as control it as a service:</span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<pre>sudo service cognos stop</pre></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Enjoy!</span></div>
Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-88397173889146739612016-07-09T08:52:00.002-05:002016-07-09T08:57:23.442-05:00How to work with MEF - RebuttalI have a problem, a real bad gene, which triggers my annoyance, when respectable publication shares really bad code examples. This morning I've read <a href="http://www.infoworld.com/article/3092986/application-development/how-to-work-with-the-managed-extensibility-framework-in-c.html" target="_blank">an article by Joydip Kandal</a>, good guy, generally speaking, even an MVP as I understand. But what he wrote about Managed Extensibility Framework on InfoWorld, especially the examples, induced an urge to respond to a number of inaccuracies.<br />
<h2>
Is MEF an IoC Container?</h2>
<div>
This question has been asked by many, and debated by many more. The best explanation was provided by Glenn Block on Scott Hanselman podcast. <a href="http://www.hanselminutes.com/148/mef-managed-extensibility-framework-with-glenn-block">http://www.hanselminutes.com/148/mef-managed-extensibility-framework-with-glenn-block</a> </div>
<div>
I like this one liner: "it's a compositional engine", which sums it up perfectly. It <b>uses </b>Dependency Injection and Inversion of Control as a <b>mechanism </b>to solve a specific problem of different extensions <b>receiving </b>what they need to <b>compose </b>themselves. Each component has no knowledge nor desire to know where each dependency is provided from. "Don't call us, we will call you."</div>
<h2>
Onto the samples</h2>
<div>
This was the sample I read through. I've added the Program class so I could run some tests.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">using System.ComponentModel.Composition;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">using System.ComponentModel.Composition.Hosting;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">using System.IO;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">using System.Reflection;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">namespace MEF_Rebutal</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> internal class Program</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> private static void Main(string[] args)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> FileLogger fileLogger = MEFContainer.Container.GetExportedValue<FileLogger>();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> DbLogger dbLogger = MEFContainer.Container.GetExportedValue<DbLogger>();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> public interface ILogger</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> string Message { get; set; }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> [Export]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> public class FileLogger : ILogger</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> public string Message { get; set; }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> [Export]</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> public class DbLogger : ILogger</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> public string Message { get; set; }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> public static class MEFContainer</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> private static CompositionContainer compositionContainer;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> public static CompositionContainer Container</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> get</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if (compositionContainer == null)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> var directoryCatalog =</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> new DirectoryCatalog(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Path.GetDirectoryName(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Assembly.GetExecutingAssembly().Location));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> compositionContainer = new CompositionContainer(directoryCatalog);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> return compositionContainer;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
First, this will not even run successfully, because the parts where never properly composed.<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgka1m1R9pO8DULYWg4xs6gqek1KeBlCbXkTN8FcRQFfY0eU3d-c8f7oTLiHlmMteisBSp1K7TP2guWwhvu1bzP9UY-J3JBVJEAiygRNRj0tiKmWWksnZojNnV4P4zsZz5EasXh9n4Ufrg/s1600/Screen+Shot+07-09-16+at+07.34+AM.PNG" imageanchor="1"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgka1m1R9pO8DULYWg4xs6gqek1KeBlCbXkTN8FcRQFfY0eU3d-c8f7oTLiHlmMteisBSp1K7TP2guWwhvu1bzP9UY-J3JBVJEAiygRNRj0tiKmWWksnZojNnV4P4zsZz5EasXh9n4Ufrg/s320/Screen+Shot+07-09-16+at+07.34+AM.PNG" width="320" /></a><br />
<br />
The reason for it is that the default behavior of a DirectoryCatalog, is to search for parts in files with a *.DLL extension. We can fix that by introducing an AssemblyCatalog and an AggregateCatalog.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> public static class MEFContainer</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> private static CompositionContainer compositionContainer;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> public static CompositionContainer Container</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> get</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if (compositionContainer == null)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> var directoryCatalog =</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> new DirectoryCatalog(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Path.GetDirectoryName(</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Assembly.GetExecutingAssembly().Location));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> var assemblyCatalog = new AssemblyCatalog(Assembly.GetEntryAssembly());</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> compositionContainer = new CompositionContainer(new AggregateCatalog(directoryCatalog, assemblyCatalog));</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> return compositionContainer;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<div>
<br /></div>
Now the composition succeeds.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGYYEfnn_Z41mxi3zsFsYCZVlNZIzEOyWSdVs-h2PKPFV_gN08out5mp62jDVZe-AnEk6ztKtkoKCvpqu8fyS2cfn5yaPawD2rCSPH16mkVlRLrmqvW87UrEJummUr7BWZvtO76hH5rb0/s1600/Screen+Shot+07-09-16+at+07.44+AM.PNG" imageanchor="1"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGYYEfnn_Z41mxi3zsFsYCZVlNZIzEOyWSdVs-h2PKPFV_gN08out5mp62jDVZe-AnEk6ztKtkoKCvpqu8fyS2cfn5yaPawD2rCSPH16mkVlRLrmqvW87UrEJummUr7BWZvtO76hH5rb0/s320/Screen+Shot+07-09-16+at+07.44+AM.PNG" width="320" /></a><br />
<br />
However, if I already know the class I am looking for, FileLogger and DbLogger, there is no reason for me to use MEF to find them for me, even if they were in a separate class library, which I would have to reference in my project, to compile my code.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> FileLogger fileLogger = new FileLogger();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> DbLogger dbLogger = new DbLogger();</span></div>
<div>
<br /></div>
<div>
In other words, it is a hard dependency, with an additional overhead of MEF.</div>
<h2>
OK, smarty pants, so how should one use it?</h2>
<div>
Alright, since it is a composition engine, let's skip for now the discussion how the project should be structured, i.e. interfaces in one class library, parts in a few others. The task at hand is to discover all classes which provide an implementation of the ILogger interface. First, we must tell the CompositionContainer to compose its parts.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> private Program()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> MEFContainer.Container.ComposeParts(this);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
</div>
<div>
<br /></div>
<div>
However, at this point nothing will really happen, since there are no imports to fill. So we must tell the composition engine what types of exports are available, and what imports are expected. There are many ways to do it, one of them being, adding the type of the export, to the Export attribute.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> [Export(typeof(ILogger))]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public class FileLogger : ILogger</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public string Message { get; set; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> [Export(typeof(ILogger))]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public class DbLogger : ILogger</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public string Message { get; set; }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
</div>
<div>
<br /></div>
<div>
Now, inside our Program class, we can define an enumerable of objects implementing the ILogger interface.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> internal class Program</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> [ImportMany]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> private IEnumerable<Lazy<ILogger>> loggers;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> private static void Main(string[] args)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> var program = new Program();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Console.WriteLine("There are {0} loggers available", program.loggers.Count());</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> foreach (var logger in program.loggers)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Console.WriteLine(logger.Value.GetType().FullName);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> private Program()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> MEFContainer.Container.ComposeParts(this);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
</div>
<div>
<br /></div>
<div>
Thanks to the MEF composition engine, the list of loggers will be populated with an instance of FileLogger and DbLogger, using <span style="font-family: "courier new" , "courier" , monospace;">Lazy<T></span> generic constructor, which additionally shields us from potential performance hit, during initialization of an object we might not need, i.e. why create a logger if we will not run into a scenario, where we actually need it. </div>
<div>
<br /></div>
<div>
The instance of a Program has no idea where each specific implementation of ILogger came from, nor does it care how it is provided. It simply expects some to become available. Even if there is none, it will still run.</div>
<div>
<br /></div>
<div>
Last but not least, the Message property, should really be a method, with a string message parameter, to be written to the respective backend, being it a file or a database.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public interface ILogger</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> void Message(String message);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> [Export(typeof(ILogger))]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public class FileLogger : ILogger</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public void Message(String message)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> //Write to file</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> [Export(typeof(ILogger))]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public class DbLogger : ILogger</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> public void Message(String message)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> //Write to database</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> }</span></div>
</div>
<div>
<br /></div>
<h2>
What else?</h2>
<div>
There are other ways to use MEF effectively, for example add additional metadata to each part's manifest, and I encourage everyone to review the available documentation from Microsoft (<a href="https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx">https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx</a>). MEF is a great library to assist in creation of loosely coupled systems, which discover its available functionality at runtime. I have used it in the past to a great success, with distributed data processing systems, where each server and instance advertised its available function to the rest of the infrastructure, and all functions and data processors available were kept in a centralized catalog. </div>
Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com1tag:blogger.com,1999:blog-5894705715945078556.post-37627214688489785312015-06-15T13:30:00.000-05:002015-06-15T13:30:12.131-05:00Exceptions, exceptions, everywhereSome developers I recently had the privilege to work with, prefer exception-based programming style for convenience, or for the lack of understanding how dangerous such style is, and how it affects performance. So I have published a short tip/study on the subject on Code Project site.<br />
<br />
<a href="http://www.codeproject.com/Tips/996594/Sometimes-We-Overlook-the-Simplest-Things">http://www.codeproject.com/Tips/996594/Sometimes-We-Overlook-the-Simplest-Things</a>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-65159152835003438132015-05-23T09:58:00.001-05:002015-05-23T11:03:18.318-05:00Can you do the maths puzzle for Vietnamese eight-year-olds that has stumped parents and teachers?<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">The article originally appeared on <a href="http://www.theguardian.com/science/alexs-adventures-in-numberland/2015/may/20/can-you-do-the-maths-puzzle-for-vietnamese-eight-year-olds-that-has-stumped-parents-and-teachers" target="_blank">The Guardian</a></span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXzOgmD4b-b2my6n5Q0Lra9Z7A1emq8guCk4QzJfuzn03ka3i8MoBviy11SvuIizhuYl08WnE3a9M1pDOYbkY83HJX2R5C6aAyP59-8ve2s2Nk9LjJBaCeHcKlGZUFF5s40CNl0ZwH4P0/s1600/f7e7f4a5-b59c-4580-88f4-ddc609584d19-bestSizeAvailable%255B1%255D.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXzOgmD4b-b2my6n5Q0Lra9Z7A1emq8guCk4QzJfuzn03ka3i8MoBviy11SvuIizhuYl08WnE3a9M1pDOYbkY83HJX2R5C6aAyP59-8ve2s2Nk9LjJBaCeHcKlGZUFF5s40CNl0ZwH4P0/s320/f7e7f4a5-b59c-4580-88f4-ddc609584d19-bestSizeAvailable%255B1%255D.png" width="320" /></a></div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Put numbers from 1 to 9 in the empty boxes so the equation makes sense.</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">So being true to the motto of "laziness is the mother of invention", instead of trying to put my wetware to work on solving it mathematically, I have invoked my C# creative subroutines and solved it for all possible scenarios ... Shameful I know. </span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<pre style="background: white;"><span style="font-family: 'Lucida Console'; font-size: 11px;"><span style="color: blue;">decimal</span>[] bag = {1, 2, 3, 4, 5, 6, 7, 8, 9};
<span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>> answers = (<span style="color: blue;">from</span> a <span style="color: blue;">in</span> bag
<span style="color: blue;">from</span> b <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a})
<span style="color: blue;">from</span> c <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b})
<span style="color: blue;">from</span> d <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c})
<span style="color: blue;">from</span> e <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d})
<span style="color: blue;">from</span> f <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e})
<span style="color: blue;">from</span> g <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f})
<span style="color: blue;">from</span> h <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f, g})
<span style="color: blue;">from</span> i <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f, g, h})
<span style="color: blue;">where</span> a + 13*b/c + d + 12*e - f - 11 + g*h/i - 10 == 66
<span style="color: blue;">select</span> <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"</span><span style="color: mediumseagreen;">{0}</span><span style="color: #a31515;">+13*</span><span style="color: mediumseagreen;">{1}</span><span style="color: #a31515;">/</span><span style="color: mediumseagreen;">{2}</span><span style="color: #a31515;">+</span><span style="color: mediumseagreen;">{3}</span><span style="color: #a31515;">+12*</span><span style="color: mediumseagreen;">{4}</span><span style="color: #a31515;">-</span><span style="color: mediumseagreen;">{5}</span><span style="color: #a31515;">-11+</span><span style="color: mediumseagreen;">{6}</span><span style="color: #a31515;">*</span><span style="color: mediumseagreen;">{7}</span><span style="color: #a31515;">/</span><span style="color: mediumseagreen;">{8}</span><span style="color: #a31515;">-10=66"</span>, a, b, c, d, e, f, g, h, i)).ToList();
<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"</span><span style="color: mediumseagreen;">{0}</span><span style="color: #ff007f;">\n</span><span style="color: mediumseagreen;">{1}</span><span style="color: #a31515;"> answers"</span>, <span style="color: blue;">string</span>.Join(<span style="color: #a31515;">"</span><span style="color: #ff007f;">\n</span><span style="color: #a31515;">"</span>, answers), answers.Count);</span><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">
</span></pre>
<div style="background: white;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br />Not to spoil the fun, I can only tell you there are 120 valid answers to this puzzle. </span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Now, if the additional rule was you are only allowed to use integer divisions, than there are only 6 valid answers.</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; font-family: 'Lucida Console'; font-size: 11px;"><span style="color: blue;">decimal</span>[] bag = {1, 2, 3, 4, 5, 6, 7, 8, 9};
<span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>> answers = (<span style="color: blue;">from</span> a <span style="color: blue;">in</span> bag
<span style="color: blue;">from</span> b <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a})
<span style="color: blue;">from</span> c <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b})
<span style="color: blue;">from</span> d <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c})
<span style="color: blue;">from</span> e <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d})
<span style="color: blue;">from</span> f <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e})
<span style="color: blue;">from</span> g <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f})
<span style="color: blue;">from</span> h <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f, g})
<span style="color: blue;">from</span> i <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f, g, h})
<span style="color: blue;">where</span> (a + 13*b/c + d + 12*e - f - 11 + g*h/i - 10 == 66) && (<span style="color: #2b91af;">Math</span>.Round(b/c, 0) == b/c) && (<span style="color: #2b91af;">Math</span>.Round(h/i, 0) == h/i)
<span style="color: blue;">select</span> <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"</span><span style="color: mediumseagreen;">{0}</span><span style="color: #a31515;">+13*</span><span style="color: mediumseagreen;">{1}</span><span style="color: #a31515;">/</span><span style="color: mediumseagreen;">{2}</span><span style="color: #a31515;">+</span><span style="color: mediumseagreen;">{3}</span><span style="color: #a31515;">+12*</span><span style="color: mediumseagreen;">{4}</span><span style="color: #a31515;">-</span><span style="color: mediumseagreen;">{5}</span><span style="color: #a31515;">-11+</span><span style="color: mediumseagreen;">{6}</span><span style="color: #a31515;">*</span><span style="color: mediumseagreen;">{7}</span><span style="color: #a31515;">/</span><span style="color: mediumseagreen;">{8}</span><span style="color: #a31515;">-10=66"</span>, a, b, c, d, e, f, g, h, i)).ToList();
</pre>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<span style="font-family: Courier New, Courier, monospace;">5+13*3/1+7+12*2-6-11+9*8/4-10=66</span><br />
<span style="font-family: Courier New, Courier, monospace;">5+13*9/3+6+12*2-1-11+7*8/4-10=66</span><br />
<span style="font-family: Courier New, Courier, monospace;">6+13*3/1+9+12*2-5-11+7*8/4-10=66</span><br />
<span style="font-family: Courier New, Courier, monospace;">6+13*9/3+5+12*2-1-11+7*8/4-10=66</span><br />
<span style="font-family: Courier New, Courier, monospace;">7+13*3/1+5+12*2-6-11+9*8/4-10=66</span><br />
<span style="font-family: Courier New, Courier, monospace;">9+13*3/1+6+12*2-5-11+7*8/4-10=66</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Parallel optimized version:</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; font-family: 'Lucida Console'; font-size: 11px;"><span style="color: blue;">decimal</span>[] bag = {1, 2, 3, 4, 5, 6, 7, 8, 9};
<span style="color: #2b91af;">List</span><<span style="color: blue;">string</span>> answers = (<span style="color: blue;">from</span> a <span style="color: blue;">in</span> bag.AsParallel()
<span style="color: blue;">from</span> b <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a})
<span style="color: blue;">from</span> c <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b}).Where(w => <span style="color: #2b91af;">Math</span>.Round(b/w, 0) == b/w)
<span style="color: blue;">from</span> d <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c})
<span style="color: blue;">from</span> e <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d})
<span style="color: blue;">from</span> f <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e})
<span style="color: blue;">from</span> g <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f})
<span style="color: blue;">from</span> h <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f, g})
<span style="color: blue;">from</span> i <span style="color: blue;">in</span> bag.Except(<span style="color: blue;">new</span>[] {a, b, c, d, e, f, g, h}).Where(w => <span style="color: #2b91af;">Math</span>.Round(h/w, 0) == h/w)
<span style="color: blue;">where</span> (a + 13*b/c + d + 12*e - f - 11 + g*h/i - 10 == 66)
<span style="color: blue;">select</span> <span style="color: blue;">string</span>.Format(<span style="color: #a31515;">"</span><span style="color: mediumseagreen;">{0}</span><span style="color: #a31515;">+13*</span><span style="color: mediumseagreen;">{1}</span><span style="color: #a31515;">/</span><span style="color: mediumseagreen;">{2}</span><span style="color: #a31515;">+</span><span style="color: mediumseagreen;">{3}</span><span style="color: #a31515;">+12*</span><span style="color: mediumseagreen;">{4}</span><span style="color: #a31515;">-</span><span style="color: mediumseagreen;">{5}</span><span style="color: #a31515;">-11+</span><span style="color: mediumseagreen;">{6}</span><span style="color: #a31515;">*</span><span style="color: mediumseagreen;">{7}</span><span style="color: #a31515;">/</span><span style="color: mediumseagreen;">{8}</span><span style="color: #a31515;">-10=66"</span>, a, b, c, d, e, f, g, h, i)).AsParallel().ToList();
</pre>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></div>
Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com1tag:blogger.com,1999:blog-5894705715945078556.post-70368436706437654622015-04-24T17:08:00.001-05:002015-04-24T17:08:40.477-05:00TEDxAmsterdam - Wubbo Ockels - 11/20/09<iframe allowfullscreen="" frameborder="0" height="270" src="https://www.youtube.com/embed/eaV-GeAPSlE" width="480"></iframe>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-46401877562305561042014-03-26T09:53:00.000-05:002014-03-26T09:53:14.612-05:00Entity Framework ... you've failed meI used to like EF, since the day I started to understand the power of a well designed ORM Framework. It was performing well in 4.1, maybe even 5.x, but 6.x is frankly ... a disaster.<br />
<br />
I started working on a simple WPF app, with MVVMLight Toolkit, and to experiment with various data binding approaches I have decided to give EF 6.1 a shot. Instead, it felt like shooting myself in the foot. Don't get me wrong, I still like the designers and the myriad of possibilities how an ObjectSet can be mapped to a set of tables and views, but I'do expect a decent performance all along. Obviously, it will not be faster than ADO.Net or DAO (yuk!), but it should be close. When my form was loading, I simply asked the provider, on a background thread, to get me the total count of all objects from one set. The query was properly prepared and executed, with just the right amount of SQL needed, but execution times were horrible: over 8 seconds for Code First approach, and over 5 seconds using EF Designer. I've only pulled a subset of tables from the database, to reduce the size of the data layer, so to wait that long for a simple count query to return was quite a shocker. Especially when the same query executed in milliseconds in SSMS and 325ms with micro-ORM Dapper. In addition to that, the Code First approach generated a bunch of SQL statements which failed due to some tables not being present in destination (I did not capture their names, but they looked to me to be code-first-designer related).<br />
<br />
Perhaps I am doing something wrong, perhaps using an incorrect approach. Until you or I mature, my dear EF, we should see other people.<br />
<br />Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com1tag:blogger.com,1999:blog-5894705715945078556.post-16268772790536651292013-11-20T15:29:00.002-06:002013-11-20T15:30:12.448-06:00Bringing back the Programs start-menu in Windows 8<span style="font-family: Trebuchet MS, sans-serif;">For months now, in Windows 8, I missed my old trusty Programs folder, where my Start button used to be. And today, thanks to Toolbars feature, I have it back. Simply:</span><br />
<br />
<ol>
<li><span style="font-family: Trebuchet MS, sans-serif;">Right click on the Toolbar</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Select Toolbars - New toolbar ...</span></li>
<li><span style="font-family: Trebuchet MS, sans-serif;">Than paste "C:\ProgramData\Microsoft\Windows\Start Menu\Programs" into the Folder location</span></li>
</ol>
<div>
<span style="font-family: Trebuchet MS, sans-serif;">Enjoy!</span></div>
Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-72987297996003748172013-06-04T09:55:00.002-05:002013-06-04T10:45:11.492-05:00Parameterized SQL and IN clauseThere are many ways to pass table value parameters to an SQL statement in C#. I did not like any of them, since they were either:<br />
<br />
<ul>
<li>Not secure - by concatenating table values, which exposes your application to SQL injection attacks</li>
<li>Not performing - by utilizing SQL Server pattern matching, i.e. LIKE '%...%'</li>
<li>Cumbersome - by requiring special type to be created on the database server</li>
<li>Quite weird - by creating CSV split function and joining the result to the original query</li>
</ul>
<div>
So I have decided to create my own and share it with the world on the CodeProject site.</div>
<div>
<br /></div>
<div>
<span style="color: #0000ee;"><u>http://www.codeproject.com/Tips/602581/Passing-NULL-and-table-values-to-parametrized-SQL</u></span></div>
Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-81275718089044348262012-11-15T09:37:00.002-06:002012-11-15T09:37:16.299-06:00Using AOP and MemoryCache to improve performanceI've submitted an article to Code Project on a simple use of AOP and MemoryCache from .Net Framework 4.<br />
<a href="http://www.codeproject.com/Articles/493971/Leveraging-MemoryCache-and-AOP-for-expensive-calls">http://www.codeproject.com/Articles/493971/Leveraging-MemoryCache-and-AOP-for-expensive-calls</a>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-29274019350285297042012-10-11T18:34:00.000-05:002012-10-11T18:34:04.311-05:00Impressed (again) with PostSharp Toolkit for Log4NetPart of my job requires me to try different application use and configuration scenarios, in an attempt to identify potential undocumented features, also known as bugs ...<br />
<br />
So today I was configuring a brand new virtual instance of Windows 2008 R2 Server. As I wanted to have it configured as close to production as possible, I refrained from the usual development environment convenience changes, like disabling UAC and running everything as Administrator. I have deployed a sample WCF Service Application which was enhanced by the PostSharp Diagnostics Toolkit for Log4Net. The app was deployed in a directory to which IIS_IUSRS had only read access. Initially I was puzzled as to why my log files are not being generated despite this fine tuned log4net configuration:<br />
<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><log4net></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <appender name="RollingFile" type="log4net.Appender.RollingFileAppender"></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <file value=".\Logs\AuMineSOA.log" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <appendToFile value="true" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <maximumFileSize value="10MB" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <maxSizeRollBackups value="5" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <layout type="log4net.Layout.PatternLayout"></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <conversionPattern value="%date [%thread] %level %logger - %message%newline" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </layout></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </appender></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <appender name="BufferingForwardingAppender" type="log4net.Appender.BufferingForwardingAppender"></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <bufferSize value="10000" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <appender-ref ref="RollingFile" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </appender></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <appender name="MemoryAppender" type="log4net.Appender.MemoryAppender"></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <onlyFixPartialEventData value="true" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </appender></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <root></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <level value="ALL" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <appender-ref ref="BufferingForwardingAppender" /></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </root></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </log4net></span><br />
<div>
<br /></div>
<div>
Than I realized that I've forgot to allow IIS_IUSRS account to write to any directory in my application. The moment I corrected it, the logs started to pour in. And that's what is so darn impressive about P#L4N (my nickname for the toolkit). It did not crash the app, it did not destabilized the webserver, it simply decided to patiently wait until the access issue is resolved. </div>
<div>
<br /></div>
<div>
By the way, I hot the web service with 512 simultaneous threads to discover that the best option for high traffic logger is to buffer incoming messages to memory, and then write them to a log file, with minimal lock. Otherwise, you actually might get a server crash due to a TextWriter cross-process file access issue. </div>
<br />
<br />Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-74101005220906962782012-10-03T14:08:00.003-05:002012-10-03T14:08:57.115-05:00Aspect Oriented ProgrammingThere has been a new video posted on Vimeo, from my friends at <a href="http://www.sharpcrafters.com/" target="_blank">SharpCrafters</a>, titled <a href="http://vimeo.com/50319144" target="_blank">Declutter Your Codebase With Aspect Oriented Programming</a>. Once I've learned about AOP, I instantly became a big fun of it. It is such a time saver. Tracing and error handling, caching, code injection, are just the few things you can do with AOP and PostSharp in particular. I use the PostSharp Diagnostics Toolkit For Log4Net on pretty much every project now.Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-20820416781842083032012-10-02T18:15:00.000-05:002012-10-02T18:24:19.773-05:00If you get stuck during VS 2012 installSave yourself some grief and before you attempt an installation of the long awaited Visual Studio 2012, disable your antivirus software and Windows Update. My installation simply got stuck and required a power off of the PC. Others reported <a href="http://social.msdn.microsoft.com/Forums/nb-NO/vssetup/thread/57e30c3e-edff-464b-9087-a065c92ad112" target="_blank">Catastrophic failure during install of KB2664825</a><br />
<br />
However, after a quick check-disk and a reboot, VS 2012 installer allowed me to simply repair the installation. Other good news is that I can now use the Documentation installer, without having to manually download documentation updates using a custom tool, like I used to with VS 2010. VS 2012 also seems to work with TFS 2010, although it initially did not recognize by bindings.<br />
<br />
For now, I am lost in the interface ... So much have changed ... It might actually be simpler, but will take some time to get used to.Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com3tag:blogger.com,1999:blog-5894705715945078556.post-80020021234105050782012-10-02T08:03:00.001-05:002012-10-02T08:23:37.943-05:00TypeScript - a new twist on JavaScript"TypeScript is a language for application-scale JavaScript development. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript." <a href="http://www.typescriptlang.org/" target="_blank">TypeScript Home</a><br />
Now that's interesting. My main issue with JavaScript was that it required a "compilation" every time a web page was open. Having worked withe the likes of IBM Cognos Report Studio, where the entire UI and functionality was neatly packaged in tidy 1MB+ of JavaScript code, I had to become quite creative in optimizing ways to speed up delivery of content over LAN and WAN links. In addition, the bigger the code, the less powerful desktop, the more time will the user have to spend just waiting for the tool to load.<br />
I am excited, as with Microsoft support this might become a viable alternative.<br />
<br />
Update: the story the genius behind Turbo Pascal, Delphi, C# and now TypeScript ... <a href="http://www.zdnet.com/microsoft-typescript-can-the-father-of-c-save-us-from-the-tyranny-of-javascript-7000005054/?s_cid=e539" target="_blank">Posted on ZDNet</a>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-16453377910034468782011-11-28T15:53:00.000-06:002011-11-28T15:53:31.098-06:00Let's talk about ... The Future ...I have not written a single post for a while, but recently had an interesting discussion with "my better half", on the subject of transportation of the future.<br />
There are but a few people living in the Big Cities of The World, that would disagree that we need a new mode or way of periodically changing our location. While lots are still waiting for the flying car, and others keep saving for a Segway, what we really need is more than evolution. The whole discussion started when I was trying to explain the recent advancements in using graphene for enhancing energy storage. If you haven't heard, just by introducing "not so perfect" graphene meshes into a lithium ion battery, researches were able to increase capacity, extend life and shorten charge cycle, by a factor of 10 in each respective category. Now, this discovery will not only have an impact on our cell phones, tablets and laptops, but it will also enable new breed of explicitly electric cars. The next logical step, will be to combine it with autonomous units, capable of driving effortlessly in most extreme traffic conditions. So 5-10 years from now, after having a "good time with friends" at a local bar, you will pull out your phone, or whatever it will be called then, and hail a cab, personal or shared, that will take you home, allowing you ample time to come up with various explanations for your late home arrival ...<br />
<br />
As I hate patents for most obvious and intuitive ideas, let everyone be warned, that this post constitutes prior art.Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com1tag:blogger.com,1999:blog-5894705715945078556.post-57650113419378453442011-08-15T11:58:00.001-05:002011-08-15T11:59:44.967-05:00ServiceReferences.ClientConfig<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">I hate that file ... Well, until recently ... One of the problems with Silverlight XAP files having the ServiceReferences.ClientConfig file buried inside the archive is that you can't really move it or deploy it from server to server without manually modifying it after each deployment. There are many solutions available on the web, but none of them that I could find, would address another problem of the same Silverlight application being accessed from two different URLs, i.e. internal and external. Well, if you are using ChannelFactory to access your WCF service, the solution is actually quite simple. Just update the endpoint URI at runtime, using information you already have. Here is how:</span><br />
<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="background-color: white; font-family: Consolas; font-size: 13px; white-space: pre;"> <span style="color: blue;">public</span> SomeServiceClient()</span><br />
<pre style="background: white; color: black; font-family: Consolas; font-size: 13;"> {
<span style="color: blue;">string</span> baseUri = <span style="color: #2b91af;">App</span>.Current.Host.Source.ToString();
baseUri = baseUri.Substring(0, baseUri.IndexOf(<span style="color: #a31515;">"/ClientBin"</span>));
<span style="color: blue;">var</span> tempChannel = <span style="color: blue;">new</span> <span style="color: #2b91af;">ChannelFactory</span><<span style="color: #2b91af;">IExcelServiceAsync</span>>(<span style="color: #a31515;">"CustomBinding_ISomeService"</span>);
<span style="color: blue;">string</span> originalUri = tempChannel.Endpoint.Address.Uri.AbsoluteUri;
<span style="color: blue;">string</span> newUri = baseUri + originalUri.Substring(originalUri.IndexOf(<span style="color: #a31515;">"/Services"</span>));
tempChannel.Endpoint.Address = <span style="color: blue;">new</span> <span style="color: #2b91af;">EndpointAddress</span>(newUri);
_channel = tempChannel.CreateChannel();</pre><pre style="background: white; color: black; font-family: Consolas; font-size: 13;"> }
</pre><pre style="background: white; color: black; font-family: Consolas; font-size: 13;"></pre><pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; font-size: 13px;"><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">
</span></pre><pre style="background-attachment: initial; background-clip: initial; background-color: white; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: black; font-size: 13px;"><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">The baseUri refers to the location of the Silverlight's ClientBin folder. The Services folder is where the WCF service originates from. Combining them together and returning a new channel, takes care of local and remote deployment, as well as accessing the same Silverlight application from two separate URLs.</span></pre>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-53705546263346635772011-02-15T13:53:00.002-06:002011-02-15T13:53:48.604-06:00Favorite quote of 02/15The things that will destroy us are: politics without principle; pleasure without conscience; wealth without work; knowledge without character; business without morality; science without humanity; and worship without sacrifice. - Mahatma Mohandas K. Gandhi (1869-1948)Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-29166316631080649992011-01-31T17:16:00.001-06:002011-01-31T17:16:43.158-06:00What the doctor ordered – Rx simplicity<p>For a while I wanted to try the <a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx" target="_blank">.Net Reactive Extensions</a> with <a href="http://www.galasoft.ch/mvvm/getstarted/" target="_blank">MVVMLight</a>, and to say the least, I am glad that I did. One of the challenges I’ve recently ran into, is associated with <a href="http://www.componentart.com/" target="_blank">ComponentArt</a> control, called TimeNavigator. As beautiful and highly functional as it is, for obvious reasons, when selecting a year, a quarter or a month, the SelectedStartTime and SelectedEndTime PropertyChanged events, do fire independently in a very short period of time from each other. In the past, I was able to cancel one of the update events, by using a BackgroundWorker and cancelling the current run, when the last update occurred within the last 100 milliseconds. It was cumbersome and I wasn’t pleased with the code and approach. I had a feeling it could be much simpler and gave Rx a try … Here is what I ended up with:</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2ce87048-aba4-4a43-886d-a0e7d77a79a5" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto"> <ol style="background: #ffffff; margin: 0 0 0 2em; padding: 0 0 0 5px;"> <li><span style="color:#ff0000">Observable</span>.FromEvent<<span style="color:#2b91af">PropertyChangedEventArgs</span>>(<span style="color:#0000ff">this</span>, <span style="color:#a31515">"PropertyChanged"</span>).Where(</li> <li style="background: #f3f3f3"> w1 => w1.<span style="color:#ff0000">EventArgs</span>.PropertyName == SelectedDateTimeRangePropertyName).Throttle(<span style="color:#2b91af">TimeSpan</span>.FromMilliseconds(100)).Subscribe(</li> <li> p1 =></li> <li style="background: #f3f3f3"> {</li> <li> <span style="color:#0000ff">var</span> t1 = p1;</li> <li style="background: #f3f3f3"> <span style="color:#2b91af">Debug</span>.WriteLine(<span style="color:#a31515">">>> {0}"</span>, p1.<span style="color:#ff0000">EventArgs</span>.PropertyName);</li> <li> });</li> </ol> </div> </div> </div> <p>This is just a sample, that does nothing except print a line when you run it in the debugger. The p1 variable in this example has a Sender property, which will contain your ViewModel, so getting the new values should not be a problem. What I like about this approach especially is the Throttle extension, which takes care of cancelling an event in case of frequent updates. But having the ability to use LINQ on event is no small feat either.</p> Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-38775377165093990502011-01-25T11:56:00.001-06:002011-01-25T11:57:36.891-06:00Resetting the T file attributeRecently, I've been approached to help a friend get his Carbonite backup going, for files that have been flagged with the T attribute. He acquired a few images and other documents, and Carbonite would not back them up, since they were downloaded from the internet and emails, and for some reason treated as temporary files. <br />
Since there is no way to set the attribute in Windows Explorer that I know of, I've decided to create a little utility to help him out. You may download the utility from <a href="http://www.bisoftware.com/utils/ResetTatt.exe">here</a> after meeting the prerequisite of having .Net Framework 3.5 installed.<br />
<br />
<i>(Disclaimer: Use this utility at your own risk. Having a backup is always recommended before testing a new utility. While all efforts have been made to ensure that no third party altered the attached code, please test it first with a decent antivirus solution, like <a href="http://www.microsoft.com/security_essentials">Microsoft Security Essentials</a>)</i>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com1tag:blogger.com,1999:blog-5894705715945078556.post-38394111191956743422010-10-20T14:54:00.001-05:002010-10-20T14:57:25.724-05:00Windows Phone 7, MVVM and UI updating<p>At a Windows Phone 7 launch in Chicago this week, I‘ve attempted to rewrite my XML processing application for the new platform, just to find out if there are any performance implications when processing large XML documents. While I was able to confirm that a WP7 device might not be the best choice to process large XML documents with LINQ, and I was faced with an interesting challenge: how does one update the UI thread properly, with MVVM on a Windows Phone 7.</p> <p>When I attempted to process my XML data from the App.Current.RootVisual.Dispatcher.BeginInvoke method, nothing was being updated in the UI, until the entire document was processed. Somehow, the UI was not being notified that my model was updated and none of the XAML bindings were refreshed.</p> <p>Thanks to Matt Hidinger from Triton-Tek, the solution is quite simple: use BackgroundWorker instead and invoke RaisePropertyChanged event on the current dispatcher.</p> <pre class="code"><span style="color: blue">private void </span>MainPage_Loaded(<span style="color: blue">object </span>sender, <span style="color: #2b91af">RoutedEventArgs </span>e)<br />{<br /> <span style="color: blue">if </span>(!<span style="color: #2b91af">App</span>.ViewModel.IsDataLoaded)<br /> {<br /> <span style="color: blue">var </span>bw = <span style="color: blue">new </span><span style="color: #2b91af">BackgroundWorker</span>();<br /> bw.DoWork += <br /> (bws,bwe) => <span style="color: #2b91af">App</span>.ViewModel.LoadData();<br /> bw.RunWorkerAsync();<br /> <br /> }<br />}</pre><br /><br /><br /><p>Then in your model …</p><br /><br /><pre class="code"><span style="color: blue">private string </span>_currentItem = <span style="color: #a31515">"Initial Current Item"</span>;<br /><br /><span style="color: blue">public string </span>CurrentItem<br />{<br /> <span style="color: blue">get </span>{ <span style="color: blue">return </span>_currentItem; }<br /> <span style="color: blue">set<br /> </span>{<br /> _currentItem = <span style="color: blue">value</span>;<br /> <span style="color: #2b91af">Deployment</span>.Current.Dispatcher.BeginInvoke(() => RaisePropertyChanged(<span style="color: #a31515">"CurrentItem"</span>));<br /> }<br />}</pre> Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-44513761960972412442010-08-17T13:52:00.000-05:002010-08-17T16:40:30.196-05:00IIS 7 Dynamic Compression<div>I've recently developed a <b>WCF RIA</b> application for a client, and the client insisted on returning large datasets, well in excess of 10,000 records. I will leave the story of figuring out how to properly specify the MaxItemsInObjectGraph service behavior attribute for some other post, but the other problem I was constantly aware of, was the data size returned from the server. With all filters set to max, the data set was well in excess of 30 megabytes. This might not be a big problem on a local network, but if some of your users are located across the big pond called Atlantic, you might want to compress your data before shipping it over. </div><div>Now, the IIS 7 console only allows you to enable or disable static compression, but it does not let you control which dynamic types are being compressed as well as the level of compression desired for each content type.</div><div>The command you are supposed to use instead is <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">AppCmd.exe</span> located in <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">C:\Windows\System32\inetsrv</span> directory. </div><div>So here are three sample commands that helped me reduce the size of my <b>WCF RIA</b> Domain Service's binary response by 80%. Needless to say I was pleasantly shocked.</div><div><br />
</div><div><i>Enable compression on WebDevel webserver (when you have multiple servers and want to do it specifically for each)</i></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">C:\Windows\System32\inetsrv>Appcmd.exe set config "WebDevel" -section:urlCompression -doStaticCompression:true -doDynamicCompression:true</span></span></div><div><br />
</div><div><i>Add mime-type application/msbin1 to dynamic compression list (service wide)</i></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">C:\Windows\System32\inetsrv>Appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/msbin1',enabled='True']" /commit:apphost</span></span></div><div><br />
</div><div><i>Set compression levels for static and dynamic content (service wide)</i></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: small;">C:\Windows\System32\inetsrv>Appcmd.exe set config -section:httpCompression -[name='gzip'].staticCompressionLevel:9 -[name='gzip'].dynamicCompressionLevel:5</span></span></div><div><br />
Last but not least, here are two articles that you should read on this very subject:<br />
<a href="http://weblogs.asp.net/owscott/archive/2009/02/22/iis-7-compression-good-bad-how-much.aspx">http://weblogs.asp.net/owscott/archive/2009/02/22/iis-7-compression-good-bad-how-much.aspx</a><br />
<a href="http://www.iis.net/ConfigReference/system.webServer/httpCompression/dynamicTypes">http://www.iis.net/ConfigReference/system.webServer/httpCompression/dynamicTypes</a></div><div></div>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-829955971057191612010-03-03T11:45:00.000-06:002010-03-03T11:50:43.211-06:00Gotta love anonymous<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">Many times you might find yourself in need of randomizing sensitive numeric data on the fly, to share it with developers. You probably write something like this:</span></span><br />
<div><br />
</div><div style="font-family: monospace;"><div><span style="color: blue;">var</span> randomBase = <span style="color: blue;">new</span> <span style="color: #2b91af;">Random</span>(<span style="color: #2b91af;">DateTime</span>.Now.Millisecond);</div><div></div></div><div><br />
</div><div><span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Than you have to type this over and over</span></span></div><div><br />
</div><div style="font-family: monospace;"><div>(someSensitiveNumber * (randomBase.NextDouble() * 0.6 + 0.7))</div><div></div></div><div><br />
</div><div><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="font-size: small;">To simplify and make the code mode elegant, you might want to use lambda expressions with Func delegates:</span></span></div><div><br />
</div><div><div style="font-family: monospace;"><div><span style="color: blue;">public</span> <span style="color: blue;">delegate</span> TResult <span style="color: #2b91af;">Func</span><TResult>();</div><div></div><div></div></div></div><div style="font-family: monospace;"><div><span style="color: #2b91af;">Func</span><<span style="color: blue;">double</span>> random = () => randomBase.NextDouble()*0.6+0.7;</div><div></div><div></div><div><span class="Apple-style-span" style="font-family: 'Times New Roman';"><br />
</span><br />
<span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">then you can use it like this:</span></span></div></div><div><br />
</div><div style="font-family: monospace;"><div>someSensitiveNumber * random()</div><div><span class="Apple-style-span" style="font-family: 'Times New Roman';"><br />
</span><br />
<span class="Apple-style-span" style="font-size: small;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Now, isn't it much easier to read?</span></span></div></div>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-30481738537770441732010-01-26T17:23:00.000-06:002010-01-26T17:23:15.569-06:00Apple - Downloads - Mac OS X - Windows<a href="http://www.apple.com/downloads/macosx/apple/windows/">Apple - Downloads - Mac OS X - Windows</a><div><br /></div><div>BootCamp 3.1 is finally out! Still no good control over fans so I can fry an egg on my MacBook Pro.</div>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-82039070319977949812010-01-26T06:36:00.000-06:002010-01-26T06:36:51.942-06:00HP Slate teases us with another video appearance -- Engadget<a href="http://www.engadget.com/2010/01/26/hp-slate-teases-us-with-another-video-appearance/">HP Slate teases us with another video appearance -- Engadget</a><div><br /></div><div>iPad? iSlate? iTablet? Who cares! The <a href="http://www.engadget.com/2010/01/26/hp-slate-teases-us-with-another-video-appearance/">HP Slate</a> has been here for a while ....</div>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0tag:blogger.com,1999:blog-5894705715945078556.post-19168731923336419642009-12-08T08:00:00.000-06:002009-12-08T08:03:15.895-06:00Pivot by Live LabsAs mentioned in the earlier post, I am experimenting with <a href="http://www.getpivot.com/">Pivot</a>, the newest collections visualization tool from Microsoft Labs ... What an awesome tool it is. I still have to figure out the dynamic collections and <a href="http://www.iis.net/expand/SmoothStreaming">smooth streaming</a> (used to broadcast 2008 Olympics on the web), but even with my static collection of over 13,000 static items supported by over a quarter million images, the tool is quite stable and responsive. I can't show you, dear reader, any samples or even screenshots, since the data I am working with is of high commercial value, but once I figure out all the tricks I might take an attempt at some publicly available data. For now, read about it, get your own activation code and happy pivoting!<br />
<br />
I almost forgot, when distributing to remote web servers don't forget to:<br />
<br />
<ul><li>Enable compression</li>
<li>copy not only the output of DZCollection, but also of DZConvert</li>
</ul>Darek Danielewskihttp://www.blogger.com/profile/02229420746524729838noreply@blogger.com0