Visual Studio Installer with to set path of script file - c#

I have a Visual Studio installer that installs a Windows Service hosting a Web Service.
What I am trying to resolve is to give users during installation a choice of where a particular script is located on the box and once they have set the location to then update the location to the app.config file which the application can then use.
At the moment during install I have added a custom folder and added to that the folder the file. This all gets installed. I want to keep this as a default, but to be able to overwrite it with the users new choice.
I have added a user interface and a text box to capture the user's choice, and a installer class, but this is failing when I try it. Where it is failing is when it is try to find my App.Config file. It says that it cannot find it. In my code, I have written:
string path = Assembly.GetExecutingAssembly().Location;
So, to me my app.config has not been installed into this location when the installation is running at that moment in time.
So, can someone please advise how I can override and save the new location.
Thanks

What you're doing won't work for a number of reasons.
Custom actions in VS setup projects run after all the files have been installed, so it's too late to choose a folder where files can be installed. UI is supposed to be at the front where the normal wizard UI forms run, but VS setups don't support custom dialogs.
Installer classes with UI tend to do strange things because they are called from the execute sequence in the MSI, and the apartment threading won't work.
You're not running in an interactive user environment. Your installer class is being called from an msiexec process running with the system context. If you need to load files, name the path explicitly.
If you're going to stick with Visual Studio setups, your best bet is to install the script to a normal default location and have your app offer a way to copy it somewhere. Then the user can copy it somewhere new whenever they want and you're running in a normal user environment.

You can not get the directory full path where the MSI is being installed using,
string path = Assembly.GetExecutingAssembly().Location;
above code will probably return a path C:\Windows\System32 which has the msiexec.exe location which handles the MSI installation. Use the following code within installer class to get the installation path.
string installationPath = Context.Parameters["assemblypath"];
Rest of your questions are not clear.

Folks
Managed to resolve this myself.
I added an afterinstall event to the Installer class. In this event I added this line of code
string assembley = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(assembley);
string path = Uri.UnescapeDataString(uri.Path);
string directory = Path.GetDirectoryName(path);
To get the config file - I did this
Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetAssembly(typeof(ProjectInstaller)).Location);
This gives me what I want and it works

Related

How to attach file to windows service?

Is it possible to attach a flat file to windows-service?
My windows-service uses few flat file (for data purposes). Usually, if it's a normal executable I would place those files in the same directory as exe. How can I achieve that with windows-service?
I've done some research on this, but all I found was:
1. Pass a path to those files as a parameter to windows-service.
2. Make a fixed path and just require those files there
But I don't like those solutions. I was wondering if it's possible to attach those files to the windows service while installing it?
How about adding these files inside the project as Embedded Resources? They won't show up on the disk, but you could still properly read them from inside the assembly itself.
Here's some reference: https://support.microsoft.com/en-ie/kb/319292
You can look up the directory that your application is installed in at runtime, using the Application.StartupPath property from System.Windows.Forms. This works for both applications and services. You should avoid hard-coding the path that you think your application is installed in, because the end user may have installed it somewhere else. You should also avoid using the current directory (i.e., opening the file by name only, without a specific path) because the user may be running your application with a different current directory.
Note that installutil does not make a copy of your service executable. So the service runs from the same directory that it was in when you installed it, and any files you place in that directory should still be there when the service is running.

XML file couldn't be detected after windows service setup

I have created a windows service. I do the setup of the service using the windows installer.
I have one XML file like a config file. Whenever i debug windows service with attaching the debug project it works fine. But after the installation i can see the event saying couldn't find the example.xml file in C:\Windows\system32. It's a repeating problem. Can anyone tell me whats going on with this. Or any suggestions?
This isn't an installer problem. Windows Services are always started with System32 as the current directory. Add this line to the Main() method in your Program.cs prior to firing up any services.
Environment.CurrentDirectory = new FileInfo(Assembly.GetExecutingAssembly().FullName).DirectoryName;
Most likely file is just not where you are looking for it.
Chances are that your code looks in "current working folder" which during debugging in VS is the same as application, but in case of starting as service/from command line is different.
Make sure your code loads file from location you expect the file to be (i.e. next to the application), but not from some relative path (like "myfile.xml").
Why are you saving stuff in the Windows folders? Unless there's a really good reason to do so, this is bad. Install your config in the same place that your app is running and get the file path with:
var folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var configPath = Path.Combine(folderPath, configFileName);
The issue is that your service is not running as Administrator. If the service is not running as Administrator, then it won't be able to read the files under system32 folder.
Change the service properties to run as Administrator. That should fix the issue.

