D365 for Operations : Getting framework with id '0' failed from Lifecycle Services

Task Recorder avec Dynamics 365 for Operation permet de sauvegarder les enregistrement dans la bibliothèque BPM de LCS.


Dans mon cas, l'utilisateur reçoit les messages d'erreur suivante:

Getting framework with id '0' failed from Lifecycle Services.



Populating the BPM tree from Lifecycle Services for the selected framework has failed.




La solution est simple. L'utilisateur doit être membre du projet dans LCS. Mais non seulement il doit et membre du projet, l'utilisateur doit aussi faire partie de l'annuaire AD dans lequel l'environnement a été déployer. En d'autre mots, vous ne pouvez pas utiliser un utilisateur externe.

Il est aussi important de noter que l'utilisateur doit se connecter au moins une fois dans LCS afin d'accepter la licence d'utilisation.



Ensuite, lorsque l'utilisateur tentera d'utiliser la fonctionnalité Save To Lifecycle Services, il devra clicquer sur Click here to connect to Lifecycle Services


D365 for Operations : System.Security.Cryptography.CryptographicException: Key not valid for use in specified state.

Lors du déploiement de mise à jour binaires d'un environnement de development, LCS m'indique que le déploiement a échoué à l'étape 52: updates script for service: RetailServer on machine DEV2

Microsoft ne donne pas beaucoup d'informations sure comment diagnostiquer les problèmes de déploiement. La seule information que j'ai trouvée est sur cet article: Apply a deployable package on a Microsoft Dynamics 365 for Operations environment. En fait, la seule recommandation est de cliquer sur Resume, ce que j'ai bien fait sans résultat positif. 

Voici comment j'ai diagnostiqué et corrigé le problème.

Tout d'abord, j'ai téléchargé le Runbook afin d'avoir plus d'informations sur l'étape 52.


Une recherche sur le tag 52 m'a permis de trouver l'information suivante:



Ensuite, j'ai téléchargé les fichiers de logs.


Dans le dossier qui contient les logs, vous allez y trouver un dossier par étapes. Dans mon cas, l'erreur se produit à l'étape 52. Dans le dossier, vous allez y trouver un fichier OUTPUT, c'est dans ce fichier que vous allez y trouver plus d'informations au sujet du problème



Message d'erreur: System.Security.Cryptography.CryptographicException: Key not valid for use in specified state.

On peut aussi y voir que le script qui cause une erreur est le suivant:

J:\DeployablePackages\996e3705-b27f-44f6-a3d5-c6eae47564eb\RetailServer\scripts\Upgrade\Core\UpdateRetailServer.ps1


En toute logique, vous pouvez voir que le DeployablePackage ID correspond aux ID de l'activité de déploiement dans LCS



J'ai finalement trouvé le fichier en question:


Ensuite, il suffit d'essayer de comprendre ce que le code effectue et de trouver l'opération en erreur. Le processus d'isolation du problème peut être laborieux puisque le script UpdateRetailServer.ps1 appelle d'autres scripts PowerShell. Dans mon cas, la ligne qui causait problème était situé dans le fichier Common-Upgrade.ps1 dans la fonction Get-ChannelDbServicingPropertyName. 


Il se trouve que Microsoft a utilisé ConvertFrom-SecureString pour encrypter la connexion string puisque celle-ci contient un mot de passe. Vous pouvez y trouver l'information encrypter à cet endroit:

HKLM\SOFTWARE\Microsoft\Dynamics\7.0\RetailChannelDatabase\Servicing


J'ai fait mon propre test et reçu la même erreur:


À ce moment, je ne sais toujours pas ce qui est encrypter. Je fais donc le même test sur une autre machine et ça me retourne l'information:

$servicingDataAsSecureString = ConvertTo-SecureString ENCRYPTEDVALUE
$servicingDataAsPlainText = [System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($servicingDataAsSecureString))
write-host $servicingDataAsPlainText


BOOM! Il me suffit de retourner sur la machine qui cause probleme et de modifier le script Common-Upgrade.ps1. J'ai remplacer la valeur encryptée par du texte claire.



Ensuite, j'ai cliqué sur Resume et le déploiement à fonctionner


Prenez note que j'ai effectué d'un workaround pour corriger le problème. Le vrai problème est que le compte axlocaladmin n'est pas capable décrypter l'information locale et je ne sais pas pourquoi.

D365 for Operations : You are not authorized to login with your current credentials.

