Changing Configuration keys in Dynamics 365 – Maintenance mode

Going into License configuration to enable or disable a configuration key you’ll probably see the warning:

This form is read-only unless the system is in the maintenance mode. Maintenance mode can be enabled in this environment by running maintenance job from LCS, or using Deployment.Setup tool locally

Not in maintenance mode.PNG

Here’s how to work around that in all but production environments:

  • Tell the other users working on that environment, since you’ll be restarting the IIS during the process.
  • Log on to the server running the AOS service and start up a command prompt in Administrator mode
  • Run the following statement where you change K to the correct drive for your AOS service:

K:\AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe –metadatadir K:\AosService\PackagesLocalDirectory –bindir K:\AosService\PackagesLocalDirectory\Bin –sqlserver . –sqldatabase axdb –sqluser <SQL admin user id> –sqlpwd <SQL users password> –setupmode maintenancemode –isinmaintenancemode true

  • Restart the IIS with the iisreset command

This leaves the environment in maintenance mode. This doesn’t mean non-functional; but you probably would like to leave the maintenance mode as soon as possible.

When you are done you run this script from a command prompt in Administration mode (again replace K with the appropriate drive letter):

K:\AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe –metadatadir K:\AosService\PackagesLocalDirectory –bindir K:\AosService\PackagesLocalDirectory\Bin –sqlserver . –sqldatabase axdb –sqluser <SQL admin user id> –sqlpwd <SQL users password> –setupmode maintenancemode –isinmaintenancemode false

Restart you IIS once more and you’re back on track.

Advertisements

Uninstall MPOS – “Mordern POS exists for other users on this computer”

While testing MPOS changes I had to do an uninstall on my laptop. But every time I tried to uninstall it told me that there was an error and it couldn’t complete the uninstall and that I should contact the administrator.

And then it reappeared in the list of installed apps.

Trying to run the Uninstall-RetailModernPOS.ps1 gave a hint of what’s wrong:

uninstall MPOS.PNG

You’ll usually find the script around here:

C:\Program Files (x86)\Microsoft Dynamics 365\70\Retail Modern POS\Tools\

There might be some clever way of fixing this, but in order to move forward I did a quick’n’dirty and not recommended way of fixing it:

Remove the check …

Edit the script by commenting out this line:

Comment quick fix.PNG

This is not recommended and definitely not in a production environment and I do not take any responsibility for any undesired outcome of this. But it did the trick for getting me forward.

Please note, that this doesn’t take away the error. So when you uninstall the next time it’ll still throw the error at you until you once again remove the check.

Database error during POS activation

For some reason – still to be discovered – I once in a while get a number sequence error while activating a POS.

getting last number sequence failed

It’s not super informative but going through the event log we find this:

An exception of type: 'Microsoft.Dynamics.Commerce.Runtime.StorageException' occurred while executing Microsoft.Dynamics.Commerce.Runtime.Messages.StartSessionRequest request by Microsoft.Dynamics.Commerce.Runtime.Workflow.Security.StartSessionRequestHandler. Error resource id: 'Microsoft_Dynamics_Commerce_Runtime_CriticalStorageError', Exception: Microsoft.Dynamics.Commerce.Runtime.StorageException: Failed to read from the database. See inner exception for details

DatabaseErrorCode: 0 ---> Microsoft.Dynamics.Commerce.Runtime.Data.DatabaseException: Violation of PRIMARY KEY constraint 'I_-1558077251_-1679712867'. Cannot insert duplicate key in object 'ax.RETAILTRANSACTIONTABLE'. The duplicate key value is (<removed by me to anonymize the data>).

The statement has been terminated. ---> System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'I_-1558077251_-1679712867'. Cannot insert duplicate key in object 'ax.RETAILTRANSACTIONTABLE'. The duplicate key value is (<removed by me to anonymize the data>).

