Monday, February 4, 2019

Quick and Easy Azure PaaS PublishSettings Import to FileZilla with PowerShell

With the advancement of Sitecore on Azure Platform as a Service (PaaS), gone are the days where you remote into a physical or virtual machine. If you need to access the application files, you'll need to download a Publish Profile settings file from the Azure Portal. Just click the button.



The Publish Profile setting file simply an XML file (surprise, surprise) with connection information about the resource - which can be directly imported to Visual Studio to deploy files.   You can manually copy those values from the FTP host endpoint (publishUrl), username (userName), and password (userPWD) nodes into an FTP client and connect.
A standard Sitecore 9 Experience Platform comes packaged with at least 9 Application Services when installed on Azure - each with unique FTP endpoints and credentials.

Our team uses the FileZilla FTP client - in which you can create a set of accessible FTP sites and share them in a locked down repository where other developers who need access can get it without downloading the Publish Profile settings themselves.

As you can imagine, working through 9 unique Publish Profile settings is rather tedious when setting up these 'racks' in FileZilla - copying and pasting via the FileZilla GUI

via GIPHY

To streamline this process when setting up a new instance of Sitecore on PaaS - or onboarding an existing Sitecore PaaS, I've written a Windows PowerShell script that eliminates the need to copy and paste anything.



Simply download each App Service's FTP Publish Profile setting file to a folder on your local machine.


Run the script and select that same folder


The script processes each .PublishSettings file and generates an AzurePaaS-FileZillaSites.xml file in the same directory.  This file is compatible with FileZilla's import feature.


In FileZilla, go to File > Import

Select the script-generated AzurePaaS-FileZilla.xml file.

Click through the Import Settings (Site Manager Entries will already be selected)

You'll get a success message when the import is successful

The entries will be available in FileZilla and ready to connect!


The benefit of this approach allows you to quickly and easily create an XML file that can be shared amongst the team of developers who would need to access those files.