D365 for Operations utilise une architecture claim pour l'authentification des utilisateurs. Il est donc très facile d'ajouter des utilisateurs d'un domaine externe, ce dont j'ai fait dans mon environnement de demo en ajouter l'utilisateur admin@mtessier.onmicrosoft.com. Toutefois, lorsque j'ai tenté de m'authentifier, j'ai reçu le message d'erreur suivant:

You are not authorized to login with your current credentials. You will be redirected to the login page in few seconds.



Le problème est le provider. Il faut s'assurer que le provider specifier pour l'utilisateur est configuré pour recevoir les demande du domaine en question. Pour corriger le problème, j'ai changé le provider pour https://sts.windows.net/mtessier.onmicrosoft.com


Dynamics AX 2012 : The reference assemblies for framework ".NETFramework,Version=v.4.0" were not found.

Lors de la synchronisation avec TFS, les messages suivants sont apparus:

MSB3644: The reference assemblies for framework ".NETFramework,Version=v.4.0" were not found.

AX1004: Reference System.Core, Version 4.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089 was not a valid model assembly.



C’est davantage un problème avec .NET Framework que Dynamics AX. Lorsque j’ai voulu installer Windows SDK for Windows 7 with .NET Framework 4, je recevais le message d'erreur suivant:

Some Windows SDK components require the RTM .NET Framework 4. Setup detected a pre-release version of .NET Framework 4. If you continue with Setup, these components will not be installed. If you want to install these components, click Cancel, then install the .NET Framework 4 from https://go.microsoft.com/fwlink/?LinkID=187668 and then rerun Setup.
Click OK to continue.

Ensuite, j’ai voulu installer Microsoft .NET Framework 4, mais je recevais le message d’erreur suivant :

The Microsoft .NET Framework 4 is already part of the operating system. No need to install the .NET Framework 4 redistributable. More information. An equal or higher version of the .NET Framework 4 has already been installed on the computer.

Afin de résoudre le problème, j’ai suivi les étapes mentionnées ici: Windows SDK Setup failure. J’ai changé temporairement la donnée de la valeur version pour 4.0.30319 dans les clés suivantes:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Full\Version
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Client\Version

Ensuite, j’ai pu installer Windows SDK. Ensuite, j’ai remis la valeur originale. 


Dynamics AX : Diagnostiquer les problèmes de verrouillage (locks) - PART 2

Il est difficile de détecter en temps réel les blocages dans une base de données. C’est pour cette raison qu’il est important de configurer SQL Extended Event. Cet outil vous permettra d’enregistrer l’historique des blocages.

Avant de configurer une session de type Extended Event, vous devez créer un dossier C:\SQLTRACE sur le serveur. Ensuite, vous pouvez exécuter la requête suivante qui vient de la solution DynamicsPerf 2.0. Celle-ci configure une session afin de collecter les requêtes bloquées pour plus de 2 secondes.

USE [master]
GO
sp_configure 'Show Advanced Options', 1
RECONFIGURE WITH OVERRIDE
GO
sp_configure 'blocked process threshold', 2
RECONFIGURE WITH OVERRIDE
GO

IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='DYNPERF_BLOCKING_DATA')
DROP EVENT SESSION DYNPERF_BLOCKING_DATA ON SERVER
GO

CREATE EVENT SESSION [DYNPERF_BLOCKING_DATA] ON SERVER 

ADD EVENT sqlserver.blocked_process_report(
ACTION(package0.collect_system_time,sqlserver.client_hostname,sqlserver.context_info)),

ADD EVENT sqlserver.xml_deadlock_report(
ACTION(package0.collect_system_time,sqlserver.client_hostname,sqlserver.context_info)),

ADD EVENT sqlserver.lock_escalation(
ACTION(package0.collect_system_time,sqlserver.client_hostname,sqlserver.context_info)) 
ADD TARGET package0.event_file(SET filename=N'C:\SQLTrace\DYNAMICS_BLOCKING.xel',max_file_size=(10),max_rollover_files=(100))
--ADD TARGET package0.ring_buffer(SET max_memory=(131072))
WITH (MAX_MEMORY=4096 KB,MAX_DISPATCH_LATENCY=5 SECONDS,MEMORY_PARTITION_MODE=PER_NODE,TRACK_CAUSALITY=ON,STARTUP_STATE=ON)
GO

ALTER EVENT SESSION [DYNPERF_BLOCKING_DATA] ON SERVER 
STATE=START
GO



Ensuite, les événements sont collectés dans les fichiers .xel


