我们想写个job,去定期下载一些dataverse里的数据,但是Power Automate实现起来又不太方便,这个时候可以用Powershell去call dataverse的rest api去实现一些精细的操作。
注册一个Azure App Registration,并添加为对应dataverse环境的application user
一般来说,我们要调用一个微软体系的service的话,我们先要创建一个azure app registration,给这个auzre app registration赋权限,然后用这个作为token去和对应的service通信。
Azure App Registration我相信微软系的程序员应该已经很熟悉了,但是给它赋予dataverse的权限却不太常规,不在Azure Portal里操作,你得去Power Platform Admin Center里搞。 点开对应环境的Settings --> Application Users,在里面添加你注册的azure app registration。
(这个图还是旧版,现在power platform admin是新版了,但是菜单的路径都是一样的)
然后你得选Business unit,我对这个东西研究不多,默认的话一个环境就一个business unit, Security Role如果想权限大一点可以用System Customizer
这样我们的azure app registration就有dataverse权限了。
PowerShell里用client secret的方式去call dataverse rest api
目前好像没有好使的Powershell Dataverse Module, Dynamic365的Powershell好像只能运行在Powershell 5上面(现在都用Powershell 7了)。Github上有一些"野生"的Dataverse Powershell Module但我没找到比较好用的。所以我还是用最基本的Invoke-RestMethod方式去调用dataverse api
用rest api获取token
以前我去拿azure app registration的token都通过MSAL.PS的方式,但是人家已经"archived"了。
我好像也找不到封装好的powershell module去拿token,要自己写了。
假设你的azure app registration配置了client secret,你可以用以下命令去拿dataverse环境的token
(2025/7 现在我已经找到新的获取azure access token的类库了,下面再开一个章节分享给大家)
$tenantId = "{your tenant id}"
$clientId = "{your azure app registration client id}"
$clientSecret = "{client secret}"
$resource = "https://{your environment org name}.crm{x}.dynamics.com/.default"
$body = @{
grant_type = "client_credentials"
client_id = $clientId
client_secret = $clientSecret
scope = $resource
}
$response = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token
拿到的token差不多是这个样子的
用client secret方式获取token请求的具体信息可以看learn.microsoft.com/en-us/entra…
注意crmx好像取决于你powerplatform environment的区域,我east asia是crm5,我网上抄的一个版本是crm4,结果跑不起来。
用Azure Powershell获取token
我一开始做这个task的时候没有找到合适的powershell sdk类库,用纯粹的rest api来拿token,结果搞不定azure app registration用证书来做credential这种情况。后来我发现用Azure PowerShell就可以搞定token。
我们这里主要用Azure Powershell里的Az.Accounts Module。 在PowerShell 7里装完Azure PowerShell后(具体安装可以看官网),我们可以用Connect-AzAccount这个命令来连azure
下面例子就是根据证书的thumbprint(你把证书导入到azure app registration就能看到这个)
$Thumbprint = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
$TenantId = 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyy'
$ApplicationId = '00000000-0000-0000-0000-00000000'
Connect-AzAccount -CertificateThumbprint $Thumbprint -ApplicationId $ApplicationId -Tenant $TenantId -ServicePrincipal
你要是想用client secret的话稍微有点麻烦
你要先把client secret转化成一个SecurePassword
$SecurePassword = ConvertTo-SecureString -String "your-client-secret" -AsPlainText -Force
然后再用client id(application id)和这个SecurePassword生成一个credential
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $SecurePassword
最后
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential
连上了之后就要拿token,获取token的时候照例我们是要告诉它我们需要的scope的,在Azure PowerShell里这个scope是ResourceUrl这个参数。ResourceUrl不用加/.default这个后缀,Azure Powershell运行的时候会自动帮你补上的
$envUrl="https://{your environment org name}.crm{x}.dynamics.com"
$token= Get-AzAccessToken -ResourceUrl $envUrl
拿到的token是个securestring,你要稍微处理一下才能用
ConvertFrom-SecureString $token.Token -AsPlainText
Dataverse Rest Api
有关dataverse rest api的详细文档可以看learn.microsoft.com/en-us/power…
需要特别说明的是,当你用rest api去访问dataverse的table时,需要用table名字的复数形式(比如要访问contact表,你要用contacts)
你可以直接在浏览器上测试api(先登入orgxxxxx.crmx.dynamics.com/ ,这样拿到了token,然后把rest api address黏贴到地址栏)
Call Rest Api
拿到了token之后,用以下代码就能调用dataverse api了(这里以获取contact数据为例子)
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
"OData-MaxVersion"="4.0"
"OData-Version"="4.0"
}
# Make the API call
Invoke-RestMethod -Uri "https://orgxxxx.crm5.dynamics.com/api/data/v9.2/contacts") -Headers $headers -Method Get