Search Results for: "resource

Simple No-Code Navigation in Windows Phone 7 Apps

1
Filed under Windows Phone 7

imageIn working with Windows Phone 7, one element that struck me as odd early on, is that the ApplicationBarIconButton (those “soft” buttons at the bottom of a normal WinPhone 7 page, highlighted in red in the screenshot) requires code in order to navigate. In other words, you MUST supply a CLICK event handler and in code behind, make use of the page’s NavigationService to perform the navigation.

Further, the URI to navigate to ends up in code behind as well.

Not ideal.

But there is a simple solution.

URIMapping

First, to make things really simple, you need to setup URI mapping. This allows your xaml to reference, say /Settings, and actually navigate to the URI /ui/SettingsPage.xaml?pvt=Main.

To do this, open up your App.xaml file and add something like this:

    <Application.Resources>
        <!-- URIs for navigation purposes -->
        <nav:UriMapper x:Key="UriMapper">
            <nav:UriMapping MappedUri="/ui/SettingsPage.xaml?pvt=Main" Uri="/Settings" />
        </nav:UriMapper>
    </Application.Resources>

Obviously, the MappedUri property is what you would normally use in conjunction with NavigationService.Navigate to actually perform the navigation. The Uri property is the new “simplified” Uri that you can use throughout your app to refer to the same page.

If you don’t already have it in your App.xaml file, be sure and add the namespace line for nav:

    xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone"

Create the New ApplicationBarIconNavigator control

Create a new class, call it ApplicationBarIconNavigator, and use the following code:

''' <summary>
''' Provides a handy extension to the ApplicationBarIconButton to facilitate direct navigation
''' </summary>
''' <remarks></remarks>
Public Class ApplicationBarIconNavigator
    Inherits ApplicationBarIconButton


    Public Property URI As Uri
        Get
            Return _Uri
        End Get
        Set(value As Uri)
            _Uri = value
        End Set
    End Property
    Private _Uri As Uri


    Private Sub ApplicationBarIconNavigator_Click(sender As Object, e As System.EventArgs) Handles MyBase.Click
        DirectCast(App.Current.RootVisual, PhoneApplicationFrame).Navigate(Me.URI)
    End Sub
End Class

This Class inherits from the normal ApplicationBarIconButton, but makes two critical changes.

First, it exposes a URI property, to allow us to specify what URI we want to navigate to.

Second, it automatically handles the Click event, and navigates to that URI.

This combination allows us to specify the URI to navigate to and handle the navigation event, all from XAML with no code on the page’s code behind at all.

The ApplicationBarDefinition

Now, in your page’s xaml, usually toward the end of the file is the definition of the ApplicationBar.

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <shell:ApplicationBarIconButton IconUri="/Images/Settings.png" Text="Settings" Click="Settings_Click"/>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>

Note that I’ve got only one button defined, and its Click event is set to About_Click, so normally, I’d have to navigate to the event handler, and add code there to perform the actual navigation:

    Private Sub Settings_Click(ByVal sender As Object, ByVal e As EventArgs)
        Me.NavigationService.Navigate(New Uri("/ui/SettingsPage.xaml?pvt=Main", UriKind.Relative))
    End Sub

Not a huge issue, but it does mean you’ve got code behind where there really doesn’t need to be any, which means more code to maintain, etc.

But, with the new control in place (you may have to perform a Build before you can add a reference on the page to it without error), and with the URIMappings set up, you can now do something like this:

    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False">
            <local:ApplicationBarIconNavigator 
IconUri="/Images/Settings.png"
Text="Settings"
Uri="/Settings" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>

At this point, you’re done! You no longer need the event handler logic because the ApplicationBarIconNavigator button will automatically handle it. And your URI complexity is isolated to just the App.xaml resources. Sweet!

One final note, if you haven’t already included one, you’ll need to add a “local” namespace declaration in your page’s xaml so that local:ApplicationBarIconNavigator will resolve.

    xmlns:local="clr-namespace:{your project name}" 

Wrapup

With MVVM frameworks like Prism, I believe this kind of functionality is baked in to some degree. But in my case, just starting out with WP7, I believe it’s important to understand the underpinnings of the system first, then progress to a higher level framework.

