InstallShield generated shortcut alters program directory? c# - c#

I have program that reads code from a .bin file stored the same directory as the main executable and .dll.
So, the program works completely fine, unless I install it with InstallShield and have shortcuts automatically created. If I open the program via any shortcut, I get an error saying that:
"options.bin" could not be found in "directory where the shortcut is currently located"
however, if I open the .exe directly then i don't get any errors and the program runs perfectly. Also, if i create my own shortcut manually after installation (with a target directory rather than a clsid), then the program will function perfectly.
here is the code that opens "options.bin":
private void btnReadFile_Click(object sender, EventArgs e)
{
try
{
byte[] prog;
using (BinaryReader reader = new BinaryReader(File.Open("options.bin", FileMode.Open)))
{
prog = reader.ReadBytes(6 + 4 * 12 + 2);
}
updateProduct(ProductOptions.createFromBytes(prog));
}
catch (Exception ex)
{
MessageBox.Show("Failed to read from 'options.bin': " + ex.Message);
}
}
why do the shortcuts created during the installation cause my program to look for the "options.bin" in the directory where the shortcut is? How can i create a shortcut at time of installation that won't cause this problem?
(oh, and i'm using Visual Studio 2012, which doesn't include any setup option, which is why i'm using installshield)

Related

C# HKEY_LOCAL_MACHINE Registry edit working in VS (Debug) but not when published to .exe

I have a requirement for an application to "run on start-up" for all users. This has to be setup by the application it's self, not by a user adding a shortcut to start-up folder or something similar. I have managed to get this to work by adding the .exe path to the registry Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. The following code successfully adds the path to the registry when in debug mode and visual studios is run as administrator.
using Microsoft.Win32;
var path = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
try
{
string baseDir = "EXAMPLE_DIR";
using (RegistryKey? key = Registry.LocalMachine.OpenSubKey(path, true))
{
if (key is not null)
{
string exePath = $#"{baseDir}\iOK2.exe";
key.SetValue("iOK2", exePath);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
However the same code fails to add to the registry when it has been "Published" to an an executable (.exe) file.
The code doesn't produce any errors, it seemingly executes and exists successfully. I have tried running as admin, creating an app.manifest and requiring admin, ensured it's compiled to 64-bit and is accessing the correct registry
Any ideas on what is happening or something I'm missing? If this fails I could potentially call a PowerShell script to edit the registry, but would rather keep dependencies to a minimum if at all possible

Cannot create a windows service with SC.exe using WPF App after its installation C#

I created a WPF Desktop Application as well as a Worker Service (all .NET 6.0 Preview 3), packed them in a .MSI Setup File using Microsoft Visual Studio Installer Projects extension, which installs the WPF Application on the machine.
While the application installs and functions correctly, I had to somehow implement the service installation which should run after the WPF Application would be installed. I created a function for that, which runs sc.exe as administrator and installs the service using Process.Start(), which looks like this:
private static void InstallService()
{
const string ServiceName = "SomeService";
var path = Path.GetFullPath(#".\SomeService.exe");
var psi = new ProcessStartInfo
{
FileName = #"C:\Windows\system32\sc.exe",
Arguments = $"create { ServiceName } binPath= { path } start= auto",
Verb = "runas",
UseShellExecute = true,
};
try
{
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show($"Installation has failed: { ex.Message + ex.StackTrace }");
}
}
The problem with this function is that it executes properly when the application is ran in Visual Studio and when it is ran from the 'bin\Release' folder created by Visual Studio. The service is then installed and can be started. When the program, however, is installed using the .MSI package, the service does not install and no MessageBox is displayed, which shows that no exceptions are thrown.
What I have tried:
When the function is executed, a UAC prompt is shown and then the
process starts. I tried running the entire application as
administrator, but that didn't solve the issue.
I also tried copying all the files from the 'bin\Release' directory into the one in which the application is installed and replacing every file with the one from 'bin\Release', so that both directories should be the same, but that also didn't solve the issue.
After the installation function is executed, the service should start with another function for starting it:
private static void RunService()
{
const string ServiceName = "SomeService";
var psi = new ProcessStartInfo
{
FileName = #"C:\Windows\system32\sc.exe",
Arguments = $"start { ServiceName }",
Verb = "runas",
UseShellExecute = true,
};
try
{
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show($"Running was not approved or failed: { ex.Message }");
}
}
This function, however, functions correctly in both cases, although obviously only when the service is previously installed, which cannot be done in the .MSI installed application. As for the use of Process.Start() instead of ServiceController class, the application should not run as administrator by default, and it is not possible with the ServiceController, so I used Process.Start() with Verb = "runas" which runs the process as administrator only showing the UAC prompt when it is needed (starts the service only when it is not already running).
Is there any way to solve this problem and install a Worker Service in a .MSI installed WPF Application?
As I further proceeded to analyze all the possible factors, I finally noticed what was causing the issue in this case.
Generally, the paths generated by Visual Studio don't have any spaces, and because of that they can be written as a command argument without double quotes. In my case, the paths which contained the Project files also didn't have any spaces, which caused the commands without double quotes to be executed normally. The installation path, however, did contain spaces, as it's designed to be more user-friendly, which caused this piece of code to not execute as intended:
// the path parameter in the command will end when there will be a space somewhere in the path
Arguments = $"create { ServiceName } binPath= { path } start= auto"
The path variable only contains the full path, which is not wrapped in double quotes.
To prevent the issue the use of double quotes is necessary, and including the \ symbol notifies the compiler that these double quotes are a part of the string:
// the path parameter is wrapped in double quotes and will be fully read
Arguments = $"create { ServiceName } binPath= \"{ path }\" start= auto"
When the path would be fully written in the code, the missing double quotes are easy to notice. When, however, using string interpolation, it may cause problems, as it did in my case.

Creating new VS2015 solutions with 2 projects programmatically using C#

I am using the following code to try to programmatically create Visual Studio 2015 projects on the fly from within an existing Console Application. Why you ask? We are putting together a library of all our code snippets and we want a test/proof test solution for each one, and since we have hundreds of these, we aren't going to do it manually.
Ultimately this will be in an MVC5 app as its own project (class library?) but for now we are just trying to get it functional within this console application.
I am trying to create a new solution with 2 projects (a console application and a unit test project).I am also not even sure I need the unit test project, or whether one even works with a console app since there is no option to add a unit test to a console app in VS2015 solution generation.
Here is the code;
public class CreateConsoleProjectsProgrammatically
{
private const string Vs2015Type = "VisualStudio.DTE.14.0";
private const string Vs2015ConsoleProject = #"X:\Code Library\Helpers\ConsoleApplication\csConsoleApplication.vstemplate";
private const string Vs2015UnitTestProject = #"X:\Code Library\Helpers\UnitTestProject\UnitTestProject.vstemplate";
private const string Vs2015CodeLibraryBasepath = #"X:\Code Library";
public static void CreateVsConsoleProjectProgrammatically(string filename)
{
// Create a solution with two projects in it, based on project
// templates, a console project and a unit test project.
var vsType = Type.GetTypeFromProgID(Vs2015Type);
//error line is below
var vsInstance= Activator.CreateInstance(vsType, true);
EnvDTE.DTE dte = (EnvDTE.DTE)vsInstance;
dte.MainWindow.Visible = false; // optional: set to true if you want to see VS doing its thing
// create a new solution
dte.Solution.Create(#"X:\Code Library\", filename);
var solution = dte.Solution;
// create a C# console application
solution.AddFromTemplate(Vs2015ConsoleProject,Path.Combine(Vs2015CodeLibraryBasepath,filename), filename);
// create a unit test project
solution.AddFromTemplate(Vs2015UnitTestProject, Path.Combine(Vs2015CodeLibraryBasepath, filename + "_Test"), filename + "_Test");
// save and quit
dte.ExecuteCommand("File.SaveAll");
dte.Quit();
}
}
Here is the error which is from the Activator.CreateInstance
Creating an instance of the COM component with CLSID {A2FA2136-EB44-4D10-A1D3-6FE1D63A7C05} from the IClassFactory failed due to the following error: 8001010a The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER)).
Not sure why I am getting a server busy error. It almost seems like its because VS is already open? But how else would the new solution be generated? I tried closing the solution and reopening it but that did nothing to solve the issue.
I also thought it may have been a connectivity issue, so I moved all the files and directories to C:\ but it produced the same error, so it wasn't an issue of using a networked drive location.
I also tried using
EnvDTE80.DTE2 dte2 = (EnvDTE100.DTE2)vsInstance;
but DTE2 is not an available property/method on EnvDTE100 according to the editor, even though I found some examples using it on the net.

SQlite using statement gives Unable to load DLL 'SQLite.Interop.dll' error on another computer

This is the code that I wrote for database connection:
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
using (SQLiteConnection con = new SQLiteConnection(connectionString))
{
try
{
con.Open();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
if (con.State == System.Data.ConnectionState.Open)
{
Console.WriteLine("Database Opened");
ushort[] writeData = new ushort[10];
writeData = parseList(byteList);
if (writeData != errorBytes)
{
writeToDb(con, writeData);
}
else
{
Console.WriteLine("Error Bytes returned! BROKEN DATA!!!");
}
//con.Close();
}
else
{
Console.WriteLine("Can't open the database!");
}
}
}`
When I run the program on the computer that I wrote the code it works properly and opens the database. However when I run my program in another computer code doesn't go into using statement and gives the exception SQLite.Interop.dll not found. I added the System.Data.SQLite.dll to my project's references. Also I have this dll file in the other computer. Do I need to add anything to the other computer to make this program work properly?
I figured it out that the problem was about SQLite dlls. When I installed the System.Data.SQLite library from NuGet Package Manager and set the platform target as x86 problem resolved. Although platform target was x86 before I asked this question but re-installing the library from NuGet Package Manager solved my problem. Before that I was using the dlls I downloaded from the http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki as reference to my project.
Try to check the connectionString, the location of the SQLite file,.. Maybe you are trying to create it somewhere where your program is not allowed to write on the other computer. Try to run your app as administrator if there is a difference. The only thing that came on my mind is that it crashes at the moment of creating the connection and therefore it is not going into the using statement.

Execute SSIS Package Using ASP.Net

Description Of Environment
I have an SSIS task which executes from asp.net, the package gets data from excel files over UNC path and puts the data into a sql server databaase . I have deployed the SSIS to file system, it has windows authentication database connections and the IIS user has database access. I can log in as the AppPoolUser I have used to host the web application and open/modify the files in question so those basic permissions are there. Web App is compiled in x86.
When it works:
When run from Visual Studio (ctrl + shift + W) it works fine and every thing is done succefuly.
When it doesn't work:
When run from client browser. it upload the file but fail in the package.
My Question
What is different about the client and server and how do I make it work? I was under the impression that when running the web app all connections go through the AppPool User so it should behave the same on any machine server included? i need to do so without the need of CMD.
c# Code running SSIS Package
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SqlServer.Dts.Runtime;
public partial class Pages_Quality : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Upload_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
string fileExt =
System.IO.Path.GetExtension(FileUpload1.FileName);
if (FileUpload1.FileName == "Breached.xlsx")
{
try
{
FileUpload1.SaveAs("*:\\***\\***\\" +
FileUpload1.FileName);
Label1.Text = "Upload Done";
Application app = new Application();
Package package = app.LoadPackage(#"*:\**\**\Quality.dtsx", null);
DTSExecResult result = package.Execute();
Label2.Text = (result.ToString());
}
catch (Exception ex)
{
Label1.Text = "ERROR: " + ex.Message.ToString();
}
}
else
{
Label1.Text = "Only Breached.xls is allowed!";
}
}
else
{
Label1.Text = "You have not specified a file.";
}
}
}
Do you have SSIS service or SSIS Component (Client Tools) installed in the machine (web server in your case) where you are deploying and running your application from?
You may have bids in the same development PC where you have Visual Studio to develop and debug your application application. Usually the SSIS component is installed along with BIDs so you do not need SSIS service to run the package. This might be the case where your package execution is fine in you development PC. However it will never work in your web server because you do not have these components installed in your web server.
Hope this will help you.
Regards,
Sandip
If you are using Excel source connection, most probably the error happened because the excel driver work under 32 bit mode only, while when you try to call it from web, it's execute under 64 bit.
Check that.
Regards

Categories

Resources