Ensuite, vous pouvez analyser les évènements avec la requête suivante:

SELECT TOP 100 *
FROM   (SELECT event_data.value('(event/@name)[1]', 'varchar(50)')                                                                 
AS EVENT_NAME,
               DATEADD(hh, DATEDIFF(hh, GETUTCDATE(), CURRENT_TIMESTAMP), event_data.value('(/event/@timestamp)[1]', 'datetime2')) AS END_TIME,
               event_data.value('(event/data[@name="duration"]/value)[1]', 'decimal(38,3)') / 1000                                 
AS DURATION,
               event_data.value('(event/data[@name="object_id"]/value)[1]', 'int')                                                 
AS OBJECT_ID,
               event_data.value('(event/data[@name="resource_owner_type"]/value)[1]', 'varchar(max)')                              
AS RESOURCE_OWNER_TYPE,
               event_data.value('(event/data[@name="index_id"]/value)[1]', 'int')                                                  
AS INDEX_ID,
               event_data.value('(event/data[@name="lock_mode"]/value)[1]', 'varchar(max)')                                        
AS LOCK_MODE,
               event_data.value('(event/data[@name="transaction_id"]/value)[1]', 'bigint')                                            
AS TRANSACTION_ID,
               event_data.value('(event/data[@name="database_name"]/value)[1]', 'varchar(max)')                                    
AS DATABASE_NAME,
               event_data                                                                                                          
AS EVENT_DATA
        FROM   (SELECT CONVERT(XML, event_data)
                FROM   sys.fn_xe_file_target_read_file('C:\SQLTRACE\DYNAMICS_BLOCKING*.XEL', NULL, NULL, NULL)) AS evts ( event_data )) AS DYNPERF_BLOCKING
WHERE  EVENT_NAME = 'blocked_process_report'
--AND END_TIME BETWEEN  '2016-02-13 10:19:37.5520000' AND '2016-02-13 10:21:17.9560000' 
ORDER  BY END_TIME DESC



Vous pouvez cliquer sur le lien dans la colonne EVENT_DATA et pouvez y voir plusieurs informations intéressantes:
  • Blocked-process
  • Waitresource
  • Waittime
  • Lockmode
  • Status
  • Hostname
  • Isolationlevel



Dynamics AX : Diagnostiquer les problèmes de verrouillage (locks) - PART 1

Dans le passé, j’ai écrit un billet au sujet des blocs dans votre base de données SQL, aujourd'hui je voulais approfondir le sujet.

Comme nous l'avons vu, il est possible de savoir les sessions SQL bloquées. De plus, nous sommes capables d'associer la session SQL (SPID) avec la session AX lorsque connectioncontext est activé sur le serveur AOS

Aujourd’hui, je veux savoir pourquoi la session est bloquée.

Afin de faire la démonstration, je vais volontairement créer un blocage dans la base de données. Dans ma première requête, je vais mettre à jour le champ ENABLE pour le ID mathieu. Toutefois, je ne vais pas commettre la transaction immédiatement, ceci aura pour effet de verrouiller la ligne pour une durée de 30min.

(SPID 78)

BEGIN TRANSACTION
UPDATE USERINFO SET ENABLE=1 WHERE ID = 'mathieu.'
    WAITFOR DELAY '00:30:00' 
ROLLBACK TRANSACTION

Dans la seconde requête, je vais tenter de faire une modification à la même ligne:

(SPID 80)

UPDATE USERINFO SET ENABLE=0
WHERE ID = 'mathieu.'

En utilisant cette requête, je suis capable de voir que mes deux requêtes sont en cours d’exécution :

Queries Running.sql

SELECT
cast(context_info as varchar(128)) AS context_info,
req.session_id AS sql_spid,
req.command,
sqltext.text,
req.status,
req.cpu_time,
req.reads,
req.writes,
req.logical_reads,
req.last_wait_type,
req.wait_time,
req.total_elapsed_time,
req.open_transaction_count,
d.name AS db_name
FROM sys.databases d, sys.dm_exec_requests req
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext
WHERE d.database_id = req.database_id 


En utilisant cette requête, je peux voir que le SPID 78 bloque le SPID 80. Mais je ne sais pas pourquoi.

Blocks.sql

USE [master]
GO