WindowsXP periodically disconnects from Windows7

4
Filed under Networking, Troubleshooting, Windows 7

Very strange, and utterly frustrating issue recently.

After I got hit by lightning, I ended up replacing an Iomega NAS storage server with a simple Win7 box running 2 raided 2TB harddrives. It was a quick build and was a little cheaper than an equivalent 4TB Iomega unit, plus it’s running real Windows, so I can do more stuff with it.

But, I’ve got several XP Virtual Machines (under VMWare Workstation), that would, very consistently, disconnect from the Win7 “server”.

I googled for days, and tried at least a dozen different suggestions but none worked.

Essentially, if I rebooted the Win7 machine, the XP machines could connect to and work with the server for a while. But eventually, the WinXP machines would loose connection to the Win7 machine and the ONLY way to get them connected again was to reboot the Win7 machine.

The main problem was that the failure was very generic: something along the lines of “The server does not have enough resources to complete the request”.

Not much to go on.

On a whim, I happened to check in the event log at one point and came across this:

Source: srv
Event ID: 2017
Level: Error
The server was unable to allocate from the system nonpaged pool because the server reached the configured limit for nonpaged pool allocations.

Googling “srv error 2017” turned up a number of new suggestions I hadn’t seen before, but one in particular on Alan LaMielle’s blog looked very promising, though he was talking about connected via SAMBA.

The Bottom Line

In a nutshell, the problem is that if you use a “normal” version of Windows more like a server (lots a machines connecting to it for files), normal Windows installs aren’t configured for that.

You need to change 2 registry entries (on the SERVER machine, in my case the Win7 machine):

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\LargeSystemCache

should be set to ‘1’, and:

HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\Size

should be set to ‘3’.

Then, either reboot, or use the Services control panel to restart the ‘SERVER’ service.

Since I’ve done that, I’ve connected several XP systems up, and run full backups overnight without a single hiccup.

Merging Assemblies, the Easy Way (part 1)

0
Filed under Code Garage, Utilities, VB Feng Shui

image Recently, I ran into a need to make use of the Mono.Cecil.dll library from a .net application I was working on. Cecil is a fantastic little project under the Mono project that allows you to interrogate an existing .net assembly (EXE or DLL file) and retrieve all kinds of information about the assembly, from the resources embedded within it to the classes and methods defined, and much more. You can even alter the contents of the assembly and write the new version back out to disk!

The thing is, Cecil comes prebuilt as a C# assembly (a DLL file), and I really did not want to have a second file required for this particular application (it’s just a little command line utility).

My first take was to use Oren Eini’s excellent concept of an assembly locator. My idea here was to embed an assembly as a binary resource, then, when requested, read that resource into a stream, load the assembly from the stream, and resolve references to it via the assembly locator.

I’m still working on that concept, because I think it’s a clever and convenient solution to the problem, but, in researching that, I happened to remember the even easier (as in, no code required at all!) solution of using ILMerge.

ILMerge

If you haven’t already discovered it, ILMerge is a Microsoft research project in the form of a single command line EXE utility, that can “merge” any number of .net assemblies with a “target” assembly, and produce either a .net DLL or EXE output file.

There’s a really good article on CodeProject describing the general use of the program. There’s even a GUI (Gilma) for it.

Automating ILMerge

What the article doesn’t go into is automating the ILMerge process. After all, you won’t want to manually run that command line utility every time you build your application!

The good thing is, it’s trivially easy to automate as long as you take care of one critical step.

  • First, download and install ILMerge from the link above.
  • Once it’s installed be sure to copy the ILMerge.exe utility to somewhere on your path (or add the folder it’s in to your path).
  • Then, grab the Mono.Cecil.dll file (or whatever DLL it is you want to merge into your main project EXE). Put it in the root folder of your project.
  • Go ahead and set a reference to that file, so you still get all the .net intellisense goodness, but be sure to set the Copy Local property for the reference to FALSE (after all, you don’t want to copy this DLL to the output folder along with the application if you don’t actually need it, right?)

    image

  • With that done, you MAY want to mark the DLL you’re embedding as “included in project” from the Solution Explorer.

image If you do this, however, make sure you also set the Copy to Output Folder to “Do not copy” (that’s the default though so it should already be set).

