Modifying log4net settings

Here’s how to modify log4net settings from a config file before initializing log4net. This can be useful for example if you have encrypted connection strings in App.config and have to decrypt them before passing them to log4net.

XmlElement log4NetSection = (XmlElement)ConfigurationManager.GetSection("log4net");

// Modify the xml, e.g. by adjusting the InnerXml property...
log4NetSection.InnerXml = StringCrypto.DecryptTaggedString(mypwd, log4NetSection.InnerXml);

XmlConfigurator.Configure(log4NetSection);

/Emil

Best practice for NHibernate: Don’t store references to ISession-instances

Do you see any (or all) of these exceptions (NHibernate.ADOException) in you NHibernate-based web application?

could not execute query
failed to lazily initialize a collection, no session or session was closed
Transaction not successfully started
The server failed to resume the transaction. Desc:86000002dc.

If you do, it might be a good idea to make sure you don’t store any ISession-references anywhere. If you do there’s a great risk that something goes wrong if two threads (i.e. two requests) are using the session at the same time as the NHibernate session implementation is not thread safe.

Instead, do this when an ISession is needed:

ISession session = SessionFactory.Factory.GetCurrentSession();

That code will get the session from the current context (which of course must be updated by your code, look here for more info).

/Emil

Distinct results sets with ICriteria in NHibernate

If you’re using ICriteria to write queries in NHibernate and you’re having citeria on items in a one-to-many relation (e.g. retrieve all departments with at least one employee named “John”) then you’re likely to have experienced that too many objects are returned (at least more than expected). In the example, all departments with multiple “Johns” will be returned once per matching employee. This is probably not what’s expected, so here’s how to fix it:

// The 'criteria' variable contains criteria on Department

// Create alias to use for employee conditions
ICriteria aliasCriteria = criteria.CreateAlias("Employees", "pr");

// Add criteria on the alias...

// We only want distinct root objects returned
criteria.SetResultTransformer(Transformers.DistinctRootEntity);

The trick is to use Transformers.DistinctRootEntity (at least in NHibernate 2.1). In earlier versions you may want to try something like this:

criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());

Related to this is also how to write criteria that counts the results without actually retrieving them, which can be very useful for paging the result set (i.e. only read a subset of the results at a time). Normally you would write something like this:

criteria.SetProjection(Projections.Count("Id"));
int numberOfItems = (int)criteria.UniqueResult();

However, this suffers from the same problem as described above. To get the correct result, do this:

criteria.SetProjection(Projections.CountDistinct("Id"));
int numberOfItems = (int)criteria.UniqueResult();

Problem solved!

Credits to my colleague Jon for helping out with these rather obscure problem solutions!

/Emil

Using PowerShell for login scripts (HTTP POST)

Here’s a small example of how to use PowerShell to pretend it’s a web browser to login to a service. In my case it’s used to let my computer get access to a customer’s network, but it could also be used to login to other services, such as public WiFi services, etc. It also serves as an example of how to do a HTTP POST operation in PowerShell, something that can be very useful in many situations.

param($username=($env:username), $password=$(throw "The 'password' parameter is required!"))

$nvc = new-object System.Collections.Specialized.NameValueCollection
$nvc.Add('username',$username)
$nvc.Add('password',$password)
$wc = new-object net.webclient
[void] $wc.UploadValues('http://123.123.123.123/loginuser', $nvc)

The code is very simple:

  • The script takes two parameters, $username and $password. Note the use of default values to get the logged in user’s username into $username (if it’s not given by the caller) and mark $password as required (an exception is thrown if the parameter is not given). The last in particular is not very obvious if you ask me.
  • We then initialize a normal .Net NameValueCollection with the names and values of the fields to post (i.e. names of the input elements in the HTTP form we’re imitating)
  • The actual HTTP-posting is done using the UploadValues method of System.Net.WebClient object.

I think simple examples like this really shows the potential of PowerShell and that making .Net types so easily accessible in the language was a really smart design desicion by the language designers.

/Emil

Calling a PowerShell script from a Windows shortcut

Executing a PowerShell script from outside PowerShell (for example via a Windows shortcut) can be a little complicated, especially if the path to the script contains spaces and it has parameters, so here’s how to do it:

powershell.exe -command "& 'C:\A path with spaces\login.ps1' -password XXX"

Note that I’m using the PowerShell & operator to execute the script. This is because I have to surround the path with quotes so that it’s interpreted by PowerShell as a single literal even though it contains spaces. If I would leave out the “&” then the quoted string would simply be interpreted as a string literal to output, so the script would not be executed.

