Thursday, November 2, 2017

C# 6

1. Defining a Parameterless Constructor for a struct

In C# 5.0, every struct had a default parameterless constructor that you couldn’t override. Using the new operator invoked this constructor and all members of the struct were assigned default values.

public struct MyPoint
{
   public double X;
   public double Y;
}


class Program
{
   static void Main(string[] args)
   {
      MyPoint pt = new MyPoint(); // default values for X, Y (0.0)
      Console.WriteLine("{0}, {1}", pt.X, pt.Y);
   }
}


In C# 6.0, you can explicitly define a parameterless constructor for a struct, giving non-default values to the members of the struct

public struct MyPoint
{
   public double X;
   public double Y;


   public MyPoint()
   {
      X = 100.0;
      Y = 100.0;
   }
}

static void Main(string[] args)
{
   MyPoint pt = new MyPoint(); // 100.0, 100.0
   Console.WriteLine("{0}, {1}", pt.X, pt.Y);
}



2. Filtering Exceptions

C# 6.0 will include support for exception filters, that is–only catching a particular type of exception if an associated expression evaluates to true.
You can filter exceptions by including an if statement after the catch expression. If the result of evaluating the expression supplied is true, the exception is caught. If not, the behavior is as if you didn’t supply a catch block.
In the example below, we don’t catch divide by zero exceptions on Saturdays


int denom;
try
{
   denom = 0;
   int x = 5 / denom;
}
// Catch /0 on all days but Saturday
catch (DivideByZeroException xx) if (DateTime.Now.DayOfWeek != DayOfWeek.Saturday)
{
   Console.WriteLine(xx);
}



3. Using Lambda Expressions for Function Members

In C# 5.0, you could use a lambda expression wherever a delegate instance was expected. For example:

Func doubleMyNumber = (i) => 2 * i;

In C# 6.0, you can also use a lambda expression as the body of a function member. This simplifies the syntax for simple methods. For example:

public class Dog
{
   public Dog(string name, int age)
   {
      Name = name;
      Age = age;
   }

   public string Name { get; protected set; }
   public int Age { get; set; }

   public void AgeIncrement() => Age++;
   public int AgeInDogYears() => Age * 7;
}



4. Using Lambdas for Getter-Only Auto-Properties

In addition to using lambda expressions for method bodies in C# 6.0, you can use a lambda expression to implement the getter of a read-only auto-property.

public string Name { get; protected set; }
public int Age { get; set; }

public string BackwardsName => new string(Name.Reverse().ToArray());


The presence of the lambda expression tells the compiler that this is a property with a getter, rather than a field


5. Auto-property initializers

In early C# times there was only one way to declare them – very explicit:

private string _name = "Joe"; // backing field
public string Name
{
   get { return _name; }
   set { _name = value; }
}


The C# 6 release serves well here. You can now initialize property inline. It’s concise and readable.

public string Name { get; protected set; } = "Joe"
public string Name { get; set; } = "Joe";
public List Ingredients { get; } = new List { "dough", "sauce", "cheese" };


All of the initializers you’ve seen so far evaluate to a static expression. Non-static expressions, like the ones below, will generate compiler errors:

// compiler errors //public string Name2 { get; set; } = Name; //public decimal Price4 { get; set; } = InitMe();

decimal InitMe() { return 5m; }


The code tries to initialize Name2 with the value of Name, another property, which won’t work. Similarly, InitMe() is an instance method that won’t compile when used as the initializer for Price4. It doesn’t matter that InitMe() returns a numeric literal. Both of these situations generate a compiler error. Here's the error message for Price4

A field initializer cannot reference the non-static field, method, or property 'PizzaBase.InitMe()'

A virtual auto-property can be initialized too. Here’s an example:

A virtual auto-property can be initialized too. Here’s an example:

During initialization of the containing type, Price initializes before the constructor executes. It initializes like a field, meaning that a Price property override isn’t called during auto-property initialization. If you wanted the polymorphic initialization, you should initialize Price in the base class constructor, like this:

public abstract class PizzaBase
{
   public string Name { get; protected set; } = "Cheeze";

   public virtual decimal Price { get; set; } = 3.00m;

   public PizzaBase(IEnumerable extraIngredients)
   {
      Price = 2.95m;
   }
}


The abstract PizzaBase class is a base class for the PepperoniPizza class shown below. This class overrides the Price property:

public class PepperoniPizza : PizzaBase
{
   public decimal ExtraPrice { get; set; } = 0.25m;

   decimal price;
   public override decimal Price
   {
      get
      {
         return price;
      }

      set
      {
         price = value + .50m;
      }
   }

   public PepperoniPizza(decimal extraFees) : base(new List { "pepperoni" })
   {
      ExtraPrice += extraFees;
      Name = "Pepperoni";
   }
}

Tuesday, September 26, 2017

Getting Started with RabbitMQ on Windows

1. ERLANG INSTALLATION

RabbitMQ runs on the Erlang virtual runtime, so we need to install Erlang first as without it we can't get RabbitMQ to work. Download Erlang at http://www.erlang.org/downloads
Ensures that the appropriate environment variable (ERLANG_HOME) has been created during the installation. If, for any reason, the environment variable is missing, you will need to create it manually.




2. RABBITMQ SERVICE INSTALLATION

Download and install Rabbit Service at http://www.rabbitmq.com/install-windows.html



3. RABBITMQ WEB MANAGEMENT PLUGIN ENABLE

RabbitMQ runs, by default, as a Windows Service and technically you shouldn’t need to do anything else to start interacting with it. However, any interaction with the service needs to happen over the command-line.


Open command line tool (Run as Administrator). The tool is located at C:\Program Files (x86)\RabbitMQ Server\rabbitmq_server-3.3.4\sbin
Run the following command to enable the plugin rabbitmq-plugins.bat enable rabbitmq_management
Then, re-install the RabbitMQ service using the commands below
rabbitmq-service.bat stop
rabbitmq-service.bat install
rabbitmq-service.bat start

To check if everything worked as expected, navigate to http://localhost:15672/mgmt. You will be prompted for username and password. The default credentials are:
Username: guest
Password: guest




4. INSTALL HANDLE.EXE FOR RABBITMQ’S FILE DESCRIPTORS

When you first log in to the RabbitMQ web dashboard, under the Overview tab you will notice that in the File descriptors field there is a question mark about the missing Handle.exe. Handle.exe enables RabbitMQ to monitor the local file system. It will still work without it but I think that it's better to make it available, so let’s go and get it at here

Download the zip file and unzip it anywhere you want. I decided to extract mine in C:\Program Files\Handle. It is important that you keep a note of the extracted path as we will need to add it to PATH environment variable so it is available to RabbitMQ.
Open the Environment Variables Windows, scroll down to the System Variables -> Path variable and click on Edit. At the end of the Variable Value, add the path to the Handle.exe by the path above
Restart the RabbitMQ
rabbitmq-service.bat stop
rabbitmq-service.bat start




5. SETUP

Now it is time to get it setup. The next batch script that we are going to use is rabbitmqctl.bat. This is the batch script that we are going to use to control and get stats on the server.
Run the command: rabbitmqctl status



You can now be sure that your RabbitMQ server is up and running, ready to server requests

The first thing you should consider doing, especially if your instance of RabbitMQ is publicly accessible, is to secure it a bit. If you run the command, rabbitmqctl list_users you will see that your server has a single user named “guest”. This is the default user that RabbitMQ creates, and it has full rights to the RabbitMQ instance. You might want to start off by creating a new user with a password and granting that user full rights. We can do this by running these commands:
rabbitmqctl add_user [username] [password]
rabbitmqctl set_permissions justin “.*” “.*” “.*”