The Tricky Part

One limitation of ILMerge is it that it can’t alter the target assembly “in place”. This means that, for instance, if you want the final resulting executable file name to be called GenerateLineMap (my utility), you can’t have VS compile the assembly to that name. You’ll need to use some other name for the initially compiled assembly.

On the Application tab of the project properties you can change that name, like so:

image

I just added “-Interim” to the Assembly Name.

Now, go to the compile tab of the project properties and click Build Events

image

Insert this as the POST BUILD EVENT

ilmerge /target:winexe /out:"$(TargetDir)$(ProjectName)$(TargetExt)" "$(TargetPath)" "$(ProjectDir)Mono.Cecil.dll"

Notice that the OUT parameter specifies the output file name via the $(ProjectName) variable (which is still “GenerateLineMap”) while the first assembly to merge is specified using the $(TargetPath) variable (which is the full filename of the output assembly, including the “-Interim”).

image

EDIT: Important note: Notice the /target:winexe option. You’ll need to change that as appropriate depending on the type of exe you’re building. In my case, I had a console app where this needed to be set to just /target:exe. Setting it to /target:winexe caused all of the console output functions to just do nothing, which threw me for a bit!

Now, just rebuild the solution and you should see two resulting EXE files in your output folder, one with the “–Interim” (which is the version WITHOUT the embedded Mono.Cecil.DLL file or whatever DLL you’ve chosen) and one WITH the embedded file. As a final cleanup, you may want to add an additional Post build step to remove the “*-Interim” files.

To test, just make sure you DO NOT have the embedded DLL anywhere on the path or in the same folder as the exe and run the exe. If everything went right, your app should work exactly the same as if the embedded DLL was included externally with the app!

Now, your application is back to being a single EXE to distribute, and it was built completely automatically by Visual Studio.

Caveats

You knew there had to be some, right?

The first is that if the dll to embed contains licensing information, it might not work properly after being embedded. I don’t have any DLLs like that to test with, but I’ve read reports about the problem at various sites on the internet. Just something to be aware of.

Second, trying to replace the originally named exe with the newly built one results in VS not being able to debug the exe in the IDE (it throws a message about the assembly manifest being different from what was expected). I haven’t worked that issue out yet. What this means is that you might need to leave any references set to “Copy to Output Folder” while debugging, and not replace the original compiled assembly, just ILMerge it into a new assembly name.

Finding the True File Location of an Executing .NET DLL

0
Filed under .NET, VB Feng Shui

image Say you've written a .NET DLL and you need to know from what folder that DLL was loaded (so you can find resources, config files, whatever).

There are any number of ways to skin that cat, but unfortunately, most won't work in the general case, but only under certain special circumstances.

Matthew Rowan does a really good job of explaining the differences here, so I'm not going to repeat his post, but the short version of the story is, it takes code that looks like this:

Dim assemblyUri As Uri = New Uri(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase))
Return assemblyUri.LocalPath

Note that this is the VB version of Matthew's clip. There a a number of other methods, but they all seem to return bogus results under various conditions.

Using Embedded Fonts In an External Flash Library

0
Filed under Uncategorized

One project I'm working on now involves showing a "preview" of a user's selected options in a window on a web page.

The options involve font selection, styles (bold, italic, etc), color, and even mirroring (reversing the text as if it was going on the inside glass of a window).

Most of that would be relatively easy in javascript and CSS, except for the font.

How the heck can you display fonts to a user that doesn't actually have those fonts installed on their machine?

Well, there's likely a number of different possibilities, but Flash represents one of the cleaner (if not mind-bogglingly complicated) approaches to the problem.

There are a number of articles on the web concerning embedded fonts in flash, so I'll try not to rehash that here. But there are a few gotchas that proved very difficult to hunt down, with virtually no mention of them on the web that I could find.

The Setup

First, I'm using Flash CS4 and ActionScript 2.0.

Create two files in Flash. I called one Test2.fla and the other Fonts.fla.

image

The Fonts.fla will be our external Fonts Resource file. Why external? Why a separate file? Well, technically, once you've gotten your fonts together, it'd be nice to not have to continue to have them installed on your machine. Separating the fonts from the flash files that will use them allows you to build the font resource SWF file once, remove all those fonts, and then still be able to work on your actual Flash file (the one with your actual movie/code in it).