Store path to directory in C# library

It's more "architecture" then "language" question.
I have a class library in my .Net solution, that generates something using images from a directory that is deployed with the application. User has to be able add new images easily, so I can't put them to resources.
This directory is attached to this class library. Is there any way to get its path? AppDomain.CurrentDomain.BaseDirectory for debug returns /bin/debug/, that isn't right of course.
i.e. - my application is installed to C:\Program Files\MyApp. So, path has to be "C:\Program Files\MyApp\ImagesLib".
BUT:
my application is downloaded from subversion and saved to d:\my projects\MyApp. So, path has to be "d:\My Projects\MyApp\ImagesLib".
How to make this path universal? The directory is created from Visual Studio (right click/Add/New Folder)
I think your architecture needs a rethink.
In the new UAC world you're expected to write to specific locations on a per user or per computer basis. If you install to Program Files for example, under UAC trying to write to your install folder may fail (depending on privileges).
Because of this you will need to use Environment.GetSpecialFolder() coupled with the SpecialFolder enum.
You can read more about these here:
http://msdn.microsoft.com/en-us/library/14tx8hby.aspx
http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx
For example, assuming you just want to store on a per computer basis:
var base_data_folder = Environment.GetSpecialFolder(SpecialFolder.CommonApplicationData);
var data_folder = Path.Combine(base_data_folder,"MyApplication");
var images_folder = Path.Combine(data_folder,"Images");
On my Windows 7 machine this would equate to:
C:\ProgramData\MyApplication\Images

Visual Studio Deployment Package Change File Permissions

Maybe this isn't possible due to Security implications...
I have a Deployment Package created in Visual Studio for a Win Form. The application references an app.config file locally and allows the user to change the settings in it, through the application.
When I deploy the application and attempt to save the changes I have made, Windows is saying "Permission denied". Is there a command I can run as part of the installation that will give the "Everyone" security permission to my app.config file....and thus allow my Application to edit it?
Thank you.
If you want to be able to write to the app.config file you need to move it to the Shared Application Data directory and modify your application to read the configuration information from there. On Win7 for example:
C:\ProgramData\YourCompany\YourApp\app.config
In C#, to get the common app data directory:
// using System.IO;
string appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
You might be able to use a custom action in your installer to run icacls in order give full access to Everyone:
icacls {Path to App.config} /grant Everyone:(F)

Is it possible to set the value of a config file to reflect chosen windows installer path?

I have a program that I am going to deploy via a Windows installer. The program outputs files to a location specified in a app.config file.
Is it possible to change the value of the config file to the path selected during the install?
So the process would be as follows.
User runs windows installer
User selects path to install program
Output variable in app.config changed to location of install
User can then edit the config file to change output variable if they wish to change the output path.
Update: Ok so now I know how to create a custom install process as per this link:
Configure App.config Application Settings During MSI Install
This is fine if you want to just use the standard set of controls but I would like a file chooser for them to be able to choose the output path, how can I do this?
Ok I figured out what I needed to do... Heres the answer...
Add an installer class to the project you want to install as per instructions in the link.
Then override the install method in that class as follows to read the path that that user inputs as install directory..
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
string targetDirectory = Context.Parameters["targetdir"];
string exePath = string.Format("{0}BarcodeScanner.exe", targetDirectory);
Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);
config.AppSettings.Settings["ILPrintExportPath"].Value = targetDirectory;
config.Save();
}
Then follow the other stages in the above link :)
As Joe said I will have to either ensure the users run the app as an administrator or install outside the program files directory so its not a perfect solution but it does what I need it to do.
See this article Configure App.config Application Settings During MSI Install which shows how to do this using a C# custom action which uses the standard .Net ConfigurationManager class to open and update the app.config file.
Why not just use Assembly.Location to get the directory the EXE is running from? I don't see any need to add a configuration setting -- it's not like this is something you want to be user-configurable after your app is installed.
var exePath = Assembly.GetEntryAssembly().Location;
var exeDirectory = Path.GetDirectoryName(exePath);
If you want that path to be by default same as install directory, you may just use Directory.GetCurrentDirectory() if there is no entry in your config. But then, there will be no possibility to set other path during install (not sure if you wanted that).

Categories

Resources