Friday, December 23, 2011

TFS vNext needs audit log reports

Because of some governmental regulations, we need to report the administrative actions over permissions on TFS. Auditors frequently request such reports from us.

I requested the audit logs of administrative actions over permissions on TFS from Microsoft in the VS vNext Wish List.

We'll see what Microsoft thinks about adding audit reports to TFS in the next version. What do you think, is it worth?

Thursday, December 22, 2011

TFS Case Study of Microsoft Turkiye

Microsoft Turkiye examined our TFS implementation and published a case study document:
http://www.microsoft.com/turkiye/casestudies/tfkb_tfs.aspx

Unfortunately the document is prepared only for Turkish audience, it has no English translation.

Sunday, June 19, 2011

Count lines of code in a database

Here is a small script to count lines of code in a database:


select
    o.type_desc as ObjectType
    ,count(*) as [ObjectCount]
    ,sum(len(m.definition) - len(replace(m.definition, char(13), ''))) as [TotalLineCount]
from sys.objects o
inner join sys.sql_modules m on o.object_id = m.object_id
where o.[type] in ('P', 'TR', 'FN', 'IF', 'V', 'TF')
and o.name not like 'aspnet[_]%'
and o.name not like 'vw[_]aspnet[_]%'
group by o.type_desc
order by o.type_desc

Monday, May 30, 2011

Sign a .Net assembly without the source code

Two different versions of an old .Net assembly caused some deployment problems. We wanted to deploy the assembly to the GAC but neither of the two versions were signed. We needed to sign the assemblies but we did not have the source code.

After a small search I found a great tool named ILMerge.
Main purpose of ILMerge is to combine more than one .Net assemblies into one assembly. The side benefit is that you can also sign the resulting assembly. It works while working with only one assembly too. This way you can sign an assembly without having the source code.
Sample command line:

ilmerge /t:library /keyfile:"c:\SomeKeyFile.snk" /out:"c:\signed\assembly.dll" "c:\unsigned\assembly.dll"

Wednesday, May 4, 2011

Entity framework class generator

I wrote a sql script to generate entity framework POCO classes: https://gist.github.com/954916

Script considers primary and foreign keys including both "one to one" and "one to many" relations.

It also writes sql object descriptions saved as extended properties to the class and property comments of POCO classes.

It is working for MS SQL 2008 and 2008 R2. I did not try to run the script on other versions.

Monday, September 6, 2010

C#: Call DynamicMethod within another DynamicMethod

Today I tried to call a dynamic method within another dynamic method.

First I built a dynamic method, m1dyn:

DynamicMethod m1dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il = m1dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);

Then I created a delegate and assigned it to a delegate variable named m1:

Func<string, string> m1 = (Func<string, string>)m1dyn.CreateDelegate(typeof(Func<string, string>));

Then I built a second dynamic method, m2dyn:

DynamicMethod m2dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il2 = m2dyn.GetILGenerator();
il2.Emit(OpCodes.Ldarg_0);
il2.Emit(OpCodes.Call, m1.Method);


I simply emitted a code which calls the method info of the first delegate variable, m1.
When I ran the code, I got the following error at the last line above:
"MethodInfo must be a RuntimeMethodInfo. Parameter name: meth"

What I had to do was to emit a call instruction with the first dynamic method variable itself, not the resulting delegate:
il2.Emit(OpCodes.Call, m1dyn);

Complete code is below:

public static void Test()
{
DynamicMethod m1dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il = m1dyn.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
Func<string, string> m1 = (Func<string, string>)m1dyn.CreateDelegate(typeof(Func<string, string>));

DynamicMethod m2dyn = new DynamicMethod("m1", typeof(string), new[] { typeof(string) });
var il2 = m2dyn.GetILGenerator();
il2.Emit(OpCodes.Ldarg_0);
il2.Emit(OpCodes.Call, m1dyn);
il2.Emit(OpCodes.Ret);
Func<string, string> m2 = (Func<string, string>)m2dyn.CreateDelegate(typeof(Func<string, string>));

string a = m2("a");
Console.WriteLine(a);
}

Tuesday, February 9, 2010

WCF BasicHttpBinding and windows authentication on IIS 6.0

Recently I tried to host a WCF service on IIS 6.0 with basic http binding.
I needed to authenticate users with windows security mode.

I configured the WCF binding like below in the web.config file:

<bindings>
<basicHttpBinding>
<binding name="BasicHttpWindowsBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>


Although I configured IIS so that anonymous authentication is not allowed and windows authentication is required, I got this error when I opened the service page with internet explorer:

System.NotSupportedException: security settings for this service require windows authentication but it is not enabled for the iis application that hosts this service

Well, it was disappointing because both service configuration and the IIS configuration was configured for windows authentication mode.

After a little struggle I found that basicHttpBinding's windows authentication is not supported by IIS 6.0.
Instead security mode of the binding should be set to Ntlm and you have to allow anonymous authentication in the IIS site settings.

Here is the complete config file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<system.web>
<compilation debug="true" />
<customErrors mode="Off" />
<authentication mode="Windows">
</authentication>
<authorization>
<allow users="somedomain\someuser"/>
<deny users="*"/>
</authorization>
</system.web>

<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5" />
<providerOption name="WarnAsError" value="false" />
</compiler>
</compilers>
</system.codedom>

<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="SvcFile" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
<directoryBrowse enabled="true" showFlags="Date, Time, Size, Extension, LongDate" />
</system.webServer>

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpWindowsBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="SomeServiceBehavior" name="SomeAssembly.SomeService">
<endpoint binding="basicHttpBinding" bindingConfiguration="BasicHttpWindowsBinding" contract="SomeAssembly.ISomeService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost/SomeAssembly/ISomeService.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SomeServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

</configuration>