Note the properties for my actual movie fla file:

image

Its basically the same settings for the Fonts.fla file, although, technically you could set it as ActionScript 3.0, I suppose. There's no script necessary for the Fonts.fla file.

Setting Up The Fonts.FLA file

Switch to the Fonts.FLA file and show the Library. Press Ctrl-L to show it if it's not already showing.

Then, Right Click in the empty space and choose New Font:

image

You'll get the Font Symbol editor window. This is where the magic happens (or doesn't, if you get it wrong).

image

There's a lot going on here, so, starting at the top.

  1. The NAME field must NOT be left as just the name of the font, no matter how tempting that may be. I suffixed the normal version of every font I embedded with "Normal", but it doesn't really matter. Just make sure it's NOT the actual name of the font.
  2. The Font field just allows you to pick the font. This means the font you want to embed MUST be actually installed on the machine. A pain, but that's what ya gotta do.
  3. The Style box will only be enabled when the font you've chosen actually has a specific style (Bold, Italic or Bold Italic) defined within the font itself. Most fonts don't, so this box will likely be disabled. If it IS enabled, choose whichever style you need to embed.
  4. The Faux Bold and Faux Italic checkboxes are enabled when the font doesn't already define a Bold or Italic style. if you want bold or italic, check the appropriate box. HUGE NOTE: These boxes are ANDed, which means if you check both, you get a faux BOLD/ITALIC font. You do NOT get a bold version of the font and an italic version. This is very important and I'll get to why in a bit.
  5. You'll need to check the "Export for ActionScript", and when you do so, the Identifier field will enable (for ActionScript 2.0 at any rate). Be sure that the name entered here IS NOT the actual font name. It needs to be something different. I usually make it the same as the NAME field above.
  6. And finally, check the Export for Runtime sharing. Since this is going to be an external font resource swf file, we need to export the font so other SWF files can reference it.

I didn't mention the SIZE file. I've put 30 there, but, from what I can tell, you should be able to put just about anything you want. The process of embedding the fonts actually converts the glyph vector outlines into a Flash friendly format, but they're still vectors, so they can essentially be scaled to any size.

That said, often at small sizes there are hints embedded in the font for particular sizes that might not make it into the embedded font vectors. I'm no font expert though, so I can't be sure of this.

Fonts, Fonts

What if you need more than one font? What if you need the Bold version of a font? What if, heaven forbid, you need the normal, bold, italic and bold italic versions of the font?

First off, even though it may alarm the Flash purists out there, there are occasions when such things are necessary. The downside, however, is that your fonts.swf file could get rather large quickly. The reason is that you're actually embedding all the font glyphs into the file. But it's worse than that.

Flash, treats every style of a font as a completely separate font. So, if you want normal and bold, well, that's two fonts. Normal, Bold and Italic? That's three complete sets of glyphs. Normal, bold, italic and bold italic? That's 4 complete sets of glyphs for that font.

Needless to say, the swf file can get large fast. Something to be aware of at any rate.

So, let's say you want to include the BOLD version of Tahoma.

image

Just repeat the above steps, but with Tahoma, the STYLE combobox is enabled (Tahoma has the Bold style predefined). Drop down the Style Combo and select Bold. Then, make sure the Name and Identifier fields are set to SOMETHING OTHER THAN "Tahoma". I just used "TahomaBold" to keep things simple.

Now, repeat those steps for EVERY FONT and EVERY STYLE of font you want to embed. What's worse, I looked for quite some time for any way to automate this process and failed. The only way to do it that I could find was completely manually. Yuck!

In the end though, you should have a library pane that looks like this (I've dragged all the fonts into the Fonts folder, but you don't have to).

image

Again, the KEY TO THIS is that NONE of the font NAME fields or the IDENTIFIER fields can be the same as the actual font.

Flash is smart enough that when you ask for "Tahoma" with a style of Bold, it'll match things up properly. But if any font is actually named "Tahoma" (i.e. in either of those two fields), Flash will only ever choose that particular named font/style, regardless of what you might ask for. Peculiar, yes, but that's what it appears to be doing.

