Monday, 22 September 2014

Remove Users from group in SharePoint 2013 from Client Object model.

This is the method that we use to remove users from groups in Sharepoint 2013

It's a bit more convoluted than it needs to be as for some reason Sharepoint 2013 appends the claim provider to the username, which means that rather than having:
 dev\duser1  
we have something like:
i:0#.w|dev\duser1  
so in order to ensure that the it will always find the relevant user, we do the extra call to ResolvePrincipal.

using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Utilities;

     public bool RemoveUser(string url, string groupName, string userName)  
     {  
       using (ClientContext context = new ClientContext(url))  
       {  
         var principal = Utility.ResolvePrincipal(context, context.Web, userName, PrincipalType.User,  
           PrincipalSource.All, context.Web.SiteUsers, false);  
         context.ExecuteQuery();  
         if (principal.Value != null)  
         {  
           string login = principal.Value.LoginName;  
           GroupCollection siteGroups = context.Web.SiteGroups;  
           Group group = siteGroups.GetByName(groupName);  
           var query = context.LoadQuery(group.Users.Where(usr => usr.LoginName == login).Include(u => u.LoginName));  
           context.ExecuteQuery();  
           User user = query.SingleOrDefault();  
           if (user != null)  
           {  
             group.Users.RemoveByLoginName(user.LoginName);  
             context.ExecuteQuery();  
           }
           return true;               
         }  
       }  
       return false;  
     }  

Monday, 1 September 2014

Product Versions in MSI installers created with WIX - part 2

In a previous post I described how to change the version of MSI installers created with WiX.

This post discusses a way of linking the version number of an assembly (library, dll, executable) to the product version.

