I install a windows service using installutil and the project installer Account property is set to User.
I install the service as the user who is currently logged on (domain/username).
The service does some stuff and creates a text file. I cannot see the text file in windows explorer but I know it is there based on the output of the service.
If I am logged in as the user who is running the service why can I not see the files the service creates?
Thanks,
Andrew
In my experience the current working directory for services defaults to the system folder instead of the folder where the entry assembly is located. Check for the file here. If you want to change the working directory you can do so in code as follows.
Assembly assembly = Assembly.GetEntryAssembly();
string assemblyFolder = Path.GetDirectoryName(assembly.Location);
Environment.CurrentDirectory = assemblyFolder;
Related
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
I have a windows service program running in C#. I have configured to run it as a local service with my config files stored in \bin\release\config\configvalues.txt. But, it does not recognize this file path and throws the "System.UnauthorizedAccessException".
I believe its looking for the files in the System32 folder and since it does not have the privilege, throws out the exception. For the workaround, my service is running with "local system" to recognize the System32\config folder. To run as a local service, which file path should the config folder be available?
Check the location of your project folder. Most likely, you'll find that it is inside your User profile folders, which the local service account does not have access to.
Deploy your project to a folder outside of any User profiles and you'll have better luck.
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.
I have developed a WCF service which uses the net.tcp binding and read and write files to the file system. When I start the windows service (in a console) I get following error even if the sample.dll is in the folder:
Unable to find assembly file sample.dll
This specific WCF service is hosted in a windows service which runs on windows 7 64bit and I have following questions:
Which account should I use for my application:
User / NetworkService / LocalSystem / LocalService
And why can’t the OS load the dll even if it is there?
Thank you in advance for your help!
For the dll you should add the following line of code right at the beginning of the OnStart method.
System.Environment.CurrentDirectory = System.AppDomain.CurrentDomain.BaseDirectory
That should allow your service to load dlls from the actual directory.
According to the MSDN documentation on the ServiceAccount, the User member prompts for a username and password. I'd guess that if you're using the User account and it doesn't have read permissions for windows/system32, that would result in your assembly failing to be found.
Perhaps change the ServiceAccount up a step to a LocalService?
I have an application that contains a sub folder that contain xml file ,that is use as a database now i want take the path of the xml file at run time ,how can i achieve this in window application?
I know how it does in asp.net using Server.MapPath but i want this is same in windows application
please help
thanks in advance .
Use Aplication.ExecutablePath property when am XML document and executable are reside in the same directory.
I think the recommended way in Windows is to use the Application.StartupPath property.
And with Path.Combine you can have your xml file path Server.MapPath-style like this:
var appPath = Application.StartupPath;
var xmlPath = Path.Combine(appPath, "data/my_db.xml");
// xmlPath now points to app-relative data/my_db.xml file
...
A nuanced answer:
The best way to access data would be to put it in Application.CommonAppDataPath or Application.UserAppDataPath so that it does not depend on the application's installed path. However, there are many reasons why you might need to avoid this.
To answer your question:
If the application is a standard forms application deployed to the client's machine by an installer or XCopy deployment, then the path to the executable is Application.ExecutablePath
If the application is Click-Once deployed, then I would not recommend using the above since the app's path is obscured, shadow-copied and put in the sandbox. You can use ApplicationDeployment.IsNetworkDeployed to test for click-once deployment then ApplicationDeployment.CurrentDeployment.ActivationUri to get the URI that the application was launched from. Your app-relative file will be on that web server; you will always be able to download it.
of course in click-once deployent it would be better to tag the file as Data in which case it would be accessible through ApplicationDeployment.CurrentDeployment.DataDirectory
if the application is a web app, then the Application class is useless. In this case you should use Assembly.GetExecutingAssembly().Location This works because currently executing assembly for a web app is almost always in the web app's /bin directory.
For a "portable" assembly where you don't have an installer, and for rare cases where you don't want to use the Application class, use Assembly.GetEntryAssembly().Location This works because it figures out what the entry point assembly is (your application) and uses that location. This is reliable because assemblies that your entry assembly load don't have to be in the same directory as the entry assembly.
You can get the directory of the currently executing assembly using
System.Runtime.Reflection.Assembly.GetExecutingAssembly().Location
from there you can get to your subdirectory.