SELECT cast(s.context_info as varchar(128)) AS ax_spid,
s.host_name,
w.session_id AS sql_spid,
w.wait_duration_ms,
r.total_elapsed_time,
t.text,
w.wait_type,
w.blocking_session_id AS sql_head_blocker,
s.cpu_time,
s.reads,
s.writes,
s.logical_reads,
r.open_transaction_count,
DB_NAME(s.database_id) AS db_name
FROM sys.dm_os_waiting_tasks w
INNER JOIN sys.dm_exec_sessions s
ON w.session_id = s.session_id
INNER JOIN sys.dm_exec_requests r
ON s.session_id = r.session_id
OUTER APPLY sys.dm_exec_sql_text (r.sql_handle) t
WHERE s.is_user_process = 1 
--AND s.program_name like '%Dynamics%'
ORDER BY sql_spid
GO

SELECT cast(s.context_info as varchar(128)) AS ax_spid,
p1.spid AS sql_spid,
p1.hostname,
p1.cmd,
text,
p1.cpu AS cpu_time,
p1.physical_io AS physical_io,
p1.memusage,
p1.open_tran
FROM sysprocesses p1
INNER JOIN sys.dm_exec_connections c
ON p1.spid = c.session_id
INNER JOIN sys.dm_exec_sessions s
ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle)
WHERE EXISTS (SELECT p2.spid FROM sysprocesses p2 WHERE p2.blocked > 0 AND p2.blocked = p1.spid)
   AND NOT EXISTS (SELECT p3.spid FROM sysprocesses p3 WHERE p3.blocked > 0 AND p3.spid = p1.spid)
   --AND s.program_name like '%Dynamics%'
GO

Dans ce cas-ci, nous pouvons voir que le SPID 78 est bloqué à cause de la commande WAITFOR. Nous pouvons aussi voir que le SPID 80 attend afin d'acquérir un lock de type Update (LCK_M_U) et celui-ci attend après le SPID 78.


J'aimerais avoir plus d’information à ce sujet et pour ceci nous pouvons vérifier les locks dans la base de données:  

Locks.sql

USE [databasename]
GO

SELECT 
  cast(context_info as varchar(128)) AS context_info,
  dm_tran_locks.request_session_id,
       DB_NAME(dm_tran_locks.resource_database_id) AS dbname,
       CASE
           WHEN resource_type = 'OBJECT'
               THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id)
           ELSE OBJECT_NAME(partitions.OBJECT_ID)
       END AS ObjectName,
       partitions.index_id,
       indexes.name AS index_name,
       dm_tran_locks.resource_type,
       dm_tran_locks.resource_description,
       dm_tran_locks.resource_associated_entity_id,
       dm_tran_locks.request_mode,
       dm_tran_locks.request_status
FROM sys.dm_tran_locks
LEFT JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id
LEFT JOIN sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID AND indexes.index_id = partitions.index_id
LEFT JOIN sys.dm_exec_sessions ON sys.dm_tran_locks.request_session_id = sys.dm_exec_sessions.session_id
WHERE resource_associated_entity_id > 0
  AND resource_database_id = DB_ID()
ORDER BY ObjectName ASC, resource_associated_entity_id

Je peux voir que la session 80 attend pour obtenir un lock de type U sur la ressource (362b1400cd67). La raison est parce que la session 78 a déjà un lock de type X sur la même ressource. Un lock de type X est incompatible avec les autres lock, pour cette raison, la session 80 doit attendre. Vous pouvez lire plus au sujet des compatibilités entre lock ici: Lock Compatibility


Je vois que le type de ressource est KEY. Ceci veut dire que le lock est sur une ligne. Vous pouvez lire plus au sujet des différents types de ressource  ici: sys.dm_tran_locks (Transact-SQL). Afin de connaître la ligne, vous pouvez exécuter cette requête. 

KEY Lock.sql

SELECT sys.fn_PhysLocFormatter(%%physloc%%) AS FilePageSlot, 
%%lockres%% AS LockResource, *
FROM USERINFO
WHERE %%lockres%% ='(362b1400cd67)' 

Et voilà, maintenant je sais que la session 80 attend après la session 78 afin de mettre a jour la ligne suivante :



DynamicsPerf : AX DM Companies to Company user integration query slow due to HASH join

Encore une fois, selon Dynamics Perf, la requête la plus "couteuse" de mon environnement Dynamics AX provient de Management Reporter. Et encore une fois, c'est la requête responsable pour l'intégration de la sécurité entre Management Reporter et Dynamics AX. 

