Effect changes in the original .csproj file - c#

I am developing an application that would add/delete project properties and references from .csproj file as necessary.
project.AddItem("Reference", "System.IO", globalProperties);
project.AddItem("Reference", "System.Collections.Generic", globalProperties);
The above code adds the items.
When I print out the ProjectItems in project.Items, I am able to see the added references. When I open the .csproj file that needs to be modified, the changes are not visible (since the copy of the file is being passed).
However, I want to effect changes in the .csproj file that is being modified.
I tried using the "ref" keyword, but doesn't work.
Can someone tell me how to go about it?
Thanks.

you have o add first an item group before your reference like that
var slItemGroup = project.Xml.CreateItemGroupElement();
project.Xml.InsertAfterChild(slItemGroup, project.Xml.LastChild);
slItemGroup.AddItem("Reference", "System.IO");
and you have to call save method of your project:
project.Save(projectFileName);

Related

Check if a <PackageReference/> tag is added to .csproj file

I have a .csproj file as follows:
If a <PackageReference/> tag is added to this csproj file, the build should fail. How do I do that? Is there any setting or a test I can add?
For example,
On my phone at the moment, however you can do the following or rather follow this (unable to test for you):
In Pre-Build Events (Right click on your project, go to Properties) of the project, add the following command:
CD $(SolutionDir)
CALL CheckProj.ps1
Then on the root of your solution, create a bat file called "CheckProj.ps1"
The contents of your script should be along the lines of:
$xml = new-object System.Xml.XmlDocument;
$xml.LoadXml( (get-content 'MyProject.csproj') );
$node = $xml.SelectNodes('//Project/ItemGroup/PackageReference');
exit $node.Count;
Then on the rebuild of the project, if exit isn't equal to 0, it'll fail the build as 0 is expected to simulate success in a build event, anything higher will end up being marked as an error and should fail the whole build process.
I'm not entirely sure why you'd want to do this, but you could do this in a test fairly easily.
Using XUnit:
[Fact]
public void NoPackageReferences()
{
string myCsproj = File.ReadAllText("path/to/my.csproj");
Assert.DoesNotContain("PackageReference", myCsproj);
}
Now, if you wanted to be more thorough, you could parse the XML... But that's probably overkill for this.

How to disable predeployment and postdeployment scripts in DacServices.Deploy()

We have some automated dacpac deployment code which correctly handles both a CreateNewDatabase and straightforward Update database scenarios in C# using Microsoft.SqlServer.Dac
Now in the CreateNewDatabase case we want to be able to run the DacServices.Deploy() with both the Pre and Post Deployment scripts disabled. I.e. they should not be executed in this scenario.
I have tried to find a suitable place in the DacDeployOptions and DacServices objects but cannot find anything that will do this.Ideally
Question 1: I would like something like DacDeployOptions.IgnorePreDeploymentScript = true Is there any means by which I could achieve this at runtime?
As an alternative, some time ago I remember seeing example code which showed how to traverse a dacpac and create a new dacpac in run time. I think this approach would allow me to simply create a new dacpac which I could pass to the Deploy and which would exclude the Pre and Post Deployment scripts. I don't like this solution but it would allow me to achieve what I need.
Question 2: Can anyone point me to some examples for this please?
My code:
var dacService = new DacServices(ConstDefaultConnectionString);
using (var dacPackage = DacPackage.Load(dacPacFilePath))
{
var deployOptions = new DacDeployOptions
{
CreateNewDatabase = true,
IncludeTransactionalScripts = false
};
dacService.Deploy(dacPackage, TestDatabaseName, true, deployOptions);
}
The question is related to: Create LocalDB for testing from Visual Studio SQL project
There are a number of approaches you can take for this, this is a bit of a brain dump (hey the clocks went back last night and I'm not even sure if the current time):
1) create an empty project that references your main project using a same database reference - when you deploy without the scripts deploy the empty one using IncludeCompositeObjects - pre/post deploy scripts are only run from the dacpac you deploy not from any referenced dacpacs but obviously the code and scheme are deployed. This describes it:
https://the.agilesql.club/blog/Ed-Elliott/2016-03-03/Post-Deploy-Scripts-In-Composite-Dacpac-not-deploying
2) use SQLCMD variables to wrap the data setups and pass in the value to the deploy.
3) make your scripts check for whether they should setup data like only insert if the table rowcount is zero
4) for reference data use merge scripts - I'm not clear if the point of this is for reference data or setting up test data
5) Use .net packaging api to remove the pre/post deploy scripts from the dacpac, this shows you how to write the scripts so you should be able to do a GetPart rather than WritePart:
https://github.com/GoEddie/Dir2Dac/blob/master/src/Dir2Dac/DacCreator.cs
On the whole I would guess that there is probably a simpler solution- if this is for testing then maybe make the data setup part of the test setup? If you are unit testing tSQLt helps you avoid all this by using FakeTable.
Hope it helps :)
Ed
Two things to try:
First, doing this type of thing is quite easy if you are using MSBuild since you can tailor a particular Configuration to include one or more pieces of the Project. In your .sqlproj file there is an <ItemGroup> section that should look similar to the following:
<ItemGroup>
<PreDeploy Include="Script.PreDeployment1.sql" />
<PostDeploy Include="Script.PostDeployment1.sql" />
</ItemGroup>
You can simply add a "Condition" that will determine if that ItemGroup is used or not. You can see these "Condition" attributes throughout the .sqlproj file (usually). So the result should look similar to:
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PreDeploy Include="Script.PreDeployment1.sql" />
<PostDeploy Include="Script.PostDeployment1.sql" />
</ItemGroup>
Then you just flip between "Release" or "Debug" in the "Active Configuration" drop-down and the pre and post deploy scripts will be included or excluded accordingly.
The other thought was to somehow reset the pre and post deployment scripts. Since you are loading the DacPac into dacPackage, you will have access to the PreDeploymentScript and PostDeploymentScript properties. I am not able to test, but it might be possible to "erase" what is there (assuming that the streams already point to the stored scripts).
DACPACs are ZIP files. Use the functionality of the System.IO.Packaging namespace to remove pre- and post-deployment scripts from an existing package.
using System.IO.Packaging;
// [...]
using (var dacPac = Package.Open(dacPacFile))
{
var preDeploy = new Uri("/predeploy.sql", UriKind.Relative);
if (dacPac.PartExists(preDeploy))
{
dacPac.DeletePart(preDeploy);
}
var postDeploy = new Uri("/postdeploy.sql", UriKind.Relative);
if (dacPac.PartExists(postDeploy))
{
dacPac.DeletePart(postDeploy);
}
dacPac.Close();
}
The file is simply overwritten after Close, so consider copying it away first, in case you want the original unchanged.
(this is partly covered by the internet resource linked in item 5) in the accepted answer; however the code shown above is all you need)

