onsdag den 15. januar 2014

Managing CRM 2011 and 2013

I fixed a series of bugs and tested my CRM powershell module against both 2011 and 2013. Enjoy.

PSCRM.zip

Add-CRMRoleMember
Disable-CrmLanguage
Disable-CrmOrganization
Disable-CRMSystemUser
Enable-CrmLanguage
Enable-CrmOrganization
Enable-CRMSystemUser
Get-CrmAvailableLanguage
Get-CrmLanguage
Get-CrmOrganization
Get-CRMRole
Get-CRMSystemUser
Get-CRMSystemUserSettings
Get-CrmUsermappingFile
Import-CrmOrganization
New-CrmConfig
New-CRMCustomerAdminRole
New-CrmOrganization
New-CRMSystemUser
Remove-CrmOrganization
Remove-CRMRole
Remove-CRMRoleMember
Remove-CRMSystemUser
Select-CrmOrganization
Set-CRMSystemUser
Set-CRMSystemUserSettings

tirsdag den 14. januar 2014

Microsoft Dynamics Nav 2013 goodies

One of the cool things about Nav 2013 is the ClickOnce deployment. Running Nav in a multi Tenant depoyment with many customers can make this a bit of a headache. First of all you need several deployments, one for each customer (seems stupid when all you need is a different ClientUserSettings.config ( maybe we could create a iis module or something to handle this ? ) anyway, for now lets keep it like that. Next if you read this page they promise us gold in the form of having several installations at the same computer. That will not work following microsofts guide thou, you need to have different assemblyIdentity names for that to work. Thank god we have powershell …

 

$baseclientpath = 'C:\NAV2013R2\Install\RoleTailoredClient\program files\Microsoft Dynamics NAV\71\RoleTailored Client\'
$baseclientcommonpath = 'C:\NAV2013R2\Install\RoleTailoredClient\CommonAppData\Microsoft\Microsoft Dynamics NAV\71\'
$templatepath = 'C:\NAV2013R2\Install\ClickOnceInstallerTools\Program Files\Microsoft Dynamics NAV\71\ClickOnce Installer Tools\TemplateFiles\'
$clickoneroot = "C:\inetpub\wwwroot\ClickOnce\$tenantid\"
$clickoneDeployment = "$($clickoneroot)Deployment\"
$clickoneApp = "$($clickoneroot)Deployment\ApplicationFiles\"

#if ( (Test-Path $clickoneroot) -ne $true) {
Copy-Item $templatepath $clickoneroot -recurse -force

if ( (Test-Path "$($clickoneroot)default.html") -ne $true) {
Copy-Item "$($clickoneroot)NAVClientInstallation.html" "$($clickoneroot)default.html"
}

Write-Host "Remove Nav ClickOnce Client Application"
if ( (Test-Path $clickoneApp) -eq $true) { Remove-Item $clickoneApp -force -recurse }
Write-Host "Copy fresh Nav ClickOnce Client Application"
Copy-Item $baseclientpath $clickoneApp -recurse -force

Write-Host "Copy fresh templates"
Copy-Item "$($templatepath)Deployment\ApplicationFiles\Microsoft.Dynamics.Nav.Client.exe.manifest" $clickoneApp
Copy-Item "$($templatepath)Deployment\ApplicationFiles\Icon.ico" $clickoneApp
Copy-Item "$($templatepath)Deployment\Microsoft.Dynamics.Nav.Client.application" $clickoneDeployment
Copy-Item "$($baseclientcommonpath)ClientUserSettings.config" $clickoneApp


Write-Host "Remove OpenXml and ReportLayout"
Remove-Item "$($clickoneApp)Add-ins\OpenXml" -recurse -force
Remove-Item "$($clickoneApp)ReportLayout" -recurse -force
Remove-Item "$($clickoneApp)Finhlink.exe" -force
Remove-Item "$($clickoneApp)finsql.exe" -force
Remove-Item "$($clickoneApp)finsql.exe.config" -force

Write-Host "Update ClientUserSettings"
$xml = [xml](Get-Content "$($clickoneApp)ClientUserSettings.config")
($xml.configuration.appSettings.add | ?{$_.key -eq 'Server'}).value = $alternateId
($xml.configuration.appSettings.add | ?{$_.key -eq 'ClientServicesPort'}).value = $ClientServicesPort.ToString()
($xml.configuration.appSettings.add | ?{$_.key -eq 'ServerInstance'}).value = $navinstancename
($xml.configuration.appSettings.add | ?{$_.key -eq 'TenantId'}).value = $tenantid
($xml.configuration.appSettings.add | ?{$_.key -eq 'ClientServicesCredentialType'}).value = 'UserName'
($xml.configuration.appSettings.add | ?{$_.key -eq 'DnsIdentity'}).value = $navcertificatesubject
($xml.configuration.appSettings.add | ?{$_.key -eq 'HelpServer'}).value = $helpserver
($xml.configuration.appSettings.add | ?{$_.key -eq 'HelpServerPort'}).value = $helpserverport
($xml.configuration.appSettings.add | ?{$_.key -eq 'ProductName'}).value = $tenantproductname
$xml.Save("$($clickoneApp)ClientUserSettings.config")

$manifestfile = "$($clickoneApp)Microsoft.Dynamics.Nav.Client.exe.manifest"
$applicationfile = "$($clickoneDeployment)Microsoft.Dynamics.Nav.Client.application"
$baseclickoneurl = "https://$alternateId/ClickOnce/$tenantid"
$manifesturl = "$($baseclickoneurl)/Deployment/ApplicationFiles/Microsoft.Dynamics.Nav.Client.exe.manifest"
$codebaseurl = "$($baseclickoneurl)/Deployment/Microsoft.Dynamics.Nav.Client.application"

Write-Host "Update manifest file"
$xml = [xml](Get-Content $manifestfile)
$xml.assembly.assemblyIdentity.name = "Microsoft.Dynamics.Nav.$tenantid" # Microsoft.Dynamics.Nav.ClickOnceClient
$xml.assembly.assemblyIdentity.version = $clientversion
$xml.Save($manifestfile)

Write-Host "Update application file"
$xml = [xml](Get-Content $applicationfile)
$xml.assembly.description.publisher = 'Microsoft Corporation and Proinfo A/S'
$xml.assembly.description.product = $tenantproductname
$xml.assembly.assemblyIdentity.name = $tenantproductname
$xml.assembly.deployment.deploymentProvider.codebase = $codebaseurl
$xml.assembly.assemblyIdentity.version = $clientversion
$xml.assembly.dependency.dependentAssembly.assemblyIdentity.name = "Microsoft.Dynamics.Nav.$tenantid"
$xml.Save($applicationfile)


& C:\NAV2013R2\mage\mage.exe -Update $manifestfile -FromDirectory $clickoneApp

& C:\NAV2013R2\mage\mage.exe -update $applicationfile -appmanifest $manifestfile -appcodebase $manifesturl
Write-Host "Microsoft Dynamics Nav 2013 for $tenantid published at https://$alternateId/ClickOnce/$tenantid"
#}