如何在Powershell里调用dataverse api

115 阅读2分钟

我们想写个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。

image.png (这个图还是旧版,现在power platform admin是新版了,但是菜单的路径都是一样的)

然后你得选Business unit,我对这个东西研究不多,默认的话一个环境就一个business unit, Security Role如果想权限大一点可以用System Customizer

image.png

这样我们的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"了。

image.png

我好像也找不到封装好的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差不多是这个样子的 image.png

用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

image.png 你要是想用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

image.png

Dataverse Rest Api

有关dataverse rest api的详细文档可以看learn.microsoft.com/en-us/power…

需要特别说明的是,当你用rest api去访问dataverse的table时,需要用table名字的复数形式(比如要访问contact表,你要用contacts

image.png

你可以直接在浏览器上测试api(先登入orgxxxxx.crmx.dynamics.com/ ,这样拿到了token,然后把rest api address黏贴到地址栏)

image.png

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