I'm very new to .Net, C# and Visual Studio. Now I want to develop a Windows Service application using C#. The Windows Service needs to write some data to some file. I'm using Visual Studio 2010. I'm using Windows XP as my operating system. I created a windows service.its installer etc.
When I install the Windows Service in the folder other than non-default folder (other than C drive), after running service it will create the file and write the text file success.
When I install the service in the default location (that when the time of installation the i cannot the default path) (please refer the attached image)
Then after installing then I run the service. But the file is not created and there is no exception thrown. The following are the codding snippet for file.
string logPath = AppDomain.CurrentDomain.BaseDirectory + "log\CastrolSdWindowsService_Log.txt";
fs = new FileStream(logPath, FileMode.Append, FileAccess.Write);
fs.Write(bytes, 0, bytes.Length);
fs.Flush();
I cannot find why the file is not created in C drive.
As stated in the comments the Program Files directory is going to be protected by the operating system and isn't the ideal place to place your application generated files. The best place to store these files is in the application data folder. There are some helper methods in the .net framework that will help you locate the folder dynamically by utilizing the Environment class and using one of the Environment.SpecialFolder enumerations to get the path to the folder.
You can chose between (as wrote above) either change path to log files and move them outside protected program file folder,
or you can change NTFS permissions to allow WRITE/MODIFY on those log files and folders that you want to write inside "program file/your app" folder.
Note, that your windows service application did not run as SYSTEM.
it may be NT AUTHORITY\LOCAL SERVICE or NT AUTHORITY\NETWORK SERVICE
Run your service then run process explorer, switch on column "USER" and check it.
Related
I have some confusion about Windows path (dev machine) and Linux path (target OS for microservice)
I created a new folder in my c# project (app/yamls), put inside a file aaa.yaml and put the file in git ignore. On my windows dev machine, I see the file in c:\myproject\app\yamls. However, my microservice will run on Linux and aaa.yaml file will reside in /app/yamls.
When I run the following, I get file is missing
string file = "/app/yamls/aaa.yaml";
System.IO.File.Exists(file) // FALSE
What should be done so the new added file in visual studio will be seen as file residing in /app/yamls like it will be in production.
Thanks
You need to code file and directory handling in a cross platform manner.
You could something like this: https://learn.microsoft.com/en-us/dotnet/api/System.IO.Path.PathSeparator?view=net-5.0&viewFallbackFrom=netcore-5.0
That System.IO.Path.PathSeparator will be / on Linux and \ on Windows
What I usually do is create an appsettings.json file with file location in there. And then change the config file depending on where it's deployed (Linux or Windows)
Path class has static members useful if manipulation of file paths required in .Net environment. Look at these:
Path.DirectorySeparatorChar
Path.AltDirectorySeparatorChar
Path.PathSeparator
Path.VolumeSeparatorChar
If you just need to create path from given components the Path.Combine(...) method is also useful.
In my win forms C# app, I am exporting my images to pdf and word. Before export, images need to be saved as bitmap. Did it like this:
// code
bitmap.Save("Image.jpeg", ImageFormat.Jpeg);
bitmap.Dispose();
Now the code for word and pdf export read this file normally from saved location. Howewer, while I was testing my desktop app, code "Image.jpeg"saves image to bin directory.
When I made installer using InstallShield and installed my program, this option works but it save my image to desktop. I don't really want that.
Managed to send it to ApplicationData directory but don't want that either...
string imageSaved = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Image.jpeg");
bitmap.Save(imageSaved, ImageFormat.Jpeg);
bitmap.Dispose();
How to navigate my file to installation directory?
Simply use Application.StartupPath
Gets the path for the executable file that started the application,
not including the executable name.
The path for the executable file that started the application. This
path will be different depending on whether the Windows Forms
application is deployed using ClickOnce. ClickOnce applications are
stored in a per-user application cache in the C:\Documents and
Settings\username directory.
For example you can use it this way:
string imageSaved = Path.Combine(Application.StartupPath, "Image.jpeg");
bitmap.Save(imageSaved, ImageFormat.Jpeg);
For ClickOnce applications, you can use ApplicationDeployment.CurrentDeployment.DataDirectory, for more information, see Accessing Local and Remote Data in ClickOnce Applications
I have created Windows Service using C# including (.exe file and .msi file in Debug folder)
ie. 1) setup.exe and Tracking_Setup.msi
Now, the problem is that when I try to run/Install setup.exe file from D:\ (any other than C:\ ) Drive it's working fine but when I try to copy this file on Desktop and then try to run/setup it's give me error like
Unable to locate application file 'Tracking_Setup.msi'.
See the setup log file located at 'C:\Users\admin\AppData\Local\Temp\VSD5AD0.tmp\install.log' for more information.
I have give permission too this file and run as administrator too but still no luck.
When you copy setup.exe on desktop also copy .msi file which will be there with setup.exe in debug directory and then try to install.
I have a default application setup created using Visual Studio 2005. When my application is installed, it's only work running as administrator, because some files are written in the Application Folder.
I have found that on Visual Studio 2010 there is a property for change this permission on some folders inside application folder.
How can I allow to my application create and edit specific files inside the application folder without run it as admin?
Here are your options, assuming that you cannot change where the application itself attempts to read/write files:
Change the default installation directory of the installer of the application, to not go inside C:\ProgramFiles, but instead to a folder just off the C:\ drive that has more lax access permissions. This was standard practice in Windows 3.1 and even Windows 95, but these days you can't get a program "certified" by Microsoft as compatible with any supported Windows version unless it installs into the proper Program Files directory. These modern OSes also have the root of the C:\ drive locked down pretty tight so you'd need administrative permissions to install the app (but not to run it).
Create a custom action for the installer which increases the access rights of the program subfolder during installation. Again, Microsoft is unlikely to certify the app if you do this, and this also requires admin permissions to install the app, meaning the average user on your network can't just pull it down and run it.
Install the files that must be altered in the "proper" places (Application Data for user-specific files, Program Data for files pertaining to the software as a whole), and then create shortcuts within the main application folder that point to the files in their accessible locations. The legacy app shouldn't know the difference.
EDIT: Here's a method straight out of the custom actions of the installer for an app I wrote that has a similar "legacy" app, which has to read/write data from config files in a subfolder of the app's "home" directory. The IDictionary passed in is the one you get from the various custom action methods (OnBeforeInstall, OnAfterInstall, OnCommit, etc), so you simply drop this into an Installer class, call it from the handler for the install event of your choice (which must be after the installer has made the file system changes), and call it:
private void SetEditablePermissionOnConfigFilesFolder(IDictionary savedState)
{
if (!Context.Parameters.ContainsKey("installpath")) return;
//Get the "home" directory of the application
var path = Path.GetFullPath(Context.Parameters["installpath"]);
//in my case the necessary files are under a ConfigFiles folder;
//you can do something similar with individual files
path = Path.Combine(path, "ConfigFiles");
var dirInfo = new DirectoryInfo(path);
var accessControl = dirInfo.GetAccessControl();
//Give every user of the local machine rights to modify all files
//and subfolders in the directory
var userGroup = new NTAccount("BUILTIN\\Users");
var userIdentityReference = userGroup.Translate(typeof(SecurityIdentifier));
accessControl.SetAccessRule(
new FileSystemAccessRule(userIdentityReference,
FileSystemRights.Modify,
InheritanceFlags.ObjectInherit
| InheritanceFlags.ContainerInherit,
PropagationFlags.None,
AccessControlType.Allow));
//Commit the changes.
dirInfo.SetAccessControl(accessControl);
}
You could manually change the NTFS folder permissions using Windows Explorer to the Application Folder. However, it would be best practice to read/write to a different folder.
Don't write anything to the application folder (under program files). Instead use the user's home folder, or, if you want to write something that's relevant to all users on the machine - ProgramData.
EDIT:
If you can't change your application code, you should still avoid placing program data files under ProgramFiles if you can. There's one other thing you can do. You can create a folder under c:\ProgramData, and just create a symbolic link to it from C:\Program Files... . That way, your legacy application still finds the data where it expects to find it.
I have a .NET CF project. In the project directory I put a simple xml file (users.xml) which has to be read by the device. When I debug the application on device emulator and try to load the file from code, the Exception is thrown (FileNotFoundException "Could not find file '\\users.xml'.").
Is there a mechanism to automatically deploy also configuration files to a device emulator?
You have you path set wrong in your code. After following the instruction of Shaihi or Sphynx to get Studio to deploy the file, the file is then in the folder with the application.
Based on the fact that you're getting an error that it cannot find "\users.xml" tells me that you're either telling it to specifically look in the root folder or you haven't specified a folder.
Windows CE requires that you provide a fully-qualified path, so your application should either use the full path it is deployed to (i.e. "\Program Files\MyApp\users.xml") or you need to construct the path:
Path.Combine(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().GetName().CodeBase
), "users.xml");
Here is how to do it in VS2005. It deploys the file along with the project.
This is for a native application - it should be similar for a managed one.
Content field specifies whether to deploy the file to the target. The file is deployed to the same directory as the application. I am not sure how VS2005 handles the deployment in case you updated the file, meaning you might need to manually delete it on the device.
VS2005 http://www.freeimagehosting.net/uploads/255e2922df.jpg
You can try adding the file to your application, setting "Build Action" to content, and enabling "Copy to Output Directory".
Also, I believe there's an option in emulator preferences which enables sharing files between emulator and the host OS.
Go to File->Configuration on the emulator and share a directory from PC. This directory becomes your storage card so if you put a file there like test.csv then you can read it from "Storage Card\test.csv" in the program. (I am using VS2008 and Windows Mobile 5.0 Pocket PC RC 2 emulator.