Assemblies refer to the same metadata but only one is a linked reference; consider removing one of the references

I am currently dealing with the error word for word:
Assemblies 'C:\Users\Jake\Desktop\AudioFileSorter\AudioFileSorter\obj\Debug\Interop.QTOControlLib.dll' and 'C:\Users\Jake\Desktop\AudioFileSorter\AudioFileSorter\libs\Interop.QTOControlLib.dll' refer to the same metadata but only one is a linked reference (specified using /link option); consider removing one of the references.
My references include several files:
AxInterop.QTOControlLib.dll
Interop.QTOControlLib.dll
Interop.QTOLibrary.dll
Interop.Shell32.dll
taglib-sharp.dll
These files are all located and referenced from a folder called libs within the base location for my project: AudioFileSorter\AudioFileSorter\libs\
An additional control reference was included as the Apple QuickTime Control 2.0 from the COM references. With the exception of this reference all other references were added by right clicking 'References' in the Solution Explorer and clicking 'Add Reference' and then browsing the libs folder to pull dll file.
Obviously, I have no idea what I am doing and I don't know how to solve it. The project worked fine yesterday and after trying to build the project to a release build everything got messed up and now I have this error. I have tried removing one of the duplicate references but then i end up just missing the reference when the app calls it during this code line:
private void SortM4PFiles(string[] files)
{
WriteLine("Begin compiling .m4p files...");
foreach (string file in files)
{
axQTControl1.URL = file;
// Create new movie object
QTOLibrary.QTMovie mov = new QTOLibrary.QTMovie();
mov = axQTControl1.Movie;
string title = mov.Annotation[(int)QTAnnotationsEnum.qtAnnotationFullName];
string artist = mov.Annotation[(int)QTAnnotationsEnum.qtAnnotationArtist];
string album = mov.Annotation[(int)QTAnnotationsEnum.qtAnnotationAlbum];
songs.Add(new Song(title, album, artist, file));
songs[songs.Count - 1].setType(".m4p");
WriteLine("Evaluated " + title);
}
// Make sure the previous .m4p is not in use
// This will prevent an IOException when the file is in use and cannot be moved
axQTControl1.URL = "";
}
Any help or explanation would be greatly appreciated. Thank you.
This was the tutorial for using the QuickTime control and reading m4p and m4a metadata.
I was trying to convert one project from packages.config to PackageReference... & I got this issue. After looking into it, I realized that, there are two references added for the same dll.
How? One from nuget & one from local COM dll. I had remove one reference to fix the issue.

How to add typed Dataset to visual studio project programmatically and keep design support

After having created a Typed DataSet for a given set of database tables (using System.Data.Design.TypedDataSetGenerator).
I can attach the generated C# file with
// VsProj is of type VsLangProj.VSProject for the current project
// artifactPath is the path to the newly created C# artifact with the
// typeddataset generated
// code.
VsProj.Project.ProjectItems.AddFromFile(artifactPath);
However when trying to open this in the designer it fails (it is certainly missing the .xsd, .xsc, .xss files).
Is there a documented way to get the .xsc / .xss files?
Ok, I found it, instead of using System.Data.Design.TypedDataSetGenerator, just set some magic properties for the ProjectItem and voila:
// xsdPath is a path to a .xsd file which was generated with System.Data.DataSet.WriteXmlSchema.
ProjectItem pi = _vsProj.Project.ProjectItems.AddFromFile(xsdPath);
// this little magic replaces having to use System.Data.Design.TypedDataSetGenerator
pi.Properties.Item("SubType").Value = "Designer";
pi.Properties.Item("CustomTool").Value = "MSDataSetGenerator";
(Of course if you were outside of Visual Studio, then it's better the previous method).

Adding Project reference programmatically

Basically, after read a couple links, i tried the above code:
foreach (EnvDTE.Project proj in soln.Projects)
{
if (proj.Name == "BLL")
{
VSLangProj.VSProject vsproj = (VSLangProj.VSProject)proj.Object;
vsproj.References.Add(#"C:\Teste\DAL\bin\Debug\DAL.dll");
}
}
All paths, project names, are hard-coded on purpouse, since im still testing how to achieve it.
Though it would act like if i did
Project folder -> References -> Add reference -> Pick one, manually (compile time)
but after loading the solution, BLL project didnt contain any PERMANENT reference to DAL project.
I think that you forget to save modified project , you have to invoke Save at the end

Categories

Resources