Using the RegEx feature of the File Class in the MSBuild Extension Pack

2
Filed under MSBuild

In case you've missed it, MSBuild is, essentially, the "new" version of that most ancient of build tools, MAKE.

Basically, it's just a way to script out the steps required to build a project from end to end, possibly including

  1. Retrieving files from a Source Respository
  2. Altering them and checked the changes back in
  3. Compiling various application projects
  4. Copying files around
  5. Compiling an installation
  6. Sending email notifications of the build success or failure

and a host of other possibilities.

In the good ol' days of MAKE and NMAKE, you had to use a particularly arcade file format to describe all this.

With MSBuild (oddly enough, it appears to come bundled with the .NET runtime, instead of one of the dev tools like Visual Studio, why is beyond me), you now configure everything through a relatively nice to look at XML file, usually named with a PROJ extension.

While MSBuild is fairly capable in it's own right, there's quite a number of things that typically need to happen during a build that it can't handle directly, such as manipulating the contents of files, setting environment variables, etc.

That's where the very thorough MSBuild Extensions pack comes in. Be sure to install it, then read the help file on how to hook up the XML Schema's so that Visual Studio can show Intellisense for the extra functionality. It just requires copying a few XSD files around, so I won't go into that here.

The Problem

One of the first things I had to do with the Extension Pack was alter the content of an RC (resource script) file that contains the version I need to use when stamping the files with a version number. I use a single, shared RC file so that it's easy to update the version number for all files in the build.

My first shot was something like this:

   <Target Name="UpdateBuildNumber">
      <MSBuild.ExtensionPack.Framework.DateAndTime TaskAction="GetElapsed" Start="1 jan 2000" Format="Days">
         <Output TaskParameter="Result" PropertyName="BuildNum"/>
      </MSBuild.ExtensionPack.Framework.DateAndTime>
      <Message Text="Build Number to use: $(BuildNum)"/>

      <ItemGroup>
         <CommonRCFile Include="Common.rc" />
      </ItemGroup>

      <MSBuild.ExtensionPack.FileSystem.File TaskAction="Replace" RegexPattern="(?'Leader'\#define BUILD \s*).*" Replacement="${Leader}$(BuildNum)" Files="@(CommonRCFile)" />
   </Target>

The Resource file itself looks like this (a snippet):

#define MAJOR          1
#define MINOR          5
#define REVISION       0
#define BUILD          100


#define COMPANYNAME       "My Company"
#define PRODUCTNAME       "My Product"

What I was looking to do was replace that "100" for the build number with a number that corresponded to the number of days since Jan 1 2000, which would yield a nice number around 3470+, decent for a contantly incrementing build number and it fits within what a resource file can declare for the BUILD field.

I ran it can immediately ran into the first problem. The elapsed days was being returns in floating point,  so I got a days value of something like 3745.5763527589. That would definitely NOT going to work as a build number.

After some tinkering, I ended up having to add a string SPLIT action to split off the integer days part, as in:

<MSBuild.ExtensionPack.Framework.TextString TaskAction="Split" String1="$(BuildNum)" String2="." StartIndex="0">
   <Output PropertyName="BuildNum" TaskParameter="NewString"/>
</MSBuild.ExtensionPack.Framework.TextString>

The trick here is that "StartIndex" property. That indicates which part of the split up string you want returned into the "Output PropertName" named property. A 0 means the first split element. Since I'm splitting on a "." that will give me the number of days with no fractional portion.

I'm sure there's a better way to do this, but I haven't dug it up yet.

One problem down, so I ran the build and everything appeared fine till I compiled the RC file, at which point I got a very strange error about the file having unexpected values.

So I pulled up Araxis Merge to compare the old and new versions of the file, and something peculiar had happened. For the resource COPYRIGHT and TRADEMARK entries, I had used the copyright and registered ascii symbols (Ascii characters 169 and 174), but once the file went through that ExtensionPack FileSystem Replace action, those values had changes to something else entirely.

I suspected encoding was the culprit, and sure enough, there is a TextEncoding property for the Replace Action that apparently can control the encoding that is performed.