The first command creates a new user with a password. The second tells RabbitMQ to grant the user configure, write, and read permissions to all queues

Now you can run: rabbitmqctl delete_user guest to delete guest




6. GET .NET RABBITMQ CLIENT

You can get RabbitMQ Client from Visual Studio with NuGet tool or go to the page at http://www.rabbitmq.com/dotnet.html to download it

Now, you are ready for coding!

Prefer this link for samples https://dotnetcodr.com/messaging/

Monday, September 18, 2017

What are environment variables in Windows?

Environment variables are, in short, variables that describe the environment in which programs run. They are used by all kinds of programs to answer questions like: What is the name of the computer where I am installed? What is the name of the user account that is running me? What is my current working directory? Where is Windows installed? Where are the temporary files stored on this computer? Where is the OneDrive folder for this user account?

In Windows, environment variables have a name and value. For example, the variable windir (short for "Windows directory") may have the value "C:\Windows" or another path where Windows is installed.

Another common variable is named PATH. Many programs need to know where to find certain files, and the PATH variable tells them where they can find what they need. Those programs look for a PATH variable automatically, so you don’t have to type it all in every time you run the program. This variable has a value consisting of many user directories. These directories are set by the different programs that are installed on the computer, and they vary widely from system to system.

The concept of environment variables exists in most operating systems, from Linux to OS X to Windows. In principle, they mean the same thing but the way they are implemented and used differs.




Types of environment variables: User and System

There are two types of variables: user variables, specific to each user account, and system variables that apply to all user accounts.

User environment variables have values that differ from user to user. As their name implies, they are specific to your user account, and they store user specific data, like the location of your user profile, the folder where temporary files are stored for your account, the location of your OneDrive folder, and so on. They can be edited by that user account but not by other user accounts. These variables can be set by the user, by Windows or by different programs working with user specific locations.

System variables are global and cannot be changed by any user. Their values are the same for all user accounts. They refer to locations of critical system resources, like the folder where Windows is installed, the location of Program Files, and so on. These variables are set by Windows, by different programs and drivers.




How to find the environment variables in Windows

In Windows 10, use Cortana’s search box and type environment. Then, click or tap on the “Edit the system environment variables” search result.

In Windows 7, type environment in the Start Menu search box and two search results are displayed: “Edit environment variables for your account” and “Edit the system environment variables.” Click on either of them.

In Windows 8.1, type the word environment while on the Start screen, and two search results are displayed: “Edit environment variables for your account” and “Edit the system environment variables.” Click or tap either of them

The Environment Variables window is opened. There are some minor visual differences between Windows versions.The options and buttons available are the same and work the same way, no matter which Windows version you are using.




How to access the environment variables from the Control Panel





How to access the environment variables from the Run window




How to view environment variables in the Command Prompt

Open cmd then type command: SET, without any other parameters, and press Enter.



How to view environment variables in the PowerShell

Open it, type the command Get-ChildItem Env: then press Enter.



Conclusion

As you can see from this tutorial, environment variables are neither easy to find nor visible in any way, while working with Windows programs. They are managed in the background by the operating system and the different programs and drivers you install. However, they are essential to the proper operation of the operating system and of your installed apps. If you change the value of important system variables, without knowing what you are doing, you will get to experience just how important these environment variables are, by causing your system to malfunction

Wednesday, September 13, 2017

Why, when and how to rebuild and reorganize SQL Server indexes

The purpose of SQL Server index is pretty much the same as the book index. It allows you to get to the information quickly, instead of navigating through the book.

SQL Server indexes are created on a COLUMN level in both tables and views. Its aim is to provide a “quick to locate” data based on the values within indexed columns.
If an index is created on the primary key, whenever a search for a row based on one of the primary key values is performed.
The SQL Server will locate searched value in the index, and then use that index to locate the entire row of data.
This means that the SQL Server does not have to perform a full table scan when searching for particular row, which is much more performance intensive task –consuming more time, and using more SQL Server resources.

