tag:blogger.com,1999:blog-186694422024-03-26T17:54:26.149+00:00Shared .NET stuffShare, discuss and improveJacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.comBlogger64125tag:blogger.com,1999:blog-18669442.post-73897573165279439582008-12-11T21:20:00.001+00:002008-12-11T21:20:29.117+00:00ArgumentNullException raised by Profile when deploying a web project<span xmlns=''><p>Your ASP.NET web site works perfectly in your development environment and you build a Visual Studio Web Deployment Project to deploy it in a production environment. You launch the default page and you get:<br /></p><p><span style='color:#c0504d; font-size:14pt'>Value cannot be null.<br/>Parameter name: type <br /></span></p><p>Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. <br /></p><p>Exception Details: System.ArgumentNullException: Value cannot be null.<br/>Parameter name: type<br /></p><p>Source Error: <br /></p><p style='background: #ffffcc'>An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. <br /></p><p>Stack Trace: <br /></p><p style='background: #ffffcc'>[ArgumentNullException: Value cannot be null. Parameter name: type]<br/>System.Activator.CreateInstance(Type type, Boolean nonPublic) +2843963<br/>System.Web.Profile.ProfileBase.CreateMyInstance(String username, Boolean isAuthenticated) +76<br/>System.Web.Profile.ProfileBase.Create(String username, Boolean isAuthenticated) +312<br/>System.Web.HttpContext.get_Profile() +108<br/>Global.Application_AcquireRequestState(Object sender, EventArgs e) +72<br/>System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92<br/>System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64<br /></p><p>The solution to this problem is hidden in the Web Deployment Project property pages. Select the "Output Assemblies" node under "Configuration Properties" and below the "Merge all outputs to a single assembly" option, uncheck "Treat as library component (remove App_code.compiled file)".<br /></p><p><br /> </p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com2tag:blogger.com,1999:blog-18669442.post-4086880292658296912008-11-28T08:56:00.007+00:002009-01-03T08:49:28.603+00:00How to configure a membership provider programmatically<span xmlns=""><p>The following C# sample code demonstrates how to configure a .NET membership provider programmatically. This code requires that you also <a href="http://jlchereau.blogspot.com/2008/11/how-to-create-connection-string.html">configure a connection string</a> named MyDatabase.<br /></p><p><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">NameValueCollection</span> objConfig = <span style="color:blue;">new</span> <span style="color:#2b91af;">NameValueCollection</span>();<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;">objConfig.Add(<span style="color:#a31515;">"connectionStringName"</span>, <span style="color:#a31515;">"MyDatabase"</span><span style="color:#000000;">);</span></span><span style="font-size:85%;color:green;"><br /></span></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"enablePasswordRetrieval"</span>, <span style="color:#a31515;">"false"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"enablePasswordReset"</span>, <span style="color:#a31515;">"true"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"requiresQuestionAndAnswer"</span>, <span style="color:#a31515;">"true"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"applicationName"</span>, <span style="color:#a31515;">"MyApp"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"requiresUniqueEmail"</span>, <span style="color:#a31515;">"true"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"maxInvalidPasswordAttempts"</span>, <span style="color:#a31515;">"5"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"passwordAttemptWindow"</span>, <span style="color:#a31515;">"10"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"commandTimeout"</span>, <span style="color:#a31515;">"30"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"passwordFormat"</span>, <span style="color:#a31515;">"Hashed"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"name"</span>, <span style="color:#a31515;">"AspNetSqlMembershipProvider"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"minRequiredPasswordLength"</span>, <span style="color:#a31515;">"8"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"minRequiredNonalphanumericCharacters"</span>, <span style="color:#a31515;">"2"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objConfig.Add(<span style="color:#a31515;">"passwordStrengthRegularExpression"</span>, <span style="color:#a31515;">"(?=^.{8,25}$)(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{\\":;'?/>.<,])(?!.*\\s).*$"</span>));</span></p><p><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">SqlMembershipProvider</span> objSqlMembershipProvider = <span style="color:blue;">new</span> <span style="color:#2b91af;">SqlMembershipProvider</span>();<br /></span></span><span style="font-family:Courier New;font-size:85%;">objSqlMembershipProvider.Initialize(objConfig[<span style="color:#a31515;">"name"</span>], objConfig);<br /></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">MembershipProviderCollection</span> colMembershipProviders = <span style="color:blue;">new</span> <span style="color:#2b91af;">MembershipProviderCollection</span>();<br /></span></span><span style="font-family:Courier New;font-size:85%;">colMembershipProviders.Add(objSqlMembershipProvider);<br /></span><span style="font-family:Courier New;font-size:85%;">colMembershipProviders.SetReadOnly();</span></p><p><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">BindingFlags</span> enuBindingFlags = <span style="color:#2b91af;">BindingFlags</span>.NonPublic | <span style="color:#2b91af;">BindingFlags</span>.Static;<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">Type</span> objMembershipType = <span style="color:blue;">typeof</span>(<span style="color:#2b91af;">Membership</span>);<br /></span></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_Initialized"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, <span style="color:blue;">true</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_InitializeException"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, <span style="color:blue;">null</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_HashAlgorithmType"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, <span style="color:#a31515;">"SHA1"</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_HashAlgorithmFromConfig"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, <span style="color:blue;">false</span>);<br /></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_UserIsOnlineTimeWindow"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, 15);<br /></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_Provider"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, objSqlMembershipProvider);<br /></span><span style="font-family:Courier New;font-size:85%;">objMembershipType.GetField(<span style="color:#a31515;">"s_Providers"</span>, enuBindingFlags).SetValue(<span style="color:blue;">null</span>, colMembershipProviders);</span></p><p>This code assumes you have the following statements in your cs file: </p><p><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:blue;">using</span> System.Web.Security;</span><span style="font-size:85%;color:green;"><br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:blue;">using</span> System.Collections.Specialized;</span><span style="font-size:85%;color:green;"><br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:blue;">using</span> System.Reflection;</span></span></p><p>Then you can use Membership functions like Membership.ValidateUser, Membership.GetUser and Membership.CreateUser.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com10tag:blogger.com,1999:blog-18669442.post-41614705445560365272008-11-17T08:17:00.004+00:002008-11-28T09:07:03.283+00:00How to create a connection string programmatically<span xmlns=""><p>The code snippet for creating a connection string programmatically in .NET C# follows:</p><p><span style="font-family:Courier New;font-size:85%;color:green;">/*<br /></span><span style="font-family:Courier New;font-size:85%;color:green;">// Opening the configuration file for a DLL, i.e. %ProgramFiles%\Memba\Velodoc\Management Console\Memba.Console.dll.config<br /></span><span style="font-family:Courier New;font-size:85%;color:green;">ExeConfigurationFileMap objExeConfigurationFileMap = new ExeConfigurationFileMap();<br /></span><span style="font-family:Courier New;font-size:85%;color:green;">objExeConfigurationFileMap.ExeConfigFilename = System.Reflection.Assembly.GetExecutingAssembly().Location + ".config";<br /></span><span style="font-family:Courier New;font-size:85%;color:green;">Configuration objExeConfiguration = ConfigurationManager.OpenMappedExeConfiguration(objExeConfigurationFileMap, ConfigurationUserLevel.None);<br /></span><span style="font-family:Courier New;font-size:85%;color:green;">*/</span></p><p><span style="font-family:Courier New;font-size:85%;color:green;">// Opening the configuration file for an executable, i.e. C:\Windows\System32\mmc.config<br /></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">Configuration</span> objExeConfiguration = <span style="color:#2b91af;">ConfigurationManager</span>.OpenExeConfiguration(<span style="color:#2b91af;">ConfigurationUserLevel</span>.None);</span></span></p><p><span style="font-family:Courier New;font-size:85%;color:green;">// Creating a connection string element from the connection string in web.config<br /></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">ConnectionStringSettings</span> objConnectionStringSettings = <span style="color:blue;">new</span><br /><span style="color:#2b91af;">ConnectionStringSettings</span>(</span></span><span style="font-family:Courier New;"><br /><span style="font-size:85%;"><span style="color:#a31515;">"MyDatabase"</span>,</span></span><span style="font-family:Courier New;"><br /><span style="font-size:85%;"><span style="color:#a31515;">"Data Source=.;Initial Catalog=MyDatabase;Integrated Security=True;Connect Timeout=30"</span>,<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;color:#a31515;">"System.Data.SqlClient"</span><span style="font-size:85%;color:green;"><br /></span></span><span style="font-family:Courier New;font-size:85%;">);<br /></span></p><p><span style="font-family:Courier New;font-size:85%;color:green;">// Get the connection strings section<br /></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">ConnectionStringsSection</span> objConnectionStringsSection = objExeConfiguration.ConnectionStrings;</span></span></p><p><span style="font-family:Courier New;font-size:85%;color:green;">// Add the new element<br /></span><span style="font-family:Courier New;font-size:85%;">objConnectionStringsSection.ConnectionStrings.Clear();<br /></span><span style="font-family:Courier New;font-size:85%;">objConnectionStringsSection.ConnectionStrings.Add(objConnectionStringSettings);<br /></span></p><p><span style="font-family:Courier New;font-size:85%;color:green;">// Save the configuration file<br /></span><span style="font-family:Courier New;font-size:85%;">objExeConfiguration.Save(<span style="color:#2b91af;">ConfigurationSaveMode</span>.Modified);</span></p><p><span style="font-family:Courier New;font-size:85%;color:green;">// Refresh and check<br /></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">ConfigurationManager</span>.RefreshSection(objConnectionStringsSection.SectionInformation.Name); </span><span style="font-size:85%;color:green;">// IMPORTANT!<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">Debug</span>.Assert(<span style="color:#2b91af;">ConfigurationManager</span>.ConnectionStrings.Count == 1);<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">Debug</span>.Assert(<span style="color:#2b91af;">ConfigurationManager</span>.ConnectionStrings[0].Name == objConnectionStringSettings.Name);<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">Debug</span>.Assert(<span style="color:#2b91af;">ConfigurationManager</span>.ConnectionStrings[0].ConnectionString == objConnectionStringSettings.ConnectionString);<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:#2b91af;">Debug</span>.Assert(<span style="color:#2b91af;">ConfigurationManager</span>.ConnectionStrings[0].ProviderName == objConnectionStringSettings.ProviderName);<br /></span></span></p><p><span style="font-size:85%;">Note that this code assumes you have the following statements in your .cs file:</span></p><p><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:blue;">using</span> System.Configuration;<br /></span></span><span style="font-family:Courier New;"><span style="font-size:85%;"><span style="color:blue;">using</span> System.Diagnostics;</span><span style="font-size:85%;color:green;"></p></span></span></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com4tag:blogger.com,1999:blog-18669442.post-6707376561966345132008-11-14T10:24:00.002+00:002008-11-28T09:07:27.443+00:00Sharing data between processes<span xmlns=""><p><a href="http://www.velodoc.com/download">Memba Velodoc Outlook Add-In</a> lets you send large files from Outlook. The first component is a VSTO add-in running in the Outlook process, which provides a user interface like WinZip and WinRar to add large files to a transfer package and hyperlinks in the email body to download these files. The second component is an executable called transfer controller which actually uploads this package to a file transfer server in the background. The transfer controller provides a user interface to monitor the progress of transfers and pause, resume and cancel transfers. A plug-in architecture makes the transfer controller compatible with several file transfer protocols and server platforms including FTP. The VSTO add-in and the transfer controller communicate together via .NET remoting which is the standard inter-process communication (IPC) mechanism in .NET.<br /></p><p>In all builds including and prior to build #081107 of release 1.0, the TCP port opened for .NET remoting on the transfer controller is hard coded. This has proved to be an issue when using windows fast user switching and terminal services sessions because each user needs his/her own instance of the transfer controller to access the user interface and they are all competing to listen on the same port.<br /></p><p>First, ensuring one and only one instance of the transfer controller process per user session is achieved using a local mutex. Note that <a href="http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx">using a global mutex is a well-known design pattern to ensure one instance of a process per machine</a>.<br /></p><p>Second, we needed a way to configure .NET remoting in the transfer controller to listen on the first available port and notify the VSTO add-in to communicate on the same port. Actually the problem is even more complicated as we cannot tell which between the VSTO add-in and the transfer controller is started first because normally the VSTO add-in starts the transfer controller, but then Outlook might be closed and re-opened while the transfer controller is already loaded. Accordingly, we needed a way to scan for an available TCP port, cache it and share it between processes. We could have used the current user registry, but since the user registry is persistent there is a risk to lock the processes into a port which is no more available. So we needed to ensure that even in the case of a crash the port used would not persist once the add-in processes had exited. We have opted for shared memory.<br /></p><p>In Windows, <a href="http://msdn.microsoft.com/en-us/library/ms810613.aspx">shared memory is a special case of memory mapped files</a>, where the file mapping object accesses memory backed by the system paging file. However, the lifetime of this memory ends when the last process connected to the shared memory object closes connection or the application exits, so there is no data persistence. If an application creates shared memory, fills it with data and exits, the data is lost and this is exactly what we need.<br /></p><p>Memory mapped files are implemented using the following Win32 kernel APIs: <a href="http://www.pinvoke.net/default.aspx/kernel32/CreateFileMapping.html">CreateFileMapping</a>, <a href="http://www.pinvoke.net/default.aspx/kernel32/OpenFileMapping.html">OpenFileMapping</a>, <a href="http://www.pinvoke.net/default.aspx/kernel32/MapViewOfFile.html">MapViewOfFile</a>, <a href="http://www.pinvoke.net/default.aspx/kernel32/MapViewOfFileEx.html">MapViewOfFileEx</a>, <a href="http://www.pinvoke.net/default.aspx/kernel32/UnmapViewOfFile.html">UnmapViewOfFile</a>, <a href="http://www.pinvoke.net/default.aspx/kernel32/FlushViewOfFile.html">FlushViewOfFile</a> and <a href="http://www.pinvoke.net/default.aspx/kernel32/CloseHandle.html">CloseHandle</a>. Note that the naming convention used in <a href="http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx">CreateFileMapping</a> and <a href="http://msdn.microsoft.com/en-us/library/aa366791(VS.85).aspx">OpenFileMapping</a> follows the convention of mutexes where a name prefixed with Global\ creates the object in the global address space (machine) and a name prefixed with Local\ or not prefixed at all creates the object in the local address space (user session).<br /></p><p>This will feature in the next build of the <a href="http://www.codeplex.com/velodocaddin">Memba Velodoc Outlook Add-In</a> due by the end of the year. In the meantime we provide here a <a href="http://www.memba.com/download/081114.blog.zip">prototype in the form of a Visual Studio 2008 console application project</a>. The first instance of the console application which you may launch should scan for an available TCP port, store it in shared memory and display it. All other instances should find that port in shared memory and display it. As a consequence, all instances of the console application should display the same shared TCP port. </p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-54472205793707103302008-11-10T10:14:00.002+00:002008-11-28T09:06:22.845+00:00Starting batch files in the current directory<span xmlns=""><p>Our development projects include batch files to build, install and clean the project. Projects are shared with source control and developers and testers have each developed their own directory structures where they store projects on their computer. Accordingly it is important that these batches work whatever their location.<br /></p><p>The magic DOS command which achieves just that is <span style="font-family:Courier New;font-size:10;"><strong>cd /d %~dp0</strong></span><br /></p><p>This command actually changes the current directory to the directory where the batch file is located.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-43357443893610258862008-10-02T11:30:00.002+01:002008-11-28T09:05:44.913+00:00Debugging installer classes<span xmlns=""><p>There are many blog posts which describe clumsy workarounds to debug installer classes but certainly not the best way to achieve it.<br /></p><p>There are two scenarios:<br /></p><ol style="MARGIN-LEFT: 38pt"><li>You really need to debug your installer class in the msiexec.exe process, and you need to buy some time to be able to attach the Visual Studio debugger to this process (menu Debug -> Attach to Process… in Visual Studio). One way to buy time is to popup a message box to halt the execution of the install method while you are attaching your debugger to the process. For more information, see <a href="http://msdn.microsoft.com/en-us/library/c6wf8e4z.aspx">http://msdn.microsoft.com/en-us/library/c6wf8e4z.aspx</a>.<br /></li><li><div>You can also conveniently run your installer class using the <a href="http://msdn.microsoft.com/en-us/library/50614e95(VS.80).aspx">installer tool</a> (InstallUtil.exe). If this scenario works for your debugging requirements:<br /></div><ol><li>Open the properties of the project containing your installer class (right-click the project in the solution explorer of Visual Studio and select contextual menu option Properties);<br /></li><li>Check the assembly name on the Application tab. In our example, the assembly name is "AssemblyName", and since our project is a class library the assembly is "AssemblyName.dll";<br /></li><li>Go to the Debug tab and in the Start Action, select Start external program and enter "C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe";<br /></li><li>On the same tab, in the start Options, enter the following command line arguments: "AssemblyName.dll /LogToConsole=true" according to point b.<br />Open your installer class in the code editor and at the top of the install method (assuming you are debugging the installation) add:<br /><span style="font-family:Courier New;font-size:10;"><span style="color:olive;">#if</span> DEBUG<br /><span style="color:blue;">if</span> (System.Diagnostics.<span style="color:#2b91af;">Debugger</span>.IsAttached)<br />System.Diagnostics.<span style="color:#2b91af;">Debugger</span>.Break();<br /><span style="color:olive;">#endif</span></span><br /></li><li>Set your project as startup project, press F5 or start debugging in Visual Studio and the debugger will automatically stop on the Debugger.Break() statement. </li></ol></li></ol></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com1tag:blogger.com,1999:blog-18669442.post-58937404704904915782008-07-28T11:56:00.002+01:002008-11-28T09:05:17.978+00:00ASP.NET Debugging Timeout<span xmlns=""><p>When you debug ASP.NET applications in IIS using Debug -> Attach To Process… and you keep the w3wp.exe process hanged on a code line for too long, it is automatically recycled and you lose your debugging session. To avoid that, go to the IIS Management Console, edit the application pool properties and set Ping Enabled = false.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com3tag:blogger.com,1999:blog-18669442.post-46185811279724978972008-07-04T10:59:00.007+01:002008-11-28T09:07:55.950+00:00ASP.NET projects deployed with Web Deployment Project 2005 do not load localized resources<p>Scott Guthrie explains <a href="http://weblogs.asp.net/scottgu/archive/2005/11/06/429723.aspx">how to use VS 2005 Web Deployment Project in his blog</a>. But if you use global resources to localize your ASP.NET application and sign and version your web deployment assembly, these localized resources will not load. If you look at the fusion log, you will find an entry like follows:</p><code>Calling assembly : Memba.WebSite.XP, Version=1.1.0.0, Culture=neutral, PublicKeyToken=a4ae091aa8097a5a.<br />===<br />LOG: This bind starts in default load context.<br />LOG: Using application configuration file: C:\inetpub\wwwroot\VelodocXP\web.config.<br />LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework\v2.0.50727\Aspnet.config.<br />LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.<br />LOG: Post-policy reference: Memba.WebSite.XP.resources, Version=0.0.0.0, Culture=fr, PublicKeyToken=a4ae091aa8097a5a<br />LOG: The same bind was seen before, and was failed with hr = 0x80131040.<br />ERR: Unrecoverable error occurred during pre-download check (hr = 0x80131040).<br /></code><br />The problem comes from the fact that aspnet_merge.exe versions your satellite resource assemblies as "0.0.0.0" whatever the version number you set for your web deployment strong named assembly.<br /><p>I have not found any way to version satellite assemblies according to the main assembly, but the following workaround works:<br /></p><ol><li>Create an AssemblyInfo.cs class file in your App_Code directory;<br /></li><li>Include the typical information including versioning information;</li><li>Add <span style="font-family:Courier New;">[assembly: System.Resources.<span style="COLOR: rgb(43,145,175)">SatelliteContractVersion</span> (<span style="COLOR: rgb(163,21,21)">"0.0.0.0"</span>)]</span><br /></li></ol>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-11453861970840575812008-05-27T17:14:00.004+01:002008-08-26T09:04:47.607+01:00Write about Velodoc, get a free license and a chance to win $100 cash<span xmlns=""><p>To celebrate the new releases of <a href="http://www.velodoc.net/">Velodoc Enterprise Edition</a>, <a href="http://www.codeplex.com/velodocxp">Velodoc XP Edition</a> and <a href="http://www.codeplex.com/velodocaddin">Velodoc Outlook Add-In</a> due in September, we will reward the best articles and blog posts written about Velodoc with a $100 cash payment to a Paypal account. The contest will run for the months of September, October and November 2008 and one article or blog post will be rewarded with the $100 cash prize each month. Better, all participants who have submitted a compliant article or blog post will get a full license serial number of Memba Velodoc Outlook Add-In worth $37 for free.<br /></p><p>How does it work?<br /></p><ol><li><div>Write and publish a new 'How-to' article or blog post comprising (definition of a compliant blog post):<br /></div><ul><li>At least 250 words giving advice, tips or a tutorial on any Velodoc product in any language that we can translate with <a href="http://www.google.com/translate_t">Google translation tools</a>,<br /></li></ul><ul><li>a screenshot of Memba Velodoc,<br /></li></ul><ul><li>3 hyperlinks, respectively to <a href="http://www.velodoc.com/">www.velodoc.com</a>, <a href="http://www.velodoc.net/">www.velodoc.net</a>, and <a href="http://www.memba.com/">www.memba.com</a>.<br /></li></ul></li><li>Submit a comment here with a link to your blog post and how to contact you if you are the winner.<br /></li><li>All participants commit to keep the blog post published for a year. Participation is limited to one original blog post per individual.<br /></li><li>We require at least 5 participating blog posts in a month to allocate the prize. Otherwise these blog posts will compete with the blog posts submitted on the following month. If this occurs in November, the contest will continue until we have 5 participating blog posts, so there should be a winner anyway.<br /></li><li>Participating blog posts will be judged on (1) quality of content and (2) number of referrals sent to our web sites as reported by our traffic analysis tools.<br /></li><li>The winning blog posts will be published here below.<br /></li><li>At the end of the contest, full licenses of Memba Velodoc Outlook Add-In will be made available to all participants who have submitted a compliant blog post.<br /></li><li>For any question, <a href="http://www.velodoc.com/en/contact.htm">use our contact form</a>.<br /></li></ol><p>Note that the process is completely transparent: all participating and winning blog posts will be available here as hyperlinks for anyone to read them.<br /></p><p><strong>September winner:</strong> <to be announced><br /></p><p><strong>October winner:</strong> <to be announced></p><p><span style="font-weight: bold;">November</span><strong> winner:</strong> <to be announced><br /></p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com2tag:blogger.com,1999:blog-18669442.post-27167284998365060792008-05-13T09:36:00.004+01:002008-11-28T09:04:34.497+00:00The Velodoc Outlook Add-In is being releasedWe are currently releasing the Outlook Add-In for Velodoc. We have posted a quick video tour on YouTube. This video demonstrates how to send large files to email contacts using Memba Velodoc Outlook Add-In and various file transfer server platforms including Velodoc servers, FTP servers, UNC File Shares, Microsoft BITS Servers and Amazon S3.<br /><br /><object height="350" width="425"><param name="movie" value="http://www.youtube.com/v/0c-qivirz8Q"><br /> <embed src="http://www.youtube.com/v/0c-qivirz8Q" type="application/x-shockwave-flash" width="425" height="350"></embed> </object><br /><br />You can also find the <a href="http://silverlight.services.live.com/invoke/66737/VelodocAddIn/iframe.html">high-definition version of the video tour on Silverlight Streaming Services</a>.<br /><br />Memba Velodoc Outlook Add-In is open-source and you can download the code from:<br /><ul><li><a href="http://www.codeplex.com/velodocaddin">Codeplex</a></li><li><a href="http://code.google.com/p/velodocaddin/">Google code</a></li><li><a href="http://sourceforge.net/projects/velodocaddin">Sourceforge.net</a></li></ul>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-34122804718472317912008-04-21T14:10:00.002+01:002008-05-13T09:35:45.492+01:00Error 1316 when installing Office 2007 PIA’s<span xmlns=""><p>If you build a setup for an Office 2007 VSTO add-in following the steps described in <a href="http://msdn2.microsoft.com/en-us/library/bb332051.aspx">Deploying Visual Studio 2005 Tools for Office Second Edition Solutions Using Windows Installer</a>, your setup may report that the installation of the Office 2007 PIA's have failed. Looking at the log or installing o2007PIA.msi separately, you will get "Error 1316. Setup cannot read from file <tempdir>\PIARedist.msi. Check your connection to the network, or CD-ROM drive. For other potential solutions to this problem, see SETUP.CHM".<br /></p><p>This occurs on fresh installs of Office 2007 with Microsoft Business Contact Manager and more generally, it seems to occur on any computer which has the Office 2007 PIA's installed using another installer than <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=59daebaa-bed4-4282-a28c-b864d8bfa513&displaylang=en">o2007pia.msi</a>, which is the one Microsoft recommends using.<br /></p><p>There seems to be a workaround which is to rename o2007pia.msi into PIARedist.msi both in the file system where bootstrapper packages are stored and in the product.xml file as shown below:<br /></p><p><span style="font-family:Courier New;"><PackageFiles><br /></span><span style="font-family:Courier New;"><PackageFile Name="PIARedist.msi"/><br /></span><span style="font-family:Courier New;"><PackageFile Name="ComponentCheck.exe"/><br /></span><span style="font-family:Courier New;"></PackageFiles><br /></span></p><p><span style="font-family:Courier New;">...<br /></span></p><p><span style="font-family:Courier New;"><Command PackageFile="PIARedist.msi"<br /> </span><span style="font-family:Courier New;">Arguments=""<br /> </span><span style="font-family:Courier New;">EstimatedInstalledBytes="30000000"<br /> </span><span style="font-family:Courier New;">EstimatedInstallSeconds="60"><br /></span><br />You will need to rebuild your setup project. </p><p>Please let me know if this workaround does not work for you.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com1tag:blogger.com,1999:blog-18669442.post-17323290985809168422008-03-31T09:01:00.002+01:002008-03-31T11:53:28.959+01:00Validating email notification HTML for Outlook 2007<span xmlns=''><p>Velodoc issues numerous email notifications. The presentation uses the latest CSS tags and sophisticated layered HTML. Everything worked fine in Outlook 2003 which uses Internet Explorer as the HTML rendering engine. Outlook 2007 and its Word 2007 rendering engine broke many little things.<br /></p><p>Although it is definitely a step back in terms of HTML rendering capability for emails, everything is explained in <a href='http://msdn2.microsoft.com/en-us/library/aa338201.aspx'>Word 2007 HTML and CSS Rendering Capabilities in Outlook 2007</a>. The article comes with a very <a href='http://www.microsoft.com/downloads/details.aspx?FamilyId=0B764C08-0F86-431E-8BD5-EF0E9CE26A3A'>handy tool to validate HTML and CSS in your development environment</a>.<br /></p><p>I have not been able to install the tool for Visual Studio 2005 SP1 on Windows Vista Ultimate x64 because I could not instantly find the registry keys described in the setup instructions, but it works perfectly with Dreamweaver 8 provided you replace "Dreamweaver MX 2004" by "Dreamweaver 8" in the default installation path.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-60341224125739805412008-03-31T08:46:00.002+01:002008-03-31T11:54:00.646+01:00FileNotFoundException in Visual Studio Setup Project<span xmlns=''><p>The <a href='http://www.velodoc.com'>Velodoc XP</a> setup project would consistently fail on a specific Windows Server 2003 server of ours but not on other computers of our network. The complete issue is described at <a href='http://www.codeplex.com/VelodocXP/WorkItem/View.aspx?WorkItemId=1005'>http://www.codeplex.com/VelodocXP/WorkItem/View.aspx?WorkItemId=1005</a>. The error message was:<br /></p><p>Exception occurred while initializing the installation: System.IO.FileNotFoundException: Could not load file or assembly 'file:///C:\WINDOWS\system32\and' or one of its dependencies. The system cannot find the file specified.<br /></p><p>Obviously, there is no such "C:\WINDOWS\system32\and" file in our application or on the system. MSI logs and fusion logs would not give any more information.<br /></p><p>We have been puzzled by this issue for quite some time. We have finally removed features from our setup one by one until we have been able to identify that a specific custom action was at the source of the problem.<br /></p><p>In the literature and samples that you will find regarding developing Visual Studio setup projects, custom action data is passed in the form /NAME = VALUE which works fine unless value contains a space.<br /></p><p>The reference documentation at <a href='http://msdn2.microsoft.com/en-us/library/2w2fhwzz.aspx'>http://msdn2.microsoft.com/en-us/library/2w2fhwzz.aspx</a> states that in setup custom actions, data should be passed as:<br /></p><p>/NAME = VALUE if not a directory and value has no space<br/>/NAME = "VALUE" if spaces are expected in a value which is not a directory<br/>/NAME = "VALUE\" if the expected value is a directory<br /></p><p>I wish we had not simply read how-to articles and sample code, but also the reference documentation.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com2tag:blogger.com,1999:blog-18669442.post-47283483845787755202008-03-17T11:30:00.002+00:002008-03-31T11:54:50.853+01:00Installing Visual Studio Extensions for WCF after an upgrade to .NET 3.0 Service Pack 1<span xmlns=''><p>Yesterday, I got stuck installing <a href='http://www.microsoft.com/downloads/details.aspx?FamilyId=F54F5537-CC86-4BF5-AE44-F5A1E805680D&displaylang=en'>Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF), November 2006 CTP</a> after my computer had been upgraded to .NET Framework 3.0 Service Pack 1. The installation fails with a warning that a prerequisite, i.e. Microsoft .NET framework 3.0, is missing.<br /></p><p>A quick search on the Internet gave me the following trick which works:<br /></p><ol><li>Add the following key and value to the registry aimed at luring the installer:<br/>[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{15095BF3-A3D7-4DDF-B193-3A496881E003}]<br/>"DisplayName"="Microsoft .NET Framework 3.0"<br /></li><li>Install vsextwfx.msi.<br /></li><li>Remove the key above.<br /></li></ol><p>Source: <a href='http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2550726&SiteID=1'>http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2550726&SiteID=1</a>.<br/>Thanks Erich.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-87573416415359216002007-12-20T14:51:00.002+00:002008-11-28T09:09:04.463+00:00New series of articles in relation to Velodoc XP Edition<span xmlns=""><p>We have released a series of articles on codeproject.com in relation to Velodoc XP Edition:<br /></p><ol><li><a href="http://www.codeproject.com/KB/ajax/InfoBox.aspx">An information box control to display messages using Ajax</a>,<br /></li><li><a href="http://www.codeproject.com/KB/ajax/progressreport.aspx">Using Ajax to display the progress of an ASP.NET server task</a>,<br /></li><li><a href="http://www.codeproject.com/KB/ajax/ImageList.aspx">An Ajax image list control to manage lists of items displayed with icons</a>,<br /></li><li><a href="http://www.codeproject.com/KB/ajax/MultiUpload.aspx">MultiUpload, a smarter file upload server control using Ajax</a>,<br /></li><li><a href="http://www.codeproject.com/KB/ajax/ProUpload.aspx">Professional file uploads with the MultiUpload and ImageList server controls</a>.<br /></li></ol><p>Enjoy the reading.<br /></p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-69793446676569269712007-11-30T09:35:00.002+00:002008-11-28T09:08:44.207+00:00Velodoc XP Edition released as open-source<span xmlns=""><p>Customers have been asking us about building Velodoc functionality into their own .NET applications. This is now possible with Velodoc XP Edition which has been released as an open-source project and published on:<br /></p><ul style="MARGIN-LEFT: 38pt"><li><a href="http://www.codeplex.com/VelodocXP">http://www.codeplex.com/VelodocXP</a><br /></li><li><a href="http://code.google.com/p/velodocxp">http://code.google.com/p/velodocxp</a><br /></li><li><a href="http://velodocxp.sourceforge.net/">http://velodocxp.sourceforge.net</a><br /></li></ul><p>Velodoc XP Edition includes:<br /></p><ul><li>ASP.NET Ajax server controls, http modules and http handlers which provide file upload and download functionality;<br /></li><li>A sample application for sending and receiving large files;<br /></li><li>A comprehensive documentation kit.<br /></li></ul><p>By releasing the core of the Velodoc platform as an open-source project, we expect to gather more customer intelligence and improve the software, so please provide feedback.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com3tag:blogger.com,1999:blog-18669442.post-32919836843281227632007-10-23T08:10:00.001+01:002007-10-23T08:10:34.185+01:00The Ajax Control Toolkit NoBot control and session state<span xmlns=''><p>You need to prevent hackers using robots to run dictionaries of user names and passwords against your login pages. The most common way to achieve that is the use of Captchas ("Completely Automated Public Turing test to tell Computers and Humans Apart"), which display an image with a code which you need to type in a text box. Captchas are often difficult to read and push away genuine users with disabilities. More elaborated Captchas include sound but they are not mainstream.<br /></p><p>The <a href='http://www.asp.net/AJAX/AjaxControlToolkit/Samples/NoBot/NoBot.aspx'>NoBot control</a> in the Microsoft Ajax Control Toolkit can be used for any type of request and in particular to protect the sign in function of a login page:<br /></p><ol style='margin-left: 38pt'><li>It makes sure too many requests (to sign in) are not issued from the same IP address;<br /></li><li>It provides an automated challenge response mechanism to ensure the request (to sign in) is issued by the (login) page;<br /></li><li>It enforces a delay between the time the (login) page is displayed and the request (to sign in) is issued.<br /></li></ol><p>The benefit of the NoBot control is that this is transparent to the user, contrary to Captchas.<br /></p><p>You implement the NoBot control on your ASP.NET page as follows:<br /></p><p><span style='font-family:Courier New; font-size:10pt'><span style='color:blue'><</span><span style='color:#a31515'>ajaxToolkit</span><span style='color:blue'>:</span><span style='color:#a31515'>NoBot</span><br /> <span style='color:red'>ID</span><span style='color:blue'>="PageNoBot"</span><br /> <span style='color:red'>runat</span><span style='color:blue'>="server"</span><br /> <span style='color:red'>OnGenerateChallengeAndResponse</span><span style='color:blue'>="PageNoBot_GenerateChallengeAndResponse"</span><br /> <span style='color:red'>ResponseMinimumDelaySeconds</span><span style='color:blue'>="3"</span><br /> <span style='color:red'>CutoffMaximumInstances</span><span style='color:blue'>="5"</span><br /> <span style='color:red'>CutoffWindowSeconds</span><span style='color:blue'>="60"</span><br /> <span style='color:blue'>/><br /></span></span></p><p>You implement the OnGenerateChallengeAndResponse event handler in code as follows:<br /></p><p><span style='font-family:Courier New; font-size:10pt'><span style='color:blue'>protected</span><br /> <span style='color:blue'>void</span> PageNoBot_GenerateChallengeAndResponse(<span style='color:blue'>object</span> sender, AjaxControlToolkit.<span style='color:#2b91af'>NoBotEventArgs</span> e)<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'>{<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'><br /> <span style='color:#2b91af'>Random</span> r = <span style='color:blue'>new</span><br /> <span style='color:#2b91af'>Random</span>();<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'><br /> <span style='color:blue'>int</span> iFirst = r.Next(100);<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'><br /> <span style='color:blue'>int</span> iSecond = r.Next(100);<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'> e.ChallengeScript = <span style='color:#2b91af'>String</span>.Format(<span style='color:#a31515'>"eval('{0}+{1}')"</span>, iFirst, iSecond);<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'> e.RequiredResponse = <span style='color:#2b91af'>Convert</span>.ToString(iFirst + iSecond);<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'>}<br /></span></p><p>Then the documentation tells you to implement the click event handler of the sign in button as follows:<br /></p><p><span style='font-family:Courier New; font-size:10pt'><span style='color:blue'>if</span> (!PageNoBot.IsValid()) {<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'><br /> <span style='color:green'>//Display a message that a robot has been detected and the request cannot be processed<br /></span></span></p><p><span style='font-family:Courier New; font-size:10pt'>}<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'><span style='color:blue'>else</span> {<br /></span></p><p><span style='font-family:Courier New; font-size:10pt'><br /> <span style='color:green'>//Process the postback event<br /></span></span></p><p><span style='font-family:Courier New; font-size:10pt'>}<br /></span></p><p>On most sites users are redirected to the login page when sessions time out. Because the NoBot control stores the calculation in session state and session state is reset in this case, the calculation challenge response would fail teh next time the user logs in unless he/she refreshes the page.<br /></p><p>The following solves the problem from the user perspective, but it also opens the door to hackers:<br /></p><p><span style='font-family:Courier New; font-size:10pt'><span style='color:blue'>if</span> ((!Page.Session.IsNewSession) && (!PageNoBot.IsValid()))<br /></span></p><p>Apart from redesigning the NoBot control, not to use session state but to use the context cache instead, I have not found a really good solution to solve this issue.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com5tag:blogger.com,1999:blog-18669442.post-71105977743024996792007-09-12T12:27:00.001+01:002007-09-12T13:50:31.087+01:00Nesting the Ajax Control Toolkit Accordion control and the ASP.NET Repeater control<h4>Requirements</h4><br /><p>Install ASP.NET Ajax extensions 1.0.</p><br /><h4>The ASP.NET page</h4><br /><p>Create an ASP.NET Ajax web site (see ASP.NET Ajax extensions) and reference the Ajax Control Toolkit in your project.</p><br /><p>Add the following statement at the top of your web page:</p><br /><pre><%@ Import Namespace="System.Collections.Generic" %> </pre><br /><p>Then insert the following code between the form tags of your web page.</p><br /><pre><asp:ScriptManager ID="ScriptManager" runat="server" ></asp:ScriptManager><br /><ajaxToolkit:Accordion ID="Accordion1" runat="server" SelectedIndex="0"<br /> FadeTransitions="true" FramesPerSecond="40" TransitionDuration="250"<br /> AutoSize="None" ><br /> <Panes></Panes><br /><br /> <HeaderTemplate><br /><div style="color:white;background-color:blue;cursor:pointer;"><br /><%# ((KeyValuePair<String, List<File>>)(Container.DataItem)).Key %><br /></div><br /> </HeaderTemplate><br /><br /> <ContentTemplate><br /> <asp:repeater id="child" datasource='<%# (List<File>)(((KeyValuePair<String, List<File>>)(Container.DataItem)).Value) %>' runat="server"><br /><br /> <HeaderTemplate><br /><table border="0" cellpadding="0" cellspacing="5" style="width:100%"><br /><thead><tr><br /><th>Id</th><th>Name</th><br /><th>Description</th><br /><th>Date</th><br /></tr></thead><br /><tbody><br /> </HeaderTemplate><br /><br /> <ItemTemplate><br /><tr><br /><td><%# ((File)(Container.DataItem)).id.ToString() %></td><br /><td><%# ((File)(Container.DataItem)).Name %></td><br /><td><%# ((File)(Container.DataItem)).Description %></td><br /><td><%# ((File)(Container.DataItem)).Date.ToString() %></td><br /></tr><br /> </ItemTemplate><br /><br /> <FooterTemplate><br /></tbody><br /></table><br /> </FooterTemplate><br /><br /> </asp:repeater><br /> </ContentTemplate><br /></ajaxToolkit:Accordion></pre><br /><h4>The code-behind file </h4><br /><p>Add the following in the code-behind file of your web page</p><br /><pre>protected class File<br />{<br /> public Guid id;<br /> public string Name;<br /> public string Description; <br /> public DateTime Date;<br /> public File()<br /> {<br /> id = Guid.NewGuid();<br /> Date = DateTime.Now;<br /> }<br />} </pre><br /><pre>protected void Page_Load(object sender, EventArgs e)<br />{<br /> if (!IsPostBack)<br /> {<br /> const string C = "Category {0}";<br /> const string N = "File {0}";<br /> const string D = "Description {0}";<br /> Dictionary<String, List<File>> dicCategories = new Dictionary<String, List<File>>();<br /> for (int i = 0; i < 5; i++)<br /> {<br /> List<File> objList = new List<File>();<br /> for (int j = 0; j < 10; j++)<br /> {<br /> File objFile = new File();<br /> objFile.Name = String.Format(N, j);<br /> objFile.Description = String.Format(D, j);<br /> objList.Add(objFile);<br /> }<br /> dicCategories.Add(String.Format(C, i), objList);<br /> }<br /> Accordion1.DataSource = dicCategories;<br /> Accordion1.DataBind();<br /> }<br />}</pre>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-79940860453304404652007-08-31T16:14:00.001+01:002007-08-31T16:14:01.519+01:00Getting Velodoc notifications out of junk email folders<span xmlns=''><p>Some Velodoc users have complained that they did not receive our email notifications.<br /></p><p>We have looked into our application logs and these notifications have definitely been sent. Looking more closely at our SMTP server logs, we have found some entries similar to the following:<br /></p><p><span style='font-family:Courier New; font-size:9pt'>2007-08-28 09:07:16 65.55.245.8 OutboundConnectionResponse SMTPSVC1 SV1 - 25 - - 550+Your+e-mail+was+rejected+for+policy+reasons+on+this+gateway.++Reasons+for+rejection+may+be+related+to+content+with+spam-like+characteristics+or+IP/domain+reputation+problems.++If+you+are+not+an+e-mail/network+admin+please+contact+your+E-mail/Internet+Service+Provider+for+help.++For+e-mail+delivery+information,+please+go+to+http://postmaster.live.com 0 0 355 0 578 SMTP - - - -<br /></span></p><p>I have confirmed myself that notifications sent to Live Hotmail addresses were not received, even in the junk e-mail folder.<br /></p><p>Although I was pretty sure about the result, I have checked that Velodoc.net was not recorded in any spam database, using <a href='http://www.dnsstuff.com/tools/ip4r.ch?ip=velodoc.net'>http://www.dnsstuff.com/tools/ip4r.ch?ip=velodoc.net</a>.<br /></p><p>Going to <a href='http://postmaster.live.com'>http://postmaster.live.com</a> as suggested, I have read about SPF and Sender ID. I already knew about it, but our DNS Servers have been hosted by Network Solutions and they do not support SPF records. They know their stuff, don't they? I have even contacted their support team and I have been told that they get little demand for it.<br /></p><p>Enquiring further, we have realized that more and more e-mail servers implement <a href='http://www.microsoft.com/senderid'>SPF/Sender ID</a>. Some are now considering <a href='http://antispam.yahoo.com/domainkeys'>DKIM/DomainKeys</a> to sign emails. So we have taken the decision to move our DNS to <a href='http://www.dnsmadeeasy.com'>DNS Made Easy</a> and to add SPF records to our domains. Note that we could have used <a href='http://www.ultradns.com'>UltraDNS</a> or <a href='http://www.easydns.com/'>EasyDNS</a>, which offer similar services.<br /></p><p>We have used <a href='http://www.dnsreport.com'>http://www.dnsreport.com</a> to identify other DNS issues. We were only missing a PTR record pointing to mail.velodoc.net. Because each of our web servers has its own SMTP server, we have changed the MX record to <a href='http://www.velodoc.net'>www.velodoc.net</a> which already has a PTR record and changed the HELO greeting of the SMTP servers to display the correct fully qualified domain name. Live Hotmail users now receive our email notifications.<br /></p><p>In the near future we will be looking at DomainKeys, but contrary to Sender ID, DomainKeys have an impact on the infrastructure because they require that we change our SMTP Servers. If you have some experience with DKIM/DomainKeys and can recommend SMTP servers that implement email authentication, please leave a comment.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-49205342325458336582007-08-29T10:29:00.001+01:002007-08-29T10:29:00.960+01:00Turning the Velodoc Flash applet into a Yahoo widget<span xmlns=''><p>Yahoo widget documentation is available at <a href='http://widgets.yahoo.com/workshop/'>http://widgets.yahoo.com/workshop/</a>.<br /></p><p>Yahoo widgets cannot host the browser to display Flash applets. All Yahoo widgets based on Flash require the use of a third party component called WebBrowser4Widgets available at <a href='http://www.centraltopic.com'>http://www.centraltopic.com</a>. Installing a Yahoo widget which uses this component is a very poor user experience. Several security warnings are displayed, which are too many reasons not to install the widget. Check samples at <a href='http://widgets.yahoo.com/gallery/?author=14327'>http://widgets.yahoo.com/gallery/?author=14327</a><br /> </p><p>For this reason, we have postponed the packaging of the <a href='http://www.velodoc.net'>Velodoc</a> applet as a Yahoo widget and wait until Yahoo widget implements a native mechanism to host Flash applets. Considering the success of Video sites like YouTube, I cannot think of any reason why they should not do it very soon.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-108521639056191102007-08-21T08:33:00.001+01:002007-08-21T08:45:01.720+01:00Adobe Captivate or Techsmith Camtasia?<span xmlns=""><p>Although most of my friends seem to prefer <a href="http://www.techsmith.com/">Camtasia</a>, I have been a long-time fan of RoboDemo, now <a href="http://www.adobe.com/products/captivate">Captivate</a>.<br /></p><p>The main difference between the two products is:<br /></p><ul><li>Camtasia records a full-motion video;<br /></li><li>Captivate records still images, keyboard strokes and mouse movements which it assembles into a video;<br /></li></ul><p>The two approaches have their own strengths and weaknesses:<br /></p><ul style="MARGIN-LEFT: 38pt"><li>Camtasia is better at recording and displaying scrolling panes, progress bars and drag-and-drop operations;<br /></li><li>Captivate gives a lot more control on the output. In fact, Captivate produces not only demonstrations but also true e-learning content.<br /></li></ul><p>The new Captivate 3.0 closes the gap and introduces full-motion recording, not in replacement but in addition to still images. Captivate is clever enough to trigger the full-motion recording when it detects a scrolling pane or a drag-and-drop. Anyway you can trigger it manually anytime.<br /></p><p>In my opinion, Captivate 3.0 is now far superior to Camtasia on all grounds except price. The Captivate product remains significantly more expansive but it is now justified.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com1tag:blogger.com,1999:blog-18669442.post-35083451112516422372007-08-17T16:48:00.001+01:002007-08-20T10:06:52.001+01:00Turning the Velodoc Flash applet into a Vista Sidebar gadget<span xmlns=""><h4>Documentation</h4><p>Step-by-step instructions on how to develop a sidebar gadget are available at:</p><ul><li><a href="http://microsoftgadgets.com/Sidebar/DevelopmentOverview.aspx">http://microsoftgadgets.com/Sidebar/DevelopmentOverview.aspx</a></li><li><a href="http://microsoftgadgets.com/Build/SidebarTutorial.zip">http://microsoftgadgets.com/Build/SidebarTutorial.zip</a></li><li><a href="http://msdn2.microsoft.com/en-us/library/ms723694.aspx">http://msdn2.microsoft.com/en-us/library/ms723694.aspx</a></li><li><a href="http://msdn.microsoft.com/msdnmag/issues/07/08/sidebar/default.aspx">http://msdn.microsoft.com/msdnmag/issues/07/08/sidebar/default.aspx</a></li></ul><p>Reference documentation is available at <a href="http://msdn2.microsoft.com/en-us/library/bb508511.aspx">http://msdn2.microsoft.com/en-us/library/bb508511.aspx</a></p><h4>Implementation</h4><p>I am always trying to start this type of RAD development from an existing example. The sample that you build in <a href="http://microsoftgadgets.com/Sidebar/DevelopmentOverview.aspx">http://microsoftgadgets.com/Sidebar/DevelopmentOverview.aspx</a> is a good starting point.</p><p>In our final gadget, the html is simply a div which is filled by Javascript code when the gadget loads:</p><ul style="MARGIN-LEFT: 38pt"><li>The Javascript event handlers are hooked as described in <a href="http://msdn.microsoft.com/msdnmag/issues/07/08/sidebar/default.aspx">http://msdn.microsoft.com/msdnmag/issues/07/08/sidebar/default.aspx</a></li><li>On page load we do one of three options:</li><ul><li>If running on Windows 64 bits, we display a message because <a href="http://kb.adobe.com/selfservice/viewContent.do?externalId=6b3af6c9&sliceId=1">Flash does not support 64-bit systems</a>.</li><li>If connection is offline, we display a message</li><li>Otherwise, we display the applet</li></ul></ul><p>The recommended approach to test a 64-bit platform is to use the <a href="http://msdn2.microsoft.com/en-us/library/ms723259.aspx">System.Machine.processorArchitecture</a> property but this always returns [Object error] on my 64-bit DELL Precision M65. So I have used <a href="http://msdn2.microsoft.com/en-us/library/ms723686.aspx">System.Environment.getEnvironmentVariable("PROCESSOR_ARCHITECTURE")</a> which seems to work consistently over the few Vista computers that I have tested.</p><p>There is apparently no function in the framework to check if the network connection is online, so I have used the same approach used in the <a href="http://jlchereau.blogspot.com/2007/08/turning-velodoc-flash-applet-into.html">Google Desktop Gadget</a>.</p><p>I have only experienced one hitch in the implementation: the Flash applet catches the mouse events before the Sidebar. As a consequence, the gadget toolbar at the top right of the gadget is never displayed, which prevents from closing or moving the gadget. The workaround I have found is to add an image at the top of the Flash applet, so that when the mouse goes over this image, the gadget toolbar is displayed.</p><img id="BLOGGER_PHOTO_ID_5099699031958645554" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZKCAL86UVS3n7j9d_dNUOLZ3Ik6PgXwKP0c0w8CCSYg7irT4zzK-kTViCn5b-8hasAwpbDWuhXnd_qIzNPvCZ3gjnTZxT9gy79yltwlZtXxXMe4s1scL2K6DmXpJb0Pj1K43z/s200/070817.png" border="0" /> <p></p><h4>Packaging</h4><p>You can package your sidebar gadgets as .zip files or .cab files renamed into .gadget files. I have used the following batch file to produce a proper package from sources located in "D:\Documents\Velodoc Sidebar Gadget\Sources". The batch file should be located in the parent directory:</p><p><span style="font-family:Courier New;font-size:85%;">rem ** remove/create a test gadget folder<br /></span><span style="font-family:Courier New;font-size:85%;">rd "%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\Velodoc.gadget\" /s /q<br /></span><span style="font-family:Courier New;font-size:85%;">md "%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\Velodoc.gadget\"<br /></span><span style="font-family:Courier New;font-size:85%;">rem ** copy all of the files into test area<br /></span><span style="font-family:Courier New;font-size:85%;">xcopy .\Sources "%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\Velodoc.gadget\" /y /s /q /EXCLUDE:exclude.txt<br /></span><span style="font-family:Courier New;font-size:85%;">%SystemDrive%<br /></span><span style="font-family:Courier New;font-size:85%;">cd "%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets\Velodoc.gadget\"<br /></span><span style="font-size:85%;"><span style="font-family:Courier New;">"%VS80COMNTOOLS%Bin\cabarc.exe" -r -p n "D:\Documents\Velodoc Sidebar Gadget\Velodoc.gadget" *<br /></span><span style="font-family:Courier New;">pause</span></span></p><h4>Test and debugging</h4><p>Testing and debugging is relatively easy, considering the logic is in the Flash applet. Simply double click the gadget file to install and test. There is no need to uninstall before a new install, provided the gadget is removed from the Sidebar.</p><h4>Distribution</h4><p>Once your gadget is ready, follow the instructions at <a href="http://gallery.live.com/submit.aspx">http://gallery.live.com/submit.aspx</a> to publish it on the Live web site.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-20961748849668486132007-08-16T19:02:00.001+01:002007-08-17T15:06:54.376+01:00Turning the Velodoc Flash applet into a Google Desktop Gadget<span xmlns=""><h4>Documentation<br /></h4><p>The Goggle Desktop SDK can be found at <a href="http://desktop.google.com/dev/index.html">http://desktop.google.com/dev/index.html</a>. The documentation is rudimentary, but there are several samples worth exploring. Besides gadgets are packaged in .gg files which can be renamed into .zip files, so that the content can be explored.</p><p>A lot of information can also be found in the forums at <a href="http://groups.google.com/group/Google-Desktop-Developer?lnk=lr&hl=en-GB">http://groups.google.com/group/Google-Desktop-Developer?lnk=lr&hl=en-GB</a>.<br /></p><h4>Implementation<br /></h4><p>My initial track was to run the Flash applet in the Sidebar as explained in <a href="http://groups.google.com/group/Google-Desktop-Developer/browse_thread/thread/2ee23c46237e5408?hl=en-GB">http://groups.google.com/group/Google-Desktop-Developer/browse_thread/thread/2ee23c46237e5408?hl=en-GB</a>. My gadget was very simple: a manifest, a localized string.xml file, the main.xml file represented below and a couple of images.</p><p><span style="font-family:Courier New;"><view height="240" width="240"><br /><div id="flashcontainer" style="text-align: center;"></div><br /><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="240" height="240"><br /><param name="movie" value="http://www.velodoc.net/Gadgets/Velodoc.Gadget.swf" /><br /><param name="wmode" value="transparent" /><br /><param name="allowScriptAccess" value="sameDomain" /><br /><param name="quality" value="high" /><br /><param name="bgcolor" value="#000000" /><br /></object><br /></view><br /></span></p><p>In particular, there was no Javascript file in this implementation.<br /></p><p>This track is a dead end because there is too much interactivity in the Flash applet and Google Desktop seems to get the events before the applet code gets an opportunity to handle them, which results in an unresponsive applet. Accordingly, the only way is to run the applet in a details view.<br /></p><p>The best example to start from is HtmlDetailsView which is part of the SDK. Do not forget to change the guid in the manifest, otherwise you won't be able to submit your project to Google at the end. The code is pretty straightforward, so please download the gadget at <a href="http://www.velodoc.net/gadgets/GDesktop/Velodoc.GDesktop.gg">http://www.velodoc.net/gadgets/GDesktop/Velodoc.GDesktop.gg</a>, rename it into a .zip file and explore.<br /></p><img id="BLOGGER_PHOTO_ID_5099363367379561250" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSsf4f_29qiOtNUm90Hc24VltuTLrEQqMigCLLB2hFmGGZtaYfuJrDwxxaCGghUVdhRzh9FP4TAmhfqDJGu8AGRgnbmNf1xYn6r6mgUPpzAp82FvKLACKI2USt7BzVD8huPC9L/s320/070816.png" border="0" /> <p>The only issue I have faced is the use of the <span style="font-family:Courier New;">system.network.online</span> property to detect the online/offline status. After simply disconnecting my network cable, the value returned was still true. So I have created the isOnline() function which uses a synchronous XMLHttpRequest of type HEAD to confirm access to the Flash applet. I did not feel that an asynchronous request was justified in this case. For more information see <a href="http://www.jibbering.com/2002/4/httprequest.html">http://www.jibbering.com/2002/4/httprequest.html</a> and <a href="http://ajaxpatterns.org/XMLHttpRequest_Call">http://ajaxpatterns.org/XMLHttpRequest_Call</a>.</p><h4>Test and debugging</h4><p>Testing is easy and does not require packaging the gadget. Double-click the gadget.manifest file and the gadget is installed in the sidebar.</p><h4>Packaging and Distribution<br /></h4><p>To package your applet, simply archive all the files in a zip file. Keep the directory structure where the manifest is at the root of the archive. Then rename the .zip extension into .gg and test. You can install your packaged gadget by double-clicking the gg file.<br /></p><p>If you upload your gadget to an IIS 6 server, you will get an error 404 when downloading it. By default IIS blocks files which have no known mime type. See: <a href="http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/0f4ac79a-dc2b-4a5f-89c1-d57266aa6ffe.mspx?mfr=true">http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/0f4ac79a-dc2b-4a5f-89c1-d57266aa6ffe.mspx?mfr=true</a>. To be able to download your gadget from an IIS server, you need to create a MIME type for the .gg extension. You can map the .gg extension to "application/octet-stream".<br /></p><p>Then the last step is to submit your gadget at <a href="http://desktop.google.com/pluginsubmit?hl=en-GB">http://desktop.google.com/pluginsubmit?hl=en-GB</a> to get some visibility.</p><p>Finally, please note that I have also opened a discussion thread regarding this gadget at <a href="http://groups.google.com/group/Google-Desktop-Developer/browse_thread/thread/6776e746840080ee?hl=en-GB">http://groups.google.com/group/Google-Desktop-Developer/browse_thread/thread/6776e746840080ee?hl=en-GB</a></p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0tag:blogger.com,1999:blog-18669442.post-75740241637581615692007-08-15T17:50:00.001+01:002007-08-15T17:59:01.629+01:00Developing a file upload applet for Velodoc with Flash<span xmlns=""><p>This article follow a recent article entitled <a href="http://jlchereau.blogspot.com/2006/10/designing-windows-sidebar-gadget-for.html">Designing gadgets and widgets for uploading files to Memba Velodoc</a>.<br /></p><h4>ActionScript 2 and the Flash 8 IDE</h4><p>This project was my first trial at Flash and in my opinion, Flash 8 presents two main difficulties for .NET developers:<br /></p><ol><li>The IDE offers rudimentary development and debugging features;<br /></li><li>Scope and addressing of objects (relative or absolute, using _parent or this) is not always clear. Sometimes relative won't work, and this is fixed with absolute addressing. The rule seems to be using relative unless you cannot get around it.<br /></li></ol><p>Apart from that, Flash is not a great development tool and I would not consider large projects in Flash, but it does a nice job for small applets.<br /></p><h4>Flash security</h4><p>As always, sandboxed security is not intuitive and error messages are unfriendly when you get them, so be prepared to spend a significant amount of development time on security. Most issues are explained at:<br /></p><ul><li><a href="http://www.adobe.com/devnet/flash/articles/fplayer_security.html">http://www.adobe.com/devnet/flash/articles/fplayer_security.html</a><br /></li><li><a href="http://www.adobe.com/devnet/flash/articles/fplayer8_security.html">http://www.adobe.com/devnet/flash/articles/fplayer8_security.html</a><br /></li></ul><p>You can also get information about the IE content activation issue at:<br /></p><ul><li><a href="http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=7c29e252">http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=7c29e252</a><br /></li></ul><h4>The user interface logic</h4><p>I have opted for a form application with the following forms:<br /></p><ul style="MARGIN-LEFT: 39pt"><li>The <strong>application form</strong> contains the background elements and the action script.<br /></li><li>The <strong>outbox form</strong> contains a To, Subject and Message text inputs and a "Select file" button. It also contains a label to display the file name and a Send button.<br /></li><li>The <strong>progress form</strong> contains a progress bar and a Cancel button<br /></li><li>The <strong>settings form</strong> allows you to define your settings.<br /></li><li>The <strong>success form</strong> confirms when a use case completed ok.<br /></li><li>The <strong>error form</strong> displays an error message when needed.<br /></li></ul><p>Except a couple of behaviours, all our script is written in Frame1 of the application form. Navigation between forms is easy to build and does not raise any major issue.<br /></p><h4>The file upload process</h4><p>The file upload process using FileReference is simple and fairly well documented in the following documentation:<br /></p><ul><li><a href="http://livedocs.macromedia.com/labs/as3preview/docs/00000142.html">http://livedocs.macromedia.com/labs/as3preview/docs/00000142.html</a><br /></li><li><a href="http://www.codeproject.com/aspnet/FlashUpload.asp">http://www.codeproject.com/aspnet/FlashUpload.asp</a><br /></li><li><a href="http://markshu.ca/imm/flash/tutorial/fileReference.html">http://markshu.ca/imm/flash/tutorial/fileReference.html</a><br /></li><li><a href="http://www.flash-db.com/Tutorials/upload/">http://www.flash-db.com/Tutorials/upload/</a><br /></li></ul><p>Nevertheless, two trick needs to be pointed out:<br /></p><p>First, FileReference posts a 0 byte request to the designated URL before posting the file. You need to make sure that your server code does not store a 0 byte file in this case.<br /></p><p>Second, FileReference emits an invalid multipart request and our server logic got caught. At the end of the request, you will find something like:<br /></p><p><span style="font-family:Courier New;">------------GI3ae0Ef1GI3cH2KM7gL6ae0GI3Ef1<br /></span></p><p><span style="font-family:Courier New;">Content-Disposition: form-data; name="Upload"<br /></span></p><p><span style="font-family:Courier New;">Submit Query<br /></span></p><p><span style="font-family:Courier New;">------------GI3ae0Ef1GI3cH2KM7gL6ae0GI3Ef1<br /></span></p><p>which should have been:<br /></p><p><span style="font-family:Courier New;">------------GI3ae0Ef1GI3cH2KM7gL6ae0GI3Ef1<br /></span></p><p><span style="font-family:Courier New;">Content-Disposition: form-data; name="Upload"<br /></span></p><p><br /> </p><p><span style="font-family:Courier New;">Submit Query<br /></span></p><p><span style="font-family:Courier New;">------------GI3ae0Ef1GI3cH2KM7gL6ae0GI3Ef1--<br /></span></p><p>The differences being an additional \r\n between the form-data and value and a missing double hyphen at the end of the request. Note that this happens when the applet runs in the Flash environment, it does not happen when the applet runs as a gadget within the Vista sidebar, but in this case, there is an additional random character at the end. We have updated our server code to handle these specificities.<br /></p><h4>Calling web services</h4><p>There are three ways to call web services in Flash:<br /></p><ol><li>Remoting is the most flexible, most complicated way. It is the low level stuff.<br /></li><li>The web service component is a data binding control which does not require any programming. You get it to work just by settings properties in dialogs.<br /></li><li>Finally mx.services.* have high level classes that make calling web services from ActionScript really easy.<br /></li></ol><p>Our requirements are not terribly complex and the mx.services.* classes have been the way to go. There is only one trick, which I have not been able to find either on the web or in the flash documentation, which is how to pass complex objects as parameters.<br /></p><h4>Styling our Flash gadget</h4><p>Styling the flash applet certainly represents the largest amount of code and time spent. We needed gradients and bevel effects that would resize. To achieve that, I have used the Flash Drawing APIs described at <a href="http://www.adobe.com/devnet/flash/articles/precision_drawing.html">http://www.adobe.com/devnet/flash/articles/precision_drawing.html</a> and skinning techniques described at <a href="http://www.adobe.com/devnet/flash/articles/skinning_3.0.html">http://www.adobe.com/devnet/flash/articles/skinning_3.0.html</a>.<br /></p><p>I have decided to postpone changing colours and localization to a future version.<br /></p><h4>Debugging and testing</h4><p>For debugging and testing, you will find the following tools helpful:<br /></p><ul><li>Get a debug version of the Flash player at <a href="http://download.macromedia.com/pub/flashplayer/updaters/9/flashplayer_9_plugin_debug.exe">http://download.macromedia.com/pub/flashplayer/updaters/9/flashplayer_9_plugin_debug.exe</a><br /></li><li>Get Flash switcher at <a href="https://addons.mozilla.org/fr/firefox/addon/3649">https://addons.mozilla.org/fr/firefox/addon/3649</a><br /></li><li>Get Flash tracer at <a href="https://addons.mozilla.org/fr/firefox/addon/3469">https://addons.mozilla.org/fr/firefox/addon/3469</a> (With Flash 9, you need to change the path in Flash Tracer Options to C:\Documents and Settings\<user>\Application Data\Macromedia\Flash Player\Logs\flashlog.txt)<br /></li></ul><p>The applet works fine in Internet Explorer. There is a bug which we have experimented in Firefox: You get a US keyboard if you define wmode="transparent". This is documented at <a href="http://blog.headlondon.com/archives/no-wmode-please-were-british/">http://blog.headlondon.com/archives/no-wmode-please-were-british/</a> but seems to have been corrected . Other issues that you may experience are documented at <a href="http://www.asserttrue.com/articles/2006/11/17/firefox-and-flash-swf-selection-and-focus-problems">http://www.asserttrue.com/articles/2006/11/17/firefox-and-flash-swf-selection-and-focus-problems</a>.<br /></p><h4>Result</h4><p>The result is available at <a href="http://www.velodoc.net/Gadgets/Velodoc.Gadget.aspx">http://www.velodoc.net/Gadgets/Velodoc.Gadget.aspx</a>.<br /></p><p>If you want to participate and improve this applet, please contact me. I'll be very happy to share the code with active contributors.<br /></p><p>Next, I'll explain how to turn this applet into gadgets and widgets for all major platforms.</p></span>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com2tag:blogger.com,1999:blog-18669442.post-79992353923096832032007-08-13T18:30:00.001+01:002007-08-13T19:18:34.978+01:00The future of Internet TV<p>Following aerial TV and cable TV, the next revolution is Internet TV or IPTV, which makes the cost of distributing TV programs even lower, allowing for much more targeted and specialized content. There are currently four types of actors that have a chance to play a major role in this exciting revolution:</p><ol><li>The major TV broadcasters</li><li>The major telecom providers</li><li>The online merchants including <a href="http://www.itunes.com/">iTunes</a></li><li>The video web sites including <a href="http://www.youtube.com/">YouTube</a></li><li>The peer-to-peer newcomers including <a href="http://www.joost.com/">Joost</a> and <a href="http://www.babelgum.com/">Babelgum</a></li></ol><p>The following criteria will make the difference between the platforms and eventually specialize them:</p><ol><li>Capacity to attract advertising dollars, which is a mix of size and segmentation of the audience</li><li>Capacity to attract paid subscriptions, which is related to the quality and exclusivity of the content and ultimately to the remuneration and protection of content producers</li><li>Capacity to display hi-res content, which is mainly a technical issue</li><li>Ease of use, especially to search for or subscribe to archived content</li><br /></ol><p>Let’s now review the various platforms and trends:</p><table cellspacing="0" cellpadding="0" border="1"><tbody><tr><td valign="top"><p align="center"></p></td><td valign="top" colspan="2"><p align="center">Ad Dollars</p></td><td valign="top" colspan="2"><p align="center">Paid Subs.</p></td><td valign="top" colspan="2"><p align="center">Hi-Res</p></td><td valign="top" colspan="2"><p align="center">Search</p></td></tr><tr><td valign="top"><p>Major TV Broadcasters</p></td><td valign="top"><p align="center">5</p></td><td valign="top"><p align="center">↓</p></td><td valign="top"><p align="center">5</p></td><td valign="top"><p align="center">↓</p></td><td valign="top"><p align="center">4</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">0</p></td><td valign="top"><p align="center">↑</p></td></tr><tr><td valign="top"><p>Major telecom providers</p></td><td valign="top"><p align="center">0</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">5</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">4</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">2</p></td><td valign="top"><p align="center">↑</p></td></tr><tr><td valign="top"><p>Online Merchants</p></td><td valign="top"><p align="center">0</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">5</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">5</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">5</p></td><td valign="top"><p align="center">↑</p></td></tr><tr><td valign="top"><p>Video web sites</p></td><td valign="top"><p align="center">2</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">1</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">1</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">4</p></td><td valign="top"><p align="center">↑</p></td></tr><tr><td valign="top"><p>P2P newcomers</p></td><td valign="top"><p align="center">1</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">0</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">3</p></td><td valign="top"><p align="center">↑</p></td><td valign="top"><p align="center">2</p></td><td valign="top"><p align="center">↑</p></td></tr></tbody></table><br /><p></p><br /><table cellspacing="0" cellpadding="0" border="1"><tbody><tr><td valign="top"><p align="center"></p></td><td valign="top"><p align="center">Weak point</p></td><td valign="top"><p align="center">Strong point</p></td><td valign="top"><p align="center">Best fit</p></td></tr><tr><td valign="top"><p>Major TV Broadcasters</p></td><td valign="top"><p align="center">Transition to Internet</p></td><td valign="top"><p align="center">Quality content and revenue stream</p></td><td valign="top"><p align="center">News and other short-life content</p></td></tr><tr><td valign="top"><p>Major telecom providers</p></td><td valign="top"><p align="center">Content</p></td><td valign="top"><p align="center">Infrastructure</p></td><td valign="top"><p align="center">Mobile phones</p></td></tr><tr><td valign="top"><p>Online Merchants</p></td><td valign="top"><p align="center">Purchasing process</p></td><td valign="top"><p align="center">Hi-Res content</p></td><td valign="top"><p align="center">Films</p></td></tr><tr><td valign="top"><p>Video web sites</p></td><td valign="top"><p align="center">Streaming bandwidth</p></td><td valign="top"><p align="center">Navigate and search</p></td><td valign="top"><p align="center">Short low-res content</p></td></tr><tr><td valign="top"><p>P2P newcomers</p></td><td valign="top"><p align="center">Works on PC + Content</p></td><td valign="top"><p align="center">Hi-Res content</p></td><td valign="top"><p align="center">Documentary</p></td></tr></tbody></table><br /><p>As more platforms will become available, the split between content producers and broadcasters will become more obvious. In this respect, I do not think that the major telecom providers, online merchants, video web sites and P2P newcomers will ever produce content, but will rather enter into agreements to obtain content. In this respect, the major TV broadcasters which both produce and broadcast content will enter in “co-opetition” agreements, for example to broadcast their programs on mobile phones.</p><p>Telecom providers are probably the biggest threat to TV broadcasters as many content producers will see in them a new channel for their content. This is probably the main reason for <a href="http://packages.sky.com/">Sky</a> to offer broadband and telephone or for Microsoft to target <a href="http://www.microsoft.com/tv/default.mspx">MediaRoom</a> at service providers.</p><p>Considering the purchasing process, online merchants will probably focus on music and films for quite some time and do not represent a significant threat for TV broadcasters and telecom providers.</p><p>I cannot imagine video web sites getting enough money from advertising to sustain their activity, they have to remain free for users and they will not be able to compete on high-quality content with TV broadcasters and telecom providers. In my opinion, their only option to survive is to get subscriptions from companies to get their own channel, for example:</p><ul><li>A BMW channel where BMW would present educative content regarding its range of cars;</li><li>A L’OREAL channel where L’OREAL would give advice to women how to make the most of their makeup using its products;</li><li>A DANONE channel where a chef would give recipes using DANONE products;</li><li>A NIKE channel which would give training advice for running the marathon.</li><br /></ul><p>The video web site could even provide links to purchase the products demonstrated, competing with video shopping channels.</p><p>P2P newcomers will have to review their business model. They are currently in a vicious circle:</p><ul><li>they do not remunerate content producers because they are free and they do not have enough advertising;</li><li>they do not have enough advertising because they do not have enough quality content attracting users;</li><li>finally, they do not have enough quality content because they do not remunerate content producers.</li></ul><p>P2P newcomers definitely need some free content to let users evaluate their technology and make the numbers, but they have a vocation at being a video encyclopedia capable of making available not only the blockbusters but more importantly confidential content like documentaries or TV archives and they won’t be able to achieve that without user subscriptions and retributions to content providers.</p>Jacques L. Chereauhttp://www.blogger.com/profile/03733988177982708738noreply@blogger.com0