Ok, just find the right encoding...

  • I tried UTF8.... Not recognized
  • UTF-8...Recognized but same result
  • ASCII...recognized but totally scrambled other parts of the file.
  • ASCII-8... not recognized
  • ASCII8... not recognized.
  • US-ASCII...recognized, but just converted the suspect characters to ? chars.

At this point, I'm starting to get a little annoyed.

Eventually, I stumbled across a blog post that mentioned a "windows-1252" encoding and sure enough, Success at last! The build number is replaced, but the rest of the file is left as it was.

So the target entry I ended up with was:

<Target Name="UpdateBuildNumber"> <MSBuild.ExtensionPack.Framework.DateAndTime TaskAction="GetElapsed" Start="1 jan 2000" Format="Days"> <Output TaskParameter="Result" PropertyName="BuildNum"/> </MSBuild.ExtensionPack.Framework.DateAndTime>

<MSBuild.ExtensionPack.Framework.TextString TaskAction="Split" String1="$(BuildNum)" String2="." StartIndex="0"> <Output PropertyName="BuildNum" TaskParameter="NewString"/> </MSBuild.ExtensionPack.Framework.TextString> <Message Text="Build Number to use: $(BuildNum)"/> <ItemGroup> <CommonRCFile Include="Common.rc" /> </ItemGroup> <MSBuild.ExtensionPack.FileSystem.File TaskAction="Replace" RegexPattern="(?'Leader'\#define BUILD \s*).*" Replacement="${Leader}$(BuildNum)" Files="@(CommonRCFile)" TextEncoding="windows-1252"/> </Target>

One final comment. This required messing with .NET regular expressions, which I'm certainly no expert on.

I ended up coming across a very handy Regular Expression Tester by Francesco Balena (a favorite author of mine from way back), called YART. One .net EXE, just unzip and use. Supports find and replace, plus has context menus for all the various .NET Regex syntax bits and pieces. This definitely saved me a pile of time.

My opinion is still up in the air about MSBuild, but, with the Extension Pack, its capabilities are certainly quite formidable.

Give it a shot!

Multi-Line String Literals

0
Filed under .NET, VB Feng Shui, XML
VB has long been my favorite development language, but, as is typical, even it can definitely be improved in innumerable ways. One aspect of VB that has always bothered me is string literals. Since VB treats EOL as significant, you can't have strings that wrap across multiple lines in the environment. This is especially problematic when you deal with SQL queries, report formatting strings, and the like. For instance, this is generally what you see when you have to deal with long SQL queries in VB code.
Dim q as String = "Select *" & vbcrlf
q &= "From MyTable" & vbcrlf
q &= "Where MyColumn = 1"
Now, you can do a few formatting tricks and clean it up a little, but even then, it's going to be cumbersome to work with. One workaround has always been to embed these long, multi-line literals in a Resource file. The VS 2008 IDE even goes so far as to allow you to enter multi-line strings in the resource editor, although you have to use Ctrl-Enter to get a new line: image If you look at the RESX file for the above resource, you'll see something like this: image All this is certainly workable, and, in many cases, isolating strings to a resource file (of some sort) can be a really good thing, but in other cases, it's just a pain. In VB10, Microsoft is finally doing what VB should have done all those years ago. They're adding "intelligent line continuation" which is to say, you can continue a line in certain syntactic situations simply by continuing the code on a new line. No need for the line continuation underscore char, etc.  It won't necessarily work everywhere (esp in places where it the code would end up ambiguous), but hey, that only makes sense. In the meantime, you can actually have multi-line string literals in VB.Net without too much pain. The trick is to use XML Literals. Generally, I'm no fan of XML literals. Once they get peppered with variable references, embedded For loops and other code, they become just so much spaghetti code, albeit with a modern twist. But, they can be handy for multi-line string literals.
Dim q as String = <String>Select *
From MyTable
Where MyColumn = 1
</String>.value
So what's going on here? First, I dim the result variable Q as a string (technically, this isn't necessary as VB can infer the type, but you get the picture). Then, I declare the XML Literal with the <String></String> tags. Everything between those tags (even across lines), gets treated as part of the string, no quotes or line continuation needed. Finally, since the result of the <String></String> tags is going to be an XElement object, and what I want is a string, I need to invoke the value property of the XElement object to retrieve its string value. And there you go. But, as with anything good, there are a few caveats.
  1. line breaks AND whitespace are preserved in the string, which means if you indent those lines, you'll get space characters where you might not have wanted them.
  2. if you want to include certain characters that are illegal in XML (for instance, the "<" or ">" characters), you'll need to escape them.

