Skip to content

Category: Revive

Dynamics CRM Bookmarklets V2

Posted in Dynamics 365, Power Platform, and Revive

About a half year ago, I’ve shared my Dynamics CRM Bookmarklets collection with you. Currently the collection has been reworked several times and the number of Dynamics CRM Bookmarklets Sammlung has been nearly doubled. I was influenced particularly with the new ideas for the bookmarklets by Jukka’s ‘CRM Navigation Hacking’ and Markus ‘Find Dependencies for Uninstalling Solutions’.

Compared to my first “Dynamics CRM bookmarklets” article, the display format has changed. Mainly because the implementation was not working clean as a hyperlink. In addition, some functions were still packed in an anonymous function.

Do you want to use one of bookmarklets, you just need to creat any bookmark in the bookmark toolbar of your browser and you change the URL to “javascript: (function () {…” and everything after the line comes from.

If you work with several browsers and want to your bookmarks synced in all of them I can recommend you Xmarks.

Updates!

  • 2017-09-21: added “open record by id”
  • 2017-09-21: updated “update view”
  • 2015-07-19: added “new solution” and “open default solution”
  • 2015-04-26: added “open perfomance center”
  • 2015-04-19: added “update view”
  • 2015-04-15: added “clear localStorage” and “clear seesionStorage”
/* Admin related bookmarklets */

//save & publish
javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.SaveForm(false); form.SaveAndPublish(); })();

//publish all
javascript: (function () { $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow.Mscrm.FormEditor.PublishAll(); })();

//get service infos
javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var orgUrl = form.Xrm.Page.context.getClientUrl(); var users; $.ajax({ type: "GET", contentType: "application/json; charset=utf-8", datatype: "json", url: Xrm.Page.context.getClientUrl() + "/XRMServices/2011/OrganizationData.svc/SystemUserSet?$filter=AccessMode/Value eq 0 and IsDisabled eq false", beforeSend: function (XMLHttpRequest) { XMLHttpRequest.setRequestHeader("Accept", "application/json"); }, async: false, success: function (data, textStatus, xhr) { var results = data.d.results; window.prompt('Copy to clipboard: Ctrl+C, Enter', "Unique Name: " + form.Xrm.Page.context.getOrgUniqueName() + ", URL: " + orgUrl + ", " + results.length + " active user"); }, error: function (xhr, textStatus, errorThrown) { alert(textStatus + " " + errorThrown); } }); })();

//get solution dependencies details
javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var SID = window.prompt("Enter Solution ID"); window.open(form.Xrm.Page.context.getClientUrl() + "/tools/dependency/dependencyviewdialog.aspx?objectid=" + SID + "&objecttype=7100&operationtype=dependenciesforuninstall"); })();

//show schema names
javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Page.ui.controls.forEach(function (a) { try { a.setLabel(a.getName()); } catch (e) { } }); })();