The parameters to the script should not be included within the single quotes since they are not part of the first literal, which should only contain the path to the script to execute.

/Emil

Working with remote Windows services in PowerShell

Here’s how to list, start and stop Windows services on a remote computer using PowerShell:

[reflection.assembly]::loadwithpartialname("System.ServiceProcess")

# List all services on the remote computer
[System.ServiceProcess.ServiceController]::GetServices('10.123.123.125')

# Stop the service and wait for it to change status
$service = (new-object System.ServiceProcess.ServiceController('Service name','10.123.123.125'))
$service.WaitForStatus('Stopped',(new-timespan -seconds 5))
$service.Stop()

# Start the service again
$service.Start()

This can come in really handy in deployment scripts, etc.

(Parts of this post came from The PowerShell Guy).

/Emil

Update: In the earlier version of this post I used new-object every time I needed a reference to the service. That’s not necessary, it’s much prettier to use a variable for the reference, so I have now updated the code.

Working with .Net assemblies in PowerShell

It’s quite easy to load and use .Net assemblies in Windows PowerShell, which of course is one of the main selling points of the script language. In this post I’ll show a few examples.

Listing all loaded assemblies:

PS> [AppDomain]::CurrentDomain.GetAssemblies()

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Conso...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c5619...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Management.Automati...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Configuration.Insta...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Comma...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Secur...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\Microsoft.PowerShell.Comma...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Management\2.0.0.0_...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.DirectoryServices\2...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c5...
True   v2.0.50727     C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c...

To load a new assembly, do the following:

[reflection.assembly]::loadfile('C:\...\bin\Entities.dll')

When an assembly has been loaded, types and code in it can be used with the new-object Cmdlet, for example:

PS> $obj = new-object Entities.Affär
PS> $obj.Affärsnummer = “2323232”
PS> $obj.Kundnamn = “Acme”
PS> $obj

Kundnummer :
Kundnamn : Acme
Organisationsnummer :
KontaktpersonKund :
Referens :
Affärsnummer : 2323232
Fas :
Betalningsvillkor :
Status : None
Fakturaaddress :
Fakturor : {}
Id : 0

PS> $obj.Validate()
Exception calling “Validate” with “0” argument(s): “Affärsnummer: Felaktig data: Affärsnummer skall alltid vara 9 siffror”
At line:1 char:14
+ $obj.Validate( < <<< ) [/code] Pretty cool, huh? (BTW, Validate() is a method on the "Affär" class.) Also note that some command completion works with imported types. For example, if I type "$obj." and then press TAB, then the console will cycle through the available members of the type in question. There's more to write about this interesting subject, so more posts will come... /Emil

Windows PowerShell reference (incomplete)

I recently decided to start learning the (fairly) new Windows PowerShell script language and thought it would be useful to write down some of its pecularities. The list below is by no means complete, it’s just my own notes when learning the language.

BTW, I’m quite impressed of the power of this script language and will be using it from now on instead of the good old CMD.EXE and BAT files. However, there is a learning curve involved and it’s steeper than it could have been. The creators’ idea of “elastic syntax” (you can write the same logic in many ways) doesn’t exactly help… Thus there is a need for a reference like this one.

Here we go:

Setup
To allow script execution, do this:

Set-ExecutionPolicy RemoteSigned

Virtual drives
More things than files can be accessed using a file system-like method using the virtual drives mechanism.

  • cert:
  • env:
  • function:
  • HKCU:
  • HKLM:
  • variable:

Example:

dir variable:*

Error handling
PowerShell has a quite powerful error handling arsenal.

Errors can be trapped:

trap { "Something bad happened: " + $_;break } 1/$null

trap { "Something bad happened: " + $_.Exception; break } 1/$null

The first example uses the $_ variable to access the ErrorRecord object of the current error, and the second example displays the underlying .Net exception (including call stack, etc).

The previous errors are stored in the $errors array.

Using the console
Display text in the console (and don’t send it down the pipeline):

write-host -fore red -back green "unreadable, colored text"

Send text to stderr:

write-error "my error"

Change the console prompt:

function prompt
{
    "$(write-host -NoNewLine -fore cyan (pwd))> "
}

The prompt function should return a single string.

Special operators

# swap variable values
$b,$c = $c,$b

# array with values 1 through 10
1..10