Handling Escape Characters

One option you have for handling escape characters is to use the XML escape sequences, as in:
Dim q as String = <String>Select * as My&gt;Test&lt;var
From MyTable
Where MyColumn = 1
</String>.value
The &gt; and &lt; will be replaced with > and < respectively. You can escape any arbitrary character with &#nnn; where nnn is the ascii code of the character. But this is code, dammit, not XML, and, at least for me, I'd much rather see normal C-style escape sequences (\r\n anyone <g> ) here than have to muck with XML "&" sequences. If we're talking about web pages and HTML, that might be a different story, though. At any rate, you can have your cake and eat it too, as it turns out. Just feed that string through System.Text.RegularExpressions.Regex.Unescape to convert those sequences, hence:
Dim q as String = System.Text.RegularExpressions.Regex.Unescape(<String>Select * as MyTestvar \r\n
From MyTable
Where MyColumn = 1
</String>.value)
Notice how the XElement.value is simply passed through to the Unescape method to process that \r\n into a normal carriage return/linefeed pair. Using that, you can now easily embed C-style escaped multi-line strings in your VB code. But wait, that Unescape call is fairly nasty to look at and use. Wouldn't it be nice if that was more or less automatic? Well, with a nice Extension Method, it can be.
<System.Runtime.CompilerServices.Extension()> _
Public Function UnEscaped(ByVal v As XElement) As String
    Return System.Text.RegularExpressions.Regex.Unescape(v.Value)
End Function

.....

Dim q as String = <String>Select * as MyTestvar \r\n
From MyTable
Where MyColumn = 1
</String>.Unescaped
First, define an Extension Method that would apply to the XElement object. This is a very simple method that just takes the associated XElement object, retrieves it's value, and runs that string through the Regex Unescape method. Since the extension method extends the XElement itself, you can now simply call the Unescaped method directly on the long string definition (the very last line in the code above). You can't get much cleaner than that. Or can you? Let me know!

Don’t Forget About the Task Scheduler

0
Filed under Utilities

A little known facet of Windows that's been there since the early days of NT is the Task Scheduler (I seem to recall actually using the AT scheduler it under NT4, but my memory is sketchy back that far<g>).

image

It's part of the Control Panel, and it essentially lets you schedule applications, scripts, etc to be run automatically, using a particular set of login credentials, at particular times.

Many applications out there can be run as Services, which means they run all the time, in the background, even before anyone has logged into the system.

But for many types of applications, running as a service isn't necessary and just takes up memory and processor time from other applications that do need to run all the time.

I happen to use a backup utility called FileBack PC. They have a service module that allows it to run as a service, complete with scheduling etc. But they charge extra for that module.

I was really wanting to schedule my backups to run late at night, and I really wanted them to happen regardless of whether I'd logged into my server or not.

That's when I remembered the Task Scheduler. Here's an example screen of a configuration to run a backup job called "NearLine Backups" every morning at 7:00am.

image

In order to setup a scheduled task, you double click on "Add Scheduled Task" and walk through the wizard that follows:

First, the introductions screen:

image

Next, select the application you want to run, in my case, it'll be FileBack.exe.

image

Choose to run it daily:

image

Set the time:

image

And finally, set the user name and password for the account that this task will be run as:

image

It's quite important to get the account and password right, since the task that is run will run with those credentials. Also, if the task needs access to certain network resources or drives, that account will have to have access to those resources.

Once you have these bits set, you can always dblclick on the task from the Scheduled Tasks list and edit various details, such as additional command line parameters for the executable being run, etc. In my case, I had to add the name of the backup job I wanted to run, like so:

c:\program files\FileBack PC\FileBack.exe "NearLine Backups"

But every application will be different.

And that's it.

If you are logged in as the user that the task will run as, and the task is scheduled to run, you're likely to actually see it start and run.

If no one is logged in, or if you're logged in as another user, you won't see anything happening.

