During installation, I am required to execute an executable (EXE) given a certain condition. The execution must be done within a custom action. The problem is that the custom action is deferred and for some reason the process is not being executed.
I need to call the .EXE with arguments. The EXE is located in a folder that is always created during installation. I need to get that path but do not know how to yet. I am using a hard-coded path for now and storing it in a property.
Calling the executable, it receives an argument that is a path where a file is located that it needs to read.
What am I doing wrong?
[CustomAction]
public static ActionResult ExecuteDrugDatabaseSetup(Session session)
{
string databaseName = "ApplicationServer";
try {
Log(session, "Beginning Drug Database Setup");
string drugsDBFilePath = session.CustomActionData.Values.Select(encodedSettings => new DatabaseUpdaterSettings(encodedSettings)).OrderBy(s => s.Sequence).Select(v => v.DrugsDBFilePath).FirstOrDefault();
string drugsDBLoaderPath = session.CustomActionData.Values.Select(encodedSettings => new DatabaseUpdaterSettings(encodedSettings)).OrderBy(s => s.Sequence).Select(v => v.DrugsDBLoaderPath).FirstOrDefault();
Log(session, "drugsDBFilePath = " + drugsDBFilePath);
Log(session, "drugsDBLoaderPath = " + drugsDBLoaderPath);
if (!string.IsNullOrEmpty(drugsDBFilePath)) {
Log(session, "Have drugs db file path");
var p = new Process();
p.StartInfo.FileName = drugsDBLoaderPath;
p.StartInfo.Arguments = "//DataPackage " + drugsDBFilePath;
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = false;
p.Start();
p.WaitForExit();
} else {
Log(session, "No drugs db file path");
foreach (DatabaseUpdaterSettings settings in session.CustomActionData.Values.Select(encodedSettings => new DatabaseUpdaterSettings(encodedSettings)).OrderBy(s => s.Sequence)) {
if (settings.DatabaseName == "ApplicationServer") {
GetUpdater(session, settings).SetupDrugDatabase();
}
}
}
return ActionResult.Success;
UPDATE
I got it to work. However, now I need to make it run with elevated privileges but without prompting me. Is there a way to achieve this?
[CustomAction]
public static ActionResult ExecuteDrugDatabaseSetup(Session session)
{
string databaseName = "ApplicationServer";
try {
Log(session, "Beginning Drug Database Setup");
// TODO: Add a RelativeWeight field to the DatabaseUpdaterSettings so we can specify the relative weights in
// the xml. Then add them all up here to get the total ticks for all updates.
ResetProgressBar(session, ProgressTicksForAllDatabaseUpdates);
// Now we will check if we have a Data File path for the DrugsDBLoader to process. This value was captured
// at the beginning of the installation. If nothing was entered, we proceed as we have always. If we have
// a path, then we just load that specific file.
string drugsDBFilePath = session.CustomActionData.Values.Select(encodedSettings => new DatabaseUpdaterSettings(encodedSettings)).OrderBy(s => s.Sequence).Select(v => v.DrugsDBFilePath).FirstOrDefault();
string drugsDBLoaderPath = session.CustomActionData.Values.Select(encodedSettings => new DatabaseUpdaterSettings(encodedSettings)).OrderBy(s => s.Sequence).Select(v => v.DrugsDBLoaderPath).FirstOrDefault();
drugsDBLoaderPath += @"Tools\";
if (!string.IsNullOrEmpty(drugsDBFilePath) && !string.IsNullOrWhiteSpace(drugsDBFilePath)) {
Log(session, "Have drugs db file path");
foreach (DatabaseUpdaterSettings settings in session.CustomActionData.Values.Select(encodedSettings => new DatabaseUpdaterSettings(encodedSettings)).OrderBy(s => s.Sequence)) {
if (settings.DatabaseName == "ApplicationServer") {
GetUpdater(session, settings).SetProgressTemplates("Drugs DB Setup", "Setting up Drugs Database", "");
}
}
// It is necessary for the process to RUN AS elevated permissions and we indicate that with the VERB property assigned.
// Since this is an external process, it must be explicitly elevated; it does not inherit the elevation of the ServerSetup
FileInfo drugsDBFile = new FileInfo(@drugsDBFilePath);
ProcessStartInfo startInfo = new ProcessStartInfo() {
FileName = Path.Combine(drugsDBLoaderPath, "DrugsDBLoader.exe"),
WorkingDirectory = "\"" + @drugsDBLoaderPath + "\"",
Arguments = $"/DataDirectory:\"{drugsDBFile.Directory}\" /DataPackage:{drugsDBFile.Name}",
CreateNoWindow = false,
WindowStyle = ProcessWindowStyle.Normal,
UseShellExecute = true
//Verb = "runas"
};
Log(session, $"Command: {startInfo.FileName} {startInfo.Arguments}");
try {
using (Process dbLoaderProcess = Process.Start(startInfo)) {
dbLoaderProcess.WaitForExit();
}
} catch (Win32Exception ex) {
if (ex.NativeErrorCode == 1223) { //The operation was canceled by the user.
Log(session, "User chose not to proceed with DrugsDBLoader");
} else {
Log(session, ex.Message);
}
ShowError(session, "Failed to update {0}: {1}. Create / examine installation log for details.", databaseName, ex.GetBaseException().Message.TrimEnd('.'));
return ActionResult.Failure;
}
} else {
// some code here
}