Unable to create a FileZilla/SFTP entry with Devolutions.PowerShell for DVLS
Hello,
I am currently migrating automation scripts from Remote Desktop Manager PowerShell to Devolutions.PowerShell for DVLS.
I managed to create SSH and Web entries using New-DSEntryBase. Now, I am trying to automatically create FileZilla SFTP entries using New-DSEntryBase.
I successfully create the entry in DVLS, but when opening it from the Web UI or from RDM app, the entry is incomplete. There is no host, no username, no password...
What I already tested:
However, exported FileZilla entries seem incomplete:
I also tried using New-DSEntryBase -FromRDMConnection and integrate the input configuration that is used in my functional RDM PowerShell script but it fails because the cmdlet expects:
Devolutions.RemoteDesktopManager.Business.Entities.ConnectionInfoEntity
while New-RDMSession returns:
RemoteDesktopManager.PowerShellModule.PSOutputObject.PSConnection
My goal is to fully automate the creation of FileZilla SFTP entries in DVLS from PowerShell.
Could you please provide:
Thank you.
Here is my non-functional JSON configuration :
$body = @{
name = "SFTP - Test 01"
group = "FOLDER01"
vaultID = "00000000-0000-0000-0000-000000000000"
connectionType = "9"
data = @{
host = "10.1.1.1"
username = "sftpuser"
protocol = 1
passwordItem = @{
sensitiveData = "MyPassword123!"
}
}
}Hello dsi1,
Thank you for contacting the Devolutions support team.
We do not recommend creating FileZilla/SFTP entries by manually inventing a New-DSEntryBase -JsonBody schema.
FileZilla is an add-on/provider-style entry, and the provider-specific data is not reliably represented by simple fields such as data.host or data.username.
Since you want to use DS cmdlets only, the supported workaround is to create one valid FileZilla entry as a template, retrieve it with Get-DSEntry -AsRDMConnection, modify the returned ConnectionInfoEntity, and then create the new entry with New-DSEntryBase -FromRDMConnection.
This avoids the New-RDMSession / PSConnection mismatch and preserves the FileZilla-specific internal fields.
Here is a script template to use.
Note that I didn't test this script, and I suggest trying it in a test vault or a test environment before executing it for the production database.
#requires -Modules Devolutions.PowerShell
function ConvertTo-PlainText {
param(
[Parameter(Mandatory)]
[System.Security.SecureString] $SecureString
)
$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
try {
[Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
}
finally {
if ($bstr -ne [IntPtr]::Zero) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
}
}
}
function Set-NotePropertyValue {
param(
[Parameter(Mandatory)]
[object] $InputObject,
[Parameter(Mandatory)]
[string] $Name,
[Parameter(Mandatory)]
[AllowNull()]
[object] $Value
)
if ($InputObject.PSObject.Properties[$Name]) {
$InputObject.$Name = $Value
}
else {
$InputObject | Add-Member -MemberType NoteProperty -Name $Name -Value $Value -Force
}
}
function New-DSFileZillaSftpEntry {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[guid] $TemplateEntryId,
[Parameter(Mandatory)]
[guid] $VaultId,
[Parameter(Mandatory)]
[string] $Name,
[Parameter(Mandatory)]
[string] $Group,
[Parameter(Mandatory)]
[string] $HostName,
[Parameter(Mandatory)]
[string] $Username,
[Parameter(Mandatory)]
[System.Security.SecureString] $Password
)
# 1. Fetch an existing working FileZilla entry as a full RDM connection entity.
$connection = Get-DSEntry `
-EntryId $TemplateEntryId `
-VaultID $VaultId `
-AsRDMConnection
if (-not $connection) {
throw "Template entry '$TemplateEntryId' was not found."
}
if (-not $connection.PSObject.Properties['AddOn'] -or -not $connection.AddOn) {
throw "The template entry does not expose AddOn settings. Use a working FileZilla AddOn entry as the template."
}
# 2. Modify the full connection object.
$connection.Name = $Name
$connection.Group = $Group
# Keep the template's ConnectionType and ConnectionSubType.
# For FileZilla AddOn entries, ConnectionSubType must remain the FileZilla add-on identifier.
$connection.AddOn.Host = $HostName
$connection.AddOn.Username = $Username
# If the object exposes a repository/vault property, keep it aligned.
foreach ($propertyName in @('RepositoryID', 'RepositoryId', 'VaultID', 'VaultId')) {
if ($connection.PSObject.Properties[$propertyName]) {
$connection.$propertyName = $VaultId
break
}
}
# 3. Create the new entry using DS cmdlet only.
$createdConnection = New-DSEntryBase -FromRDMConnection $connection
$createdEntryId = $createdConnection.ID
if (-not $createdEntryId) {
$createdEntryId = $createdConnection.Id
}
if (-not $createdEntryId) {
throw "The entry was created, but the new entry ID could not be resolved from the returned object."
}
# 4. Update the password using DS JSON update pattern.
# Update-DSEntryBase documentation shows password updates through data.passwordItem.SensitiveData.
$plainPassword = ConvertTo-PlainText -SecureString $Password
try {
$createdEntry = Get-DSEntry -EntryId $createdEntryId -VaultID $VaultId
if (-not $createdEntry.PSObject.Properties['data'] -or -not $createdEntry.data) {
throw "The created entry does not expose a data object through Get-DSEntry."
}
if (-not $createdEntry.data.PSObject.Properties['passwordItem'] -or -not $createdEntry.data.passwordItem) {
Set-NotePropertyValue -InputObject $createdEntry.data -Name 'passwordItem' -Value ([pscustomobject]@{})
}
Set-NotePropertyValue `
-InputObject $createdEntry.data.passwordItem `
-Name 'SensitiveData' `
-Value $plainPassword
$jsonBody = $createdEntry | ConvertTo-Json -Depth 25
Update-DSEntryBase -JsonBody $jsonBody | Out-Null
}
finally {
$plainPassword = $null
}
# 5. Return the created entry.
Get-DSEntry -EntryId $createdEntryId -VaultID $VaultId
}
# Example usage
$password = Read-Host "SFTP password" -AsSecureString
New-DSFileZillaSftpEntry `
-TemplateEntryId '11111111-1111-1111-1111-111111111111' `
-VaultId '00000000-0000-0000-0000-000000000000' `
-Name 'SFTP - Test 01' `
-Group 'FOLDER01' `
-HostName '10.1.1.1' `
-Username 'sftpuser' `
-Password $password
Best regards,
Patrick Ouimet
Sorry, but it's not working. I'm getting almost no value from the template entry. In particular, there's no "AddOn" property. I only get :
Just to reiterate, I can create the entry, but it doesn't contain some of the data I need: