Determining the Update Rollup Version of the CRM installed


Hi,

Just sharing two useful posts which would help us to identify the update rollup version installed in our CRM environment.

For CRM 2011

http://crmdynamo.com/2011/09/crm-2011-update-rollup-release-build-numbers-and-how-to-find-them/

For CRM 4.0

http://crmdynamo.com/2010/03/check-which-update-rollup-version-is-installed-on-your-crm-environments/

Bye.

Try out – Ribbon Workbench for Dynamics CRM 2011


Hi,

Today i came across this new tool for Ribbon editing in CRM 2011.

http://www.develop1.net/public/page/Ribbon-Workbench-for-Dynamics-CRM-2011.aspx

The tools looks really wonderful.

Will try it out soon.

Bye.

 

 

How t0 – Create a master detail report in SSRS without using Sub report.


Suppose we have simple master (Person) and detail (Favorite
Actor and Favorite
Movie) tables in our database .

To write a report that doesn’t make use of sub reports we need to have a single dataset as shown below

Create a new report project and drag the List control for Master table and two Tablix inside List for the detail records.

Select the list and set Group Properties for the Row Groups as shown below.

Select the row for the first tablix that shows Favorite Actor information, right click it and specify group properties as FAID (i.e. primary key for that table)

Do the same for the other tablix (Movie table).

Run the report, it will show the following output

To hide the tablix if there is no data, set its Hidden Property using the following expression

For tablix 1 à
=IIF(IsNothing(Fields!FAID.Value),True,False)

For tablix 2 à
=IIF(IsNothing(Fields!FMID.Value),True,False)

The DataSet query

</p>
<p>select P.Id, P.FirstName, P.LastName,fa.Id as FAID,fa.firstname,fa.lastname, fm.Id as FMID,fm.Movie from Person P<br />
left outer join FavoriteActor as FA on P.Id = FA.PersonId<br />
left outer join FavoriteMovie as FM on P.Id = FM.PersonId</p>
<p>

Hope it helps

Advertisements

Getting the IncidentId on resolving a Case in post Close plugin.


Hi,

To get the id of the case record which is getting resolved in the plugin, we need to make use of IncidentResolution inputparameters of the context.


Entity incRes = this.Context.InputParameters["IncidentResolution"] as Entity;
 Guid caseId = ((EntityReference)incRes.Attributes["incidentid"]).Id;

Bye.

Use “Close” message when we “Resolve” an Incident (Case) in CRM.


We had one plugin which was registered against “SetState” and “SetStateDynamic” message. It used to run when we were doing “Cancel Case” from the ribbon.

We thought the same message will work in case of “Resolve Case“.

However in case of Resolve Case, we need to use or register our plugin against the “Close” message.

InputParametersà

Hope it helps.

Sample code for Encryption\Decryption of Password (strings) in C#


Hi,