As always, you'll want to test and verify that what you think should be happening actually is. But, using the Task Scheduler is certainly something to keep stashed in the toolkit!

Home Theater

0
Filed under Media

image I'm a big Home Theater fan. Ok, maybe not in the sense of being fond of having one, but I certainly do admire some of the installations and techniques that are being used out there. Installations like the one here just blow my mind.

Funny how just about anyone I've ever talked to, though, that actually has a setup like this (ok, maybe not quite this nice), ends up rarely using it.

While it's a nice thought, and, for a hobbyist, could definitely chew up some free weekends, plus a pile of cash, dedicating an entire room to a home theater has always seemed like a bit of a waste to me.

Take this setup here. What else could you possibly do in this room? Play video games? Ok. Anything else? When the extended family comes in for the holidays, are they going to gather in there? Is the family going to gather in there to watch Dr Who before going to bed?

It just doesn't seem like someplace that would foster a good family experience. Maybe I'm wrong. I also am of a school of thought that says there's no need for more than one TV in a house. 3 PC's per person, sure, but just the one TV. I know, I know. How quaint<g>.

But I do admit, for that one TV, I like it to be a good one. I picked up a 36" Mitsubishi tube TV back in '94, when such behemoths weren't all too commonplace. Now, a 36" TV is, um, quaint.

When our family watches TV, we want to do it on a big screen, so the only decent alternative I saw was a projector/screen combo. And since I didn't want to dedicate an entire room to a home theater, the equipment needed to be unobtrusive and disappear if we weren't using it, as only a projector/screen can.

imageIn the end, I went with a Draper motorized tab-tensioned screen (craigslist) and a Panasonic AE900U projector (ebay). I was really looking for an AX200U (the next up model number), but when a 900U came up at a really good price, I couldn't walk away from the deal.

Besides, from reading the specs (www.ProjectorCentral.com is an excellent resource for those), the two units are virtually identical, with the 200 supporting 1080P being the major difference.

This projector has turned out to be utterly fantastic. Contrast is great and the picture is terrifically bright, even with all the lights on and the windows open (though, admittedly, the windows are shaded by trees outside).

And if I turn down the lights, even a bit, the picture really pops.

What's better, the Panasonic units (both the 900 and 200) have one of the best picture positioning systems around. Not only can you move the image without moving the projector (so you can tweak things once the projector is mounted), the zoom lens allows for a very wide range of positioning the projector from the screen. It's one of the few reasonably priced projectors that can do an 80" image from over 17' away.

Now then, my audio gear pales. Ah, next project...

Compressing Memory Streams

0
Filed under Uncategorized

One thing that has definitely taken some getting used to (for me anyway) in VB.NET is the whole concept of streams.

I like the idea, generally, but I was working through some code to stream debugging info into a resource in an already compiled EXE file when I ran into a problem with decompressing the resource data.

It just wouldn't decompress properly.

After backtracking and puzzling over it, I discovered that the problem was actually in the compression phase.

   Private Function pCompressStream(ByVal UncompressedStream As MemoryStream) As MemoryStream
      Dim CompressedStream As New System.IO.MemoryStream()
      Using GZip As New System.IO.Compression.GZipStream(CompressedStream, System.IO.Compression.CompressionMode.Compress)
         GZip.Write(UncompressedStream.ToArray, 0, UncompressedStream.Length)
      End Using
      Return CompressedStream
   End Function

Note the Dim GZip line? If you look at the overloads, there's a possible 3'rd option, LeaveOpen. It defaults to false.

From what I can tell, if you connect a GZipStream up to a FileStream, there's no need for this parameter. When the GZip closes, the file is closed and on you go.

But, with MemoryStreams, it's quite unlikely that you'd want to close the resulting output memory stream after zipping data into it.

But that's exactly what happens if you don't set LeaveOpen to True.

What's worse. You need to Close the GZipStream before reading that MemoryStream(either by using a USING block as I have, or by calling Close directly). If you don't, garbage collection might not happen for some time and the final data in the internal GZip buffers won't get written to your memory stream, resulting in only partial compressed data, which definitely won't decompress properly!

All this is likely old hat to grizzled .NET heads, but if you're like me and coming from an extensive VB6/assembler background, it can certainly causing some headscratching for a bit.