tag:blogger.com,1999:blog-32963351779138667712024-03-13T05:42:37.328-04:00C O D E R YAdventures in .NET, SQL, Java, SAP ECC6, etc.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.comBlogger49125tag:blogger.com,1999:blog-3296335177913866771.post-72787263959013214032012-09-07T10:36:00.000-04:002012-09-07T10:42:56.261-04:00ASP.NET MVC Image Helper that accepts nullsOne of the things I liked about ASP.NET's ASP:Image tag was that it would not render an HTML image tag if the url was null. Using @Url.Content in an image tag throws an error, but I was able to easily accomplish the same behavior as ASP:Image using Razor with the following code (90%+ of the source is from <a href="http://stackoverflow.com/questions/4707518/razor-and-html-helpers">this StackOverflow question</a>):
<br />
<pre style="background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4FvxmqL_cdc1cncj0p2ptdhR5UJARO9bz6Krz66R4eLJzm-8TerQ231D_exMp2mneNdPK3doMfcBfiE08lY8hlLTsArltshvcvkGBN1Wy3Gieer9691od3XgpGthnEchFv6uXdMijhpt-/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public static class ImageHelper
{
public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText)
{
return Image(helper, id, url, alternateText, null);
}
public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)
{
MvcHtmlString ret;
if (url == null)
{
ret = null;
}
else
{
// Instantiate a UrlHelper
var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
// Create tag builder
var builder = new TagBuilder("img");
// Create valid id
builder.GenerateId(id);
// Add attributes
builder.MergeAttribute("src", urlHelper.Content(url));
builder.MergeAttribute("alt", alternateText);
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
// Render tag
ret = new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
}
return ret;
}
}
</code></pre>
I'm really just testing out different blog code formatting options, but I think this is at least a bit useful :-)
Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-1512832234452548412012-07-25T10:45:00.000-04:002012-07-25T10:45:19.110-04:00IIS 7 URL Rewrite debuggingI needed to redirect a url from one domain to another while also removing part of the path, i.e.<br />
<br />
<b>http://www.test.com/folder/test.aspx</b><br />
to<br />
<b>http://www.newtest.com/test.aspx</b><br />
<br />
I used IIS 7's "<a href="http://www.iis.net/download/urlrewrite">URL Rewrite</a>" module, and the test tool showed that my regex appeared to work correctly, but nothing was actually being redirected. I finally turned on "Failed Request Tracing Rules", added a rule to catch all 404 errors, and was able to look through the resulting log and quickly determine the error.<br />
<br />
Here's the setup:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikmaZcIi3eH-gnUa_6LaycnbTDCSRLKlCHIgda3x8AQtBZ6vSOEszgs4PTK0wDhJ1kw6EuwsFS2DvoDFqhbPQdFR8lEkeEqykPojjPfzsHDKpgT4wXBZmma3I7ITCOeeVTFSQPLr16deE/s1600/failed1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikmaZcIi3eH-gnUa_6LaycnbTDCSRLKlCHIgda3x8AQtBZ6vSOEszgs4PTK0wDhJ1kw6EuwsFS2DvoDFqhbPQdFR8lEkeEqykPojjPfzsHDKpgT4wXBZmma3I7ITCOeeVTFSQPLr16deE/s320/failed1.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4gbIKP3s6rnnltMLLWQN7HN1IClXB-kjnLe92pXtFVZaQQeXl4H2pjSw3aWLaCW8H6OZvQCwMwqEtH0a8DBqQAxzpciX5WnnpyzZpl-sUX1ppjVmx8Y5fPgWAe-ojlma8ayBASGV5I3k/s1600/failed2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4gbIKP3s6rnnltMLLWQN7HN1IClXB-kjnLe92pXtFVZaQQeXl4H2pjSw3aWLaCW8H6OZvQCwMwqEtH0a8DBqQAxzpciX5WnnpyzZpl-sUX1ppjVmx8Y5fPgWAe-ojlma8ayBASGV5I3k/s320/failed2.png" width="320" /></a></div>
<br />
<br />
<br />
The log files are in the regular log files directory, under the "FaileReqLogFiles" directory by default. Open the file with or similar to the name "fr000001.xml", and search for your redirection rule name. You should see lots of debugging details to help you determine why the redirect didn't work. In my case, I was trying to match the slash before the folder as well as after it, but IIS was only looking at the part of the path after the domain name, so it never matched.<br />
<br />
And here's the rule setup to redirect from a domain to another domain while replacing part of the path, in case anybody needs it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0q542e-HG0ZH7oEGFpvFDIJL5qQx6QDCWeBn_7YvQFU30MF17t8z5zICaITfmfBWjryXqi24wy0i53rJdseLQn58pbVUiBYs2jeDq_D6QSc9h46C7eXA9EIcwvdbl3V2tvOmkg0YHVqU/s1600/failed3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0q542e-HG0ZH7oEGFpvFDIJL5qQx6QDCWeBn_7YvQFU30MF17t8z5zICaITfmfBWjryXqi24wy0i53rJdseLQn58pbVUiBYs2jeDq_D6QSc9h46C7eXA9EIcwvdbl3V2tvOmkg0YHVqU/s320/failed3.png" width="320" /></a></div>
<br />
Under "Match URL --> Pattern", add a regex similar to this:<br />
<br />
<b>folder\/(.*)</b><br />
<br />
This gets the url that contains the folder name with a slash after it, then creates a backreference for anything else that follows it, that you can refer to as "{R:1}".<br />
<br />
Under "Redirect URL", enter:<br />
<br />
<b>http://www.newtest.com/{R:1}</b><br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-73304460027217907572012-05-11T11:42:00.000-04:002012-05-11T13:22:41.713-04:00Generic XML attribute parserI may just end up using something like LINQ to XSD for this (if possible), but I wanted to see how easy it would be to write an XML parser that takes in an element of any kind, and returns a strongly-typed value. Here's what I came up with:<br />
<br />
<pre class="csharpcode"><span class="kwrd">private</span> T parseAttr<T>(XElement x, <span class="kwrd">string</span> elemName)
{
Type type = <span class="kwrd">typeof</span>(T);
T parsedValue;
<span class="kwrd">try</span>
{
parsedValue = type.IsEnum ? (T)Enum.Parse(<span class="kwrd">typeof</span>(T), x.Element(elemName).Value) : (T)Convert.ChangeType(x.Element(elemName).Value, <span class="kwrd">typeof</span>(T));
}
<span class="kwrd">catch</span>
{
parsedValue = <span class="kwrd">default</span>(T);
}
<span class="kwrd">return</span> parsedValue;
}</pre>
<br />
which can be used like this (example is from a LINQ projection):<br />
<br />
<pre class="csharpcode">let picks =
<span class="kwrd">from</span> pick <span class="kwrd">in</span> playerPicks.Element(<span class="str">"PlayerList"</span>).Descendants(<span class="str">"Player"</span>).Elements(<span class="str">"Picks"</span>)
select <span class="kwrd">new</span> PlayerPick
{
TickerSymbol = parseAttr<<span class="kwrd">string</span>>(pick, <span class="str">"TickerSymbol"</span>),
Status = parseAttr<Status>(pick, <span class="str">"Status"</span>),
PickCall = parseAttr<PickCall>(pick, <span class="str">"PickCall"</span>),
StartPrice = parseAttr<<span class="kwrd">double</span>>(pick, <span class="str">"StartPrice"</span>),
EndPrice = parseAttr<<span class="kwrd">double</span>>(pick, <span class="str">"EndPrice"</span>),
StartDate = parseAttr<DateTime>(pick, <span class="str">"StartDate"</span>),
EndDate = parseAttr<DateTime>(pick, <span class="str">"EndDate"</span>)
}</pre>
<br />
It works on regular types as well as enums. I'm not completely happy with it - "Convert" is generally less useful than .Parse(), but I couldn't figure out how to use Parse with generics on static methods (i.e. (T).Parse()).<br />
<br />
Also, it's hardly bulletproof, but I think I may validate the whole XML document first anyway if it doesn't take too long. Not sure if I'll end up using this or not - I was just amazed about how easy this was to write using generics, and thought it might be useful to somebody.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-61876623863506795272012-05-07T10:22:00.003-04:002012-05-07T10:26:54.787-04:00Renaming an ASP.NET MVC solution in Visual Studio<span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left;">The Platinum Bay blog has a good </span><a href="http://www.platinumbay.com/blogs/dotneticated/archive/2008/01/01/renaming-and-copying-projects-and-solutions.aspx?CommentPosted=true#commentmessage" style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left;">writeup</a><span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left;"> on how to rename a Visual Studio project correctly (so that the underlying folders are renamed and re-hooked up). </span><br />
<div style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left;">
<br /></div>
<div style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left;">
But I still ran into problems - an MVC project that I renamed returned the following error :</div>
<blockquote>
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter. </blockquote>
<blockquote>
The request for 'Home' has found the following matching controllers:<br />
(new project namespace).Controllers.HomeController<br />
(old project namespace).Controllers.HomeController</blockquote>
<div style="text-align: left;">
<span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left;">A file system search even turned up nothing, but I finally figured out the solution while reading a <a href="http://msdn.microsoft.com/en-us/magazine/dd695917.aspx">great in-depth article on controllers</a> by Scott Allen, where he states:</span><br />
<blockquote class="tr_bq">
<span style="background-color: white; color: #333333; font-family: 'Segoe UI', 'Lucida Grande', Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 16px; text-align: -webkit-auto;">...if you tell the factory to look for a "Home" controller, the factory can return a newly instantiated instance of a HomeController class regardless of the namespace or assembly it lives in—as long as it implements IController</span></blockquote>
<span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px;">If you've build the old project, you'll probably have old debugging dlls in the project's "bin" folder, so MVC will search and find those. Clear them out and rebuild, and everything should work. </span><span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px;">By the way, you could actually just follow the instructions in the error, and specify your route like this:</span></div>
<div style="text-align: left;">
<span style="font-family: Arial, Helvetica; font-size: x-small;"><br /></span></div>
<pre class="csharp">routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] {"(new project namespace)"}
);
</pre>
<pre class="csharp"></pre>
<pre class="csharp" style="text-align: -webkit-auto;"><span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left; white-space: normal;">but it's cleaner to delete the old .dlls, as they could potentially cause you other problems as well.</span><span style="background-color: white; text-align: left;"> </span><span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left; white-space: normal;">I'm very surprised that even the VS 11 beta still doesn't rename solutions correctly out of the box.</span></pre>
<pre class="csharp"><span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left; white-space: normal;">
</span></pre>
<pre class="csharp"><span style="background-color: white; font-family: Arial, Helvetica; font-size: 13px; text-align: left; white-space: normal;">
</span></pre>
<pre class="csharp"></pre>Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-29857840786692099952012-04-26T14:27:00.000-04:002012-04-26T14:33:51.441-04:00Querying fact tables for lower-level members (SAP BPC - MS version)Top-level dimension members aren't represented at all in BPC fact tables (SQL side), so if you need to find records that belong to a top-level member, you either need to manually look up all of the lower-level members, or have a query do it for you. Here's one I put together using a basic recursive CTE that will give you all records that contain lower-level members, given a higher-level member:<br />
<br />
<pre class="csharpcode">WITH a
AS (
SELECT *
FROM mbrDataSrc_F
WHERE [ID] = 'Top_Level_Datasource_Name' --top parent
UNION ALL
SELECT b.*
FROM mbrDataSrc_F b
JOIN a
ON b.PARENTH1 = a.[ID]
)
SELECT *
FROM tblFactForecast
WHERE DataSrc_F IN (
SELECT [ID]
FROM a
)
</pre>
<pre class="csharpcode"></pre>
If you're not familiar with them, the SQL after the UNION is the recursive part (some <a href="http://msdn.microsoft.com/en-us/library/ms186243.aspx">more info</a> on recursive Common Table Expressions). I use them a lot in place of derived tables for their slightly cleaner syntax, but don't usually have too much of a need for recursion.<br />
<br />
BTW, I don't believe in SELECT *, except for ad-hoc queries, which this one was for me. There is an <a href="http://stackoverflow.com/questions/1178867/resultset-and-select-performance">interesting discussion about it</a> over at StackOverflow.com - basically, minimal performance gains in most situations, but more clean and safer to select the actual columns.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-80800879043163977162012-02-08T09:39:00.000-05:002012-02-10T15:53:48.292-05:00FizzBuzzApparently, the "FizzBuzz" problem is a common programming interview question. I came across it while reading <a href="http://www.hanselman.com/blog/YouCantTeachHeightMeasuringProgrammerCompetenceViaFizzBuzz.aspx">You Can't Teach Height - Measuring Programmer Competence via FizzBuzz</a> on Scott Hanselman's blog.<br />
<br />
The "FizzBuzz" problem is:<br />
<blockquote class="tr_bq">
<em style="background-color: white; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13px; font: inherit; line-height: 19px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; vertical-align: baseline;">Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.</em></blockquote>
After reading this, my first thought was to write code to solve the problem. Funny that the end of Hansleman's post states:<br />
<blockquote>
One other thing that's amazing to me ... is that some of the programmers who read these blogs feel the need to <strong style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 13px; font-weight: bold; font: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">actually solve the FizzBuzz problem</strong>.<br />
They've completely - no, I need a work with more oomph - utterly? missed the point.</blockquote>
I'm pretty sure the point of his post is just that an interviewer should ask the applicant to <i>show </i>what he/she can do, rather than just talk about it. I agree with this. And I always have a better feeling about a place where I interview if they at least have me provide code samples and have me talk about them.<br />
<br />
But I've got to agree with one of the commenters:<br />
<blockquote class="tr_bq">
<span style="background-color: white; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; text-align: left;">Missed the point?? Developers are problem-solvers - OF COURSE we're going to try to code a solution! :-)</span></blockquote>
I love puzzles. So I tried coding it without looking up anything, then compiling to see if it worked. I first used a switch/case statement, so that if a number was both a multiple of 3 and 5, it would fall through both and output "FizzBuzz" without needing a separate case to handle both, something like this:<br />
<br />
<pre class="csharp" name="code">switch (i)
{
case i % 3 == 0:
Console.WriteLine("Fizz");
case i % 5 == 0:
Console.WriteLine("Buzz");
default:
Console.WriteLine(i);
}
</pre>
<br />
Whoops. C# only allows constants in switch/case statements, and it doesn't support break fall-throughs, either (need to use "goto"!). So I tried to mimic it with regular if/then statements. But at the same time, I also had the idea to make it a method, so I ended up with this:<br />
<br />
<pre class="csharp" name="code">using System;
using System.Collections;
using System.Text;
namespace FizzBuzz
{
class Program
{
static void Main(string[] args)
{
foreach (string i in fizzBuzz())
{
Console.WriteLine(i);
}
Console.ReadLine();
}
private static IEnumerable fizzBuzz()
{
bool isReplaced = false;
for (int i = 1; i < 101; i++)
{
if (i % 3 == 0)
{
yield return "Fizz";
isReplaced = true;
}
if (i % 5 == 0)
{
yield return "Buzz";
isReplaced = true;
}
if (!isReplaced)
{
yield return i.ToString();
}
isReplaced = false;
}
}
}
}
</pre>
This works, but for numbers like 15, it outputs Fizz and Buzz on two separate lines. It would be better off combining the 3 and 5 multiple case first, and having one if/else statement.<br />
<br />
By the way, this doesn't loop twice - it starts the loop in main, goes into the fizzBuzz method, runs the logic until it gets to a "yield" statement, then finishes the loop in main, then runs the next iteration of the loop. It then picks up where it left off in the fizzBuzz method. This approach would let you format each string iteration differently if you wanted to (i.e. having the word "Fizz" output in green).<br />
<br />
So my next thought was to compare my solution to others. I found <a href="http://c2.com/cgi/wiki?FizzBuzzTest">this</a>, which has a number of solutions in many different languages (none use the enumerable interface idea).<br />
<br />
The Articulating Ideas blog has a <a href="http://www.zoharbabin.com/which-fizzbuzz-solution-is-the-most-efficient">really interesting post</a> on efficient ways to solve the problem using C# - the bitwise operator one is very interesting (and a bit beyond my current coding skills):<br />
<br />
<pre class="csharp" style="background-attachment: initial !important; background-clip: initial !important; background-color: #f9f9f9; background-image: none !important; background-origin: initial !important; clear: none !important; color: #110000; font-size: 12px; line-height: 1.333 !important; overflow-x: visible !important; overflow-y: visible !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important; width: auto !important;"><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: green;">[</span><span style="color: green;">]</span> messages <span style="color: green;">=</span> <span style="color: green;">new</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: green;">[</span><span style="color: green;">]</span><span style="color: green;">{</span><span style="color: #0600ff; font-weight: bold;">null</span>, <span style="color: #666666;">"Fizz"</span>, <span style="color: #666666;">"Buzz"</span>, <span style="color: #666666;">"FizzBuzz"</span><span style="color: green;">}</span><span style="color: green;">;</span>
<span style="color: #6666cc; font-weight: bold;">int</span> acc <span style="color: green;">=</span> <span style="color: red;">810092048</span><span style="color: green;">;</span> <span style="color: teal; font-style: italic;">//11 00 00 01 00 10 01 00 00 01 10 00 01 00 00</span>
<span style="color: #6666cc; font-weight: bold;">int</span> c <span style="color: green;">=</span> <span style="color: red;">0</span><span style="color: green;">;</span>
<span style="color: #0600ff; font-weight: bold;">for</span> <span style="color: green;">(</span><span style="color: #6666cc; font-weight: bold;">int</span> i<span style="color: green;">=</span><span style="color: red;">1</span><span style="color: green;">;</span> i <span style="color: green;"><</span> <span style="color: green;">=</span> N<span style="color: green;">;</span> <span style="color: green;">++</span>i<span style="color: green;">)</span> <span style="color: green;">{</span>
c <span style="color: green;">=</span> acc <span style="color: green;">&</span> <span style="color: red;">3</span><span style="color: green;">;</span>
result <span style="color: green;">+=</span> <span style="color: green;">(</span>c <span style="color: green;">></span> <span style="color: red;">0</span> <span style="color: green;">?</span> messages<span style="color: green;">[</span>c<span style="color: green;">]</span> <span style="color: green;">:</span> i<span style="color: green;">.</span><span style="color: blue;">ToString</span><span style="color: green;">(</span><span style="color: green;">)</span><span style="color: green;">)</span> <span style="color: green;">+</span> <span style="color: #666666;">", "</span><span style="color: green;">;</span>
acc <span style="color: green;">=</span> acc <span style="color: green;">>></span> <span style="color: red;">2</span> <span style="color: green;">|</span> c <span style="color: green;"><</span> <span style="color: green;"><</span> <span style="color: red;">28</span><span style="color: green;">;</span>
<span style="color: green;">}</span></pre>
<br />
<br />
I'm surprised that this solution wasn't the clear winner (it tied another very slick version that doesn't use modulo, and was only a little faster than another using modulo). Division is usually the most expensive math operation, and shifting bits lets you get around that very cleverly (if you are clever enough to know how to use it...).<br />
<br />
It really is true that 100 different programmers will come up with 100 different solutions to the same problem.<br />
<br />Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com1tag:blogger.com,1999:blog-3296335177913866771.post-2904091660768968042012-02-04T22:41:00.002-05:002012-02-04T23:00:39.255-05:00C# "??" operatorI just ran across something I hadn't seen before - a two question mark operator. I found it in the AccountMembership service method in the default AccountModel.cs file that's used when you start a new ASP.NET MVC 3 project. Here's the line of code:
<br />
<pre class="csharp" name="code">_provider = provider ?? Membership.Provider;
</pre>
I did a little research and found it's just a shortcut for this, using an iif/conditional:
<br />
<pre class="csharp" name="code">_provider = provider != null ? provider : Membership.Provider;
</pre>
which of course is a shortcut for this regular if statement:
<br />
<pre class="csharp" name="code">if(provider != null) {
_provider = provider;
} else {
_provider = Membership.Provider;
}
</pre>
<br />
More info here: <a href="http://msdn.microsoft.com/en-us/library/ms173224.aspx">http://msdn.microsoft.com/en-us/library/ms173224.aspx</a>
<br />
Very cool. I love the terseness of C#.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-15052727056029903982011-10-13T14:23:00.000-04:002012-02-04T22:40:15.859-05:00Not happy with .NET's FileSystemWatcherI created a Windows Service to watch for a specific file, which heavily relies on the FileSystemWatcher class. I'm not sure it was worth the hassle over using Timer to just check for the file at a certain interval.<br />
<br />
FileSystemWatcher fires an event when a file is created, which is great, except that it seems that it fires the millisecond the file starts to be created (acting more like a "Creating" event...). This was causing problems for me, because my relatively small file was apparently still being written to while I was trying to send it as an attachment and subsequently delete it. There is no "ReallyDoneBeingCreated" event. There is a "Change" event, but that was causing me even more problems.<br />
<br />
I ended up adding "Thread.Sleep(30000)" (waits for 30 seconds) after it sees there is a new file. This is crap. I HATE doing stuff like this, but it works, since it takes about a second to create the file in my case. The only other thing I could think of doing is having some crazy recursive try/catch loop that fails, tries again and again until it succeeds. This is ugly, too, but would probably be better if the file size was unknown.<br />
<br />
My kludge is upsetting me to the point that I may just end up re-writing the code to use a timer interval to check for a new file, but that is a bit backwards, too. Can't win. Anybody know of a better way of doing this?Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-27907703087062686272011-09-09T09:26:00.000-04:002011-09-09T09:34:19.851-04:00Converting a QuickTime .mov (ProRes codec) to a Windows AVIOn the phone last month to our video production agency, I told them I could work with any video format. Yesterday I was afraid they had proved me wrong.<br />
<br />
They sent me a QuickTime .mov encoded with the ProRes codec. This was their source format, and the goal was to ensure no loss of quality on their side, so this wasn't just some crazy attempt on their part to trip me up :-). In any case, I figured any standard video converter (like AVC) could handle this, but nothing I tried worked. I then remembered the amazing FFMPEG from my DVR-building days, and was sure this could easily do the conversion if I could just figure out the correct command-line args. Still no luck. I kept getting the error, "swScalar: Unknown format is not supported as input pixel format". Some searching provided some clues that this was due to mapping, so based on a forum post suggestion, I tried adding the flags, "-map 0:0 -map 0:1". I then got a "codec type mismatch error". I installed the ProRes QuickTime decoder, but this didn't help either.<br />
<br />
Finally, I happened upon the following solution:<br />
<br />
- install AviSynth (<a href="http://avisynth.org/mediawiki/Main_Page">http://avisynth.org/mediawiki/Main_Page</a>)<br />
- add the QTSource dll to AviSynths "plugins" directory (<a href="http://www.tateu.net/software/dl.php?f=QTSource">http://www.tateu.net/software/dl.php?f=QTSource</a>)<br />
- install VirtualDub (<a href="http://www.virtualdub.org/">http://www.virtualdub.org/</a>)<br />
<br />
Then you just need to write an AviSynth script in the same directory as the video file and name it with an ".avs" extension:<br />
<pre class="csharp" name="code">QTInput("C:\test.mov", audio=1)
BicubicResize(720,486,0.1,1.00).AssumeFPS(29.97)
</pre>
<br />
(BTW, the documentation for QTSource says to use audio=true, but AviSynth was having none of that.)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
- open the .avs file as if it was a video in VirtualDub<br />
- save as .avi<br />
<br />
Whew. I was about five minutes away from admitting defeat and asking them for a different format. Aside from bruising my ego a bit, this would have wasted at least another day or two that I didn't have to spare.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com3tag:blogger.com,1999:blog-3296335177913866771.post-68744984032261326152011-07-28T11:52:00.007-04:002012-02-02T13:06:56.973-05:00C# recursive file counterI am constantly surprised with how easy .NET makes things sometimes. I needed a quick recursive file counter output to a report, and was able to write this in just a few minutes, using some new methods available in .NET 4 (EnumerateFiles/Directories) (UPDATE: not sure what I was thinking here - .GetFiles()/.GetDirectories() provides pretty much the same thing - array vs. generic list):<br />
<br />
<pre class="csharp" name="code">static void Main(string[] args)
{
string startingDir = @"C:\files";
string reportFile = @"C:\file_count.txt";
using (StreamWriter report = new StreamWriter(reportFile))
{
countFiles(startingDir, report);
}
}
private static void countFiles(string dir, StreamWriter report) {
DirectoryInfo directory = new DirectoryInfo(dir);
IEnumerable<FileInfo> files = directory.EnumerateFiles();
IEnumerable<DirectoryInfo> dirs = directory.EnumerateDirectories();
report.WriteLine(String.Format("{0}: {1}", dir, files.Count()));
foreach (var d in dirs)
{
countFiles(d.FullName, report);
}
}</pre>
<br />
<br />
It works very quickly (100,000 files in as much as 8 directories deep in less than 30 seconds on a modest machine), and couldn't have been more straightforward to write.<br />
<br />
BTW, if all you need is just a total file count, this works well:<br />
<br />
<pre class="csharp" name="code">DirectoryInfo d = new DirectoryInfo(startingDir);
int totalCount = d.EnumerateFiles("*.*", SearchOption.AllDirectories).Count();</pre>
<br />
<br />
After thinking about this some more, I wonder if this may even be easier/more efficient with LINQ. I've got to try that for fun, and check the performance of each.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com1tag:blogger.com,1999:blog-3296335177913866771.post-85115638611753570612011-07-20T09:49:00.019-04:002011-07-20T17:03:40.889-04:00Graphical Saccades<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNnU_ZiYU4BlVpLbO63dWM3X6ZaoHF2S1iwzNfD-L91aSAIZuUunB-dvMT0f0JyvyNys7JI2MqDnhFnvTN5V1tBriujPFDxWagYLPJubj5DBQgOzMw6ErDHfIQM46jukiQw63sas_hVAY/s1600/saccades.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="float:right; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 366px; height: 125px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNnU_ZiYU4BlVpLbO63dWM3X6ZaoHF2S1iwzNfD-L91aSAIZuUunB-dvMT0f0JyvyNys7JI2MqDnhFnvTN5V1tBriujPFDxWagYLPJubj5DBQgOzMw6ErDHfIQM46jukiQw63sas_hVAY/s400/saccades.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5631451754377793602" /></a>My son is working through some vision issues, and one of the exercises his vision therapist has him do is called "saccades", basically quick movements of the eyes in the same direction. She gave us a web site that had an animated gif that sequentially displayed a bunch of lines of numbers, at varying distances apart.<div><br /></div><div>This was quite boring for my son, so my wife had an idea for me to make a version of this with pictures of things that he liked. He absolutely LOVES this version of the "game", and wants to play it all the time! </div><div><br /></div><div>The exercise randomly displays 20 images at varying distances (five lines with four images per line), and can include the same image more than once. The speed can be adjusted before the run, or in progress.</div><div><br /></div><div>From what I understand, the important part of the exercise is just to track and identify sequentially revealed items at the same pace, but at varying distances apart. I would love to hear from any vision therapists out there, though, to make sure that this is correct, and that a graphical version still satisfies the objective. Our therapist is out for a few weeks, so I can't ask her about it now, but I'll update the post when I get any new information. </div><div><br /></div><div>If you want to try it out yourself, <a href="https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B-n7GjZtU23MYmJiM2FhNDktNWM5Ni00MTk3LWFjYWMtMTI5M2U1OTExZTI2&hl=en_US">here's a zip file</a> (under the Google Docs icon, click "File" --> "Download Original") with the code and a few sample images. It's set up to go with 30 random images, but it's easily customizable if you want to use your own images, or add more. To run it, just unzip the .zip file, and double-click on the .html file that best fits your screen.</div><div><br /></div><div>In the meantime, I'm working on getting the exercise set up on its own web site, but I'm having a hard time finding a free web site provider that allows HTML.</div><div><br /></div><div>Technically, this was a breeze to do with jQuery. I define an array of images, and use code similar to JavaScript built-in "setTimeout", but with the ability to adjust the interval in progress (thanks, <a href="http://stackoverflow.com/users/8815/peter-bailey">Peter Bailey</a>, for the brilliant <a href="http://stackoverflow.com/questions/1280263/changing-the-interval-of-setinterval-while-its-running">function</a>). The key lines are:</div><br /><pre name="code" class="java">vi = setVariableInterval(function() {<br /> if (currentItem == 20) {<br /> this.stop();<br /> }<br /><br /> randomSpacer = Math.floor(Math.random() * maxPixelLength) + minPixelLength;<br /> randomPicture = Math.floor(Math.random() * pictures.length);<br /><br /> replacementPic = "<img class='p' src='" + pictures[randomPicture].src + "' width='100' height='75' style='margin-left: " + randomSpacer + "px;' />";<br /> $(pics[currentItem]).replaceWith(replacementPic);<br /><br /> currentItem++;<br />}, initialInterval);<br /></pre><div><br />"randomSpacer" and "randomPicture" create random numbers up to the defined maximums. And the jQuery line just replaces each placeholder with a random image. "pics" lets me access via index all images that use the "p" class (they are initially set up with placeholders).</div><div><div><br /></div><div><pre name="code" class="java">pics = $(".p");</pre></div><div></div></div>Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-31860440553852299522011-06-09T08:25:00.004-04:002011-06-09T12:16:47.472-04:00Avoiding the "Destination configuration already initialized" error in SAP .NET Connector 3<div>SAP's documentation suggests using a line similar to the following to create a connection to SAP:</div><div><br /></div><div>RfcDestinationManager.RegisterDestinationConfiguration(new Config());</div><div><br /></div><div>where Config() is a class that contains connection settings.</div><div><br /></div><div>This works fine, except, you occasionally get the error, "Destination configuration already initialized", because the connection hasn't timed out. SAP's documentation that I've seen (the .chm help file and the "Overview" document) doesn't address this issue at all, and their sample code doesn't contain any examples of how to close a connection.</div><div><br /></div><div>I've found that the following code works:</div><div><br /></div><div><div>Config c = new Config();</div><div>RfcDestinationManager.RegisterDestinationConfiguration(c);</div></div><div>...</div><div>(processing code)</div><div>...</div><div>RfcDestinationManager.UnregisterDestinationConfiguration(c);</div><div><br /></div><div>However, if you've just tried to connect without using "unregister", you'll have to wait until the old connection times out itself before trying the code above (the sample config code SAP provides keeps the connection open for 10 minutes).</div><div><br /></div><div>Overall, I've found the new SAP Connector 3 to be a HUGE step up from v2, though it is quite a pain having to re-write all of my v2 applications. But I easily prefer a few months of re-writing over being tied to VS2003. Thanks, SAP, for updating this - I thought you had forgotten about us .NET developers.</div><div><br /></div><div><br /></div>Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com11tag:blogger.com,1999:blog-3296335177913866771.post-26019268804853510282011-04-13T09:51:00.005-04:002011-04-13T10:06:21.219-04:00Displaying ActiveDirectory's "whenChanged" attribute in C#"whenChanged" comes through without the time offset. Not a big deal to fix it, but a quick Google search yielded no results on how to deal with it. Here's my solution to properly display Eastern Daylight/Standard time:<br /><pre>TimeZone localZone = TimeZone.CurrentTimeZone;<br />DateTime generalizedDate = DateTime.Parse(result.Properties["whenChanged"][0].ToString());<br />double hourDelta = localZone.IsDaylightSavingTime(generalizedDate) ? -4D : -5D;<br />DateTime lastUpdated = generalizedDate.AddHours(hourDelta);</pre>BTW, Sysinternals' <a href="http://technet.microsoft.com/en-us/sysinternals/bb963907">AD Explorer</a> is great for finding out meta information (i.e. data type, property name) about AD attributes.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com1tag:blogger.com,1999:blog-3296335177913866771.post-86953787345064252582010-07-13T16:45:00.006-04:002010-07-13T16:55:41.472-04:00EXCEPT to compare output of two queries<span style="font-weight: bold;">Very</span> helpful SQL Server 2005+ commands:<br /><br /><a href="http://weblogs.sqlteam.com/jeffs/archive/2007/05/02/60194.aspx">http://weblogs.sqlteam.com/jeffs/archive/2007/05/02/60194.aspx</a><br /><br />I had to find the different rows of two pretty complex, non-related queries, and decided to look up if there was an easier way to do than by exploiting UNION (a technique I think I picked up from the same author, actually...). Turns out you just need to put and EXCEPT in between the queries. That's it.<br /><br />I just found this last week and have probably already used it five times. It makes me want to get a book on SQL Server 2008 to see what other time-savers I can find, especially I'm analyzing LOTS of data these days.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-13956490817371974512010-06-25T15:17:00.003-04:002010-06-25T15:24:45.589-04:00Quick way to see what SQL data was updatedI had a crazy update query I was trying to troubleshoot, and for the life of me could not figure out why it insisted on updating some rows after they had already been updated by a prior run. Here's the quick one-time-use trigger I came up with to see exactly what was updated:<br /><br /><pre><br />CREATE TRIGGER dbo.ViewUpdatedRecords<br /> ON (table name)<br /> AFTER UPDATE<br />AS<br />BEGIN<br /> SELECT *<br /> INTO UpdatedRecords<br /> FROM INSERTED<br />END<br />GO<br /></pre><br /><br />It only works one time, as SELECT INTO creates a table and will complain if a table by that name already exists. But it only took a minute to write, and helped me solve my issue very quickly.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-89935456567027862092010-04-27T22:48:00.003-04:002010-04-27T23:14:58.735-04:00New DVR, finallyI've finally put together a DVR out of spare parts. I built one before (and even got mentioned in <a href="http://www.wired.com/science/discoveries/news/2006/03/70328?currentPage=2">Wired</a> magazine), making my regular desktop do double duty, with a wireless 802.11B connection to the living room. On the TV side, a small Linux box (Hauppauge MediaMVP) decoded the video and handled the remote. It worked well about 95% of the time, but when it didn't work, it was a nightmare to troubleshoot. And you couldn't use the microwave, talk on the phone, or look funny at it... It also took me a month to build - mostly spent researching and tuning my network connection and figuring out my way around FFMPEG to compress the video.<br /><br />When we moved to another house, it just wouldn't work reliably anymore, no matter what I did. I ditched the project for awhile, but picked it back up again when I got a free 10-year old computer - a Celeron 733Mhz with 64MB RAM. This was more an exercise in getting a slimmed down version of Linux (Mythbuntu/Xubuntu) to work more than anything else. I was able to get it to record shows, but not play them :-)<br /><br />A few weeks ago, my neighbor gave me an old Dell 4300 1.8GHz machine. It wouldn't boot, but I found out that all it needed was a new power supply. I put an nVidia 5200 128MB card in it, a new quieter fan, and 1GB of RAM that I had saved from another dead computer, and it runs XP Media Center 2005 great (as long as you buy the $20 nVidia PureVideo software - not sure why this is required, but it is). It even runs Hulu perfectly (if you set it to medium quality) via a browser, but it chokes using Hulu desktop for some reason.<br /><br />So now my kids are happy b/c they always have their PBS shows on tap, and my wife is happy, as she can watch her CBS shows. And this one only took me a few hours to set up. The thorn has been removed from my side.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-30552311181774839392010-04-09T09:52:00.010-04:002010-04-09T10:46:42.748-04:00SQL job retry (with additional logic) on failHere's some code I put together to get a SQL Server 2005 job to retry on fail. I spent a while looking for how to just have the job scheduler retry on fail, and found nothing. Of course, right after I coded and tested this, I found out a way to easily retry individual steps on fail, which is probably the way you want to do it 95%+ of the time :-), but just in case someone has the need to retry a job programatically and insert additional logic, or have more control over the process, or just wants to see how it could otherwise be done (ok, maybe at this point I'm just trying to justify wasting 20 minutes of my life coding this manually...), here's the code:<br /><br />USE msdb<br /><br />IF(<br />SELECT COUNT(*)<br />FROM sysjobhistory<br />WHERE<br /> -- status 0 = error<br /> run_status = 0<br /> -- isolate the step we're looking for<br /> AND step_name = '(job outcome)'<br /> -- job unique ID (find this out by going to the job properties, and selecting "Script")<br /> AND job_id = '48F4EE80-62C7-4DFF-8F6F-D009F616DA07'<br /> -- today's date in the same style as the job history table format<br /> AND run_date = CONVERT(VARCHAR(8), GETDATE(), 112)<br />) > 0<br />BEGIN<br />-- insert additional logic here<br /><br />EXEC sp_start_job @job_name='[JOB YOU WANT TO RETRY]'<br />END<br /><br /><br />And here's the easy way:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij1MiAA0ycZw35Bh072O2AOHn4Vjz7GD0qYFwhbkYlZ762KjVFVPBZM3nTbE5NhcLY39AU7_VttqpJtHAh1IjqsJkBxo2L5BY_WO1d5tIY3xSBU1tdlfXu4asOor1liUk_boD_WnzdtmY/s1600/job_step.png"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 400px; height: 130px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEij1MiAA0ycZw35Bh072O2AOHn4Vjz7GD0qYFwhbkYlZ762KjVFVPBZM3nTbE5NhcLY39AU7_VttqpJtHAh1IjqsJkBxo2L5BY_WO1d5tIY3xSBU1tdlfXu4asOor1liUk_boD_WnzdtmY/s400/job_step.png" alt="" id="BLOGGER_PHOTO_ID_5458142376782452114" border="0" /></a>Right-click on the job, choose "Properties". Click on "Steps", and select the step you want to retry. Click on "Advanced", and set the "Retry attempts" and "Retry interval". Repeat for additional steps. Done. D'oh!Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-58425031878183880192010-01-13T10:53:00.013-05:002010-01-14T21:31:33.494-05:00Back to WindowsI'm back on Windows after a few months of using Linux exclusively at home. I still like Linux quite a bit, and am running a few distros in virtual machines now just so I can keep my skills up (and to support relatives who I switched to Linux - more on that in a bit), but I switched my main OS back to Windows because of the lack of usable audio and video tools, which I use all the time.<div><br /></div><div>Not sure if "usable" is really the right word, but for me it's just so much more of a pain to work with the audio and video tools I found on Linux that were supposedly "best of breed" (Rosegarden and Ardour for audio, Kino and PiTiVi for video. I tried to get the Cinelerra and the highly-rated OpenShot video editor to work, but ran into lots of issues.) The audio tools were very difficult to set up, and the interfaces are nowhere near as slick as Mackie Tracktion 2 for Windows. Kino and PiTiVi were a total joke.</div><div><div><br /></div><div>I initially bought into the idea that since it was open source software, I could fix and improve the software I wanted to work with. But the IDEs that I tried are nowhere near the level of VisualStudio, the languages they were written in I was unfamiliar with, and I just don't have the time to learn right now. Never mind that coding for audio and video applications is difficult to begin with. I might get into this someday, but I didn't want to deal with it now (I usually LOVE this type of stuff).</div><div><br /></div><div>I did have great successes with converting two of my computer virus-prone relatives to Linux. One works for a major financial institution that has web software that won't work without the Microsoft JVM! Also, Windows security updates wreak havoc on the software. My solution was to install Ubuntu, and use Sun's VirtualBox with a working snapshot of XP. If he ever got a virus, he could just revert back to the snapshot. The financial software now works perfectly, and for the first time in years, he actually like using his computer. I also put my dad on Linux Mint, and he keeps telling me how much he loves it (aside from a few minor annoyances, but nothing like dealing with viruses and malware on Windows).</div><div><br /></div><div>To be fair, both were using Windows XP - another virus-prone relative who I do tech support for has been on Windows 7 for a few months now (protected primarily with Microsoft Security Essentials), and has not had an issue yet, and loves her computer now as well.</div><div><br /></div><div>There were initial hardware compatibility and other issues with both of these installs that took a bit of time for me to work through, but both systems are rock-solid stable now. I think Linux can work very well if you are just primarily browsing the web and just need to work with Office-type software (Sun's OpenOffice works very well if you're not doing anything crazy). It can also work well in other situations, depending on your exact needs.</div><div><div><br /></div><div>Having switched back to XP myself, I find myself missing a few of the nice features on Linux now. The Bash shell is wicked powerful and a quick way to do system administration, having multiple virtual desktops is great, and I love how configurable pretty much everything is. Also, not having to worry about viruses nearly as much is awesome. I'm sure I will try it again someday.</div><div><br /></div></div></div>Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com4tag:blogger.com,1999:blog-3296335177913866771.post-59174918020613658532009-11-05T10:38:00.012-05:002009-11-06T11:12:37.446-05:00Xubuntu 9.04 running smoothly on a 1999 iBookMy friend Shaun gave me an old iBook to play around with, and after messing with it for about a week, I gave up on it. It was incredibly slow, especially with networking. I looked online and did lots of optimizations, and got it to run a bit faster, but it was just painful to use. Since I didn't have the OS reinstall CD, I figured I was out of options.<br /><br />About a month ago, I started playing around with Linux, and am really getting into it now. I did a few searches and found that there's PowerPC builds of Ubuntu. Given the modest hardware specs (300MHz G3, 192MB RAM), I decided to try <a href="http://cdimage.ubuntu.com/xubuntu/ports/releases/jaunty/release/">Xubuntu 9.04 (alternate install)</a>. Xubuntu doesn't have all the slickness of Ubuntu, but it usually works really well on old hardware (I've got it zipping along on an old 700MHz PIII box w/ 192MB RAM, that functions as my DVR (using <a href="http://www.mythbuntu.org/">Mythbuntu</a>)).<br /><br />I'll give a rundown of the problems I encountered below (mostly related to the iBook itself, not Xubuntu), but the bottom line is after ~3 hours, I have a very decent-performing and very usable laptop now.<br /><br />Problems<br />- The CD drive wouldn't recognize a CD. I <a href="http://support.apple.com/kb/HT1379">reset the PRAM</a> and shot come compressed air onto the laser. Holding the "C" key down on boot still didn't work, but holding the "Option" key down gave me a boot menu - the CD took a while to show up, but it eventually did.<br /><br />- The battery wasn't holding a charge. There were two problems here - the power cord was a bit frayed and had to be positioned just right to work (temporarily solved with electrical tape), and the <a href="http://support.apple.com/kb/HT1431">PMU needed to be reset</a>.<div><br /></div><div>- Wireless wouldn't work. Wireless issues Ubuntu turned me off of Linux two years ago, but I was hoping that since this was a PPC build, that they would have the Apple Wireless stuff figured out. And they do, except that Xubuntu didn't support the wireless encryption scheme I was using. Fortunately, this was an easy fix - just install and configure <a href="http://wicd.sourceforge.net/">wicd</a> (it's in the repositories - no need to download it from the web site).</div><div><br /></div><div>Done - working laptop. I kind of feel bad having deMAC-ed a Mac, though (I was a HUGE Mac fanboy back in the day). Maybe I'll put a dock application at the bottom of the screen as an homage :-), or just go all out and do <a href="http://xubuntublog.wordpress.com/2008/02/15/design-your-own-desktop-with-xfce-44-part-2/">this</a>.</div><div><br /></div><div>UPDATE: Just found this helpful link that lists all distros that support the PowerPC architecture:</div><div><a href="http://distrowatch.com/dwres.php?resource=ppc">http://distrowatch.com/dwres.php?resource=ppc</a></div><div><br /></div>Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com1tag:blogger.com,1999:blog-3296335177913866771.post-31054192570545279302009-09-30T09:51:00.017-04:002009-10-12T10:51:09.977-04:00Moving to Linux, at least temporarily<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCtYKM_tVwUUV8BMJdqxABxRJF-ic2iR7fIjYbm1ZmRWaha6IVgCLpszpwAHcs2IUjG-t6ylEaiCr4TBWHyZooaZAr4dthKVPWzeFPkUayuvdfqLax5wvzYqz9ftI_T_J7sHJIo9q_nZg/s1600-h/thumb_gloria.png"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCtYKM_tVwUUV8BMJdqxABxRJF-ic2iR7fIjYbm1ZmRWaha6IVgCLpszpwAHcs2IUjG-t6ylEaiCr4TBWHyZooaZAr4dthKVPWzeFPkUayuvdfqLax5wvzYqz9ftI_T_J7sHJIo9q_nZg/s200/thumb_gloria.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5387289884650183154" /></a>Something was up with my Windows install, and for the life of me I couldn't figure it out. The sound was very choppy, Windows startup time and Internet browsing were incredibly slow. I ran every virus/spyware/malware scanner I could think of, cleaned the registry out carefully with CCleaner, reinstalled my sound card drivers, removed always running apps that I didn't need, defragmented the hard drive, defragmented the page file and registry hives, etc, and still had the same problem.<br /><br />About to reinstall Windows XP on my 10-year-old computer, I decided to give <a href="http://www.ubuntu.com/">Ubuntu</a> another shot, pledging to boot only Ubuntu for a week, and attempting to fix whatever issues came up. I had tried it at v7.04 and was generally impressed, but eventually scrapped it mostly because Windows was working fine for me, my Digital Audio Workstation wasn't supported, and there were no "killer apps" I could think of to keep me on Linux.<br /><br />So I installed Ubuntu 9.04, and was about as impressed as I was with 7.04. I worked through a few initial issues, but everyone in the forums I was reading said something like, "[whatever issue] isn't a problem on <a href="http://www.linuxmint.com/">Linux Mint</a>". After reading that for about the 5th time, I decided to make a Live USB of Linux Mint 7, and was completely blown away. Pretty much everything just worked out of the box, and the interface looked absolutely stunning and more user-friendly. What really sold me, though, was that it was based on Ubuntu 9.04, so it's got lots of built-in support.<br /><br />So I wiped Ubuntu and installed Mint, and mostly haven't missed Windows at all. I still do have a full-screen video issue using the generic video drivers - the "nv" drivers work, but only give me a resolution of about 320 x 240. UPDATE: Installing the latest nv driver fixed this.<br /><br />Most of the programs I want are available on Linux - Firefox, Photoshop (via Wine), Picasa, and Netbeans, mostly. But I can't find a DAW that supports MIDI to work. I spent quite a bit of time reading up on this, and it looks like I need a realtime Linux kernel, which can be installed with apt-get, but it seems like nobody can get it working with Linux Mint. I did find <a href="http://revver.com/video/1187744/hyper-low-latency-audio-with-a-real-time-kernel/">this video</a>, but it looks very complex (though promising). I've got to spend a lot more time with it, but I may just set up a Windows partition with only my DAW on it.<div><br /></div><div>The "killer app" for me so far is not having to really worry about viruses, spyware, etc. nearly as much (the computer is used by a number of people). I do have ClemAV running now, and am looking into whether or not I need more protection, but I like what I've read so far - that Linux out-of-the-box is leaps and bounds above Windows in regards to these things.</div><div><br /></div><div>And my son LOVES the Linux Education games - GCompris and Childsplay. To my surprise, he was WAY into the Childsplay letter finding game, which is great because he's working on his lower case letters now. I can't wait to hack these games a bit and put in some customized graphics for the kids.</div>Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com2tag:blogger.com,1999:blog-3296335177913866771.post-52820307349404705892009-07-10T14:47:00.009-04:002009-09-30T13:20:30.491-04:00Quick SQL --> Excel export w/ column namesI know there's lot of ways to do this, including an SSIS/DTS package, but here's another quick way I pieced together for ad-hoc exports with that I haven't seen outlined before:<br /><br />1. Run the query in SQL Server Management Studio (w/ "Results to Grid")<br />2. Copy all data from the grid (right-click on the unlabled box at the top left of the grid, choose "copy"), and paste into second row in Excel.<br />3. Back in SQL, run this query:<br /><pre name="code" class="SQL"><br />SELECT sc.name<br />FROM syscolumns sc<br /> INNER JOIN sysobjects so<br /> ON so.id = sc.id<br />WHERE so.name = '[table name]'<br />ORDER BY sc.colid<br /></pre><br />4. Paste the results into Excel in a new sheet.<br />5. Copy the row, then "paste special" --> "transpose" into the first row in the original worksheet, so that they paste as columns.<br /><br />This will probably break down for very large tables, but I just did this with 96 columns, and 10,000+ rows without issues.<br /><br />Some more ways to accomplish this:<br /><a href="http://www.mssqltips.com/tip.asp?tip=1202">http://www.mssqltips.com/tip.asp?tip=1202</a><br /><br />BTW, not sure why there's not a "Results to .csv format" in SQL Server Management Studio. "Results to Text" seems rather useless...<br /><br />UPDATE: <a href="http://www.davidkearns.com/">Dave Kearns</a> points out an even easier way to do this:<br /><br />In SQL Server Management Studio, go to "Tools" --> "Options" --> "Query Results" --> "SQL Server" --> "Results to Grid" --> check "Include column headers when copying or saving the results"Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com2tag:blogger.com,1999:blog-3296335177913866771.post-31142346474584222502009-04-17T12:08:00.011-04:002009-07-09T16:27:59.182-04:00Forcing label values to be displayed to the right of a bar (ASP.NET 3.5 chart control)As I've previously written, the new ASP.NET 3.5 chart control is great. However, a minor thing that doesn't work well is displaying value labels for bar charts. It displays the value to the right of the bar except for the longest bar when it determines that it wouldn't fit within the scale. So, if you have a bar with a value of 98, and you have your axis interval set to 25, it will display "98" in the bar. This doesn't necessarily look good, depending on what color the bar is, and it is also inconsistent with the other bars.<br /><br />Here's my solution (C#):<br /><pre name="code" class="csharp"><br />Chart1.DataBound += delegate(System.Object o, System.EventArgs ea) {<br /> double longestBarLength = Chart1.Series[0].Points.FindMaxByValue().YValues[0],<br /> padding = 10d,<br /> roundedUpBarLengh = Math.Ceiling((longestBarLength + padding) / 25) * 25;<br /><br /> Chart1.ChartAreas[0].AxisY.Maximum = roundedUpBarLengh;<br />};<br /></pre><br /><br />I'm determining the longest bar length w/out looping thanks to a nice built-in function "FindMaxByValue()" which gets me access to the DataPoint object with the largest value, and I'm just grabbing the Y Value from it (in my case, there's only one Y value).<br /><br />Then I specify a set padding to make room for the value label to be displayed on the right side of the bar (10 seems to work well for numbers in the 100's at least). Lastly I'm pushing the value whatever the longest bar length is to the nearest 25 and setting the axis max value to that number.<br /><br />This all needs to be done after the data is already there, obviously, so this is all wrapped in the databound event handler.<br /><br />I'll add pics later.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-62694474119654177092009-03-26T13:19:00.008-04:002009-03-26T14:38:21.662-04:00Great .NET 3.5 Charting Control from MicrosoftI don't know how I missed this when it was released a few months ago, but this control is awesome - it generates very professional-looking charts that you used to have to pay hundreds of dollars for, and it looks just as good as the best charting tools I've seen.<br /><br />The organization scheme seems a little convoluted to me, but it probably just seems that way because I was just trying to do a simple 3D bar chart, and the scheme is set up to allow a very high level of customization. I also ran into a few web.config-related snags while getting my code up and running, but nothing that I couldn't fix within a few minutes of searching the web.<br /><br />Example screenshots and everything you need to get started are <a href="http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx">here</a>.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0tag:blogger.com,1999:blog-3296335177913866771.post-29587874621486282302009-02-18T09:06:00.003-05:002009-02-18T11:05:21.935-05:00Interesting SAP JCo error<span style="color:blue;"><b>Exception Details: </b> com.sap.mw.jco.JCO$Exception<br />Type conflict when calling a function module (field length).<br /><br /><b> Possible Source of Error: </b><br /> Class Name: <i>com.sap.mw.jco.rfc.MiddlewareRFC$Client</i><br /> File Name: <i>MiddlewareRFC.java</i><br /> Method Name: <i>nativeExecute</i><br /> Line Number: <i>-2</i></span><br /><br />Line Number -2? Those SAP guys sure are tricky with their coding before the file even starts.<br /><br />BTW, SAP JCo is a major nightmare to get working. If somebody brings you a JCo project and says "this should be easy", my advice is to run away as fast as you can.<br /><br />UPDATE: I solved this problem, no thanks to the error message. I was trying to pass in a field as an Export instead of an Import. Which makes perfect sense, expect the original VBScript/COM code that I am re-writing this from uses the call "[function].Exports()" for an import (and the code works!).Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com1tag:blogger.com,1999:blog-3296335177913866771.post-72421184108797439682008-12-11T19:51:00.010-05:002008-12-18T09:33:10.420-05:00Camera Focal Range Data applicationI'm currently using a point & shoot camera (Canon S2 IS), but have a DSLR on the way (Canon Rebel XS). The DSLR comes with a kit lens that ranges from 18-55mm (28.8mm - 88mm in 35mm equivalents), which is quite a bit shorter than my p&s (up to 432mm equiv!). So I got worried that I wouldn't be too happy with just the kit lens. At the same time, I wanted to try out LINQ in .NET, so a quick project was born...<br /><br />I wrote a bare-bones console application that reads in EXIF data from images, extracts the focal length of each, and uses some simple LINQ queries that lets me see exactly how many photos were taken in wide, normal, tele, and super tele modes. It recurses through directories from a starting directory you specify, and tries to get info on all JPEG images.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifLjaQ_oe_GGUZg3vVh9oxVoplUgVSI2rz96PT8FgEQLdgbpsEiVLl1tavH-3spghvcprUY6Ep9uV3GN60RFuPg440gmX6kEKfh58efAG01hJL7DCAZWkIVU1LHGXLxYEkIpwEQc2Kcr4/s1600-h/screenshot.gif"><img style="cursor: pointer; width: 400px; height: 166px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifLjaQ_oe_GGUZg3vVh9oxVoplUgVSI2rz96PT8FgEQLdgbpsEiVLl1tavH-3spghvcprUY6Ep9uV3GN60RFuPg440gmX6kEKfh58efAG01hJL7DCAZWkIVU1LHGXLxYEkIpwEQc2Kcr4/s400/screenshot.gif" alt="" id="BLOGGER_PHOTO_ID_5278702747797925906" border="0" /></a><br /><br />Right now, there's no nice GUI, it's not multi-threaded, you can only search one folder at a time, there is no progress bar, and you can't actually see what images fall into which category, but if there's any interest in this app at all, I'll add all that sometime soon.<br /><br />Also, you have to enter a 35mm focal length equivalent for the categories to be accurate. This is annoying, because for point and shoots, that info is sometimes hard to find. I had to actually take a picture all the way zoomed in, and compare the specs on dpreview.com with the EXIF data (72mm max zoom in the EXIF = 432mm max zoom in the specs, so it has a multiplier of "6"). I may end up looking up the multipliers on a bunch of popular cameras and just ask the user to select his/her camera, or optionally manually enter the focal length multiplier if the user's camera is not on the list.<br /><br />Anyway, the application is fully working in it's current state - all you need is the .NET 3.5 framework. If you want to use the app and can't figure out the proper multiplier to use, just post a comment here, and I or another reader can certainly help you out.<br /><br />No crazy code in this app, but here's the LINQ part:<br /><pre name="code" class="csharp"><br />//generic list<br />private List<double> zoomData;<br />...<br />zoomData = new List<double>();<br />...<br />//code in the directory/file loop<br />zoomData.Add(focalLength * focalLengthX);<br />...<br />int shortTele = (from t in zoomData where t > 100 && t <= 150 select t).Count();</pre><br />In my case, I was happy to see that I had a significant amount more wide and normal shots than telephoto shots, so maybe I won't need an extra lens after all.<br /><br />You can download the app <a href="http://gruskada.googlepages.com/Zoom_Data.zip">here</a>.<br /><br />UPDATE: Picasa somehow figures out the 35mm equiv. from the EXIF data. I'm going to figure out how they're doing it and update my application soon.Anonymoushttp://www.blogger.com/profile/10641305923669467133noreply@blogger.com0