nameof (C# Reference)

Další skvělá feature C# 6.0, žádné hardcoded řetězce:

using Stuff = Some.Cool.Functionality
class C {
static int Method1 (string x, int y) {}
static int Method1 (string x, string y) {}
int Method2 (int z) {}
string f<T>() => nameof(T);
}

var c = new C()

nameof(C) -> "C"
nameof(C.Method1) -> "Method1"
nameof(C.Method2) -> "Method2"
nameof(c.Method1) -> "Method1"
nameof(c.Method2) -> "Method2"
nameof(z) -> "z" // inside of Method2 ok, inside Method1 is a compiler error
nameof(Stuff) = "Stuff"
nameof(T) -> "T" // works inside of method but not in attributes on the method
nameof(f) -> "f"
nameof(f<T>) -> syntax error
nameof(f<>) -> syntax error
nameof(Method2()) -> error "This expression does not have a name"

 

 

Zdroj: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/nameof

Vývoj vlastního CmdLetu v C# – příprava projektu Visual Studia

Vývoj vlastního PowerShell příkazu (CmdLet) je velice snadné a rychlé – ideální pro často opakované akce, případně akce u zákazníka, kde nemusí být vždy vzdálený přístup do jeho infrastruktury. Za posledních pár let už jsem jich napsal desítky a jsem jsem z toho stále nadšen, hlavně tou jednoduchostí, v podstatě jsem tím zcela nahradil jednoúčelové konzolové aplikace, kde již navíc není nutné řešit parsování argumentů, přehledná výpis na konzolovou obrazovku, všechno je již tak nějak vyřešeno. Jako příklad jednoho z CmdLetů bych uvedl snadné nasazení jedné naší aplikace hostované v Azure, kde s každým zákazníkem bylo vždy nutné přihlásit se na portál Azure, vytvořit hosting pro aplikaci, nastavit domény, standard mód, vytvořit a nastavit DB, connection string do aplikace, vytvořit storage provider, přihlašovací údaje zapsat do aplikace, nastavit zálohování, a tak bych mohl pokračovat….. až po finální nahrání zkompilované verze – prostě práce na minimálně 2-4h a to ještě s rizikem chyby. Nyní k tomu slouží dva CmdLety, jeden pro přihlášení k Azure, druhý už pro založení tenantu a provedení všech potřebných akcí zcela automaticky.

V tomto prvním díle ukážu pouze základ, založení Visual Studio projektu a jeho nastavení.

Základem vlastního PowerShell CmdLetu je založený projekt typu Class Library

image 

image

Volba verze .NET Frameworku je závislá na požadované verzi PowerShellu, pokud například skriptujete akce pro SharePoint 2010, musíte nastavit .NET Framework verze maximálně 3.5.

  • PowerShell 2.0 – .NET Framework 3.5
  • PowerShell 3.0 – .NET Framework 4
  • PowerShell 4.0 – .NET Framework 4.5
[more]

Po založení projektu je nutné ručně přidat potřebné reference, hlavní referencí je System.Management.Automation.dll, kterou naleznete (případně dle vaší verze PowerShellu):
C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0

image

Následně se již můžeme vrhnout na prvním CmdLet, pro první sample klasicky Hello World, založíme novou třídu a pojmenujeme jí GetHelloWorldMessage:

image

A začneme přidávat atributy a base třídu:

  • importujte namespace System.Management.Automation
  • třída GetHelloWorldMessage musí být zděděna z objektu PSCmdlet
  • přidejte atribut CmdLet k nově vytvořené třídě, první parametr definuje jednu z povolených akcí, respektive prefixů (na funkci samotného CmdLetu nemá vliv, jenom definuje standard) a druhý parametr určující název samotné Powershell funkce, tentokrát bez prefixu již daného výčtovým typem VerbsCommon, výsledek tedy může být:
    [Cmdlet(VerbsCommon.Get, „HelloWorldMessage“)]
    Samotný příkaz tedy bude dostupný jako Get-HelloWorldMessage

Samotnou funkčnost implementujete přetížením metody ProcessRecord(), která je definována v base PSCmdLetu a navíc přidáme jeden vstupní parametr pro specifikaci jména uživatele – tento parametr je označen jako povinný.

image

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Threading.Tasks;

namespace DevIT.PowerShell.Samples
{
    [Cmdlet(VerbsCommon.Get, "HelloWorldMessage")]
    public class GetHelloWorldMessage : PSCmdlet
    {
        [Parameter(Mandatory = true, HelpMessage = "Zadejte Vaše jméno.")]
        public string YourName { get; set; }
        protected override void ProcessRecord()
        {
            WriteVerbose("Spouštíme hrozně složitou akci...");
            WriteObject(string.Format("Vítejte, {0}!", YourName ?? string.Empty));
        }
    }
}

 

Nyní už jenom zkompilujeme, spustíme konzoli PowerShellu, nalistujeme adresář s výsledným DLL souborem a importujeme ho do sady dostupných PowerShell příkazů:

Import-Module .\DevIT.PowerShell.Samples.dll

Následně již můžeme zavolat příkaz Get-HelloWorldMessage:

image

Případně rovnou s parametrem Get-HelloWorldMessage -YourName “Pavel”

Nebo klasicky parametrem –? zobrazit dostupné volby, při prvním volání nápovědy však budete vyzván k přegenerování nápovědy, která se generuje na základě atributů uvedených u CmdLetu i samotných parametrů:

image

SQL LINQ vs. Guid.Empty

Nikdy jsem na to zatím nenarazil, nebo si toho minimálně nevšimnul, ale v LINQ dotazu platí následující:

Guid.Empty != new Guid("00000000-0000-0000-0000-000000000000")

konkrétní příklad:

var a = query.Where(row => row.InvoiceId == Guid.Empty);

var b = query.Where(row => row.InvoiceId == new Guid("00000000-0000-0000-0000-000000000000"));

logicky bych čekal, že výsledek bude identický, tedy a i b budou obsahovat kolekci identických objektů, ale výsledek je ten, že a obsahuje prázdnou kolekci, b obsahuje všechny záznamy kde je InvoiceId rovno Guid.Empty, což je sice to samé, LINQ to ale zjevně interpretuje jinak a první příklad je tedy nefunkční, respektive nevrací očekáváné výsledky.

Na otázku PROČ jsem nenašel žádnou smysluplnou odpověď. BUG?

Visual Studio 2010–Vypnutí hlášky Attach Security Warning

Hláška: Attach Security Warning

Popis:  Attaching to this process can potentially harm your computer.  If the information below looks suspicious or you are unsure, do not attach to this process.

image

[more]

Postup deaktivace:

  • zavřít všechny instance Visual Studia
  • zkontrolujte, zda jste členem lokální uživatelské skupiny debuggers (Control Panel, Administrative Tools, Local Security Policy, Security Settings, Local Policies, User Rights Assignment, Debug Programs).
    image
  • Pomocí regedit.exe změňte hodnotu klíče HKCU\Software\Microsoft\VisualStudio\10.0\Debugger\DisableAttachSecurityWarning z 0 na 1
  • Spusťte Visual Studio

Error 348: Compilation failed. Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Tuto chybu jsem tak nějak nepochopil, zřejmě je to bug ve Visual Studiu 2010. Projekt nelze kompilovat a hlásí to chybu “error 348: Compilation failed. Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.”

Na jediné řešení na které jsem přišel je, že je potřeba otevřít .csproj v poznámkovém bloku a odstranit elementy <ProjectTypeGuids>, následně znovu otevřít projekt.

Zvláštní, ale funguje to.

ILSpy–nová alternativa k již placenému RedGate .NET Reflector

Společnost RedGate se bohužel rozhodla zpoplatnit asi nejznámější produkt mezi .NET vývojáři, a to produktu .NET Reflector (http://www.reflector.net/).

Tento produkt měl sice spoustu much, ale hodně krát nám pomohl objasnit chování některých nedeterministických funkcí a knihoven, zejména v SharePointu. To co mě mrzí nejvíce není ani samotné zpoplatnění (v celku zanedbatelných 35 USD), ale to že RedGate na tom od převzetí od vývojáře Lutz Roedera  v roce 2008 neudělal vůbec nic! Tedy integraci do menu Visual Studia nepovažuji za pokrok.

    

Naštěstí se objevila další open source alternativa jménem ILSpy: http://wiki.sharpdevelop.net/ilspy.ashx

image

 

Která je až nápadně podobná .NET Reflectoru, takže přechod není tak bolestný Obličej s očima v sloup 

Samotný ILSpy je ale založený na UI WPF, .NET Reflector stále využívá Windows Forms. To ale samozřejmě není z pohledu funkčnosti důležité, hlavní jsou skutečné features:

ILSpy Features

  • Assembly browsing
  • IL Disassembly
  • Decompilation to C#
    • Supports lambdas and ‚yield return‘
  • Saving of resources
  • Search for types/methods/properties (substring)
  • Hyperlink-based type/method/property navigation
  • Base/Derived types navigation
  • Navigation history
  • BAML to XAML decompiler
  • Save Assembly as C# Project
  • Find usage of field/method
  • Extensibile via plugins (MEF)

 

ILSpy Roadmap

  • Improve the decompiler
    • Add support for object initializers
  • Assembly Lists
  • Improve search performance
  • Debugger
  • Bookmarks
  • Find usage of type/property/event

 

Stránka projektu: http://wiki.sharpdevelop.net/ilspy.ashx

Twitter: http://twitter.com/ilspy

Nelze modifikovat nastavení IIS WAMREG admin Service – nastavení DCOM je zašednuté/disabled na Windows Server 2008 R2

Problém je v tom, že aktuálně přihlášený uživatel nemá přístup k danému klíči v registrech systému.

Konkrétně jde o klíč v registrech:

HKEY_CLASSES_ROOT\AppID\{61738644-F196-11D0-9953-00C04FD919C1}

Aby jste tedy mohli změnit nastavení konkrétního DCOM objektu, je potřeba provést změnu nastavení v registrech a tento klíč přiřadit vlastníkům ze skupiny Administrators.

Pokud nyní zavřete správu DCOM objektů a znovu otevřete, již bude možné modifikovat nastavení IIS WAMREG admin Service DCOM objektu.

SharePoint Search Crawler indexuje na publishing portálu kompletně celou stránku–jak indexovat pouze obsah bez navigace a ostatních rušivých elementů

Search Crawler na publishing portálu indexuje vždy kompletní stránku, tak jak dostane HTML, tak ho uloží do své databáze. To je ovšem problém, neboť následně při vyhledávání vyhledává texty i v navigaci webu nebo hlavičce a patičce. Tyto elementy jsou ale ve většině případů pro všechny stránky na portále stejné, uživatel tak dostává nerelevantní výsledky (navíc stále stejné):

image

Neexistuje možnost, jak automaticky donutit Search Server, aby toto chování změnil a například ignoroval stále stejné elementy na stránce, případně jinak pomocí tagu vynechával zvolené oblasti v master page.

Udělal jsem si proto malého pomocníka, který se vloží do masterpage v podobě:

[more]

<DevIT:SearchCrawlTrimmedControl runat="server" SearchAccount="MySearchAccount">

zde vlozte menu, header, footer... vse co chcete skryt pred indexerem

</DevIT:SearchCrawlTrimmedControl>

Kde uvnitř ovládacího prvku SearchCrawlTrimmedControl jsou všechny elementy, které chci skrýt před indexerem obsahu. Tato třída pak následně podle přistupujícího účtu skryje nebo zobrazí vybrané elementy.

/// <summary> 
/// Ovladaci prvek pro skyti vsech nepotrebnych veci v masterpage pri indexovani - aby se indexoval pouze samotny obsah stranky 
/// <DevIT:SearchCrawlTrimmedControl runat="server">  
/// <!-- zde vlozte menu, header, footer... vse co chcete skryt pred indexerem --> 
/// </DevIT:SearchCrawlTrimmedControl> 
/// </summary> 
public class SearchCrawlTrimmedControl : Control 
{ 
    public string SearchAccount 
    { 
        get { 
            string ret = ViewState["SearchAccount"] as string; 
            if (string.IsNullOrEmpty(ret)) 
                return "spsearch"; 
            return ret; 
        } 
        set { ViewState["SearchAccount"] = value; } 
    }

    protected override void Render(HtmlTextWriter writer) 
    { 
        bool render = true; 
        SPUser cu = SPContext.Current.Web.CurrentUser; 
        if (cu != null) 
        { 
            if (cu.LoginName.ToLower().EndsWith(SearchAccount)) 
            { 
                render = false; 
            } 
        } 
        if (Context.Request != null && Context.Request.UserAgent != null && 
            Context.Request.UserAgent.ToLower().Contains("robot")) 
        { 
            render = false; 
        } 
        if (render) 
        { 
            base.Render(writer); 
        } 
        else 
        { 
        } 
    } 
}