Lorsque j'exécute la requête manuellement, elle prend 14 heures à compléter et me retourne 14000 lignes. Pendant les 14 heures d'exécution, le CPU du serveur SQL tourne à l'entour de 25%. Cette requête ne causait pas problème il y a deux semaines, qu'est-ce qui a changé ? J'ai découvert que les permissions à certains utilisateurs ont été modifiées. En effet, chaque rôle assigné à un utilisateur a été modifier afin d'être appliqué à certaines entités légales au lieu de toutes les entités légales.

Bien sûr, le client ne veut pas changer les permissions en place, j'ai donc ouvert un billet avec Microsoft. On m'a dit que c'est un bug connu: 

Bug 3794820: AX DM Companies to Company user integration query slow due to HASH join

Quoique la requête ne soit pas optimale dans mon cas, Microsoft n'a pas l'intention de corriger le problème puisque la requête offre une bonne performance dans une majorité des cas. Heureusement, une autre solution s'est offert, celle d'activer le SQL Trace Flag 4199.

Suite à l'activation du flag 4199, la requête prend 35 min à exécuter au lieu de 14 heures. N'oubliez pas que cette tâche est configurée pour être exécuté à toutes les 5 minutes par Management Reporter, je recommande de modifier la fréquence à 24 heures ici : DynamicsPerf : Requêtes Longues (Long Queries)

Voici la requête en question:

select T.USERKEY, T.NAME, T.ALIAS, T.DOMAIN, T.SECURITYID, MAX(T.GENERALLEDGERROLETYPE) GENERALLEDGERROLETYPE, T.COMPANYKEY, T.ISENABLED
from (
select UI.RECID USERKEY, UI.NAME, UI.NETWORKALIAS ALIAS, UI.NETWORKDOMAIN DOMAIN, SID SECURITYID, 
CASE st.AOTNAME 
WHEN 'SysSecSecurityMaintain' THEN 5
WHEN 'LedgerBalanceSheetDimMaintain' THEN 4
WHEN 'LedgerFinancialJournalReportBGenerate' THEN 3
WHEN 'LedgerBalanceSheetDimPrintGenerate' THEN 3
WHEN 'LedgerViewFinancialStatement' THEN 2
END GENERALLEDGERROLETYPE, l.RECID COMPANYKEY, UI.ENABLE ISENABLED
from [MicrosoftDynamicsAX_TESSIER]..USERINFO UI
inner join [MicrosoftDynamicsAX_TESSIER]..SECURITYUSERROLE sur on UI.ID = sur.USER_ and UI.PARTITION = sur.PARTITION
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLE sr on sur.SECURITYROLE = sr.RECID
and (GETUTCDATE() between sur.VALIDFROM and sur.VALIDTO OR 
(sur.VALIDFROM = '1/1/1900' and sur.VALIDTO = '1/1/1900'))
inner join [MicrosoftDynamicsAX_TESSIER]..SECURITYUSERROLECONDITION c on c.SECURITYUSERROLE = sur.RECID and c.PARTITION = sur.PARTITION
inner join (SELECT T1.SECURITYTASK AS SECURITYTASK
,T2.SECURITYROLE AS SECURITYROLE
FROM [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLETASKGRANT T1
CROSS JOIN [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLEEXPLODEDGRAPH T2
WHERE (T1.SECURITYROLE = T2.SECURITYSUBROLE)
GROUP BY T1.SECURITYTASK
,T2.SECURITYROLE) v on v.SECURITYROLE = sr.RECID 
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYTASKEXPLODEDGRAPH g on g.SECURITYTASK = v.SECURITYTASK
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYTASK st on g.SECURITYSUBTASK = st.RECID
inner join (Select l.RECID, l.PARTITION, CI.DATAAREA from [MicrosoftDynamicsAX_TESSIER]..LEDGER l 
inner hash join [MicrosoftDynamicsAX_TESSIER]..DIRPARTYTABLE CI on CI.PARTITION = l.PARTITION and CI.INSTANCERELATIONTYPE = 41 and l.PRIMARYFORLEGALENTITY = CI.RECID) l on UI.PARTITION = l.PARTITION and l.DATAAREA = c.DATAAREA
Where 
UI.EXTERNALUSER = 0 AND
UI.[SID] != '' AND
UI.[ACCOUNTTYPE] = 0 AND
sur.ASSIGNMENTSTATUS = 1 AND
st.AOTNAME in (
'SysSecSecurityMaintain',
'LedgerBalanceSheetDimMaintain', 
'LedgerFinancialJournalReportBGenerate', 
'LedgerBalanceSheetDimPrintGenerate',
'LedgerViewFinancialStatement')
union all
-- get users and their assigned tasks for all companies where the task hasn't been constrained to a company
select UI.RECID USERKEY, UI.NAME, UI.NETWORKALIAS ALIAS, UI.NETWORKDOMAIN DOMAIN, SID SECURITYID, 
CASE st.AOTNAME 
WHEN 'SysSecSecurityMaintain' THEN 5
WHEN 'LedgerBalanceSheetDimMaintain' THEN 4
WHEN 'LedgerFinancialJournalReportBGenerate' THEN 3
WHEN 'LedgerBalanceSheetDimPrintGenerate' THEN 3
WHEN 'LedgerViewFinancialStatement' THEN 2
END GENERALLEDGERROLETYPE, l.RECID COMPANYKEY, UI.ENABLE ISENABLED
from [MicrosoftDynamicsAX_TESSIER]..USERINFO UI
inner join [MicrosoftDynamicsAX_TESSIER]..SECURITYUSERROLE sur on UI.ID = sur.USER_ and UI.PARTITION = sur.PARTITION
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLE sr on sur.SECURITYROLE = sr.RECID
and (GETUTCDATE() between sur.VALIDFROM and sur.VALIDTO OR 
(sur.VALIDFROM = '1/1/1900' and sur.VALIDTO = '1/1/1900'))
inner join (SELECT T1.SECURITYTASK AS SECURITYTASK
,T2.SECURITYROLE AS SECURITYROLE
FROM [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLETASKGRANT T1
CROSS JOIN [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLEEXPLODEDGRAPH T2
WHERE (T1.SECURITYROLE = T2.SECURITYSUBROLE)
GROUP BY T1.SECURITYTASK
,T2.SECURITYROLE) v on v.SECURITYROLE = sr.RECID  
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYTASKEXPLODEDGRAPH g on g.SECURITYTASK = v.SECURITYTASK
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYTASK st on g.SECURITYSUBTASK = st.RECID
inner join (Select l.RECID, l.PARTITION from [MicrosoftDynamicsAX_TESSIER]..LEDGER l 
inner hash join [MicrosoftDynamicsAX_TESSIER]..DIRPARTYTABLE CI on CI.PARTITION = l.PARTITION and CI.INSTANCERELATIONTYPE = 41 and l.PRIMARYFORLEGALENTITY = CI.RECID) l on UI.PARTITION = l.PARTITION
Where 
UI.EXTERNALUSER = 0 AND
UI.[SID] != '' AND
UI.[ACCOUNTTYPE] = 0 AND
sur.ASSIGNMENTSTATUS = 1 AND
st.AOTNAME in (
'LedgerBalanceSheetDimMaintain', 
'LedgerFinancialJournalReportBGenerate', 
'LedgerBalanceSheetDimPrintGenerate',
'LedgerViewFinancialStatement',
'SysSecSecurityMaintain')
and not exists (select 1 from SECURITYUSERROLECONDITION c where c.SECURITYUSERROLE = sur.RECID and c.PARTITION = sur.PARTITION)
union all
-- get all administrators for all companies where the admin's aren't limited to specific companies
select UI.RECID, UI.NAME, UI.NETWORKALIAS, UI.NETWORKDOMAIN, SID, 5 RoleType, l.RECID, UI.ENABLE ISENABLED
from [MicrosoftDynamicsAX_TESSIER]..USERINFO UI
inner join [MicrosoftDynamicsAX_TESSIER]..SECURITYUSERROLE sur on UI.ID = sur.USER_ and UI.PARTITION = sur.PARTITION
inner join [MicrosoftDynamicsAX_TESSIER_Model]..SECURITYROLE sr on sr.RECID = sur.SECURITYROLE
and (GETUTCDATE() between sur.VALIDFROM and sur.VALIDTO OR 
(sur.VALIDFROM = '1/1/1900' and sur.VALIDTO = '1/1/1900'))
inner join (Select l.RECID, l.PARTITION from [MicrosoftDynamicsAX_TESSIER]..LEDGER l 
inner hash join [MicrosoftDynamicsAX_TESSIER]..DIRPARTYTABLE CI on CI.PARTITION = l.PARTITION and CI.INSTANCERELATIONTYPE = 41 and l.PRIMARYFORLEGALENTITY = CI.RECID) l on UI.PARTITION = l.PARTITION
where
UI.EXTERNALUSER = 0 AND
UI.[SID] != '' AND
UI.[ACCOUNTTYPE] = 0 AND
sur.ASSIGNMENTSTATUS = 1 AND
AOTNAME in ('SysSecSecurityAdministrator') 
)
T
Group by T.USERKEY, T.NAME, T.ALIAS, T.DOMAIN, T.SECURITYID,  T.COMPANYKEY, T.ISENABLED
order by T.COMPANYKEY

AX 2012 R3 Export & Import environment configurations

Parmi les tâches quotidiennes d'un administrateur de Système Dynamics AX, on y trouve entre autres le rafraichissement des environnements. La tâche consiste à copier un environnement vers un autre. Plusieurs tâches doivent être executé pour compléter le rafraichissement d'un environnement. Entre autres, il faut reconfigurer certains composants, par exemple la configuration SSRS ou tout simplement l'URL du serveur Help.

J'ai mis en ligne deux scripts qui permet d'exporter et importer la configuration dans un fichier XML different composants d'un environnement Dynamics AX . Avant d'effectuer la restauration des base de données, j'exporte la configuration AX. Ensuite je performe la restauration de la BD et re-import la configuration. J'ai mis mes scripts sur codeplex.



D365 for Operations : DNS record is already used by another public IP.

Lors du déploiement de Dynamics 365 for opération - Démo (Release 1611 - ARM enabled) v61, j'ai reçu le message d'erreur suivant:

ARM Deployment [DEMO] finished with state [Failed], error details
DNS record demodemo.eatuse.cloudapp.azure.com is already used by another public IP.




J'ai donné le nom DEMO à mon environnement. Il semble que Microsoft a oublié de valider la disponibilité du nom "demo" lors de prises d'information.

Le déploiement de l'environnement a été compléter correctement et je pouvais mon l'adresse IP public avec le nouveau nom:

Dynamics AX 2012 : Crash du client AX sur les machines Citrix

Un de mes clients avait un problème de déconnexion persistant. Le problème semblait aléatoire parmi tous ses utilisateurs qui utilisaientt Citrix. Nous étions incapables de reproduire le problème.

Les messages d’erreur suivants se trouvaient sur le serveur AOS:

Object Server 01:  No ping from client session 6 (User: mathieu, ClientType: GUI). Terminating the session.
Object Server 01:  No ping from client session 20 (User: mathieu, ClientType: Worker). Terminating the session.
Object Server 01:  No ping from client session 21 (User: mathieu, ClientType: Worker). Terminating the session.

La fenêtre du client AX disparaissait tout simplement ou l’utilisateur recevait le message suivant:

The server is unavailable. Check your configuration and network connection and try again.

Sur la machine Citrix, l’erreur était la suivante:

RPC exception 1726 occurred in session 6 process is AX32.exe thread is 5964 (user: mathieu, ClientType: GUI)

Finalement, il existe un hotfix pour ce problème;



Sources: 

D365 for Operations : User account from identify provider does not exist in 'Microsoft'

Le déploiement de Dynamics AX 365 for Operations requiert l'activation de ARM. Lors du processus d'activation, j'ai eu deux problèmes distincts en suivant les etapes de ce lien: Azure Resource Manager onboarding.

Tout d'abord, lors de l'activation, j'ai reçu le message d'erreur suivant:

An Unexpected error has occured. Please try again later. If the problem persists contact support for further assistamce.

Pour corriger ce problème, j'ai utilisé le Azure Tenant Domain lié à O365 mathdax.ca au lieu de mtessier.onmicrosoft.com. Malheureusement, je ne sais pas pourquoi je ne peux pas utiliser mtessier.onmicrosoft.com.



Le deuxième problème est survenu lors de l'autorisation. Après avoir cliqué sur le lien Authorize, je dois m'authentifier et lorsque je tente d'utiliser mon compte associer à Azure, je revois le message d'erreur suivant:

User Account 'mtessier@hitachi-solutions.com' from identity provider 'live.com' does not exist in tenant 'Microsoft' and cannot access application 'ID' in that tenant.



Le problème est dû au fait que je veux utiliser un abonnement Azure qui n'est pas lié à mon compte O365. La solution se trouve ici: Deal with Dynamics Deployment Services [wsfed-enabled]

D365 for Operations : Permissions nécessaires pour pouvoir déployer

Réussir à déployer Dynamics 365 for Operations est tout un défie ! Je voulais documenter quelques cas dont j’ai fait face. Le premier: avoir les accès nécessaires.

Tout d’abord, vous devez avoir un compte qui répond aux critères afin de pouvoir faire le déploiement.

Si vous êtes partenaire, mais que vous n’utilisez pas un compte O365, vous serez incapable de créer un projet Dynamics 365 for Operations.



Si vous êtes un prospect avec un compte Office 365, vous allez pouvoir créer un projet Dynamics 365 for Operation, mais incapable d’effectuer un deploiement. Le signe "+" est manquant.



Afin de pouvoir créer un projet Dynamics 365 for Operation ainsi que l'option de déployer, vous devez être partenaire ou client AX, mais aussi utiliser un compte Office 365.






Dynamics AX 2012 : License miner job run failed

J'ai trouvé l'erreur suivante dans le journal d'événement:

Object Server 01:  License miner job run failed: 75 

L'erreur est provoqué par le rapport Named User License Count report et est dû à l'existence d'utilisateur AX qui ne sont plus dans Active directory.

Voici un job qui identifie les utilisateurs actifs qui ne sont pas trouvables dans l'actif directory:

static void navax_findBadUserNames(Args _args)
{
    UserInfo                userInfo;
    container               con;
    ;   while select forUpdate userInfo
        where   userInfo.Enable &&
                userInfo.AccountType != UserAccountType::ADGroup
    {
        con = SysUserLicenseMiner::getUserRoles([userInfo.Id, userInfo.company]);
        if (conLen(con) == 0)
        {
            warning(strFmt("Userid: %1, username: %2", UserInfo.networkAlias, UserInfo.name));
        }
    }
}


Source: http://dynamicsnavax.blogspot.ca/2015/05/error-in-getting-sid-when-running-named.html

Dynamics 365 : Déploiement et administration

Voici l'information que j'ai trouver sur le déploiement et l'administration de Dynamics 365.

Dynamics 365

TechNet
  • Microsoft Dynamics 365 IT Pro Technical Library
    • Dynamics 365 (online and on-premises)
      • Deployment and Administration
        • Subscription Management for Dynamics 365 (online)
          • Release history
          • Important information for CRM Online customers
          • Switch from Dynamics CRM Online to Dynamics 365 (online)
          • Try Dynamics 365 (online)
          • Manage Microsoft Dynamics 365 (online) updates
          • Policies and Communications for Dynamics 365 (online)
          • Restrict access to Dynamics 365 (online) with trusted IP rules
          • Get started administering Microsoft Dynamics 365 (online)
          • Manage subscriptions, licenses, and user accounts
          • Manage Microsoft Dynamics 365 (online) instances
          • Manage email notifications
          • Migrate Microsoft Dynamics 365 (online) to Microsoft Dynamics 365 (on-premises)
          • Accessibility in Microsoft Dynamics CRM
        • Administering Dynamics 365
          • What's new for administrators and customizers in Microsoft Dynamics 365
          • After you update: next steps to success with Microsoft Dynamics CRM
          • Getting started
          • Manage security, users, and teams
          • Audit data and user activity
          • Customize your Dynamics 365 system
          • Manage configuration data
          • Manage product catalog configuration
          • Manage your data
          • Set up and manage phones and tablets
          • Integrate (synchronize) your email system with Microsoft Dynamics 365
          • Extend Dynamics 365 with integration and solutions
          • Microsoft Cognitive Services integration with Dynamics 365
          • Add interoperation features to Microsoft Dynamics 365 (online)
          • Add Office 365 Online services
        • Reporting & Analytics for Dynamics 365
          • Get started writing reports
          • Working with Microsoft Dynamics 365 reports
          • Working with SQL-based reports (Dynamics 365 on-premises only)
          • Test and troubleshoot reports
          • Publish reports
          • Report considerations and best practices
          • Example reports
          • Copy reports between Microsoft Dynamics 365 (on-premises) deployments
          • Customize Microsoft Dynamics 365 Power BI content packs
    • Dynamics 365 (on-premises)

Dynamics 365 for Operations Help Wiki

Dynamics 365 Help & Training

Dynamics 365 : Comment ajouter une instance de non-production

Il est possible d'ajouter des instances de Dynamics 365 pour vos environnements autres que Production. Pour ce faire, il faut cliquer sur Admin centers --> Dynamics 365


Par défaut, il y a déjà une instance Sandbox, mais elle n'est pas configuré. Cliquer sur l'instance et cliquer sur Configure


Sélectionner les applications que vous désirez dans votre nouvelle instance


Donner un nom à votre instance et taper une URL unique.


Sélectionner le groupe de sécurité et la langue et cliquer sur Configure



Après quelques secondes, l'instance est prête.