This is more suited to a library/framework, where you want to ensure that the product version is the same as the library/framework.
  1. On the library project, edit the AssemblyInfo.cs file:

  2. Remove these two lines:
    [assembly: AssemblyVersion("1.0.0.0")]
    [assembly: AssemblyFileVersion("1.0.0.0")]
  3. Create a new File called VersionInfo.cs on the Properties folder.

  4. Contents of file should be:
    [assembly: System.Reflection.AssemblyVersion("0.0.0.*")]
  5. Edit the project file (you'll need to unload the project if you want to do it from Visual Studio) and at the end, you'll find a commented out section. Get rid of it (everything between <!-- -->) and add the following:
  6. <Target Name="BeforeBuild"> < <WriteLinesToFile Condition=" '$(Version)' != '' " File="Properties\VersionInfo.cs" Overwrite="True" Lines="[assembly: System.Reflection.AssemblyVersion(&quot;$(Version)&quot;)] // Auto-generated by build process" /> </ </Target>
  7. On the product.wxs file on your WiX project, just add the following:
  8. <Product Id="12c0deff-c0de-c0de-c0de-123f422c0dea" Name="Name" Language="1033" Version ="!(bind.FileVersion.filAB3D3C60ED5901936249D5C56B6C90A6)" Manufacturer="ManyRootsofallevil" UpgradeCode="fafffaff-c0de-c0de-c0de-123f422c0dea">
    Where filAB3D3C60ED5901936249D5C56B6C90A6 is the id of your library file
  9. Finally, add the following to the wix project. Make sure this is on the initial PropertyGroup Element:
  10. <Version Condition=" '$(Version)' == ''">0.0.0.1</Version>
You can now build this using:

msbuild solution.sln /p:Version=1.3.3.7

Friday, 29 August 2014

TIL - Copy References in GAC to output folder

A while back I had this problem, looks like there is a simple solution:

<Reference Include="DocumentFormat.OpenXml, Version=2.5.5631.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
 <SpecificVersion>False</SpecificVersion>
 <Private>True</Private> <HintPath>..\..\..\OpenXml SDK 2.5\DocumentFormat.OpenXml.dll</HintPath>
</Reference>
Setting <Private>True</Private> ensures that the reference is copied to the output folder, looks like setting it to Copy Local, just doesn't do the trick

Thursday, 21 August 2014

TIL - DeploymentItem files not copied in MSTest

I have a set of unit tests that need an xml file to work  and I despite me using the DeploymentItem attribute the test was not working.

Turns out that DeploymentItem will only copy from the build directory, so I set the Copy to Output Directory property of the file to Copy always:


Monday, 18 August 2014

Product Versions in MSI installers created with WIX - part 1

I must confess that in the past I used to do this manually or not at all (loud gasps) as I've never had a fully functioning CI environment but, this has changed recently so here it goes.

In essence the challenge is to change the version number of the installer every time a new build is done, so that the build number is reflected in both Windows (Control Panel -> Programs and Features ) and the file itself, e.g. installer.1.0.0.0.msi

There are two main ways of doing this, that I know of:
  • Pass the build number to the Wix Installer.
  • Get the build number from a library or executable.

In this post, I will discuss the first way, all changes unless stated are made to the wix project file (wixproj extension), so you will need to unload the project from Visual Studio or use another editor to make these changes.

We need a Property to hold the version number, which appropriately is called VersionNumber, I've made sure that this is populated with a default value, in case the build is done from Visual Studio.
<VersionNumber Condition=" '$(VersionNumber)' == '' ">0.0.0.0</VersionNumber>
I then appended the version number to the installer:
<OutputName>Installer.$(VersionNumber)</OutputName>
We then need to add a preprocessor variable to each build configuration, I've called it MSIVersion, as this is the version of the msi package:
<DefineConstants>MSIVersion=$(VersionNumber)</DefineConstants>
and finally we use this preprocessor variable in the product definition in the Product.wxs file.
<Product Id="01010101-deaf-beef-c0de-863f442f44fb" Name="MROAE" Language="1033" Version="$(var.MSIVersion)" Manufacturer="MROAE" UpgradeCode="01010101-daaa-beef-c0de-863f442f44fb">
This solution can now be build with the following command:
msbuild mysolution.sln /p:VersionNumber=1.0.0.1
A sample wixproj file can be found below with changes detailed above:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <PackageVersion>3.8</PackageVersion>
    <ProjectGuid>{02af16dd-0000-0000-0000-d60ba5af40cc}</ProjectGuid>
    <SchemaVersion>2.0</SchemaVersion>
    <OutputType>Package</OutputType>
    <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
    <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
    <VersionNumber Condition=" '$(VersionNumber)' == '' ">0.0.0.0</VersionNumber>
    <Name>Installer</Name>
    <OutputName>Installer.$(VersionNumber)</OutputName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <OutputPath>bin\$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>Debug;MSIVersion=$(VersionNumber)</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <OutputPath>bin\$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>MSIVersion=$(VersionNumber)</DefineConstants>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Service.wxs" />
    <Compile Include="Product.wxs" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Service\Service.csproj">
      <Name>Service</Name>
      <Project>{000c956c-0000-0000-0000-970884f34476}</Project>
      <Private>True</Private>
      <DoNotHarvest>True</DoNotHarvest>
      <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
      <RefTargetDir>INSTALLFOLDER</RefTargetDir>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="Icons\Product.ico" />
     </ItemGroup>
  <ItemGroup>
    <Folder Include="Icons" />
  </ItemGroup>
  <ItemGroup>
    <WixExtension Include="WixUtilExtension">
      <HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
      <Name>WixUtilExtension</Name>
    </WixExtension>
  </ItemGroup>
  <Import Project="$(WixTargetsPath)" />
  <!--
 To modify your build process, add your task inside one of the targets below and uncomment it.
 Other similar extension points exist, see Wix.targets.
 <Target Name="BeforeBuild">
 </Target>
 <Target Name="AfterBuild">
 </Target>
 -->
</Project>

And the Product File(product.wxs)

<Product Id="01010101-deaf-beef-c0de-8f3f4a2f44fb" Name="MROAE" Language="1033"
Version="$(var.MSIVersion)" Manufacturer="MROAE" 
UpgradeCode="01010101-daaa-beef-c0de-8f3f4a42f44b">

Monday, 11 August 2014

Uninstall MSI from command line


From a command prompt, run with elevated permissions:
msiexec /x {ba5eba11-deaf-beef-ce11-ca5e1337c0de} /qn
where {ba5eba11-deaf-beef-ce11-ca5e1337c0de} is the product code of the application you want to uninstall.

From PowerShell, run with elevated permissions:
msiexec /x "{ba5eba11-deaf-beef-ce11-ca5e1337c0de}" /qn
If you don't know the product code you can get it from the registry, using wmic or from PowerShell using the following command:
gwmi -Class win32_product | ?{$_.Name -match "product name"}
For 7-zip the product code is:

PS C:\Users\Bob> gwmi -Class win32_product | ?{$_.Name -match "7-zip"}

IdentifyingNumber : {23170F69-40C1-2702-0920-000001000000}
Name              : 7-Zip 9.20 (x64 edition)
Vendor            : Igor Pavlov
Version           : 9.20.00.0
Caption           : 7-Zip 9.20 (x64 edition)

Wednesday, 6 August 2014

TIL - Send CTRL + ALT + DEL to Remote Destop Connection

I needed to change my password on the test domain today but I only log on to the test domain through a remote desktop connection, so in order to do a CTRL + ALT + DEL on the remote desktop, I did:

CTRL + ALT + END


Monday, 4 August 2014

List Entity relationships in CRM 2011/2013 - Brain Dump 6

Cleaning up my inbox today when I found this SQL query, in short a quick way of listing all the relationships for a particular entity:

SELECT distinct (rel.name),ent.name,
        Case [CascadeDelete]
                         when 0 then 'None'
                         when 1 then 'All'
                         when 2 then 'Referential'
                         when 3 then 'Restrict'
                        end as CascadeDelete
      ,Case [CascadeAssign]
                         when 0 then 'None'
                         when 1 then 'All'
                         when 2 then 'Referential'
                         when 3 then 'Restrict'
                        end as CascadeAssign
      ,Case [CascadeShare]
                         when 0 then 'None'
                         when 1 then 'All'
                         when 2 then 'Referential'
                         when 3 then 'Restrict'
                        end as CascadeShare
      ,Case [CascadeUnShare]
                         when 0 then 'None'
                         when 1 then 'All'
                         when 2 then 'Referential'
                         when 3 then 'Restrict'
                        end as CascadeUnShare
      ,Case [CascadeReparent]
                         when 0 then 'None'
                         when 1 then 'All'
                         when 2 then 'Referential'
                         when 3 then 'Restrict'
                        end as CascadeReparent
      ,Case [CascadeMerge]
                         when 0 then 'None'
                         when 1 then 'All'
                         when 2 then 'Referential'
                         when 3 then 'Restrict'
                        end as CascadeMerge
       from MetadataSchema.Relationship rel
      
join  MetadataSchema.Entity ent on rel.ReferencedEntityId = ent.entityid
where rel.name like '%<entityname>%'
order by ent.Name

And the results:


Wednesday, 23 July 2014

TIL - Hidding HTML elements with jQuery in IE.

The snippets of code below are equivalent, however the code in red does not work in IE (at least IE 9 and 11)

$('#myid').prop('hidden', true);
$('#myid').hide();

$('#myid').prop('hidden', false);
$('#myid').show();

Monday, 21 July 2014

Update Entity from JavaScript in Ms Dynamics CRM 2011/2013 using OData endpoint

Posting this for future reference:

function updateEntity(entityName, id, entity ) {

    var url = oDataUrl + "/" + entityName + "Set(guid'" + id + "')";

    entityData = window.JSON.stringify(entity);

    return $.ajax({
        type: "POST",
        contentType: "application/json;charset=utf-8",
        datatype: "json",
        data: entityData,
        url: url,
        beforeSend: function (x) {
            x.setRequestHeader("Accept", "application/json");
            x.setRequestHeader("X-HTTP-Method", "MERGE")
        },
    });
}
entityName is the logical entity name.
id is the Id of the record that we want to update
entity is a object that contains that values that need changing.
 e.g.:
 account = {};
 account.Name = "New Name"; 

 oDataUrl is the Url of the OData endpoint for your organization