Relational indexes can be created even before there is data in the specified table, or even on tables and views in another database.

After indexes are created, they will undergo automatic maintenance by the SQL Server Database Engine whenever insert, update or delete operations are executed.

These automatic modifications will continuously scatter the information in the index throughout the database – fragmenting the index over time. The result – indexes now have more pages where logical ordering (based on the key value) differs from the physical ordering inside the data file. This means that there is a high percentage of free space on the index pages, and that SQL Server has to read higher number of pages when scanning each index. Also, ordering of pages that belong to the same index gets scrambled and this adds more work to the SQL Server when reading an index – especially in IO terms.

The Index Fragmentation impacts the SQL Server can range from decreased efficiency of queries, for servers with low performance impact, all the way to the point where SQL Server completely stops using indexes and resorts to the last-straw solution, full table scans for each and every query. As mentioned before, full table scans will drastically impact SQL Server performance and this is final alarm to remedy index fragmentation on the SQL Server.

The solution for fragmented indexes is to REBUILD or REORGANIZE indexes. But, before considering maintenance of indexes, it is important to answer two main questions:

1. What is the degree of fragmentation?

2. What is the appropriate action? Reorganize or rebuild?




Detecting fragmentation

Generally, in order to solve any problem, it is essential to first and foremost locate it, and isolate affected area before applying the correct remedy.

Fragmentation can be easily detected by running the system function sys.dm_db_index_physical_stats which returns the size and the fragmentation information for the data and indexes of tables or views in SQL Server. It can be run only against a specific index in the table or view, all indexes in the specific table or view, or vs. all indexes in all databases:

The results returned after running the procedures include following information:






  • avg_fragmentation_in_percent – average percent of incorrect pages in the index 
  • fragment_count – number of fragments in index 
  • avg_fragment_size_in_pages – average number of pages in one fragment in an index



Analyzing detection results

After the fragmentation has been detected, the next step is to determine its impact on the SQL Server and what action should be taken.

There is no exact information on the minimal amount of fragmentation that affects the SQL Server in specific way to cause performance congestion, especially since the SQL Server environments greatly vary from one system to another.

However, there is a generally accepted solution based on the percent of fragmentation (avg_fragmentation_in_percent column from the previously described sys.dm_db_index_physical_stats function)


  • Fragmentation is less than 10% – no de-fragmentation is required. It is generally accepted that in majority of environments index fragmentation less than 10% in negligible and its performance impact on the SQL Server is minimal.
  • Fragmentation is between 10-30% – it is suggested to perform index reorganization
  • Fragmentation is higher than 30% – it is suggested to perform index rebuild


Here is the reasoning behind the thresholds above which will help you to determine if you should perform index rebuild or index reorganization:

Index reorganization is a process where the SQL Server goes through existing index, and cleans it up. Index rebuild is a heavy-duty process where index is deleted and then recreated from scratch with entirely new structure, free from all piled up fragments and empty-space pages.

While index reorganization is a pure cleanup operation which leaves system state as it is without locking-out affected tables and views, the rebuild process locks affected table for the whole rebuild period, which may result in long down-times that could not be acceptable in some environments.

With this in mind, it is clear that the index rebuild is a process with ‘stronger’ solution, but it comes with a price – possible long locks on affected indexed tables.

On the other side, index reorganization is a ‘lightweight’ process that will solve the fragmentation in a less effective way – since cleaned index will always be second to the new one fully made from scratch. But reorganizing index is much better from the efficiency standpoint, since it does not lock affected indexed table during the course of operation.

Servers with regular maintenance periods (e.g. regular maintenance over weekend) should almost always opt for the index rebuild, regardless of the fragmentation percent, since these environments will hardly be affected by the table lock-outs imposed by index rebuilds due to regular and long maintenance periods.

How to reorganize and rebuild index:


Using SQL Server Management Studio:


  1. In the Object Explorer pane navigate to and expand the SQL Server, and then the Databases node
  2. Expand the specific database with fragmented index 
  3. Expand the Tables node, and the table with fragmented index 
  4. Expand the specific table 
  5. Expand the Indexes node 
  6. Right-click on the fragmented index and select Rebuild or Reorganize option in the context menu (depending on the desired action):
  7. Click the OK button and wait for the process to complete
Reorganize indexes in a table using Transact-SQL

USE MyDatabase;
GO

ALTER INDEX ALL ON MyTable REORGANIZE;
GO

Rebuild indexes in a table using Transact-SQL

USE MyDatabase;
GO

ALTER INDEX ALL ON MyTable REBUILD;
GO



Rebuild or reorganize indexes with ApexSQL Backup

Final option when rebuilding or reorganizing SQL Server indexes is to use ApexSQL Backup – a tool for database jobs management and automation.

ApexSQL Backup allows users to perform and schedule index de-fragmentation jobs from user-friendly graphical user interface. In addition to automation features, which allow the user to perform regular maintenance on their indexes, ApexSQL Backup allows rebuilding/reorganizing indexes on multiple tables/views at once. Additionally, ApexSQL Backup can send an email notification on job completion. Additionally, all scheduled jobs, as well as completed activities can be inspected and altered from the comprehensive view screens.

To schedule index reorganize/rebuild job with ApexSQL Backup, do the following:

  1. Start the application
  2. In the main ribbon choose appropriate index defragmentation job:
  3. Provide SQL Server and database details, choose tables and views to be included in the defragmentation job and click the OK button:
  4. To provide schedule details, click on the Schedules radio button, and chose schedule frequency and duration, and then click the Create button:
  5. To complete the schedule, click on the Create button:


With this, the reorganize/rebuild job has been created and will be executed as per specified schedule. All scheduled jobs can be seen in the Schedules pane.

Source from https://solutioncenter.apexsql.com/why-when-and-how-to-rebuild-and-reorganize-sql-server-indexes/

Thursday, July 20, 2017

C# Func vs Action

The difference between Func and Action is simply whether you want the delegate to return a value (use Func) or not (use Action)

Func is probably most commonly used in LINQ - for example in projections: list.Select(x => x.SomeProperty) or filtering: list.Where(x => x.SomeValue == someOtherValue) or key selection: list.Join(otherList, x => x.FirstKey, y => y.SecondKey, ...)

Action is more commonly used for things like List.ForEach: execute the given action for each item in the list





Traditional way of using Delegate

//Declare delegate
public delegate void PrintMessage(string message);
public delegate int Calculate(int x, int y);


class SimpleClass
{
   public void SayHello(string name)
   {
      Console.WriteLine("Hello {0}", name);
   }


   public int Add(int x, int y)
   {
      return x+y;
   }
}

//Use delegate
var sc = new SimpleClass();
var printer = new PrintMessage(sc.SayHello);
printer("Pollux");

var calculator = new Calculate(sc.Add);
var result = calculator(5,10);



Action

This delegate was introduced in Framework 2.0. We can now use Action delegate to pass a method as a parameter without explicitly defining the delegate. The compiler will take care of it. This delegate can accept parameters but without a return type.

Action act = delegate(string name)
{
   Console.WriteLine("Hello ", name);
};


Call the delegate use act(4, 5)



Func

This was introduced in Framework3.5. This delegate is different from Action in the sense that it supports for return value.

Func fn = delegate(int x, int y)
{
   return x+y;
};


Call the delegate use Console.WriteLine(“Using Func<> :” + fn(6, 6));

Monday, July 3, 2017

How to resolve a System.Security.Principal.IdentityNotMappedException?

Sometimes when working with a non-English version of Windows, we get kinda problem
"Some or all identity references could not be translated"
This indicates that we are getting a System.Security.Principal.IdentityNotMappedException
What does it mean?


