I have two C# projects, one of them, the library, contains a database file which is modified during PreBuildEvent. Its contents are correctly updated and available in bin\Debug folder of this library project.
The problem occurs because in the other project, the UI application, the database file is the same as before my changes in PreBuildEvent.
In the example below, I will use a text file (it behaves the same):
ProjectLib.csproj
TextFile1.txt
Build action: Content
Copy to Output Directory: Copy if newer
PreBuildEvent:
echo test > $(TargetDir)TextFile1.txt
Contents of TextFile1.txt in ProjectLib\bin\Debug:
test
Application.csproj
Contents of TextFile1.txt in Application\bin\Debug:
"empty"
From where the database file is picked? From $(ProjectDir) or $(TargetDir)? EDIT: The database file is picked from $(ProjectDir). You can see this executing the build using msbuild. At the end there is a target named _CopyOutOfDataSourceItemsToOutputDirectory and this shows the source as $(ProjectDir).
Is there a way to modify the file in the PreBuildEvent - the file in library bin\Debug - and have it correctly output to application bin\Debug?
Why are you designing your build system to have two separate projects overwrite a critical dependency?
Related
I have a very simple .NET console application in Visual Studio. I am trying to write some words into a text file.
using (StreamWriter file = File.AppendText("log1.txt"))
{
file.WriteLine("Hello from the text file");
}
If the file does not exist, the application creates it in the autogenerated folder bin/Debug.
Is there a way to create this file in the project's directory, where I have .csproj file?
And more important, in real-world applications, when you work with files, you keep them in bin/Debug? That's why .NET creates them there firstly?
Is there a way to create this file in the project's directory, where I have .csproj file?
Yes, but this can only be done while you are working on your project. Once you are done developing it and try to publish it you won't have access to the location where you have .csproj file, because after publishing you can install it on any PC and it wont have the project you are working on.
And more important, in real-world applications, when you work with files, you keep them in bin/Debug?
No, I assume by real-world applications in your context you mean a published project '.exe' that you can run on any PC. Windows provides you three Data folders that you should use when writing your program so that it works smoothly after publishing:
User Data
Roaming User Data
All User Data
You can acess the above folders in .NET application using the Environment.SpecialFolder:
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
As per your given code, try this :
var fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"log1.txt");
using (StreamWriter file = File.AppendText(fileName))
{
file.WriteLine("Hello from the text file");
}
This way you will be able to publish your program and it will still work smoothly without hard-coding the path as you were doing previously.
That's why .NET creates them there firstly?
If you don't specify a complete path, and just the file name .NET looks into the working directory of the executable, which in this case is bin/Debug
Is there a way to create this file in the project's directory, where I have .csproj file?
Yes. As explained here (second answer) you can use the post-build event to write down the value of $(ProjectDir) in a text file (using command echo $(ProjectDir) > ..\..\projectdir.txt). This macro contains the directory of your .csproj. This command will create the file projectdir.txt with your project directory after a build process so you read this file contents in your code and use what is inside it to pass to File.AppendText as the base directory to create your file log1.txt.
And more important, in real-world applications, when you work with files, you keep them in bin/Debug? That's why .NET creates them there firstly?
That depends on what you want to do. In your case the code creates the file at bin/Debug because that is where your executable are being executed. When you omit the full path to File.AppendText and just pass "log1.txt" as argument, it will create the file in the same folder as the executable are at. If you want a different folder you should specify the folder here (e.g. File.AppendText("C:/log1.txt") will create the file at C:/.
You can create the text file in the root of your project and use copy always to have them in the same place as your executable. If this is just a readonly text file then it's OK because windows doesn't allow you to modify the files reside in Programs folder in OS drive.
If you want your code to modify these text file then you need to put them in appdata folder. In real world example I did this on many project. All the database work my winforms, WPF application need goes in AppData folder.
I have designed and created two seperate windows application ( say winapp1 and winapp2). Winapp1 creates a file(say file.txt) in the disk containing some text. And I need to merge this file.txt with precompiled version of winapp2 ie winapp2.exe so that the winapp2 can display it.
Winapp1 creates a file with different contents each execution time. And for each file there will be a copy of winapp2 that needs to be merged.
Is there a way to this? If there is, help me.
And my English is not so good. Thanks for reading this.
The easiest solution, (assuming that releasing the source code for winapp2 to the system that runs winapp1 doesn't present problems) is to have the entire source for the winapp2 project accessible to winapp1. The source should include a blank copy of the file as an embedded resource. Winapp1 can then modify the source file and use MSBuild to build a fresh copy of Winapp2.
To modify the text file, you should be able to just use the normal file manipulation .NET methods and to call MSBuild, you may be able to do it via a .NET class, but you can certainly just call the msbuild executable from the relevant .NET framework folder in %windir%\Microsoft.NET\Framework\ and pass in the full path of the project file.
I am new in mvc and c# and I can't solve following problem:
I am trying to create a folder named "Items" in solution folder.
I have tryed to use CreateDirectory method:
Directory.CreateDirectory("~/Images");
But it didn't work for me - folder wasn't created ..
Partly working solution was to create a folder by :
Directory.CreateDirectory(Server.MapPath("~/Images"));
"Items" folder was created, but it is not included in the solution:
How to create folder in solution directory so that it is included in project ?
(I needs to by done by code not by hand)
You need to understand what solution and csproj file is used for
In general, they're being designed and used for development with Visual Studio, and once the project is compiled, all these files will be ignored and excluded from the deployment package
Directory.CreateDirectory(Server.MapPath("~/Images"));
The code above simply create the directory if not existed yet in the deployment package at run-time, so you won't see it in your solution unless you run the project locally (either debug/release mode, it does not matter here). However, everything will run normally in hosted environment (ex: IIS).
For your information, here's the brief of what solution and csproj is
solution (.sln) file: contains information to manage one or many individual projects, contains build environments (for each project), start up mode (useful when you want to start multiple projects in one run), project dependencies and so on. Take a note that VS also read from suo file (solution user options) which is used to defined user-custom preferences (you should not include the .suo file in the version control, because it's custom settings)
csproj file: define the structures of project, what the namespace is, what is static folders, embedded resources, references, packages, etc.
Lastly, if you create the folder manually, VS will auto include that folder into deployment package AND csproj, but depends on the file type, you might need to change the Build Action and Copy To Output Directory in file properties.
Hope it helps.
A deployed web application on a web server doesn't have any notion of Visual Studio solution or projects. So the Directory.CreateDirectory(Server.MapPath("~/Images")) is the correct way to create a folder inside your web application at runtime but we cannot be talking about including it into a solution because this hardly makes sense in a pre-compiled web application. If you create the directory on your local development machine, you could always manually include the folder to the corresponding .csproj file, but at runtime this will not make any difference whatsoever.
The reason I wanted to create a folder (if didn't exist) was to make sure it exits before I try to store image in it.
After reading posts here and a few google searches I have concluded that the proper way to handle image upload would be
To create (In my case) folder "Images" by hand to be sure it exists
Then storing uploaded img in existing folder:
string path =Server.MapPath("~/Images/"+ UploadedImageName);
file.SaveAs(path);
I'm writing some integration tests for some SQL scripts that live in a folder separate from the project. Since the setup of the machine I'm writing on the tests on differs from the machine they will be run on, I would like to include them as resource files rather than hard coding any paths. However the default behavior for adding an existing file as a resource file simply copies the file, which is not what I want in case any of the SQL scripts get updated.
Does anyone know the best way to get the resource file to actually reference the SQL scripts that are in a folder separate from the project, or to somehow copy them into the assembly at compile time so I don't have to load them via absolute/relative paths?
Edit: For clarity, I'm trying to get the resource file to act as a symlink to the original file at compile time. Adding an existing file to a resource in file in Visual Studio simply makes a copy of the file, which means any changes to the original are not propagated to the resource file.
After asking on IRC, someone guided me to what I was looking for. You are able to add an existing file to a project as a link (there is an arrow on the Add box when in the file dialog), and set it's Build Action property to Embedded Resource
https://support.microsoft.com/en-us/kb/306234
Daniel posted a link on how to actually read an embedded resource:
How to read embedded resource text file
I am writing a short batch file to prepare a control library DLL with Examples project for deployment via sip file and have the following question.
Given a csproj file at known location and a DLL at known location, is it possible to programmatically update the csproj from the batch file (via third party command line exe, or other scripting) to add the new DLL?
My folder structure is
/Build
/SDK
/WPF
/4.0 : ControlLibrary.dll sits here
/Examples
/WPF
/4.0 : Examples.csproj sits here
Assuming the batch file is at the /Build level, is there any way to modify Examples.csproj to reference ControlLibrary.dll ?
Just to clarify, the reason why I have the structure like this is I wish to deploy an examples csproj to ship with my control library. Examples.csproj should reference the obfuscated control library under SDK/. Examples.csproj also exists on dev trunk (where it has been copied from) and in the development solution it references output of ControlLibrary.csproj on non obfuscated form.
Essentially what im creating here is a folder structure to zip up and ship the ControlLibrary plus examples, hence, the need to update the reference.
Update - Solved using Powershell
Please see this related question and answer on adding and removing references using Powershell
csproj files are XML files - you can easily write a command line application to manipulate these files (adding, removing nodes etc).
You can call such a command line application from your batch file.
You can find the schema for this file at:
%windir%\Microsoft.NET\Framework\[framework version]\Microsoft.Build.xsd
As described in this SO answer.
I don't understand why you would need to modify the csproj file in your case. Just make sure the library reference in the csproj file is relative, i.e. ..\..\..\SDK\WPF\4.0\ControlLibrary.dll and it will keep working fine even if you move the complete folder hierarchy to a new location.
If you're trying to simplify adding the library to new projects though, take a look at NuGet. It's the best way for distributing and deploying libraries.