VMware Digital Workspace Community
vcelestino
Contributor
Contributor
Jump to solution

syncml, CSP, and registry. Oh my.

Good afternoon community.

New guy here. Just reaching out to see if anyone has had experience or can even provide some good resources for SyncML XML Syntax. My challenge is to replace a registry item WebValue located at HKLM\Software\App1.

I took the code from an existing profile

<wap-provisioningdoc id="b046b0ed-0c4c-4161-8075-b73efa3f1053" name="customprofile">/
<characteristic type="com.airwatch.winrt.registryoperation" uuid="731b71e2-a938-4d7f-98f6-1abdca4d4b5a">
<parm RegistryPath="HKLM\SOFTWARE\App1" Action="Replace">
<Value Name="WebValue" Data="1" Type="DWORD" />
</parm>
</characteristic>
</wap-provisioningdoc>

I can modify it ok for my needs, but just seeing if there are other sorts of resources that you've come across that can help expand my knowledge how this works.

So far these have helped me:

Configuration service provider reference - Windows Client Management | Microsoft Docs

Understanding Windows Group Policies: VMware Workspace ONE Operational Tutorial | VMware

But just seeing if there are other sources of information I may not be aware of.

Thanks in advance!

Reply
0 Kudos
1 Solution

Accepted Solutions
AaronWhittaker
Enthusiast
Enthusiast
Jump to solution

I gave up on trying to do regkeys via CSPs and converted to PowerShell commands. I found this script somewhere on the internet, forget where, but it converts a PowerShell file to a profile. I have only had a few issues since, the biggest one being that it's a custom setting so as long as the profile has been accepted by the device, it will be marked as 'installed' in the console, even if the script failed. And also, because its a profile, if the user then manually changes the setting after, it wont reapply. For that you need a baseline.

param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$false,HelpMessage="PowerShell Script Path")][String] $FilePath,
    [Parameter(Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Architecture")][ValidateSet('32','64')][Int] $Arch
)

if (Test-Path -Path $FilePath )
{
    $Base64Script = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-content -Path $FilePath -Raw)))
}
else {
    Write-Error -Message "File doesn't exist." -ErrorAction Stop
    Exit
}

if ( $Arch -eq 32)
{
    $CommandLine = "powershell -EncodedCommand " + $Base64Script
}
else {
    $CommandLine = "&`$env:SystemRoot\sysnative\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand " + $Base64Script
}

if ($CommandLine.Length -gt 32767 )
{
    Write-Error -Message "Command line is greater then 32767 characters which the maximum for Windows. " -ErrorAction Stop
    Exit
}

[XML] $WapProfile = '<wap-provisioningdoc id="" name="customprofile"><characteristic type="com.airwatch.winrt.powershellcommand" uuid=""><parm name="PowershellCommand" value=""/></characteristic></wap-provisioningdoc>'

#Generating a new GUID for the profile
Write-Debug -Message "Generating New GUIDs"
$WapProfile.'wap-provisioningdoc'.id = [GUID]::NewGuid().ToString()
$WapProfile.'wap-provisioningdoc'.characteristic.uuid = [GUID]::NewGuid().ToString()

#Adding Command Line
Write-Debug -Message "Adding Command Line"
$WapProfile.'wap-provisioningdoc'.characteristic.parm.value = $CommandLine

#Exporting XML to File
Write-Debug -Message "Writing file"
try {
    $FileDirectory = (Get-Item -Path $FilePath).Directory.ToString()
    $XmlFileName = "PSProfile-{0:yyyyMMdd-HHmmss}.xml" -f (Get-Date)
    $XmlFilePath = $FileDirectory + "\" + $XmlFileName
    [System.Xml.XmlWriterSettings] $XmlSettings = New-Object System.Xml.XmlWriterSettings
    #Preserve Windows formating
    $XmlSettings.Indent = $true
    $XmlSettings.OmitXmlDeclaration = $true
    #Keeping UTF-8 without BOM
    $XmlSettings.Encoding = New-Object System.Text.UTF8Encoding($false)
    [System.Xml.XmlWriter] $XmlWriter = [System.Xml.XmlWriter]::Create($XmlFilePath, $XmlSettings)
    $WapProfile.Save($XmlWriter)
}
catch
{
    Write-Debug -Message "Error Catched"
    Write-Error "XML Writing Error"
    Write-Error -Message $Error[0]
}
finally
{
    if ($XmlWriter -ne $null)
    {
        Write-Debug -Message "Clearing"
        $XmlWriter.Dispose()
    }
}

 

And make sure that the Target is 'Workspace ONE Intelligence Hub' and that the commands are not atomic. Hope that helps

View solution in original post

5 Replies
AaronWhittaker
Enthusiast
Enthusiast
Jump to solution