The first thing to understand is that in Windows, User Accounts and Groups have a unique and immutable identifier known as a Security Identifier (SID). When working with User Accounts and Groups in Windows, you can work with them via their SID or by their name.

In Windows, a user is represented by an Access Token (You can find more information on Access Tokens at http://msdn.microsoft.com/en-us/library/windows/desktop/aa374909(v=vs.85).aspx) which can be associated with a process or to a thread (via impersonation).
The token contains the user’s SID and all the Groups the user is a member of. The token contains the Group SIDs. (The groups are NOT stored by their names)

There are Win32 APIs that allows an application to translate between the name and the SID:



These Win32 APIs actually calls the LSA APIs. (One difference with these APIs is that they allow to translate multiple names/SIDs instead just one.)


When converting between a Name and a SID and vice versa, you can encounter an error if the translation can’t be done. The common Win32 Error code that you will see is 1332 also known as ERROR_NONE_MAPPED which translates to “No mapping between account names and security IDs was done.”

At the LSA API level where status errors are returned, the error is: STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED. In .NET, the error code is mapped as the following exception:System.Security.Principal.IdentityNotMappedException

Why would the translation APIs fail? Well, the API remarks provides some details on how the translation is done. It uses a lookup order to translate (there is also a local cache as well)

In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, LsaLookupSids can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in the SIDhistory field of an account in the forest. The SIDhistory field stores the former SIDs of an account that has been moved from another domain. To perform these searches, the function queries the global catalog of the forest.

So a translation failure could happen if you have an issue with your Domain(s) or an issue with SID History. So the first step in determining the issue is identifying which user or SID is the issue. Once you have identified the User or SID, you can then review its relationship with the caller (who is this and what domain do they belong to and what domain does the system belong to where the caller is running)

Finally, a word of advice, internally most APIs are going to be working with SIDs so you can avoid the translation error and improve performance by always trying to work with SIDs.
You’ll notice that most classes in .NET such as IsInRole() allows you to specify a SID instead of the name (via the SecurityIdentifier class). WindowsIdentity.Groups allows you access to the SID as well.


Example:
I want to set permission for a user

static void SetPermission(string directory)
{
   var directoryInfo = new DirectoryInfo(directory);
   var directorySecurity = directoryInfo.GetAccessControl();
   CanonicalizeDacl(directorySecurity);
   directorySecurity.AddAccessRule(new FileSystemAccessRule("BUILTIN\\IIS_IUSRS", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
   directoryInfo.SetAccessControl(directorySecurity);
}


This code would be failed if it run in a non-English version of Windows because the "BUILTIN\\IIS_IUSRS" could not be translated. Exactly the "BUILTIN" could not be translated. To fix this problem, I could change to remove "BUILTIN" or use an SID instead.

static void SetPermission(string directory)
{
   var directoryInfo = new DirectoryInfo(directory);
   var directorySecurity = directoryInfo.GetAccessControl();
   var sid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
   directorySecurity.AddAccessRule(new FileSystemAccessRule(sid, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
   directoryInfo.SetAccessControl(directorySecurity);
}


Refer these links for SID
https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
https://msdn.microsoft.com/en-us/library/cc980032.aspx

Using statement inside Vs outside

A namespace declaration looks like: MyCorp.TheProduct.SomeModule.Utilities
This could be equivalence


namespace MyCorp
{
   namespace TheProduct
   {
      namespace SomeModule
      {
         namespace Utilities
         {
            ...
         }
      }
   }
}

The rule to resolve the namespace is: First, search the inner most "scope" for a match. If nothing is found then goes out 1 level, continue searching,next and so on... Until a match is found.
Let check the code

With using outside

using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct; <-- br="" change="" nothing="" this="" uncommenting="" would=""> using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

namespace MyCorp.TheProduct.SomeModule.Utilities
{
   class C
   {
      Ambiguous a;
   }
}


In the above case, to find out what type Ambiguous is, the search goes in this order:


  1. Nested types inside C (including inherited nested types)
  2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
  3. Types in namespace MyCorp.TheProduct.SomeModule
  4. Types in MyCorp.TheProduct
  5. Types in MyCorp
  6. Types in the null namespace (the global namespace)
  7. Types in System, System.Collections.Generic, System.Linq, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, and ThirdParty



With usings inside:
namespace MyCorp.TheProduct.SomeModule.Utilities
{
   using System;
   using System.Collections.Generic;
   using System.Linq;
   using MyCorp.TheProduct;
   using MyCorp.TheProduct.OtherModule;
   using MyCorp.TheProduct.OtherModule.Integration;
   using ThirdParty;

   class C
   {
      Ambiguous a;
   }
}


Now, search for the type Ambiguous goes in this order:

  1. Nested types inside C (including inherited nested types)
  2. Types in the current namespace MyCorp.TheProduct.SomeModule.Utilities
  3. Types in System, System.Collections.Generic, System.Linq, MyCorp.TheProduct, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration, and ThirdParty
  4. Types in namespace MyCorp.TheProduct.SomeModule
  5. Types in MyCorp (MyCorp.TheProduct is already searched)
  6. Types in the null namespace (the global namespace)



No matter what we put the using inside or outside the namespace declaration, there's always the possibility that someone add a new type later with identical name ambiguous to one of the namespaces which has higher priority.
Also, if a nested namespace has the same name as a type, it can cause problems.

It's always dangerous to move the using form outside to inside and vice versa. The search hierarchy is changed and another type would be found. Therefore, chose one convention and stick to it.

One advantage of having using outside is that we can rename the using directives look like using AC=System.Security.AccessControl

Tuesday, March 7, 2017

Create an offline installer for Visual Studio 2017

Download the setup file you want

Edition File
Visual Studio Enterprise vs_enterprise.exe
Visual Studio Professional vs_professional.exe
Visual Studio Community vs_community.exe


Create an offline installation folder

To create an offline installation with all languages and all features, use one of the commands from the following examples. Run cmd in Administrator privilege.

Visual Studio Enterprise vs_enterprise.exe --layout c:\vs2017offline
Visual Studio Professional vs_professional.exe --layout c:\vs2017offline
Visual Studio Community vs_community.exe --layout c:\vs2017offline


Install from the offline installation folder

  1. Install the certificates (They are in the Certificates folder, which is in your Layout folder. Simply right-click each one to install it.)
  2. Run the installation file. For example, run:
    c:\vs2017offline\vs_enterprise.exe


Additional tips for offline installers

There are many options you can use to customize your offline installer. Here are a few examples of how to customize it by language locale

  • To download all workloads and components for only one language, run:
    vs_enterprise.exe --layout C:\vs2017offline --lang en-US
  • To download all workloads and components for multiple languages, run:
    vs_enterprise.exe --layout C:\vs2017offline --lang en-US de-DE ja-JP
  • To download one workload for all languages, run
    vs_enterprise.exe --layout C:\vs2017offline --add Microsoft.VisualStudio.Workload.Azure
  • To download two workloads and one optional component for three languages, run:
    vs_enterprise.exe --layout C:\vs2017offline --add Microsoft.VisualStudio.Workload.Azure Microsoft.VisualStudio.Workload.ManagedDesktop Component.GitHub.VisualStudio --lang en-US de-DE ja-JP
To learn more about the options you can use to customize your installation, see our  Use command-line parameters to install Visual Studio 2017  page.


How to update an offline installer

You might want to update your offline installer at a later date. Here's how.
  • To update a Visual Studio instance that you installed from an offline installation folder, run the Visual Studio Installer, and then click Update.
  • To refresh your offline installation folder so that it includes the latest updates, run the --layout command again. Make sure to point to the same folder that you used before; this way, only those components that have been updated since you last ran --layout will be downloaded.
If you want to update your offline installation, run the  --layout  command again. Make sure to point to the same folder that you used before; this way, only those components that have been updated since you last ran  --layout  will be downloaded.

Thursday, February 16, 2017

Windows File System: Maximum Path Length Limitation

In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length for a path is MAX_PATH, which is defined as 260 characters. A local path is structured in the following order: drive letter, colon, backslash, name components separated by backslashes, and a terminating null character. For example, the maximum path on drive D is "D:\some 256-character path string" where "" represents the invisible terminating null character for the current system codepage. (The characters < > are used here for visual clarity and cannot be part of a valid path string.)

NOTE: File I/O functions in the Windows API convert "/" to "\" as part of converting the name to an NT-style name, except when using the "\\?\" prefix as detailed in the following sections.

The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). To specify an extended-length path, use the "\\?\" prefix. For example, "\\?\D:\very long path".

NOTE: The maximum path of 32,767 characters is approximate, because the "\\?\" prefix may be expanded to a longer string by the system at run time, and this expansion applies to the total length.

The "\\?\" prefix can also be used with paths constructed according to the universal naming convention (UNC). To specify such a path using UNC, use the "\\?\UNC\" prefix. For example, "\\?\UNC\server\share", where "server" is the name of the computer and "share" is the name of the shared folder. These prefixes are not used as part of the path itself. They indicate that the path should be passed to the system with minimal modification, which means that you cannot use forward slashes to represent path separators, or a period to represent the current directory, or double dots to represent the parent directory. Because you cannot use the "\\?\" prefix with a relative path, relative paths are always limited to a total of MAX_PATH characters.

There is no need to perform any Unicode normalization on path and file name strings for use by the Windows file I/O API functions because the file system treats path and file names as an opaque sequence of WCHARs. Any normalization that your application requires should be performed with this in mind, external of any calls to related Windows file I/O API functions.

When using an API to create a directory, the specified path cannot be so long that you cannot append an 8.3 file name (that is, the directory name cannot exceed MAX_PATH minus 12).
The shell and the file system have different requirements. It is possible to create a path with the Windows API that the shell user interface is not able to interpret properly.

TIP: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. However, you must opt-in to the new behavior.

A registry key allows you to enable or disable the new long path behavior. To enable long path behavior set the registry key at HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD). The key's value will be cached by the system (per process) after the first call to an affected Win32 file or directory function (list follows). The registry key will not be reloaded during the lifetime of the process. In order for all apps on the system to recognize the value of the key, a reboot might be required because some processes may have started before the key was set.
The registry key can also be controlled via Group Policy at Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths.
You can also enable the new long path behavior per app via the manifest:


<application xmlns=urn:schemas-microsoft-com:asm.v3>
    <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
        <ws2:longPathAware></ws2:longPathAware>
    </windowsSettings>
</application>



These are the directory management functions that no longer have MAX_PATH restrictions if you opt-in to long path behavior: CreateDirectoryW, CreateDirectoryExW GetCurrentDirectoryW RemoveDirectoryW SetCurrentDirectoryW.

These are the file management functions that no longer have MAX_PATH restrictions if you opt-in to long path behavior: CopyFileW, CopyFile2, CopyFileExW, CreateFileW, CreateFile2, CreateHardLinkW, CreateSymbolicLinkW, DeleteFileW, FindFirstFileW, FindFirstFileExW, FindNextFileW, GetFileAttributesW, GetFileAttributesExW, SetFileAttributesW, GetFullPathNameW, GetLongPathNameW, MoveFileW, MoveFileExW, MoveFileWithProgressW, ReplaceFileW, SearchPathW, FindFirstFileNameW, FindNextFileNameW, FindFirstStreamW, FindNextStreamW, GetCompressedFileSizeW, GetFinalPathNameByHandleW.