Just sharing the helper classes that we have used in our project.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace WindowsFormsApplication5
{
 public class SaltedHash
 {
 #region Fields

/// <summary>
 /// Delimiter character
 /// </summary>
 private string delimiter = " ";

/// <summary>
 /// Hash Provider
 /// </summary>
 private HashAlgorithm hashProvider;

/// <summary>
 /// Salth length
 /// </summary>
 private int salthLength;

#endregion Fields

#region Constructors

/// <summary>
 /// Initializes a new instance of the SaltedHash class.
 /// </summary>
 /// <param name="hashAlgorithm">A <see cref="HashAlgorithm"/> HashAlgorihm which is derived from HashAlgorithm. C# provides
 /// the following classes: SHA1Managed,SHA256Managed, SHA384Managed, SHA512Managed and MD5CryptoServiceProvider</param>
 /// <param name="theSaltLength">Length in bytes</param>
 public SaltedHash(HashAlgorithm hashAlgorithm, int theSaltLength)
 {
 this.hashProvider = hashAlgorithm;
 this.salthLength = theSaltLength;
 }

/// <summary>
 /// Initializes a new instance of the SaltedHash class.
 /// </summary>
 public SaltedHash()
 : this(new SHA256Managed(), 4)
 {
 }

#endregion Constructors

#region Methods

/// <summary>
 /// Gets the hashed string with salt
 /// </summary>
 /// <param name="data">The data to hash</param>
 /// <returns> The hashed string </returns>
 public string GetHashedString(string data)
 {
 string hash, salt;
 this.GetHashAndSaltString(data, out hash, out salt);
 return hash.Replace(this.delimiter, String.Empty) + this.delimiter + salt.Replace(this.delimiter, string.Empty);
 }

/// <summary>
 /// Verifies the data and hash
 /// </summary>
 /// <param name="data">The data to compare</param>
 /// <param name="hashedData">The hash to compare with</param>
 /// <returns>Returns bool flag</returns>
 public bool VerifyHashString(string data, string hashedData)
 {
 if (String.IsNullOrEmpty(hashedData))
 {
 return false;
 }

string[] split = hashedData.Split(this.delimiter.ToCharArray());

if (split == null || split.Length != 2)
 {
 return false;
 }

return this.VerifyHashString(data, split[0], split[1]);
 }

/// <summary>
 /// The actual hash calculation is shared by both GetHashAndSalt and the VerifyHash functions
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="salt">The salt byte array</param>
 /// <returns>
 /// A byte array with the calculated hash
 /// </returns>
 private byte[] ComputeHash(byte[] data, byte[] salt)
 {
 // Allocate memory to store both the Data and Salt together
 byte[] dataAndSalt = new byte[data.Length + this.salthLength];

// Copy both the data and salt into the new array
 Array.Copy(data, dataAndSalt, data.Length);
 Array.Copy(salt, 0, dataAndSalt, data.Length, this.salthLength);

// Calculate the hash
 // Compute hash value of our plain text with appended salt.
 return this.hashProvider.ComputeHash(dataAndSalt);
 }

/// <summary>
 /// Given a data block this routine returns both a Hash and a Salt
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 private void GetHashAndSalt(byte[] data, out byte[] hash, out byte[] salt)
 {
 // Allocate memory for the salt
 salt = new byte[this.salthLength];

// Strong runtime pseudo-random number generator, on Windows uses CryptAPI
 // on Unix /dev/urandom
 RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();

// Create a random salt
 random.GetNonZeroBytes(salt);

// Compute hash value of our data with the salt.
 hash = this.ComputeHash(data, salt);

random.Dispose();
 }

/// <summary>
 /// The routine provides a wrapper around the GetHashAndSalt function providing conversion
 /// from the required byte arrays to strings. Both the Hash and Salt are returned as Base-64 encoded strings.
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 private void GetHashAndSaltString(string data, out string hash, out string salt)
 {
 byte[] hashOut;
 byte[] saltOut;

// Obtain the Hash and Salt for the given string
 this.GetHashAndSalt(Encoding.UTF8.GetBytes(data), out hashOut, out saltOut);

// Transform the byte[] to Base-64 encoded strings
 hash = Convert.ToBase64String(hashOut);
 salt = Convert.ToBase64String(saltOut);
 }

/// <summary>
 /// This routine verifies whether the data generates the same hash as we had stored previously
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 /// <returns>
 /// True on a succesful match
 /// </returns>
 private bool VerifyHash(byte[] data, byte[] hash, byte[] salt)
 {
 byte[] newHash = this.ComputeHash(data, salt);

//// Compare hash
 if (newHash.Length != hash.Length)
 {
 return false;
 }

for (int lp = 0; lp < hash.Length; lp++)
 {
 if (!hash[lp].Equals(newHash[lp]))
 {
 return false;
 }
 }

return true;
 }

/// <summary>
 /// This routine provides a wrapper around VerifyHash converting the strings containing the
 /// data, hash and salt into byte arrays before calling VerifyHash.
 /// </summary>
 /// <param name="data">The data byte array</param>
 /// <param name="hash">The hash byte array</param>
 /// <param name="salt">The salt byte array</param>
 /// <returns>
 /// Returns bool flag
 /// </returns>
 private bool VerifyHashString(string data, string hash, string salt)
 {
 byte[] hashToVerify = Convert.FromBase64String(hash);
 byte[] saltToVerify = Convert.FromBase64String(salt);
 byte[] dataToVerify = Encoding.UTF8.GetBytes(data);
 return this.VerifyHash(dataToVerify, hashToVerify, saltToVerify);
 }

#endregion Methods
 }
}

the C# version of the following code

http://msdn.microsoft.com/en-us/library/ms172831.aspx


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace WindowsFormsApplication5
{
 class Simple3Des
 {
 TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();

public Simple3Des(string key)
 {
 // Initialize the crypto provider.
 tripleDes.Key = TruncateHash(key, tripleDes.KeySize / 8);
 tripleDes.IV = TruncateHash("", tripleDes.BlockSize / 8);
 }

private byte[] TruncateHash(string key, int length)
 {
 SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
 // Hash the key.
 byte[] keyBytes = System.Text.Encoding.Unicode.GetBytes(key);
 byte[] hash = sha1.ComputeHash(keyBytes);

// Truncate or pad the hash.
 Array.Resize(ref hash, length);
 return hash;
 }

public string EncryptData(string plaintext)
 {

// Convert the plaintext string to a byte array.
 byte[] plaintextBytes = System.Text.Encoding.Unicode.GetBytes(plaintext);

// Create the stream.
 System.IO.MemoryStream ms = new System.IO.MemoryStream();
 // Create the encoder to write to the stream.
 CryptoStream encStream = new CryptoStream(ms, tripleDes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

// Use the crypto stream to write the byte array to the stream.
 encStream.Write(plaintextBytes, 0, plaintextBytes.Length);
 encStream.FlushFinalBlock();

// Convert the encrypted stream to a printable string.
 return Convert.ToBase64String(ms.ToArray());
 }

public string DecryptData(string encryptedtext)
 {

// Convert the encrypted text string to a byte array.
 byte[] encryptedBytes = Convert.FromBase64String(encryptedtext);

// Create the stream.
 System.IO.MemoryStream ms = new System.IO.MemoryStream();
 // Create the decoder to write to the stream.
 CryptoStream decStream = new CryptoStream(ms, tripleDes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

// Use the crypto stream to write the byte array to the stream.
 decStream.Write(encryptedBytes, 0, encryptedBytes.Length);
 decStream.FlushFinalBlock();

// Convert the plaintext stream to a string.
 return System.Text.Encoding.Unicode.GetString(ms.ToArray());
 }

&nbsp;

}
}

Bye.