Using Windows system variables in a SSIS Package (Visual Studio) - windows

I've created a Windows system variable called DATA_PATH which references to a path.
I'm trying to use it in a Flat File Connection Manager in Visual Studio like this: %DATA_PATH% or #[DATA_PATH], but it is not working.

Correct, you cannot make up syntax and expect it to work.
There are 4 approaches I can come up with to make use of a Windows environment variable in an SSIS package.
Use command line arguments
Use Configuration
Use a Script Task
Use Execute Process Task
My sample package looks like the following + a Project Parameter named ScalaHome data type of string and initialized to the same "NOT DEFINED"
Parameter/Variable via invocation
At run-time, you can specify the value of variables. For example, when I run this command
dtexec /file ./Order.dtsx /Set \Package.Variables[User::Counter].Properties[Value];3
It will run the Order package and initialize the value of my variable User::Counter to 3.
Extending that pattern, you can run your package and use your environment variable value to set a package value.
dtexec /file ./Order.dtsx /Set \Package.Variables[User::LocalPath].Properties[Value];%DATA_PATH%
If you're using parameters, the command would be something like
dtexec /package Order.dtsx /project ./MyProj.ispac /PAR "$Package::LocalPath";"%DATA_PATH%"
EXCEPT, that won't work because
The Parameter option can only be specified with the ISServer option.
So instead, even though there is a /parameter option, you need to use the /SET route. In this example, I'm going to reference my existing SCALA_HOME environment variable
Before
dtexec /proj C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\bin\Development\SO_Trash.ispac /pack SO_74786096.dtsx /rep eiw
Microsoft (R) SQL Server Execute Package Utility
Version 14.0.3456.2 for 32-bit
Copyright (C) 2017 Microsoft. All rights reserved.
Started: 8:54:58 AM
Info: 2022-12-13 08:52:58.86
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: $Project::ScalaHome:->NOT DEFINED
End Info
DTExec: The package execution returned DTSER_SUCCESS (0).
Started: 8:52:58 AM
Finished: 8:52:58 AM
Elapsed: 0.422 seconds
After
dtexec /proj C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\bin\Development\SO_Trash.ispac /pack SO_74786096.dtsx /rep eiw /SET \Package.Variables[$Project::ScalaHome];"%SCALA_HOME%"
Microsoft (R) SQL Server Execute Package Utility
Version 14.0.3456.2 for 32-bit
Copyright (C) 2017 Microsoft. All rights reserved.
Started: 8:53:14 AM
Info: 2022-12-13 08:53:15.15
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: $Project::ScalaHome:->C:\Program Files (x86)\scala
End Info
DTExec: The package execution returned DTSER_SUCCESS (0).
Started: 8:53:14 AM
Finished: 8:53:15 AM
Elapsed: 0.359 seconds
The development experience is a bit fiddly because even though you can specify CmdLineArguments, adding the same /SET \Package.Variables[$Project::ScalaHome];"%SCALA_HOME%" in there had no effect
Configurations
We're gonna go old-school here as this is no longer a favored method for handling configurations with the advent of the SSIS Catalog. But it still exists, it's just harder to access in the Project Deployment Model. Right-click on a package and select Property. Find the Configurations collection and click the ellipses ...
Check the "Enable Package Configurations" box
Click Add...
In the resulting wizard, pick your Configuration Type and find the Environment Variable
In the Next window, you need to set the target property, aka push that value into a local variable. Here I'm using User::ConfigValue and importantly I am expanding the Properties tree and selecting the Value
Give it a name
Ok and Close.
Now when you run it, you'll see 2 information messages. The first that it's trying to use config and the second will be our Script Task spitting out values.
Info: 2022-12-13 09:14:23.72
Code: 0x40016038
Source: SO_74786096
Description: The package is attempting to configure from the environment variable "SCALA_HOME".
End Info
Info: 2022-12-13 09:14:23.84
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: User::ConfigValue:->C:\Program Files (x86)\scala
End Info
Script Task
Add a read-write variable to the mix.
// Lazy approach and beware the lack of checking
public void Main()
{
var value = System.Environment.GetEnvironmentVariable("SCALA_HOME");
Dts.Variables[0].Value = value;
Dts.TaskResult = (int)ScriptResults.Success;
}
Reference answer for C# and accessing environment variables https://stackoverflow.com/a/185214/181965
Execute Process Task
Pop the value of the environment variable into an SSIS variable. The command I'll use is cmd.exe as the process. Arguments are /C echo %SCALA_HOME% Note that I'm routing the StandardOutput to my variable
Putting it all together
C:\Users\bfellows>dtexec /proj C:\Users\bfellows\source\repos\SO_Trash\SO_Trash\bin\Development\SO_Trash.ispac /pack SO_74786096.dtsx /rep eiw /SET \Package.Variables[$Project::ScalaHome];"%SCALA_HOME%"
Microsoft (R) SQL Server Execute Package Utility
Version 14.0.3456.2 for 32-bit
Copyright (C) 2017 Microsoft. All rights reserved.
Started: 9:25:32 AM
Info: 2022-12-13 09:25:32.27
Code: 0x40016038
Source: SO_74786096
Description: The package is attempting to configure from the environment variable "SCALA_HOME".
End Info
Info: 2022-12-13 09:25:32.48
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: User::ConfigValue:->C:\Program Files (x86)\scala
End Info
Info: 2022-12-13 09:25:32.48
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: User::EPTValue:->C:\Program Files (x86)\scala
End Info
Info: 2022-12-13 09:25:32.48
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: $Project::ScalaHome:->C:\Program Files (x86)\scala
End Info
Info: 2022-12-13 09:25:32.48
Code: 0x00000000
Source: SCR Echo Back SCR Echo Back
Description: User::SCRValue:->C:\Program Files (x86)\scala
End Info
DTExec: The package execution returned DTSER_SUCCESS (0).
Started: 9:25:32 AM
Finished: 9:25:32 AM
Elapsed: 0.469 seconds
Echo back script
My all purpose tester script. Pick the variables you want to have written to the Output window as ReadOnly variables.
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
namespace ST_710ef65337734ee281706ce24a9162f1
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
bool fireAgain = false;
foreach (Variable item in Dts.Variables)
{
Dts.Events.FireInformation(0, "SCR Echo Back", string.Format("{0}:->{1}", item.QualifiedName, item.Value), "", 0, ref fireAgain);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
Closing thoughts
The "right" answer is super dependent on you and your organization.
If you were engaging me as a consultant, I'd advise against trying to make use of the environment variable. I'd advise you to create a Project level parameter so that all packages can reference the same value. Then when deployed the SSIS catalog and promoted through the environments, I would use the Configuration section of the SSISDB to set the current value for your data path.
If you choose to go against the advice, the Script Task is the cleanest and most native approach but many organizations have silly commandments of Thou Shalt Not Use Script Task/Component in SSIS packages.
Old blog articles I referenced while assembling this answer
https://billfellows.blogspot.com/2008/09/ssis-configuration-precedence.html
https://billfellows.blogspot.com/2016/04/biml-script-task-test-for-echo.html

Related

Eanbling/Disabling preprocessor for VS C++ code compilation from command line

We are trying to compile our Qt + C++ code from command prompt using VS.
Qt version: 5.15.2 - msvc20129 compiler
VS: 2019 v16.8.4
OS: Windows 10
We are creating 2 versions of binary. One is to provide to the customer. And the second version is to generate a build for test automation team. To generate build for test automation team, we need to enable few additional lines in the source code, for which we are using some preprocessors. And the same needs to be disabled for customer build. To avoid code changes to enable and disable the preprocessor, we thought of doing it from the command prompt. And with some search on Google we learned about the CL option. Following are the steps we are following:
The code compilation is getting triggered from Jenkin's server. We are reading a check box state to enable or disable TA build from buld configuratoin page.
By default the preprocessor are disabled (not defined). So additional code for test automation, will be commented.
So if the checkbox in the build configuration page (of jenkin's server) is checked then we are passing a string "true" while executing the batch file. As follows:
call path/code_build.bat true
If the 1st argument received by the batch file is "true", we care calling the CL command to enable the preprocessor. As follows:
set CL=/DENABLE_TEST_AUTOMATION_FLAG
By putting echo statements, we can see that the first argument we are receiving is "true". And accordingly we are setting the test automation flag as follows.
echo --------------------------------- Build - Release -----------------------------------
echo command line argument %1
if "%1%"=="true" (
echo --------------------------------- ENABLE_TEST_AUTOMATION_FLAG enabled ------------------------
set CL=/DENABLE_TEST_AUTOMATION_FLAG
) else (
echo --------------------------------- ENABLE_TEST_AUTOMATION_FLAG disabled -----------------------
)
But the section of code which required for the TA build is not getting enabled.
And also if there is any better way of doing the same (enabling preprocessor from command line, while compiling the code from command prompt)

SSIS Custom Task Error - Code: 0xC001F02A Source: Package Description: Cannot create a task from XML for task

I am trying to create a custom package. I made a simple test package, to send an email using outlook interop. I was able to get the task to show up in the ssis toolbox by switching the server version to 2012. however I get the following error when trying to run it in vs on my local machine,
Error: 0xC0010026 at Custom Task: The task has failed to load. The
contact information for this task is "".
I then tried to run it in dtexec to see if i could get more information.
Microsoft (R) SQL Server Execute Package Utility Version 11.0.7001.0
for 32-bit Copyright (C) Microsoft Corporation. All rights reserved.
Started: 3:53:50 PM Error: 2021-01-14 15:53:50.27 Code: 0xC001F02A
Source: Package Description: Cannot create a task from XML for
task "Custom Task", type "SSISCustomTaskLibrary.CustomTaskTest,
SSISCustomTaskLibrary, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=4fdef094ddc47664" due to error 0x80070057 "The
parameter is incorrect.". End Error Error: 2021-01-14 15:53:50.27
Code: 0xC0010018 Source: Custom Task Description: Failed to
load task "Custom Task", type "". The contact information for this
task is "". End Error Error: 2021-01-14 15:53:50.28 Code:
0xC0010026 Source: Custom Task Description: The task has failed
to load. The contact information for this task is "". End Error Error:
2021-01-14 15:53:50.28 Code: 0xC0024107 Source: Custom Task
Description: There were errors during task validation. End Error
Error: 2021-01-14 15:53:50.28 Code: 0xC0010025 Source: Package
Description: The package cannot execute because it contains tasks that
failed to load. End Error DTExec: The package execution returned
DTSER_FAILURE (1). Started: 3:53:50 PM Finished: 3:53:50 PM Elapsed:
0.109 seconds
so I fiddled some more and found that if after I loaded the task I switched back to 2019, task disappeared from the toolbox but it ran successfully. however the properties were not working and show an error for every property. I took a screenshot and added it to the project which is located here, https://github.com/w-storey/SSISCustomTaskTestSolution.git
I am using visual studio 2019 with the data tools installed. I added the dll to the gac using these commands
"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8
Tools\gacutil" /u SSISCustomTaskLibrary "C:\Program Files
(x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\gacutil" /iF
"\source\repos\Tests\SSISCustomTaskTestSolution\SSISCustomTaskLibrary\bin\Release\SSISCustomTaskLibrary.dll"
copy
"\source\repos\Tests\SSISCustomTaskTestSolution\SSISCustomTaskLibrary\bin\Release\SSISCustomTaskLibrary.dll"
"C:\Program Files (x86)\Microsoft SQL Server\110\DTS\Tasks"
so the question is how can I get this task custom task to work?

passing msiexec command line params to a child process started by msiexec

I have a requirement to update config files with the command line provided arguments for some reason, the file is not being updated so I wrote a small utility app in c# to be started by msiexec. The intention is to get the commandline params to this app so that it would open the config file and update it during the course of installation.
My app was executed fine but when trying to read the parent process (msiexec) command line params, I get something like C:\windows\msiexec /V not the ones I specify on the msiexec command line (I'm not even using /V)
Any ideas about what could be the issue? If you have a better way to handle this please suggest.
Thanks.
Update:
Sorry for the confusion, I was using WiX installer and I start the WiX generated .msi on the command line as below for eg.
C:\> msiexec /I foo.msi ARG1="v1" ARG2="v2"
ARG1 and ARG2 are defined in Wix installer script.
What I'm looking at is a way to access the command line params ARG1="v1", ARG2="V" by a small application which will be started by msiexec (the app is specified in Wix installer script as custom action).
Ideally, when I use xmlFile (tried xmlConfig as well), my WiX installer script should be able to update my config files with v1, v2 but its not happening so wrote an application that should be able to read v1 & v2 and write to the config file.
using xmlFile I get the following error:
ExecXmlFile: Error 0x8007006e: failed to load XML file: Error 25531. Failed to open XML file , system error: -2147024786 MSI (s) (E4!54) [18:11:36:714]: Product: -- Error 25531. Failed to open XML file , system error: -2147024786 –
Doesn't get any meaningful info. I used the msiexec argument /l*v to generate the logging.
Log excerpt:
Actually xmlFile should do my requirement but I get the following error while using it. Any help on this would be greatly appreciated.
MSI (s) (E4:00) [18:11:32:110]: Executing op: ActionStart(Name=ExecXmlFile,,) Action 18:11:32: ExecXmlFile.
MSI (s) (E4:00) [18:11:32:111]: Executing op: CustomActionSchedule(Action=ExecXmlFile,ActionType=3073,Source=BinaryData,Target=ExecXmlFile,CustomActionData=1030//cloudRecognition/connectiontype130//cloudRecognition/connectionaddress192.168.128.59;192.168.128.261030//cloudRecognition/connectionport50001;50001)
MSI (s) (E4:DC) [18:11:32:113]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIA419.tmp, Entrypoint: ExecXmlFile
MSI (s) (E4:EC) [18:11:32:113]: Generating random cookie.
MSI (s) (E4:EC) [18:11:32:115]: Created Custom Action Server with PID 10104 (0x2778).
MSI (s) (E4:68) [18:11:32:402]: Running as a service.
MSI (s) (E4:68) [18:11:32:403]: Hello, I'm your 32bit Elevated custom action server.
ExecXmlFile: Error 0x8007006e: failed to load XML file:
Error 25531. Failed to open XML file , system error: -2147024786
MSI (s) (E4!54) [18:11:36:714]: Product: -- Error 25531. Failed to open XML file , system error: -2147024786
CustomAction ExecXmlFile returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Are you passing the arguments as MSI properties? If yes, then you can read them from the MSI database. Check this:
http://www.alteridem.net/2008/05/20/read-properties-from-an-msi-file/
I am guessing you are setting environment specific application properties to the Config file? If so, why don't you have all the properties defined in the config file and make the application smart enough to read the right properties (by checking the environment)? I would do that.
Above comments are just based on the limited information you provided. You would have your own reasons to do so :)
It seems to me that you need to add a CustomAction to your install process.
You might need both or just one, depending of the request that you have.
To Update Configuration files can you use XmlFile CustomAction, to change modify any XML file.
To launch a Quiet Execution CustomAction
I believe that this will allow you to change the values of the configuration file during the installation. You can find a nice introduction to CustomActions and their types here. Have a look at the type 2 CustomAction.
 
Edit for follow question in Answer section:
When is the CA scheduled to launch during the installation process?
Do you have a log file for the install?
 
Re-edit
Without Code or more information about the installation process, I can't really help more.
Helpfull info would be:
Where in the installation sequence is your CA launched?
What WiX Element are you using to change the values in your file.
Did you try to create an installer that does just the part that you are having trouble with, to isolate the behavior.

SubSonic 3 Regenerate ActiveRecord Class Automatically?

I have a SQLite database and SubSonic3, finally got a clue on how to generate the .cs from the .tt in Visual Studio. My stuff builds now.
I can kick off MSBuild automatically to build my project, but I would like to add a pre-build event to regen the ActiveRecord.cs cleanly so any database changes end up there for future Unit tests.
How can I simulate the 'run external tool' in the Visual Studio GUI?
Thanks.
You can run the TextTemplating tool from the command line:
C:\Program Files\Common Files\Microsoft Shared\TextTemplating\1.2\TextTransform.exe "path/to/your/ttfile.tt" -out <outFileName>
Use TextTransform.exe /help for more command line arguments you can use.
At this time, the SubSonic's Settings.ttinclude file must be run from within the VisualStudio application, and can not be run from the command line. This is because Settings.ttinclude uses the project context to locate the App.config / Web.config file so that it can look up the connection string.
Attempting to run via command line using TextTransform.exe will result in the error:
error : Running transformation: System.InvalidCastException: Unable to cast object of type 'Microsoft.VisualStudio.TextTemplating.CommandLine.CommandLineHost' to type 'System.IServiceProvider'.
This stems from this method in Settings.ttinclude:
public EnvDTE.Project GetCurrentProject() {
IServiceProvider _ServiceProvider = (IServiceProvider)Host;
...
}
By hacking the Settings.ttinclude file, you can set up Subsonic to run from the command line.
Just modify it to set your connection string as the return value of GetConnectionString and taking out all other logic.

Why do I get a 1720 error when my InstallShield setup tries to run my VBS custom action?

The Custom Action is configured as follows:
Custom Action Name: MyCustomAction
VBScript Filename: <PathVar01>\MyFolder\MyVBSfile.vbs
ScriptFunction: MyFunction
Return Processing: Synchronous (Check exit code)
In-Script Execution: Immediate Execution
It is being executed via the following InstallScript code:
result = MsiDoAction(ISMSI_HANDLE,"MyCustomAction");
When the setup reaches that line in InstallScript, the installer shows an error alert, stating:
"Error 1720.There is a problem with
this Windows Installer package. A
script required for this install to
complete could not be run. Contact
your support personnel or package
vendor."
The result code returned by MsiDoAction is that of '1603', which, according to winerror.h, is:
//
// MessageId: ERROR_INSTALL_FAILURE
//
// MessageText:
//
// Fatal error during installation.
//
#define ERROR_INSTALL_FAILURE 1603L
Why is this happening? I was starting to doubt that the file was included properly. Yet, I am pointing to the correct file, and I've tried including the VBS via the InstallShield Support Files, thinking this would ensure the file was present with the setup, but same result.
Running the setup with logging enabled revealed the problem:
Action 13:29:19: MyCustomAction.
Action start 13:29:19: MyCustomAction.
Error 1720.There is a problem with
this Windows Installer package. A
script required for this install to
complete could not be run. Contact
your support personnel or package
vendor. Custom action MyCustomAction
script error -2146827278, Microsoft
VBScript compilation error: Expected
identifier Line 163, Column 37,
blnExample,)
To run a setup with logging enabled:
"C:\SetupFolder\setup.exe" /V"/l*v
c:\Install.log"
This forum thread was helpful.

Resources