The statement has been terminated.

   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)

   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)

   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)

   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()

   at System.Data.SqlClient.SqlDataReader.get_MetaData()

   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)

   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest)

   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)

   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)

   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)

   at System.Data.SqlClient.SqlCommand.ExecuteReader()

   at Microsoft.Dynamics.Commerce.Runtime.DataAccess.SqlServer.SqlServerDatabaseProvider.ExecuteStoredProcedure(IDatabaseConnection connection, String procedureName, IEnumerable`1 parameters, IDictionary`2 outputParameters, Action`1 resultCallback, Nullable`1& storeProcedureResultValue)

   --- End of inner exception stack trace ---

   at Microsoft.Dynamics.Commerce.Runtime.DataAccess.SqlServer.SqlTypeHelper.HandleException(SqlException sqlException)

   at Microsoft.Dynamics.Commerce.Runtime.DataAccess.SqlServer.SqlServerDatabaseProvider.ExecuteStoredProcedure(IDatabaseConnection connection, String procedureName, IEnumerable`1 parameters, IDictionary`2 outputParameters, Action`1 resultCallback, Nullable`1& storeProcedureResultValue)

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.SqlServerDatabaseContext.<>c__DisplayClass15_0.<ExecuteStoredProcedure>b__0()

   at Microsoft.Dynamics.Commerce.Runtime.Framework.RetryPolicy.<>c__DisplayClass13_0.<ExecuteAction>b__0()

   at Microsoft.Dynamics.Commerce.Runtime.Framework.RetryPolicy.ExecuteAction[TResult](Func`1 func, Action`3 onTransientError)

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.SqlServerDatabaseContext.ExecuteStoredProcedure(String procedureName, ParameterSet parameters, ParameterSet outputParameters, Action`1 resultCallback, Int32& returnValue)

   --- End of inner exception stack trace ---

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.SqlServerDatabaseContext.ExecuteStoredProcedure(String procedureName, ParameterSet parameters, ParameterSet outputParameters, Action`1 resultCallback, Int32& returnValue)

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.SqlServerDatabaseContext.ExecuteStoredProcedureScalar(String procedureName, ParameterSet parameters, ParameterSet outputParameters)

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.TransactionLogSqlServerDataService.Save(RequestContext context, Int64 channelId, DataTable dataTable)

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.TransactionLogSqlServerDataService.Save(SaveTransactionLogDataRequest request)

   at Microsoft.Dynamics.Commerce.Runtime.DataServices.SqlServer.TransactionLogSqlServerDataService.Execute(Request request)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context, IRequestHandler handler, Boolean skipRequestTriggers)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context, IRequestHandler handler)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context)

   at Microsoft.Dynamics.Commerce.Runtime.Services.TransactionLogService.SaveTransactionLog(SaveTransactionLogServiceRequest request)

   at Microsoft.Dynamics.Commerce.Runtime.Services.TransactionLogService.Execute(Request request)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context, IRequestHandler handler, Boolean skipRequestTriggers)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context, IRequestHandler handler)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context)

   at Microsoft.Dynamics.Commerce.Runtime.Workflow.AuthenticationHelper.LogTransaction(RequestContext context, TransactionType transactionType, String transactionId)

   at Microsoft.Dynamics.Commerce.Runtime.Workflow.Security.StartSessionRequestHandler.Process(StartSessionRequest request)

   at Microsoft.Dynamics.Commerce.Runtime.SingleRequestHandler`2.Execute(Request request)

   at Microsoft.Dynamics.Commerce.Runtime.CommerceRuntime.Execute[TResponse](Request request, RequestContext context, IRequestHandler handler, Boolean skipRequestTriggers).

 

So the problem/symptom is centred around RetailTransactionTable. I haven’t found the actual source of the problem and what I’m suggesting as quick’n’dirty fix is not to be used in a live environment or anywhere else but sandboxes where it won’t affect anything close to live data.

I create a new query on the SQL server running the retail server database and use the following TSQL to rename a transaction id:

update [AxDB].[ax].[RETAILTRANSACTIONTABLE]
set TRANSACTIONID = '<transactionid_found_in_event_log + something else like a B>'
 where TRANSACTIONID = '<transactionid_found_in_event_log>'

After that the retry button brings you back on track and the activation can continue:

Activation success

As said, it ain’t pretty and I do not suggest this as a solution to be used anywhere. But it will get you passed that error. There’s probably a better solution and maybe a root source, but until then …

Oh, and I do not take any responsibility of bad things coming out of this … 😉

Peripheral Simulator in new release of Dynamics 365 Operations

With one of the latest releases of Dynamics 365 Operations we have the option of simulating hardware peripherals like printers, cash drawers and so on.

The idea is to allow the user to simulate the flow of the retail processes including printers, drawers, scales, payments and so on but without having to occupy your co-workers desk piling up all of your retail hardware.

Here is what you need to do. Start by going to the hardware profiles. In the demo data a new profile has been added called Virtual. It has been set up with a profile that will work pretty much out of the box.

Besides the data a new button has been added allowing the download of the simulator:

hardware-profile-and-download-button

The simulator download hasn’t received the prettiest name, but that aside it is working great.

peripheralsimulator

The installer is very much a next-next-next installer and does not require any action taken unless you have specific wishes regarding installation folder.

Once installed you get this new application:

retail-peripheral-simulator

Already at this point we get an idea of what to expect. But before getting everything up and running you need to do a couple of more things.

First, we need to tell the store that the hardware station should use the new hardware profile:

hardware-profile-o

Run your 1070 and 1090 jobs (depending on which setup changes you made).

Now, starting up the POS you might end up with a series of hardware station errors that could look something like this:

hardware-station-error-3hardware-station-error-2comm-error-cash-drawer

To get passed this we should shortly touch upon how this works. According to the hardware profile we are using all communication is OPOS based so we need to get that onboard our POS machine as well. I used this one that previously was recommended during the installation of the POS software: Link to OPOS software

With that done you should be ready to start up your POS. You might have to manually go in and enable the use of the hardware station.

So first test could be a safe drop. In this case I pull out 10 USD:

make-safe-drop

That leaves a safe drop receipt in the printer:

safe-drop-receipt

And the drawer needs to be closed again:

cash-drawer-open

Click the Close drawer button to close it:

cash-drawer-closed

Let’s sell something. In this case a shirt:

transaction

I would like to pay this with a credit card so I switch to my simulator and select the MSR.

no-card-created

Click the + button to create new card:

create-master-card

The number is found on this page: credit card generator

Next step is to click the Pay card button in the POS followed by the Swipe card button in the Simulator. This adds the card info to the tender information in the POS:

card-details-in-pos

Completing the transaction you get a receipt in the printer:

receipt-from-transaction

This will definitely change the way we make demos of the POS with Dynamics 365 Operations.

 

Automated startup and shutdown of Azure VMs

This document describes in headlines how to setup automated start and shutdown of Azure VMs. To go through the steps, you are required to have access to the management portal at https://portal.azure.com and administration rights.

By shutting down the servers when not used there is a noticeable amount to be saved.

Prerequisites

Automation Account

To run the automation scripts, you need an Automation Account. Notice, that the account must be created under the same subscription as the servers that should be managed by the account.

The fastest way to locate the accounts is to search for the Automation Accounts service:

account1

To create a new account, click the Add button:

account2

Give the account a name, specify a resource group (or create a new) and a location:

account3

When created (it takes a moment), select the new account:

account4

Shut down servers

Runbooks

All activity is kept in runbooks. The account comes with 4 default runbooks which we for this scope leaves as is.

shutdown1

We are going to create our runbooks based on a template that gives us the functionality we need out of the box. To do this click Browse gallery:

shutdown2

The list of available templates is long. The first one we are going to use is the “Stop Azure V2 VMs”.

shutdown3

When we click on it we can see a graphical presentation of the flow. This is not relevant to go through in this document. Click the Import button to use the template:

shutdown4

Give the new runbook a name and a description:

shutdown5

After the runbook has been created, click Edit:

shutdown6

From here we can change the runbook including default values for the runbook. We can also test the runbook with different values.

In this case we are not going to change anything so we publish it right away by clicking the Publish button:

shutdown7

Scheduled runs

Next step is to schedule the runbook to run every afternoon. To do this click the Schedule button:

schedule1

To do this we need to things: A schedule and the parameters to run the runbook with. First the schedule:

schedule2

In this scenario we want the VMs to be stopped every day at 18:00:

schedule3

To run the runbook we need to specify the resource group name and the name of the VM.

schedule4

This information is found on the information page of the VM in the Azure portal.

Add it to the parameters:

schedule5

Now the scheduler will shut down the server matching the parameters every day at 18:00.

If you leave the VM name blank all servers in the resource group will be affected.

Starting VMs

To create a runbook to start the VMs go to the gallery and select the Start Azure v2 VMs template:

startup1

Give it a name and description:

startup2

Click edit to access the runbook just created:

startup3

Publish the runbook. Again we do not want to change anything:

startup4

Create a schedule to start the VM every working day at 7:00:00. In this case we don’t start them up in the weekends; but if somebody starts a VM it is automatically shut down by the previously created runbook.

startup5

You just saved a lot of money on the VM…

 

Create scheduled runs for every VM you can shut down at night.