Once you've completed an import, use FileZilla's Site Manager to organize these entries into folders then export it again from FileZilla (this will encrypt the passwords using your FileZilla's master password).




Friday, January 11, 2019

Translating Text in Sitecore using Microsoft Cognitive Services and PowerShell


Microsoft Cognitive Services is an impressive set of powerful, easy to integrate APIs for developers. With AI at its core, Cognitive Services strives to solve business problems using Vision, Speech, Knowledge, Search, and Language service offerings.  Recently announced, it's now easier than ever to start using Cognitive Services with a simplified key mechanism.

Creating a Cognitive Service in Azure itself is dead simple. It take less than 5 minutes to spin up a Cognitive Service resource and you're ready to develop. The above video will help get you started.☝

So, what can we do with these services in Sitecore?

Cognitive Services Is Not That New

We've seen folks across the Sitecore community utilising this technology since its inception in 2016 - specifically the Computer Vision API. From bulk image alt tagging using Computer Vision and PowerShell and automatic image alt tag generation module, to a fully integrated Cognitive Services module from the infamous Mark Stiles.

These are really great adaptations of these APIs, but I wanted to explore these services myself.

Translator Text API

The Translator Text API is easy to integrate in your applications, websites, tools, and solutions. It allows you to add multi-language user experiences in more than 60 languages, and can be used on any hardware platform with any operating system for text-to-text language translation.
The Translator Text API is part of the Azure Cognitive Services API collection of machine learning and AI algorithms in the cloud, and is readily consumable in your development projects.
What is Translator Text API?

Being completely obsessed with PowerShell, I figured I'd give it a go.  For my demo, I want to allow content authors to right-click on a Sitecore item, select a Translate Text Fields PowerShell script, configure some option in a dialog and click Continue.



The script should create a new language version in the target language selected and translate all text fields selected.

Pricing

Before starting, it should be noted that the Free tier for translations is 2 million characters per month. 
Since we're keeping this integration simple, it's not likely we'll hit the limit.



Let's Script It

Building the dialog is pretty straightforward. Get the context item, grab the applicable languages and fields (Single-Line and Multi-Line only for simplicity and API restriction avoidance), and set the dialog options:

We'll need a function that we can call to process the item after obtaining the selections from the dialog.  We expect to call it like this:

Translate-Item -TargetItem $item -FromLang $selectedFromLanguage -ToLang $selectedToLanguage -FieldsList $fieldSelectionArray

The function should issue an authentication token from the Cognitive Service, generate a new language version for the item in the target language, and call another function to translate the original field value to the target language:

The Issue-CognitiveApiToken in the above function issues the authentication token we need to send with our request to the translation API.

We can send a request to the translation API with the issued token in a new function that will be responsible for processing the actual translation:

Putting It All Together

Now that we've got commands to interact with the Translation API, we can build out the contextual PowerShell script to provide some options for our content author.

Adding this script to one of the Context Menu (PowerShell Script Library) folders (eg. /sitecore/system/Modules/PowerShell/Script Library/SPE/Core/Platform/Content Editor/Context Menu) will allow the script to be executed contextually.


Final Result


I can see this being a good use-case for Dictionary items specifically as there are some restrictions for content length size that the API will reject.  However, this is simply a demo of what is possible here (definitely not production-ready 🤪).



Feel free to take and use any part of the script here and build something cool!

Wednesday, January 2, 2019

Sitecore Icon Search v2.0 and Firefox Support


With the holidays behind us and 2019 in full swing, I’m excited to share new updates to the Sitecore Icon Search browser extension offering.  Considering I had some significant time off from work, I was able to pack in several exciting new features in between holiday festivities that I hope will make the experience even better for Sitecore developers.

Chrome Extension v2.0

Improved Search with Synonyms

When the Sitecore Icon Search Web App was released, one suggestion that stood out was



It's true, the search relied solely on the icon's name.  Unless you get the right name, you may miss an icon that may work better in your situation.

Well, phase 2 is here!

Utilizing the Google Vision API and Datamuse API, I wrote a couple of PowerShell scripts to process each icon in the dataset through each respective API and added the results into a new ‘attributes’ column to the existing data file (this column is hidden from general view).

The Google Vision API processed the image itself and primarily provided color attributes for every icon.  When searching, specifying a color may narrow down or help target the right icon.


Using the Datamuse API, I passed in the name of each icon and returned a maximum of 10 synonyms per icon and stored it into the ‘attributes’ column as well.   You can now search for a generalized term and likely retrieve new icons that may work for you



Offline / Localized Environment Support

Another feature that’s been requested has been to allow the extension to function when an internet connection is unavailable.   This makes plenty of sense as development is often done locally and doesn’t always require an online connection.

The problem stems from how the extension loads the icon images.  Up until now, the source of the icons has always been direct references to Sitecore’s website.  Images are lazy loaded based on the user’s search parameters.  When you lose internet connection, for icons that haven’t cached, you’d see broken images:

Not cool.

The extension is now 'context aware' and detects when you’re within the Sitecore shell.  Therefore, the extension will rely on the current local Sitecore URL to load icons (instead of relying on Sitecore’s domain).  This allows the extension to work offline.

Additionally, icons that are not available for the specific version of Sitecore will display a message stating it.

When you attempt to load the extension outside of a local Sitecore solution while offline, a pop-up will display:


If you select Offline Settings, you’ll be taken to the options menu where you can enable the Image URL Override option and set a URL domain to a local Sitecore instance.  By enabling this setting, offline the extension will always use this local domain vs the Sitecore domain, allowing more control in offline mode.



Firefox Add-on v1.0


via GIPHY

I realize that not everyone uses Google Chrome as their primary browser.  Even I use Firefox as my backup browser.  Luckily, Firefox offers a very similar development structure for ‘Add-ons’.  With some fiddling, I managed to port over the Chrome extension to a Firefox Add-on. 😊👍

Version 1.0 contains all the same features built for Google Chrome up to now.

Add it here!


As always, I'm open for feedback.  DM me on Twitter for any bugs, issues, or suggestions.

Wednesday, December 19, 2018

Sitecore Icon Search Chrome Extension: What's New in v1.2

Back in March of this year, I created and released the Sitecore Icon Search Web Application.  With generally well-received reception - I  decided to expand the idea by building a version of the app as a Google Chrome Extension.  Last Halloween, v1.0 of the Sitecore Icon Search Chrome Extension was born and released.
Like any personal project, I'm inclined to continue making this a better, more useful experience for developers who are actively building templates in Sitecore as time goes by.

In versions 1.0.0 through 1.1.0, I resolved some minor bugs (specifically when utilizing the Template Manager - Sitecore is IFRAME inception) as well as working through a data refactor in order to load the icons table significantly faster than originally released.

So what's new?


The process prior to v1.2 required users to select/focus on the Icon field's text box under the Appearance section of an item prior to opening and selecting an icon from the extension for it to automatically populate the field.  In version 1.2+, the extension can now configure, change, and save icon selections in Sitecore automatically - which should streamline the process even further.

In other words, there's a new user process:
Simply click on an item in Sitecore, open the Sitecore Icon Search Chrome Extension and select the desired icon.

Behind the scenes, the extension automatically:

1) Enables the Standard Fields checkbox under the Views tab in the Ribbon (if it's not already enabled) as a means to access the Appearance section.

2) Sets the Icon field under the Appearance section to the selected icon (user does not need to select the Icon field).  A copy of the selected icon's relative path will still be copied to the clipboard.

