Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Hi,
We started using the .net SDK in combination with the Qlik-Cli for Windows version for deploying apps to multiple streams.
For every stream we would like to change some variables in the Data load editor. Is that possible with the SDK? I found some options for changing the script with the engine JSON api but not with the SDK.
We have these 3 variables that we use to connect databases, we would like to change for every stream:
let CustomerName = 'CustomerA'
let DWH_CustomerName = 'DWH_CustomerA'
let Source_CustomerName = 'Source_CustomerA'
Would it be possible to search and replace these variable values in the load script?
Kind Regards
this can be achieved in PowerShell too, but takes a little setup first.
First you need to download and Extract the QlikSense.NetSDK from the following
https://www.nuget.org/packages/QlikSense.NetSDK
as well as a Version 6.0.x of Newtonsoft.json.
https://www.nuget.org/packages/Newtonsoft.Json/6.0.1
once you have extracted both, you will need to update the following to the correct locations.
add-type -path "D:\Extracted\Nuget\packages\newtonsoft.json\6.0.1\lib\net45\Newtonsoft.Json.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Engine.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.JsonRpc.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.Client.dll"
Once these "Add-Type" commands have been run, we can access the QlikSese.NetSDK C# Objects in PowerShell.
The Following will need the SenseServerURL updated to reflect the environment you wish to connect to and when run will prompt for Credentials to use to establish the NTLMViaProxy connection.
$SenseServerURL = "https://sense01"
$QlikCeredentials = Get-Credential
$ProxyUsesSSL = $true
$TrustAllCerts = $true
#Create the Location Object
$Location = [Qlik.Engine.Location]::FromUri($SenseServerURL)
#Establish a Authenticated Session to the Location.
[Qlik.Engine.LocationExtensions]::AsNtlmUserViaProxy($Location,$ProxyUsesSSL,$QlikCeredentials,$TrustAllCerts)
once the authenticated connection has been established you can then use the Location object for the subsequent requests, such as Getting the AppIdentifier for the App you want to update the Script on.
#Get All App Identifiers
$AppIdentifiers = [Qlik.Engine.LocationExtensions]::GetAppIdentifiers($Location)
#Get App Identifiers for Apps With a Specific name
$AppIdentifiersByName = [Qlik.Engine.LocationExtensions]::AppsWithNameOrDefault($Location,"Operations Monitor")
#Get App Identifier for App With a Specific ID
$AppID = "39beb78d-ddc4-4346-8023-92c023851385"
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($Location,$AppID)
once you have the AppIdentifier you can get the Qlik Engine App
$Session = $null
$NoData = $true
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location,$AppIdentifiersByID,$Session,$NoData)
Once you have the Qlik Engine app you can then call the GetScript() and SetScript("ScriptString") Methods.
obviously this is just an example, and you can adapt the UpdatedAppScript sent back as required.
#Once we have the App we can Get the Load Script
$AppScript = $QEApp.GetScript()
#WE can them manipulate the Load Scripts
$UpdatedAppScript = $AppScript -replace "ValueToReplace","ReplacedWith"
#and finally update the app with the new Load script
$QEApp.SetScript($UpdatedAppScript)
To extend this a little further you can use Qlik-CLI-Windows to get information from the QRS to get Apps published to a specific stream, then use that information to get the AppIdentifier and then the Qlik Engine App.
#Example.
#You can use Qlik-CLI-Windows to get all of the APPIDs for apps published to a specific stream
$QRSAppsByStream = Get-QlikApp -filter "Stream.Name eq 'Everyone'"
#Then for each app in the stream we can get the AppIdentifier and App
$QEApps = ForEach ($QRSApp in $QRSAppsByStream){
$AppID = $QRSApp.Id
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($Location,$AppID)
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location,$AppIdentifiersByID,$null,$true)
$QEApp
}
And finally putting it altogether.
We use the Qlik-CLI-Windows to get all the apps in the Everyone stream
Then we cycle through each of them getting the AppIdentifier and Qlik Engine App, Getting the Script for each and manipulating it by replacing "ValueToReplace" with "ReplacedWith"
#Qlik-CLI-Windows
$StreamName = "Everyone"
Connect-Qlik -TrustAllCerts
$QRSAppsByStream = Get-QlikApp -filter "Stream.Name eq '$StreamName'"
#QlikSense.NetSDK
add-type -path "D:\Extracted\Nuget\packages\newtonsoft.json\6.0.1\lib\net45\Newtonsoft.Json.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Engine.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.JsonRpc.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.Client.dll"
$SenseServerURL = "https://sense01"
$QlikCeredentials = Get-Credential
$ProxyUsesSSL = $true
$TrustAllCerts = $true
$Location = [Qlik.Engine.Location]::FromUri($SenseServerURL)
[Qlik.Engine.LocationExtensions]::AsNtlmUserViaProxy($Location,$ProxyUsesSSL,$QlikCeredentials,$TrustAllCerts)
$Session = $null
$NoData = $true
$QEApps = ForEach ($QRSApp in $QRSAppsByStream){
$AppID = $QRSApp.Id
#Get the AppIdentifier
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($Location,$AppID)
#Get the QEApp
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location,$AppIdentifiersByID,$Session,$NoData)
#Once we have the App we can Get the Load Script
$AppScript = $QEApp.GetScript()
#We can them manipulate the Load Scripts
$UpdatedAppScript = $AppScript -replace "ValueToReplace","ReplacedWith"
#and finally update the app with the new Load script
$QEApp.SetScript($UpdatedAppScript)
}
Yes, certainly. All endpoints available in the engine JSON API are also exposed in the SDK. In your case it's just a matter of doing a combination of "GetScript" and "SetScript" like this:
var script = app.GetScript();
var newScript = ...do changes to script...
app.SetScript(newScript);
And then you're likely to want to finish it up with a "DoReload" to refresh the app data based on your script modifications:
app.DoReload();
this can be achieved in PowerShell too, but takes a little setup first.
First you need to download and Extract the QlikSense.NetSDK from the following
https://www.nuget.org/packages/QlikSense.NetSDK
as well as a Version 6.0.x of Newtonsoft.json.
https://www.nuget.org/packages/Newtonsoft.Json/6.0.1
once you have extracted both, you will need to update the following to the correct locations.
add-type -path "D:\Extracted\Nuget\packages\newtonsoft.json\6.0.1\lib\net45\Newtonsoft.Json.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Engine.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.JsonRpc.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.Client.dll"
Once these "Add-Type" commands have been run, we can access the QlikSese.NetSDK C# Objects in PowerShell.
The Following will need the SenseServerURL updated to reflect the environment you wish to connect to and when run will prompt for Credentials to use to establish the NTLMViaProxy connection.
$SenseServerURL = "https://sense01"
$QlikCeredentials = Get-Credential
$ProxyUsesSSL = $true
$TrustAllCerts = $true
#Create the Location Object
$Location = [Qlik.Engine.Location]::FromUri($SenseServerURL)
#Establish a Authenticated Session to the Location.
[Qlik.Engine.LocationExtensions]::AsNtlmUserViaProxy($Location,$ProxyUsesSSL,$QlikCeredentials,$TrustAllCerts)
once the authenticated connection has been established you can then use the Location object for the subsequent requests, such as Getting the AppIdentifier for the App you want to update the Script on.
#Get All App Identifiers
$AppIdentifiers = [Qlik.Engine.LocationExtensions]::GetAppIdentifiers($Location)
#Get App Identifiers for Apps With a Specific name
$AppIdentifiersByName = [Qlik.Engine.LocationExtensions]::AppsWithNameOrDefault($Location,"Operations Monitor")
#Get App Identifier for App With a Specific ID
$AppID = "39beb78d-ddc4-4346-8023-92c023851385"
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($Location,$AppID)
once you have the AppIdentifier you can get the Qlik Engine App
$Session = $null
$NoData = $true
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location,$AppIdentifiersByID,$Session,$NoData)
Once you have the Qlik Engine app you can then call the GetScript() and SetScript("ScriptString") Methods.
obviously this is just an example, and you can adapt the UpdatedAppScript sent back as required.
#Once we have the App we can Get the Load Script
$AppScript = $QEApp.GetScript()
#WE can them manipulate the Load Scripts
$UpdatedAppScript = $AppScript -replace "ValueToReplace","ReplacedWith"
#and finally update the app with the new Load script
$QEApp.SetScript($UpdatedAppScript)
To extend this a little further you can use Qlik-CLI-Windows to get information from the QRS to get Apps published to a specific stream, then use that information to get the AppIdentifier and then the Qlik Engine App.
#Example.
#You can use Qlik-CLI-Windows to get all of the APPIDs for apps published to a specific stream
$QRSAppsByStream = Get-QlikApp -filter "Stream.Name eq 'Everyone'"
#Then for each app in the stream we can get the AppIdentifier and App
$QEApps = ForEach ($QRSApp in $QRSAppsByStream){
$AppID = $QRSApp.Id
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($Location,$AppID)
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location,$AppIdentifiersByID,$null,$true)
$QEApp
}
And finally putting it altogether.
We use the Qlik-CLI-Windows to get all the apps in the Everyone stream
Then we cycle through each of them getting the AppIdentifier and Qlik Engine App, Getting the Script for each and manipulating it by replacing "ValueToReplace" with "ReplacedWith"
#Qlik-CLI-Windows
$StreamName = "Everyone"
Connect-Qlik -TrustAllCerts
$QRSAppsByStream = Get-QlikApp -filter "Stream.Name eq '$StreamName'"
#QlikSense.NetSDK
add-type -path "D:\Extracted\Nuget\packages\newtonsoft.json\6.0.1\lib\net45\Newtonsoft.Json.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Engine.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.JsonRpc.dll"
add-type -path "D:\Extracted\Nuget\packages\qliksense.netsdk\15.1.1\lib\net452\Qlik.Sense.Client.dll"
$SenseServerURL = "https://sense01"
$QlikCeredentials = Get-Credential
$ProxyUsesSSL = $true
$TrustAllCerts = $true
$Location = [Qlik.Engine.Location]::FromUri($SenseServerURL)
[Qlik.Engine.LocationExtensions]::AsNtlmUserViaProxy($Location,$ProxyUsesSSL,$QlikCeredentials,$TrustAllCerts)
$Session = $null
$NoData = $true
$QEApps = ForEach ($QRSApp in $QRSAppsByStream){
$AppID = $QRSApp.Id
#Get the AppIdentifier
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($Location,$AppID)
#Get the QEApp
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location,$AppIdentifiersByID,$Session,$NoData)
#Once we have the App we can Get the Load Script
$AppScript = $QEApp.GetScript()
#We can them manipulate the Load Scripts
$UpdatedAppScript = $AppScript -replace "ValueToReplace","ReplacedWith"
#and finally update the app with the new Load script
$QEApp.SetScript($UpdatedAppScript)
}
Thanks a lot for the detailed explanation. I am trying to implement this, but I have one additional question.
I tried a reload of the data from the app, when I run:
$QEApp.DoReload()
When I run I get a response True but the app doesn't reload.
Do I need to run another command?
Thank you
Perhaps you need to do a "DoSave" as well?
if you call the DoReload method.
$QEApp.DoReload
you can see that it requires a number of overloads.
OverloadDefinitions
-------------------
bool DoReload(int mode, bool partial, bool debug)
we can find more information on what each of these is on the following DoReload method
$QEApp.DoReload(0,$False,$False)
however, you will notice in the "Returns" section of the DoReload method page.
If the data load has successfully finished, no matter how the indexing behaves, _true_ is returned. This happens even if there is a timeout, a memory limit is reached, or any other error occurs during the indexing.
With that in mind you, if your reload takes a while you may be hitting a timeout... so you may be better off using the DoReloadEx method as this will return a DoReloadExResult that contains a link to the ScriptLog file which may be useful in determining any errors.
$DoReloadExParams = [Qlik.Engine.DoReloadExParams]::new()
$QEApp.DoReloadEx($DoReloadExParams)
Alternatively.
if you used the sample script I provided where we leveraged Qlik-CLI to find the app, before using the QlikSense.NetSDK
you will have a variable called AppID.. which you can use this with the Qlik-CLI to run the Reload via the QRS.
Invoke-QlikPost -path "/qrs/app/$($AppId)/reload"
Hi Marc,
Thanks again for you reply.
Like I wrote earlier I am new to this, working with API's and Qlik-CLI.
So I have a couple of followup questions:
When I use this:
$DoReloadExParams = [Qlik.Engine.DoReloadExParams]::new()
$QEApp.DoReloadEx($DoReloadExParams)
What does that ::New() do?
The above command returns the outcome if it's true or false, that is really helpful for checking if the app was published correctly.
But it doesn't change the Lastreloadtime. Would that be possible? Or should we also run the invoke command to get that fixed? Because the invoke command updates the Lastreloadtime but doesn't give any information if the reload task was successful or not.
Again both Marc and yko thanks allot for your help!
Regards,
Hendri
$DoReloadExParams = [Qlik.Engine.DoReloadExParams]::new()
This creates a new .net object of the type DoReloadExParams (same as New-Object Qlik.Engine.DoReloadExParams)
you can view the object by running the variable $DoReloadExParams by itself.
this object type is a input requirement for the Method DoReloadEx.
$QEApp.DoReloadEx($DoReloadExParams)
performing the reload in this method will cause the app to reload and this will be visible in the apps last reload time.
however it does not update the LastReloadTime in the QMC as this is linked to the QRS Apis.
in order to see the updated time in both you will need to use the QRS Api to perform the reload rather then the DoReload method
Invoke-QlikPost -path "/qrs/app/$($AppId)/reload"
Thank again, I tried the reload but it didn't change the date/time of the reload, but I will use both to solve this.
Hi,
After creating a script for this to change a load script, I still hit an issue. When I reload the script with this code:
$computerName="qlik-test.xxx.xx"
$computerPort="4747"
$userDirectory="QLIK-TEST"
$userName="abc"
$uri = "wss://$($computerName):$($computerPort)"
$location = [Qlik.Engine.Location]::FromUri($uri)
[Qlik.Engine.LocationExtensions]::AsDirectConnection($location,$userDirectory,$userName)
$AppIdentifiersByID = [Qlik.Engine.LocationExtensions]::AppWithId($location,$newappToPublishid)
$QEApp = [Qlik.Engine.LocationExtensions]::App($location,$AppIdentifiersByID,$Session,$NoData)
$DoReloadExParams = [Qlik.Engine.DoReloadExParams]::new()
$QEApp.DoReloadEx($DoReloadExParams)
Invoke-QlikPost -path "/qrs/app/$($newAppToPublishId)/reload"
But when I put this in a loop to go through different apps and check if the reload is correct with the script that is stored when doing a reload. Everyting is working fine. But when I check the app, then I see that the reload didn't go correctly.
For example if I reload app A, and publish this to stream A then the first time it runs correct.
When i change App A to reload into another stream, say stream B then the change of app A is correct but when i reload the app to publish in stream B it still contains the information of stream A. But when I look in the script log file it should be correct, but when i check in the app it is not reloaded.
Any idea how to solve this?