//get all optionsets
javascript: (function () { var osa = ""; var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Page.ui.controls.forEach(function (c, i) { if (c.getControlType() == "optionset") { var osv = "
Name: " + c.getName() + "
"; frames[0].$("#" + c.getName() + "_i").find("option").first().nextAll().each(function () { osv += "
Value: " + $(this).attr("value") + " - Text: " + $(this).attr("title") + "
"; }); osa += "
" + osv + "
"; } }); (window.open("#", "#").document.open()).write("
" + osa + "
") })(); //show hidden fields javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Page.ui.controls.forEach(function (c) { try { c.setVisible(true); } catch (e) { } }); })(); //get formtype javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var ft = ["1 = CREATE", "2 = UPDATE", "3 = READ_ONLY", "4 = DISABLED", "5 = QUICK_CREATE", "6 = BULK_EDIT"]; window.prompt('Copy to clipboard: Ctrl+C, Enter', ft[(form.Xrm.Page.ui.getFormType()) - 1]); })(); //get document.readystate javascript: (function () { alert(document.readyState) })(); //godmode javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Page.ui.tabs.forEach(function (a) { try { a.setVisible(true); a.setDisplayState("expanded"); a.setLabel(a.getName()); a.sections.forEach(function (b) { try { b.setVisible(true); b.setLabel(a.getName()); } catch (e) { } }) } catch (e) { } }); form.Xrm.Page.data.entity.attributes.forEach(function (d) { try { d.setRequiredLevel("none"); } catch (e) { } }); form.Xrm.Page.ui.controls.forEach(function (c) { try { c.setVisible(true); c.setLabel(c.getName()); c.setDisabled(false); c.clearNotification(); } catch (e) { } }); })(); //enable all fields javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Page.ui.controls.forEach(function (c) { try { c.setDisabled(false); } catch (e) { } }); })(); //update view javascript:(function(){var f=null,myUrl="",mV="",vT="",rT="",FetchXml="",LayoutXml="",entity={};f=$("iframe").filter(function(){return $(this).css("visibility")=="visible"})[0].contentWindow;if (f==undefined || f==null){return}myUrl=f.Xrm.Page.context.getClientUrl()+"/XRMServices/2011/OrganizationData.svc/";mV=window.prompt("GIUD of the view:");if (mV=="" || mV==null){return} vT=window.prompt("View type? 1 System OR 2 User");if (vT=="" || vT==null){return} if (vT==1){vT="SavedQuerySet"} else if (vT==2){vT="UserQuerySet"} else {alert("Error.");return}rT=window.prompt("Update Xml? 1 Fetch OR 2 Layout"); if (rT=="" || rT==null){return}var req=new XMLHttpRequest();req.open("GET", encodeURI(myUrl+vT+"(guid'"+mV+"')?$select=ColumnSetXml,Name,FetchXml,LayoutXml"),false);req.setRequestHeader("Accept", "application/json"); req.setRequestHeader("Content-Type","application/json;charset=utf-8");req.onreadystatechange=function(){if (this.readyState==4){req.onreadystatechange=null;if(this.status==200){var result=JSON.parse(req.responseText).d;FetchXml=result.FetchXml;LayoutXml=result.LayoutXml }else{alert(this.statusText);return}}};req.send();if (FetchXml=="" && LayoutXml==""){return}if (rT=="1"){entity.FetchXml=window.prompt("FetchXml:",FetchXml); if (entity.FetchXml=="" || entity.FetchXml==null){return}} else if (rT=="2"){entity.LayoutXml=window.prompt("LayoutXml:",LayoutXml);if (entity.LayoutXml=="" || entity.LayoutXml==null){return}}else{alert("Error.");return}var req2=new XMLHttpRequest();req2.open("POST",encodeURI(myUrl+vT+"(guid'"+mV+"')"),false);req2.setRequestHeader("Accept","application/json");req2.setRequestHeader("Content-Type","application/json;charset=utf-8");req2.setRequestHeader("X-HTTP-Method","MERGE");req2.onreadystatechange=function(){if (this.readyState==4){req2.onreadystatechange=null;if (this.status==204 || this.status==1223){if(window.confirm("Done! Publish all?")){f.Mscrm.FormEditor.PublishAll()}}else{alert(this.statusText);return}}};req2.send(JSON.stringify(entity))})(); //open performance center javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var Perf = form.Mscrm.Performance.PerformanceCenter.get_instance(); Perf.TogglePerformanceResultsVisibility(); })(); //new solution javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/tools/Solution/edit.aspx"); })(); /* Record related bookmarklets */ //open record by id javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var ty = "etc", tc = window.prompt("Entity?", "schema name or type code"), id = window.prompt("GUID?", "without braces"); if (isNaN(tc)) { ty = "etn" } window.open(form.Xrm.Page.context.getClientUrl() + "/main.aspx?" + ty + "=" + tc + "&id=%7b" + id + "%7d&pagetype=entityrecord"); })(); //show record properties javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var id = form.Xrm.Page.data.entity.getId(); var etc = form.Xrm.Page.context.getQueryStringParameters().etc; form.Mscrm.RibbonActions.openFormProperties(id, etc); })(); //get field value javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var v, f = window.prompt("Enter field name"); var a = form.Xrm.Page.getAttribute(f); switch (a.getAttributeType()) { case "optionset": case "boolean": v = a.getSelectedOption().text; break; case "lookup": v = a.getValue()[0].name; break; default: v = a.getValue(); break; } window.prompt('Copy to clipboard: Ctrl+C, Enter', v); })(); //get entity typecode javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var name = form.Xrm.Page.data.entity.getEntityName(); var typeCode = form.Xrm.Page.context.getQueryStringParameters().etc; if (typeCode) { window.prompt('Copy to clipboard: Ctrl+C, Enter', typeCode.toString() + " = " + name) } })(); //get dirty fields javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var message = "The following fields are dirty: \n"; form.Xrm.Page.data.entity.attributes.forEach(function (attribute, index) { if (attribute.getIsDirty() == true) { message += "\u2219 " + attribute.getName() + "\n"; } }); alert(message); })(); //get data Xml javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.prompt("Copy to clipboard: Ctrl+C, Enter", form.Xrm.Page.data.entity.getDataXml()); })(); //create new record javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; try { var name = form.Xrm.Page.data.entity.getEntityName(); } catch (e) { } var y = prompt('Type the schema name of the entity to create:', name ? name : 'account'); if (y) { window.open(form.Xrm.Page.context.getClientUrl() + "/main.aspx?etn=" + y + "&pagetype=entityrecord"); } })(); //activate record javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Mscrm.CommandBarActions.activate(form.Xrm.Page.data.entity.getId(), form.Xrm.Page.data.entity.getEntityName()); })(); //get record url javascript: (function () { var url = document.getElementById('crmContentPanel').getAttribute('src'); if (url.indexOf('/read/page.aspx') == -1) { if (url.indexOf(Xrm.Page.context.getOrgUniqueName()) != -1) { window.prompt('Copy to clipboard: Ctrl+C, Enter', Xrm.Page.context.getClientUrl() + url.replace('/' + Xrm.Page.context.getOrgUniqueName(), '')); } else { window.prompt('Copy to clipboard: Ctrl+C, Enter', Xrm.Page.context.getClientUrl() + url); } } else { window.prompt('Copy to clipboard: Ctrl+C, Enter', window.location.href); } })(); //get record id javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.prompt("Copy to clipboard: Ctrl+C, Enter", form.Xrm.Page.data.entity.getId().slice(1, -1)) })(); //save javascript: (function () { $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow.Xrm.Page.data.entity.save(); })(); //save and new javascript: (function () { $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow.Xrm.Page.data.entity.save('saveandnew'); })(); //save and close javascript: (function () { $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow.Xrm.Page.data.entity.save('saveandclose'); })(); //refresh form javascript: (function () { $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow.Xrm.Page.data.refresh() })(); //refresh & save form javascript: (function () { $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow.Xrm.Page.data.refresh(true) })(); //open record from lookup javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var elem = form.document.activeElement; var id = elem.getAttribute("id"); var guid = null; var type = null; if (elem.getAttribute("isInlineLookup") == "true") { guid = elem.getAttribute("oid"); type = elem.getAttribute("otypename") } else if (id != null) { var pos = id.lastIndexOf("_"); if (pos > -1) { var suffix = id.substring(pos + 1); if (["ledit", "lookupDiv", "i"].indexOf(suffix) > -1) { id = id.substring(0, pos) } id = id.replace("_i_ledit_multi", "").replace("_ledit_multi", "") } var control = form.Xrm.Page.getControl(id); if (control != null) { var field = control.getAttribute(); if (field != null) { var value = field.getValue(); if (value != null) { var record = value[value.length - 1]; guid = record.id; type = record.entityType } } } } if (guid != null && guid != "" && type != null && type != "") { var url = form.Xrm.Page.context.getClientUrl() + "/main.aspx?etn=" + type + "&id=" + guid + "&pagetype=entityrecord"; window.open(url) } else { alert("Unable to open record. Make sure you're clicked into a lookup field with a value.") } void (0); })(); }) /* Navigation related bookmarklets */ //open CRM calendar javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/workplace/home_calendar.aspx"); })(); //open CRM announcements javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/home/homepage/home_news.aspx"); })(); //open mobile express javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/m"); })(); //open moca client javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; var url = form.Xrm.Page.context.getClientUrl(); window.open(url + "/nga/main.htm?org=" + form.Xrm.Page.context.getOrgUniqueName() + "&server=" + url); })(); //open advanced find javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/main.aspx?pagetype=advancedfind"); })(); //open RecordWall javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Utility.openWebResource("msdyn_/RecordWall.htm"); })(); //open PersonalWall javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; form.Xrm.Utility.openWebResource("msdyn_/PersonalWall.htm"); })(); //open solution list javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/tools/Solution/home_solution.aspx?etc=7100&sitemappath=Settings%7cCustomizations%7cnav_solution"); })(); //open default solution javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/tools/Solution/edit.aspx?id=%7bfd140aaf-4df4-11dd-bd17-0019b9312238%7d"); })(); //open diagnostic page javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/tools/diagnostics/diag.aspx"); })(); //open entity editor javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; try { var etc = form.Xrm.Page.context.getQueryStringParameters().etc; } catch (e) { } form.Mscrm.RibbonActions.openEntityEditor(etc); })(); //open systemjobs javascript: (function () { var form = $("iframe").filter(function () { return $(this).css("visibility") == "visible" })[0].contentWindow; window.open(form.Xrm.Page.context.getClientUrl() + "/tools/business/home_asyncoperation.aspx"); })();

Should you have own ideas or bookmarks that I have not covered here, you can send me them very gladly.

E-mail tracking with custom email fields

Posted in Dynamics 365, Power Platform, and Revive

Anyone who has ever worked with the Dynamics CRM for Outlook client, is familiar with the procedure of email tracking. You press the “Track” button and the CRM client creates on an e-mail record on the CRM server which again resolves the recipient and sender addresses, and linked to the corresponding records. But what if I want to same more e-mail addresses?

Are e-mails tracked when the e-mail adress is noted in a custom field?

The entity “Contact” has by default already three e-mail address fields. So, I’ve created a custom field as the fourth e-mail field.

When creating your own e-mail address field, it is important that chooses the “e-mail” format. So the CRM know that it can search here for e-mail addresses. By the way is then performed a validation in this field and the e-mail address is formatted as a mailto link, so that your email client will directly open when you click it.

Next, I’ve created a contact record with four different e-mail addresses and wrote them a message to them and tracked it.

Conclusion to E-mail tracking with custom E-mail fields

In the following screenshot you can see that it works perfectly. All present and the new e-mail address field are actually assigned only by tracking to the contact, to set a regarding was not necessary.

Workflow ExecutionTimeSpan

Posted in Dynamics 365, Power Platform, and Revive

Last week I had a problem as part of a service request at Microsoft. I should test how long it takes to create a record for a particular entity by a workflow. The whole thing had to be very precise, because the request has been caused by an excessive execution time of a plug-in chain when such a record has been created.

Experimental Setup

The workflow should create a new contact, based on the data of an existing contact record. Let’s name it a Light-copy without relations. It is so configured that an entry in the systemjobs will be created.

Workflow-Log

Unfortunately, the workflow log is not as meaningful as intended. It contains the only times to the minute.

But that brings me at least an idea. Dynamics CRM stores the data internally with a higher accuracy than it displays it on the surface. Now I just have to get that data, mind you in a CRM Online system.

Workflow ExecutionTimeSpan

Since it is well known fact that you can not access the database in CRM Online directly, I planned to create a query that returns “Created On” and “Modified on” of my workflow. I used the OData Query Designer from the Dynamics XRM Tools to create that query.
When selecting the fields for my query I found a field named “Zeitspanne für Ausführung” field, or in English “ExecutionTimeSpan”. BINGO! That sounds good!

The Query

YOURSERVERURL/xrmservices/2011/OrganizationData.svc/AsyncOperationSet?$select=Name,StartedOn,CreatedOn,CompletedOn,ModifiedOn,ExecutionTimeSpan&$filter=OperationType/Value eq 10&$orderby=CreatedOn desc

To make the URL more understandable for you:

  • The Organization Data Service (OData) URL of your CRM.
    YOURSERVERURL/xrmservices/2011/OrganizationData.svc
     
  • The table from which I need the data.
    AsyncOperationSet?
     
  • The columns from the table that I would like to see as result.
    $select=Name,CreatedOn,StartedOn,CompletedOn,ModifiedOn,ExecutionTimeSpan
     
  • There should be only system jobs of type “Workflow” being returned.
    $filter=OperationType/Value eq 10
     
  • Finally, I would like to have the results sorted by creation date, so that the most recent are on top.
    Who wants to look for a long time.
    $orderby=CreatedOn desc

The Result

<xml version="1.0" encoding="utf-8" standalone="yes">
    <feed xml:base="http://od4u-crm2013.cloudapp.net/FC/XRMServices/2011/OrganizationData.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
      <title type="text">AsyncOperationSet</title>
      <id>http://od4u-crm2013.cloudapp.net/FC/xrmservices/2011/OrganizationData.svc/AsyncOperationSet</id>
      <updated>2014-10-05T08:07:34Z</updated>
      <link rel="self" title="AsyncOperationSet" href="AsyncOperationSet" />
      <entry>
        <id>http://od4u-crm2013.cloudapp.net/FC/XRMServices/2011/OrganizationData.svc/AsyncOperationSet(guid'40107141-ab4b-e411-80df-00155d572098')</id>
        <title type="text">LightCopy</title>
        <updated>2014-10-05T08:07:34Z</updated>
        <author>
          <name />
        </author>
        <link rel="edit" title="AsyncOperation" href="AsyncOperationSet(guid'40107141-ab4b-e411-80df-00155d572098')" />
        <category term="Microsoft.Crm.Sdk.Data.Services.AsyncOperation" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
        <content type="application/xml">
          <m:properties>
            <d:Name>LightCopy</d:Name>
            <d:CreatedOn m:type="Edm.DateTime">2014-10-04T09:46:04Z</d:CreatedOn>
            <d:StartedOn m:type="Edm.DateTime">2014-10-04T09:46:17Z</d:StartedOn>
            <d:CompletedOn m:type="Edm.DateTime">2014-10-04T09:46:22Z</d:CompletedOn>
            <d:ModifiedOn m:type="Edm.DateTime">2014-10-04T09:46:22Z</d:ModifiedOn>
            <d:ExecutionTimeSpan m:type="Edm.Double">1.7</d:ExecutionTimeSpan> 
            <d:ModifiedOn m:type="Edm.DateTime">2014-10-04T09:46:22Z</d:ModifiedOn>
          </m:properties>
        </content>
      </entry>
    </feed>

In the marked area you can see the columns that we have retrieved and in line 23 the value of workflow ExecutionTimeSpan.
Thus, so the workflow had an execution time of 1.7 seconds.

With Power Query for Excel you can you view the data a little more beautiful, or a whole series of workflows to evaluate and calculate averages with Excel or be generated diagrams. Simply Excel.

Hope it helps!

Pass parameters to HTML Webresource

Posted in Dynamics 365, Power Platform, and Revive

A HTML webresource can not just only show HTML elements on your form, furthermore you can work with JavaScript in it and interact with your form. IF you want to access the Xrm namespace of the form inside your HTML webresource, you simply need prepend “window.parent” to your function call.

This looks like in this example:

var myId = window.parent.Xrm.Page.data.entity.getId();

If you need a lot of such calls, you can make your life easier and create your own local variable and assign it the complete Xrm namespace
This could look like this:

var Xrm = window.parent.Xrm;
    var myId = Xrm.Page.data.entity.getId();

Pass parameters to HTML Webresource

Alternatively, you can also pass static values to your webresource. Just add a custom parameter in properties dialog of the webresource.

You can access the custom and contaxt parameters with the following script inside your webresource:

function getWebresourceParameter()
    {
        var userParameters = [], passedParameters = [];
        if (location.search != "")
        {
            var vals = location.search.substr(1).split("&");
            for (var i = 0; i < vals.length; i++)
            {
                vals[i] = vals[i].split("=");
                if (vals[i][0].toLowerCase() == "data" && vals[i][1] != "")
                {
                    var userVals = decodeURIComponent(vals[i][1]).split(",");
                    for (var j = 0; j < userVals.length; j++)
                    {
                        passedParameters[userVals[j].split("=")[0].trim()] = userVals[j].split("=")[1].trim();
                    }
                }
                else
                {
                    passedParameters[vals[i][0]] = vals[i][1];
                }
            }
        }
        return passedParameters;
    }

The custom parameters should be in the form “Name=Value” should be separated by comma.

The debugger shows you all the accessible parameters:

Context parameters are green marked, custom parameters blue.

You can now access your values through the named array.

var wrParameters = getWebresourceParameter();
    var myRelName = wrParameters["relName"];

Have fun with it!