I gave up on trying to do regkeys via CSPs and converted to PowerShell commands. I found this script somewhere on the internet, forget where, but it converts a PowerShell file to a profile. I have only had a few issues since, the biggest one being that it's a custom setting so as long as the profile has been accepted by the device, it will be marked as 'installed' in the console, even if the script failed. And also, because its a profile, if the user then manually changes the setting after, it wont reapply. For that you need a baseline.

param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$false,HelpMessage="PowerShell Script Path")][String] $FilePath,
    [Parameter(Mandatory=$true,ValueFromPipeline=$false,HelpMessage="Architecture")][ValidateSet('32','64')][Int] $Arch
)

if (Test-Path -Path $FilePath )
{
    $Base64Script = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-content -Path $FilePath -Raw)))
}
else {
    Write-Error -Message "File doesn't exist." -ErrorAction Stop
    Exit
}

if ( $Arch -eq 32)
{
    $CommandLine = "powershell -EncodedCommand " + $Base64Script
}
else {
    $CommandLine = "&`$env:SystemRoot\sysnative\WindowsPowerShell\v1.0\powershell.exe -EncodedCommand " + $Base64Script
}

if ($CommandLine.Length -gt 32767 )
{
    Write-Error -Message "Command line is greater then 32767 characters which the maximum for Windows. " -ErrorAction Stop
    Exit
}

[XML] $WapProfile = '<wap-provisioningdoc id="" name="customprofile"><characteristic type="com.airwatch.winrt.powershellcommand" uuid=""><parm name="PowershellCommand" value=""/></characteristic></wap-provisioningdoc>'

#Generating a new GUID for the profile
Write-Debug -Message "Generating New GUIDs"
$WapProfile.'wap-provisioningdoc'.id = [GUID]::NewGuid().ToString()
$WapProfile.'wap-provisioningdoc'.characteristic.uuid = [GUID]::NewGuid().ToString()

#Adding Command Line
Write-Debug -Message "Adding Command Line"
$WapProfile.'wap-provisioningdoc'.characteristic.parm.value = $CommandLine

#Exporting XML to File
Write-Debug -Message "Writing file"
try {
    $FileDirectory = (Get-Item -Path $FilePath).Directory.ToString()
    $XmlFileName = "PSProfile-{0:yyyyMMdd-HHmmss}.xml" -f (Get-Date)
    $XmlFilePath = $FileDirectory + "\" + $XmlFileName
    [System.Xml.XmlWriterSettings] $XmlSettings = New-Object System.Xml.XmlWriterSettings
    #Preserve Windows formating
    $XmlSettings.Indent = $true
    $XmlSettings.OmitXmlDeclaration = $true
    #Keeping UTF-8 without BOM
    $XmlSettings.Encoding = New-Object System.Text.UTF8Encoding($false)
    [System.Xml.XmlWriter] $XmlWriter = [System.Xml.XmlWriter]::Create($XmlFilePath, $XmlSettings)
    $WapProfile.Save($XmlWriter)
}
catch
{
    Write-Debug -Message "Error Catched"
    Write-Error "XML Writing Error"
    Write-Error -Message $Error[0]
}
finally
{
    if ($XmlWriter -ne $null)
    {
        Write-Debug -Message "Clearing"
        $XmlWriter.Dispose()
    }
}

 

And make sure that the Target is 'Workspace ONE Intelligence Hub' and that the commands are not atomic. Hope that helps

vcelestino
Contributor
Contributor
Jump to solution

This definitely helps. Thanks for the recommendation. Now that you mention PowerShell, maybe even a sensor will be able to accomplish this task. This way, I can return values if it fails or succeed.

Something about toolsets like this, there are multiple ways to skin this cat.

Cheers!

Reply
0 Kudos
Phil_Helmling
VMware Employee
VMware Employee
Jump to solution

There are many ways to do this, which is a good thing and a bad thing 😉

I like the script Aaron suggested, and it could certainly help. Here is a repo with a bunch of example profiles to do stuff in the registry, ADMX etc - https://github.com/helmlingp/WS1UEM_Profiles

Phil

Reply
0 Kudos
JoelBarrett2
Contributor
Contributor
Jump to solution

Have you tried using https://vmwarepolicybuilder.com/ ?

This site lets you build SyncML directly from the MS CSPs. Then you can cut and paste it into a Custom Settings profile in UEM.

Hope that helps,

Joel

 

--
Joel Barrett
Staff Solution Engineer
EUC C1 Team
VMware, Inc.
Reply
0 Kudos
JoelBarrett2
Contributor
Contributor
Jump to solution

To follow-up on the VMwarePolicyBuilder.com tool. When you go into the tool, if you select one of the many available CSPs, all you have to do to get the SycnML scripts to show up is to type something in an open field of the CSP. Then the SyncML code will show up on the right side of the screen. You can copy and paste that code into your Custom Settings profile in UEM. 

--
Joel Barrett
Staff Solution Engineer
EUC C1 Team
VMware, Inc.
Reply
0 Kudos