Thursday, January 8, 2015

WPF Zooming

... in response to MarkLTX, who posted an awesome article about zooming and how double-animation makes the user-experience much better ( http://www.codeproject.com/Tips/860914/Add-Zooming-to-a-WPF-Window-or-User-Control ):

In addition to the article I would like to mention a method which wasn't described. I think it is the most natural way in a WPF application to use XAML-Binding (without any code behind) and to use the slider only, instead of using an animation as e.g.: Word 2013 does it (maybe they also have an animation to keep things smooth, but if so, I don't really recognize it). Anyway, the animation was added to give the user a better feeling about what is going on and to show him (through the animation) that the current action which will be proceed is "zooming" and not any magic which confuses him.

I think that the user-activity of changing a slider makes it unnecessary to do any other things (as long as the performance of the application is OK).

Here a sample application which uses a slider to zoom:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<Window x:Name="window"
        x:Class="ZoomerApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Height="350"
        Width="525">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <WrapPanel Margin="10,10,10,0">
            <WrapPanel.LayoutTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="{Binding Value, ElementName=ZoomSlider}"
                                    ScaleY="{Binding Value, ElementName=ZoomSlider}" />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                </TransformGroup>
            </WrapPanel.LayoutTransform>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>
                <Button>Hello</Button>

        </WrapPanel>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Slider x:Name="ZoomSlider"
                    Width="100"
                    HorizontalAlignment="Right"
                    Margin="10,2,10,0"
                    Grid.Column="0"
                    Value="1" />
            <StackPanel Orientation="Horizontal"
                        Grid.Column="1">
                <Label Content="{Binding Value, ElementName=ZoomSlider}"
                       ContentStringFormat="{}Zooming: {0:N2}" />
            </StackPanel>
            <Button Width="100"
                    Content="OK"
                    Margin="20,2,0,10"
                    Height="25"
                    Grid.Column="3"
                    IsDefault="True" />
            <Button Width="100"
                    Margin="2,2,10,10"
                    Content="Cancel"
                    Height="25"
                    Grid.Column="4"
                    IsCancel="True" />
        </Grid>
    </Grid>
</Window>


What I did:
  • I created a window with a main grid and 2 containers inside...
    • the top container is a WrapPanel which will be zoomed
    • the bottom container has a slider which sets the zoom level
  • The binding is on the slider.value (so I named the slider ZoomSlider to be able to call it by its element-name). There are much more elegant ways, but I think this one is elegant enough for this quick sample.
  • line 18 and 19 are the most important
    • a binding is set up on the value of the slider
    • the value is set on line 49 to default 1 what equals 100%
  • line 52 creates a label which visualizes the content of the slider.value.
I used to create zooming like this and always got good feedback about it (I think the main reason is because it behaves so similar to the word-solution). What also makes this solution attractive for the developer is that no code in the code-behind is needed to accomplish zooming (as long as the zooming level should not be persisted).

kind regards, Daniel

Monday, December 29, 2014

windows start-script for applications

I wrote a WCF service (started as command line application) and had the problem that it needs to be started with admin privileges. So I wrote a dos-script that can either start the server and/or the client and checks the privileges in the first place. Writing a dos script was a little bit like time traveling for me, but finally I managed and understood it. Here my findings:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@echo off
echo _________________________________________________
echo.
echo            HERE A FANCY SERVICENAME
echo _________________________________________________
net session >nul 2>nul
if %errorLevel% equ 0 (
   echo Success: Administrative permissions confirmed.
) else (
   echo Failure: Current permissions inadequate.
   goto end
)
echo.
echo.
set /P startServer=Should the server be started? (y/n) 
set /P startClient=Should the client be started? (y/n) 

IF /I "%startServer%"=="y" (
  echo starting server
  start cmd /c "Server.exe"
) else (
  echo starting server skipped
)

IF /I "%startClient%"=="y" (
  echo starting client
  start cmd /c "Client.exe"
) else (
  echo starting client skipped
)