# read file (or variable) content. NB, no whitespace after "{"!
${c:\boot.ini}

# encapsulate in array if needed
@( "foobar" )

# initialize an empty array
$a = @()

# initialize an array with 1 element
$a = ,1

# initialize an array
$a = 1,2,3

# (assigns elements from the array to variables $b == 1, $c == 2,3)
$b,$c = $a

# retrieves values for index 0 and 2 from an array
$a[0,2]

# retrieves values for index 0 through 2 from an array
$a[0..2]

# expression sequence (all results is merged into an array)
"foo"; "bar"
 
# & - execute script block
$a = { Get-Process | Select -First 2 }
& $a

# . - same as &, but execute in current scope
$x = 2
. { $x = 3 }
$x          # $x is now 3, if we used & instead it would still be 2

# % can be use as a shortcut for the Foreach-Object Cmdlet
1..5 | % { $_ * 3 }

# ? can be used as a syntax shortcut for the Where-Object Cmdlet
1..17 | ? { $_ % 2 -eq 0 }

Hash tables (object imitations)

# initialize hash table
$user = @{FirstName = "John"; LastName="Smith"}

# object property syntax
$user.FirstName = "Mary"

# array syntax
$user["FirstName"] = "Mary"

# all values from the hash table
$user.Values

# all keys from the hash table
$user.Keys

# all values from the hash table using an array as input
$user[$user.keys]

Constants
These are fairly self-explanatory:

  • $true
  • $false
  • $null

 

Built-in variables

  • $_ – “current” object variable used in many contexts, i.e. foreach-object and where-object Cmdlets
  • $home – current user’s home directory
  • $profile – path to the current user’s profile script in PowerShell (executed at PowerShell startup). NB: This script does not necessarily exist!
  • $OFS – Output Field Separator, used when converting lists to strings. Example:
    $OFS="|";[string] @(1,2,3)
    
  • $matches – hash table contained matches after wildcard or regex pattern matching
  • $args – parameter array for a function or script
  • $input – input object array for functions in a pipeline
  • $error – array of errors (error[0] is the latest one)
  • $? – boolean error status of last command
  • $LastExitCode – exit code of the last command or EXE
  • $host – reference to the application hosting PowerShell. $host.ui is useful for reading/writing text to and from the console
  • $foreach – enumerator in foreach statement
  • $switch – enumerator in switch statement

 

Pattern matching
Wildcard matching (true/false):

"foo bar" -like "f*bar"

Regular expressions (true/false + matching results in $matches):

"foo bar" -match "([a-z]*) ([a-z]*)"; $matches

Output:
True

Name                        Value
----                           -----
2                              bar
1                              foo
0                              foo bar

Discarding output of a command

Any of the following will do the trick:

[void] (dir)
dir | Out-Null
dir > $null

Conditional and looping statements

The switch statement is mighty cool:

switch (3) { 1 {"one"} 3 {"three"} default {$_}}
switch (1..5) { 1 {"one"} 3 {"three"} default {$_}}
switch (1..5) { {$_ -gt 3} { "[$_]" } default { $_} }
switch -wildcard ("one", "two", "three", "four", "five") { t* { "[$_]" } default { $_} }
switch -regex ("one", "two", "three", "four", "five") { ^o.* { "[$_]" } default { $_} }

That’s it for now. I will probably extend this posting later as i discover more things that are difficult to remember…

/Emil

hibernate.cfg.xml not found in ASP.Net application?

In later versions of NHibernate it’s possible to separate NHibernate configuration from normal application configuration (which is normally done in App.config/Web.config) by using a separate file called hibernate.cfg.xml.

Works great, but there is one thing to keep in mind in ASP.Net applications, namely that it should be placed in the bin/ folder, not in the root folder fo the application! Took me quite some time to figure out! So if you have the same problem as me, just move it to that folder 🙂

/Emil

Finding dependencies on a table column

This will list stored procedures, views, etc. that uses a given table column:

SELECT OBJECT_NAME(sd.id) Dependent_Object,
      (SELECT xtype FROM sysobjects so WHERE so.id = sd.id) Object_Type
FROM sysobjects so
INNER JOIN syscolumns sc ON so.id = sc.id
INNER JOIN sysdepends sd  ON so.id = sd.depid and sc.colid = sd.depnumber
WHERE so.id = OBJECT_ID('tblcategorypage')
AND sc.name = 'categorytype'

Credits for this tip to SQLServerCentral.

/Emil