3) Saves the item.

I often wonder: Why isn't this built into Sitecore?

If a user prefers the original workflow (pasting the copied icon's relative path into the Icon field manually), the auto-set and auto-save feature can be disabled by unchecking a checkbox in the extension's options.


When this option is disabled, the extension will skip the auto-set and auto-save step and only copy the relative icon path to the clipboard:

What's even greater is that the extension and process within works across ALL VERSIONS OF SITECORE (tested as far back as 6.5 and as recently as 9.1)!

 I'm looking forward to continually enhancing this project into 2019.  If you have any issues or feedback, or ideas -- please please PLEASE leave a comment below.

If the extension has been useful for you, please give it a rating in the Chrome Webstore 😁

Thursday, November 15, 2018

Which Version of Sitecore Is This Again?

As someone working with multiple clients spanning various Sitecore versions, I often lose track of which versions of Sitecore I have installed 😑   Sometimes, I want to verify if an issue I've come across is a known issue in that version. Other times, I may be providing information about possible upgrade opportunities.

In any case, there are several approaches to identifying which version of Sitecore a site is using.

The Sitecore Shell

If you have access to the Sitecore shell, head to the Content Editor, click the System Menu button and select License Details.



If your Sitecore version is v 7.5 or lower, you can also find the version on the log in screen (update name not included):



Sitecore.Version.XML

Accessing /sitecore/shell/sitecore.version.xml is one of the easiest and quickest ways to find out version details - and it's always available on the CM server (Sitecore Knowledgebase: How to identify the Sitecore version and installed components)


Again, you're left on your own to find the update name yourself.

Sitecore.Kernel.dll

If you have access to the file system, you can navigate to the /bin folder, find the Sitecore.Kernel.dll and open the file's Properties.  Under the Details tab, the Sitecore Product Version will be visible here.



One caveat to this approach is that starting in Sitecore 8.2 (Initial Release), the product version listed in the Sitecore.Kernel.dll start with version 10.0.0.5597 - making it a little more difficult to quickly identify the Sitecore Product Version:

8 = 10.  Math.

Luckily, this Sitecore Stack Overflow Answer has the mappings you'll need.
Sitecore has provided additional information on their Versioning Policy page regarding their approach to product versioning.

Sitecore PowerShell Extensions

If you have access to the CMS and SPE is installed, running the $PSVersionTable command lists the Sitecore build version. Running $PSVersionTable.BuildVersion will display the Major, Minor, Build, and Revision numbers.  


This information is pulled directly from the Sitecore.Kernel.dll.
Referencing the previously mentioned Sitecore Stack Overflow Answer will give you the product's update name.  




Identifying Local Sitecore Versions with PowerShell

Initially, I wanted to come up with a way to identify every version of Sitecore I have installed on my local machine.  I used PowerShell (naturally)  to write a script that lists all installed Sitecore sites registered in IIS and their respective mapped update name based on an inspection of the Sitecore.Kernel.dll.

Here's the script:


Here's the result:

Listing all my local Sitecore instances with their respective 
With the release of the Sitecore Icon Search Chrome Extension, I was super happy with my experience building a Chrome extension - so I decided to give it another go and build the Sitecore Version Detector Chrome Extension.

That's right. The Sitecore Docs site runs on 7.2 Update-4.  Time for an upgrade? 
The extension is simple - built in pure HTML and Javascript - and checks two things:

Is the site using Sitecore? 

We can determine if a site is built on Sitecore by checking for the response on the site's /layouts/System/VisitorIdentification.aspx URL.  This file has been around since the days of DMS/OMS and is central to Sitecore's tracking mechanism. It's also always accessible from delivery servers!

If it's there, we can assume that the site is using Sitecore.

Which version of Sitecore is being used? 

Using the second method listed at the beginning of this post, the extension requests the current tab's /sitecore/shell/sitecore.version.xml URL for an XML response.  This file, while not always accessible on delivery servers, is often left exposed 💀

If it is accessible, we can parse the Major, Minor, Build and Revision values from the XML, then map to the appropriate update version name.

If a Sitecore version is detected, it will display the full revision (with the update name) and link to its respective http://sdn.sitecore.net or http://doc.sitecore.net version page.

The version's Mainstream Support End Date also displays below the version with a link to the Sitecore Product Lifecycle page 😏

Note: While this may often determine versions for live Sitecore sites (especially older versions of Sitecore), not all environments provide the means to determine the version of Sitecore it runs on as an end-user.  

Enjoy!


Thursday, September 6, 2018

Azure PaaS Sitecore Logs using AzureAILogs.html

When hosting Sitecore XP solutions on Azure PaaS – you’ll quickly find out that accessing and viewing Sitecore logs is different than you may be used to.

Sitecore has a great Knowledgebase article available (Access logs and diagnostics data in Sitecore XP on Azure Web Apps) which describes a couple approaches for obtaining the Sitecore logs on a PaaS environment using both Azure Application Insights or FTP.

Grabbing recent log files is pretty straightforward once you’ve configured FTP credentials to access your Sitecore instance.  Simply FTP into the instance (Filezilla is my favorite), navigate to /LogFiles/Application, sort by date, and download the relevant logs.



My preferred approach, however, is utilizing the AzureAILogs.html file that Sitecore provides within the “Using Azure Application Insights REST API” section of the KB article:


Enabling the API Key also requires a few clicks in the Azure portal, but the instructions for enabling this feature are outlined well – and it only takes a couple of minutes to complete.

If you download and open the HTML file locally, the output is pretty sweet:


Once you input the Sitecore app's App Insights App ID and API key, clicking the 'Update Roles' button retrieves the relevant roles for the application (CM, CD, Reporting, and Processing).

Having obtained the roles, you can select one or multiple roles, configure any specific options (recency // checkbox to only show errors // number of entries), and click the 'Get logs from AI' button to make the call.

You’ll end up with filtered and descending log entries you’d typically get from Sitecore logs:

The bonus here is the 'Download logs' button will download the log files – which are also compatible with Sitecore Log Analyzer.

This is super handy as-is, but I also wanted to make it a little easier to access online.  Specifically:

  1. I don’t want to input in the App ID and API key every time I want to use this tool.
  2. I want to access this from our CM environment, similar to any other admin page.
By adding a few old-fashioned lines of Javascript to my copy of the AzureAILogs.html file (just before the requestHandler function), the page was able to accept two URL query parameters (‘appid’ and ‘apikey’) to prefill the two input values.


For example:
AzureAILogs.html?appid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&apikey=0000000000000000000000000000000000000000

In order to access this from our CM Authoring environment, I simply added the HTML page to the /sitecore/admin directory.

Once I was able to hit the page from the server, I tacked on our App ID and API Key to the URL and bookmarked the page.   Voila - simple yet effective.

Of course, this is just one of many ways to view Sitecore logs on a PaaS environment - but I found it to be one of the most useful.

Friday, August 17, 2018

Basic Sitecore Audit Trail with Powershell


Update: This report has been included in the latest version SPE v5.0: 
https://github.com/SitecorePowerShell/Console/issues/1033


Here's a question posted to our internal Sitecore Slack channel yesterday:

The answer was 'no'.

This isn't the first time our clients have requested 'Audit Trail' functionality before, either. And we're talking about the basics here:

  • • When did a user log in?
  • • When did a user log out?
  • • Who published what, and when?
  • • When was this item's workflow executed and by whom?

Unfortunately, there isn't an 'out of the box' solution to easily obtain this data.
The most common "solution" has always been to utilize the Sitecore Log Analyzer's Audit tab - which is great for developers, but not for CMS users.

This tool has saved my sanity so many times. 

Others in the community have shared promising solutions in the past, most of which have become unsupported over time. The Sitecore Audit Trail Marketplace module, for example, was last updated in 2015 and only supports up to version 7.5 (fun fact: mainstream support for this version ended in December 2017!).  Additionally, the setup was heavy - requiring a custom database connection. It also, unfortunately,  had it some known issues associated with it.
While the feature set was fairly extensive, a simpler solution still wasn't available.

The Advanced System Reporter also has an audit feature, but again the last time this module was updated was in 2015 and supports up to version 8.0.

And then it hit me.
POWERSHELL!!!!

You've got to know this by now...my default reaction to any problem is to ask myself: "can this be done using Powershell?".

The idea was to create a Powershell report that consumes the accessible Sitecore log files which already contain the data we need.  The report should include all lines marked as 'AUDIT'' and split into columns.  The user should be able to provide a date range to narrow down the audit.  

Powershell would automatically provide the rest: keyword filtering, sorting, exporting, etc. 

Let's script it.

In order to allow a user to configure a date range, we need to create an interactive dialog

The result:



If the user clicks cancel, we'll want to abort the whole operation.
Otherwise, we'll proceed and create the properties needed for our final ListView.
We'll call a function named Get-Audit where our logic will process.


Within the Get-Audit function, we first obtain the location of the Sitecore log folder (UPDATE: We'll use $SitecoreLogFolder instead. SPE creates a variable $SitecoreLogFolder and resolves the path for you: https://doc.sitecorepowershell.com/working-with-items/variables).  We'll the pull the log files from the resolved log path and filter out everything but the standard log. files:

We'll make sure the user has selected a date range and filter the list of files using those inputs. If a user didn't set a date range, we'll simply use the original file set - which will display the most recent entries. While we're at it, we'll define a 'regex' string used to filter only AUDIT items, and an array object to hold our line objects:


We'll start a loop based on our file count. From there, we can get the contents of the file.


We need a way to include the date for each line object (specifically for our final sorting), so we'll build out a simple date string which we'll use later.


We'll now loop through each line in the file and check if it's marked as 'AUDIT'. If the condition matches, we'll append the simple date string we created previously to the beginning of the line string and sanitize the string by removing double-spaces. In some cases, the audit line will contain ManagedPoolThread #XX instead of an ID. We'll sanitize this as well.

The line now looks like this:
8/17/2018 8324 00:13:47 INFO AUDIT (sitecore\Anonymous): Logout

We'll use the space between each data point to our advantage and split each property into individual objects. The username requires some general sanitation, but more importantly, we'll build out one more DateTime object which we'll use to sort the lines before returning our array. 


Finally, we sort and return our array for the table to process.


Final Script

Putting it all together, our script looks like this:


When the script runs, we get a pretty clear view of who's been doing what:

As always, feel free to use, modify, and build on it as you see fit. This has only been tested on a handful of environments so far, so bugs are still possible.
If you do spot any issues, feel free to report them in the comments - or make the necessary changes and submit a pull request to https://github.com/strezag/sitecore-audit-trail-powershell.

Happy SitecorePowershelling!