:end


  • line #1 calls a "hidden from dos-box" action (using @) and disables the printing of the actual commands (only the result of the call will be displayed, but not the call).
  • optionally here a title can be set (using dos: title FANCYNAME) or clearing the screen can be done using command cls
  • following lines show a header
  • then there is a little hack by calling net session. There is no need to understand what this command is doing. The only important information is, that it quits with error 5 (access denied) if you are not currently running in admin-mode. Standard output stream and error output stream will be redirected to nul (to nowhere), so that the only effect is that the errorcode is set to 5 (failed to call the application) or 0 (everything worked fine). 
  • line #7: The errorlevel is a pre-defined variable set by the return code of the previous application. (Unluckily I am not sure if successful applications always reset this variable properly to zero. If you want to be sure then use the command "set" to overwrite the value to zero).
  • the following shows success or error message and jumps on error to the label in line 32 what means that the script stops there.
  • echo. prints an empty row. echo without . shows whether the echo-ing is on or no (as disabled in line #1).
  • set /P requests the console to read from standard in and to write the result to the variable.
  • now we can check for the inputted values (/I for case-insensitive). The 2 equal-signs are similar to equ, but refer to text equality and not to numeric equality
  • start calls an application run in its own dos-box what is a metaphor for run asynchronously without checking the return value or %errorlevel%. I started an own command prompt and call the command with /c parmeter.
pitfalls: 
  • the brackets work exactly the way they were shown above. Separation to own lines are not only forbidden, the script simply doesn't work anymore. 
  • if the server needs some time to startup and the client should be called a few seconds later, then it is a good trick to use a ping localhost (normally 4 seconds for standard 4 packets) to "waste" some time. (start cmd /c "ping localhost >nul 2>nul && Client.exe) Another solution is the command "timeout" what seams appropriate to.

cheers,
Daniel

Tuesday, December 16, 2014

ASP.NET developer efficiency

... because I was asked how to develop asp.net faster... here my top 10 shortcuts which boosted my work (in vs-studio 2013 using the standard key mapping for c# developers)

  1. press ctrl + "," to move between files
  2. press f12 to go to definition
  3. press ctrl k+r for find all references
  4. press f8 to move in the list of found items
  5. press ctrl+shift+b to compile
  6. press ctrl + "-" to jump back in history (regarding cursor position)
  7. press ctrl + alt + p to attach to process (w3wp for iis hosted asp.net) and type the name of the process
  8. press ctrl + shift + f to find stuff / h to replace
  9. press ctrl + "." to add references, implement interfaces and stuff
  10. press alt+tab to jump to browser, f5 for refresh (sorry for mentioning that :-) ).

cheers, Daniel

Thursday, December 11, 2014

nullpointerexception - history

... because today my program won 1:0 against me by raising a nullpointerexception I was willing to check out who invented the null pointer.

So thank you Mr. Tony Hoare, thank you very much! Built in 1965 for "algol w".
His quote: "I call it my billion dollar mistake". 
I would advice him to count that in hours of searching and not in dollars...


kind regards,
Daniel

Tuesday, December 2, 2014

kill only connections of a concrete DB

Today I had the problem that in a dead-lock situation a colleague (responsible for a database on my db server) wanted to fix the situation himself. While using activity monitor he found out which process (more or less equals to connection) was responsible for the fault-situation and wanted to set up a kill statement.

For activity monitor he needed the rights ( http://msdn.microsoft.com/en-us/library/ms175518.aspx ):

  • VIEW SERVER STATE

    and
  • CREATE DATABASE, 
  • ALTER ANY DATABASE, or 
  • VIEW ANY DEFINITION 
Long story short he was not allowed to call kill and I was quite happy about it, because it makes sense that a data owner is not allowed to kill processes of other unrelated services. In fact to kill his own processes could also be accomplished by restarting the corresponding server application, so he seems to have some kind of power anyway. I liked to hear, that I hadn't have to get in touch with the process search, so I needed to enable process killing. My problem was how to secure the whole system against other kill requests and still offer the functionality. 

Some research later I found the concept of impersonation (execute as), but I couldn't imagine how. I tried to allow the user (who failed to kill processes) to switch its user context to a more privileged user. Nothing won, because he is still able to do what he likes. So I created a stored procedure which encapsulates this logic (-> security by obscurity... if you don't know you can switch, you wouldn't try it). Better, but not good enough, because the source of the stored procedure definition was readable, so it is easy to understand which execute as statements has to be executed to become privileged and a security issue (as good as worst case). I tried a lot using master DB, other schemas and so on and found in the end the following link.


... with 5 golden rules which in fact really worked for me. 

  1. We create a new database and set the TRUSTWORTHY flag on
  2. We create a login with the permissions we want
  3. Set the login as the owner of the new database
  4. We create a stored procedure that does the work we want within the new database.
  5. We add the EXECUTE AS OWNER clause to the SP
These were really good tips and finally it worked to impersonate the execution! I just had to hard code the database name which the executor is allowed to kill (in the following code snippet DBNAME1) and check whether the - now - reachable sysprocesses table has an entry with passed in spid and hard coded database.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
   if(  exists (select 
  * 
  from master.sys.sysprocesses sproc
  where db_name(dbid) = 'DBNAME1' and 
  sproc.spid = @kill_spid)) 
   begin
 
 print 'resolved as DBNAME1 connection ... connection will be killed';
 SET @KillStmt = 'kill ' + CAST(@kill_spid AS VARCHAR(50)) + ''
 PRINT @KillStmt
 
 EXECUTE(@KillStmt)

   end else begin
 
 print 'connection was not established to DBNAME1 ... request will be ignored';

   end

kind regards,
Daniel

Friday, November 28, 2014

UnitTesting with DateTime.Now

Today I needed to unit test a component which uses System.DateTime.Now (C# .NET) ...

The good answer:this actually works using System.Fakes (sorry, no idea in which edition, but in ultimate it works perfectly). In the past microsoft seemed to use "moles" (see: http://research.microsoft.com/en-us/projects/moles/ ) instead of "fakes".

Using fakes:

  • Create a Unit-Test Project
  • Select References
  • Right-Click on "add fakes assembly" 
    • this adds ref to "...Fakes.dll"
    • Fakes Folder with xml stuff
  • now you enabled fakes for system (most of the time mscorlib will be faked too by VS)... 
  • start to use it


Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
        [TestMethod]
        public void CheckCurrentDate_ResultFixed2012()
        {
            // Arrange
            using (ShimsContext.Create())
            {
                // Act
                System.Fakes.ShimDateTime.NowGet = () => new DateTime(2012, 12, 31);

                // Assert
                Assert.AreEqual(2012, DateTime.Now.Year);
            }
        }


Kind regards, Daniel

Thursday, November 6, 2014

Expression Trees: good ideas and bad ideas

Today I had a look at expression trees. There are some really cool solutions using expression trees, which make the world of developers a better place.

I focused on the usage in combination with PropertyChanged where we have a lot to do with constant ("magic") strings which refer to the calling property name. In standard WPF projects we put this RaisePropertyChanged - boiler plate code like in the example http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx in every setter of a property.

A new and modern possible solution as used in

is to work with expression trees. 


The concept is:
  • still use caller member name if possible
  • make a lambda function which has only 1 expression tree leaf: the property.
  • push the lambda function as parameter inside (as expression tree)
  • In the expression tree read the name of the property which is handed in and use its name as string like in the original way
The function to read the described expression tree is quite simple (as shown in http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression/2916344#2916344 ) . The following example code shows how it works:

1
2
3
4
5
6
        private string GetMagicString(Expression<Func<object>> exp) 
        {
         
            return (exp.Body as MemberExpression ??
                ((UnaryExpression)exp.Body).Operand as MemberExpression).Member.Name;
        }

Important here is:

The difference is that you will get a UnaryExpression if your expression represents a value type whereas you will get a MemberExpression if your expression represents a reference type.

So you can call GetMagicString(() => MyProp) and get back MyProp as string.

This is a good idea, because now you get a compile error if you mistype your input. Quite cool.

Attention! You can implement magic strings with expression trees too and have the same problem as mentioned before. 


1
2
3
            MessageBox.Show(
                PrintStaticInfo(
                    (machinename) => string.Format("{0} is the machine name", machinename)));

You see we use machinename as parametername and push this expression tree into method PrintStaticInfo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
        private string PrintStaticInfo(Expression<Func<string,string>> expression)
        {
            string value = string.Empty;
            switch (expression.Parameters[0].Name.ToLower())
            {
                case "username":
                    value = Environment.UserName;
                    break;
                case "machinename":
                    value = Environment.MachineName;
                    break;
            }
            return expression.Compile()(value);
        }

This function inserts the value for a given parameter by name. The parameter name if mistyped breaks exactly the same way as PropertyChanged does if the wrong property name was inserted. Ugly code, different ways :-).

kind regards, Daniel