Creating Folders in C# Project Using CMake - c#

I've used source_group dozens of times with C++ Projects to organize my files, yet for C# Projects this does not seem to work:
set (FOO myfoo.cs)
set (BAR mybar.cs)
set (FILES
App.xaml
App.xaml.cs
MainWindow.xaml
MainWindow.xaml.cs
)
set (PROPERTIES <property files here>)
add_executable(
${CMAKE_PROJECT_NAME}
App.config
${FILES}
${FOO}
${BAR}
${PROPERTIES}
)
source_group(Models FILES ${FOO})
source_group(ViewModels FILES ${BAR})
Do folders not work for C# Projects via CMake? Or what am I doing wrong?
EDIT: Forgot to mention, in my main CMakeLists.txt file I already have:
if (WIN32)
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
endif (WIN32)
I then call add_subdirectory where the above CMakeLists.txt is. This setup seems to work okay for my other C++ project that is added in the same way.

You can use the VS_CSHARP_Link property to set how a file is viewed in a C# project. (Don't ask for documentation; I can't find any. I learned about this setting by perusing the source code. Looks like it first appeared in version 3.18.)
For example, after adding ${SOME_ROOT_DIR}/some/path/to/someFile.cs to your project's sources, control how it's organized with:
set_source_files_properties("${SOME_ROOT_DIR}/some/path/to/someFile.cs"
PROPERTIES VS_CSHARP_Link "My own folder\someFile.cs")

It seems that in C# Projects, source_group is not honored. However, folders are still possible simply by giving it a directory structure in the list, like so:
set(MODELS
Models/CompileOptionsModel.cs
)
set(VIEWMODELS
ViewModels/CompileOptionsViewModel.cs
)
set(PROPERTIES
...
)
set(Files
...
)
add_executable(
${APPNAME}
App.config
${MODELS}
${VIEWMODELS}
${FILES}
${PROPERTIES}
)
This will result in folders Models and ViewModels appearing.

Related

Call method from interface or abstract class within static void

I'm usually a javascript developer, but for my company I just started learning c# in order to use the CimatronE 13 API to develop custom command line PDM tools for this 3D modelling software.
As I'm making progress understanding the programming language, there's this frustrating situation where I want to use an API endpoint method but I can't manage to get it working.
The Cimatron documentation says the following:
IPdm::GetRelatedDocuments
Syntax: RelatedDocuments = GetRelatedDocuments ( DocumentPath );
This method allows you to get related files from compound types of files, for example Assembly or Drawing.
Input: (String) DocumentPath,
Path to file. For example \Documents\Location\Folder\Document. The file must be Assembly or Drawing.
Return: (Variant) RelatedDocuments,
Variant type array each element of which contain two dimensioned string type array of files related to selected one.
This looks pretty straight forward to me, so I tried calling it in multiple ways from within the static void Main() method, but I keep getting errors:
var RelatedDocuments = interop.CimBaseAPI.IPdm.GetRelatedDocuments("path");
CS0120: An object reference is required for the non-static field, method, or property 'IPdm.GetRelatedDocuments(string)'
interop.CimBaseAPI.IPdm pdm = new interop.CimBaseAPI.IPdm();
var RelatedDocuments = pdm.GetRelatedDocuments("path");
CS0144: Cannot create an instance of the abstract class or interface 'IPdm'
Any ideas? It's probably simple but I'm still a noob with c# :p
EDIT:
Cimatron documentation about the interface interop.CimBaseAPI.IPdm:
Properties:
Get
Query (String, DocumentEnumType, DocumentEnumUnit )
Variant
Methods:
A lot, including Variant GetRelatedDocuments ( String )
As how I see it now... interop.CimatronE.IPdm is an interface and in order to use it's methods, we first need access to the Cimatron application. Using the application object, we can use it's methods to get the desired interfaces such as IPdm and use their methods.
The following code gives no errors from the compiler but does when executing. This seems to be related to version 13 of CimatronE, since the application object works just fine using version 12. A lot has changed between these versions which I think is the reason the API is not functioning properly, outdated.
interop.CimAppAccess.AppAccess AppAcc = new interop.CimAppAccess.AppAccess();
interop.CimatronE.IApplication CimApp = /*(interop.CimatronE.IApplication)*/AppAcc.GetApplication();
interop.CimatronE.IPdm pdm = CimApp.GetPdm();
var RelatedDocuments = pdm.GetRelatedDocuments("path");
Console.WriteLine(RelatedDocuments);
Please correct me if I'm wrong! (since I just started and still learning c#)
I ran into this same issue with Cimatron 14.
I needed to make some changes in Visual Studio for things run properly with Cimatron.
Run Visual Studio in administrator mode
Set your Debug & Release Solution Platform to 'x64'
It was also recommended to point the build path for release & debug to the same folder as the Cimatron references. In my case 'C:\Program Files\3D Systems\Cimatron\14.0\Program'. However my code appears to run fine without this.
I created the Cimatron Application with this code (VB.Net):
Dim gAppAccess As New CIMAPPACCESSLib.AppAccess 'Define an AppAccess object to get running active application
Dim gApp As CIMAPPACCESSLib.Application 'Define an Application object
gApp = gAppAccess.GetApplication 'Getting running active application
If gApp Is Nothing Then
gApp = New CIMAPPACCESSLib.Application 'Creating a new instance of a Cimatron application
End If
References: Interop.CIMAPPACCESSLib.dll & interop.CimServicesAPI.dll
It is my understanding that Cimatron 15 may also requires some manifest changes.
There is some help information in the Cimatron program under Cimatrom Modules > Cimaton SDK that may be mildly helpful.

C# WPF Localization - Ignoring other cultures and loading default Resources

I'm trying to localize my app, I've created several Resources.[culture].resx but program ignores them all and always loads default Resources.resx.
I have this code in App construtor (and in OnStartup event)
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
My resources are called Resources.en-US.resx, Resources.cs-CZ.resx and Resources.resx
Code in WPF is
xmlns:p="clr-namespace:WpfThermalLabelEditorApp.Properties"
Title="{x:Static p:Resources.Title}"
This should load en-US localization but it doesn't. Loads default. I tried to delete AssemblyInfo and even putting <UICulture> tags into csproj
Not sure if this is the answer, but FWIW: I always set both CurrentCulture and CurrentUICulture like so;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(languageAbbreviation);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(languageAbbreviation);
And be sure to double check the abbreviation you use is the same for all references. That should fix your problem.
EDIT1: Make sure your resource files are set to public, the access modifier should be somewhere near the top when you're viewing the resource file. Double check this says public and rebuild. Also, to call your resource file key do so like this:
<TextBlock xmlns:local="clr-namespace:WpfApplication2" Text="{x:Static local:Resource1.myname}"/>
Where...
"WpfApplication2" is replaced with your project name
"Resource1" is replace with the name of your resource file (without culture id, e.g. for your case it would just be Resources)
"myname" is replaced with the key you want
I came across the same problem, the solution was to clean and rebuild the project. No need to create new project.
Well, after 2 days I've solved my problem. My solution was correct. I have no idea what was wrong but I've created a new project, moved all my data to a new one and suddenly everything worked as a charm.
Here is a few usefull links:
WPF localization and globalization
Localization tutorial
Localization tutorial 2

How to output a file from a roslyn code analyzer?

I'm using the roslyn API to write a DiagnosticAnalyzer and CodeFix.
After I have collected all strings and string-interpolations, I want to write all of them to a file but I am not sure how to do this the best way.
Of course I can always simply do a File.WriteAllText(...) but I'd like to expose more control to the user.
I'm also not sure about how to best trigger the generation of this file, so my questions are:
I do not want to hard-code the filename, what would be the best way to expose this setting to the user of the code-analyzer? A config file? If so, how would I access that? ie: How do I know the directory?
If one string is missing from the file, I'd like to to suggest a code fix like "Project contains changed or new strings, regenerate string file". Is this the best way to do this? Or is it possible to add a button or something to visual studio?
I'm calling the devenv.com executable from the commandline to trigger builds, is there a way to force my code-fix to run either while building, or before/after? Or would I have to "manually" load the solution with roslyn and execute my codefix?
I've just completed a project on this. There are a few things that you will need to do / know.
You will probably need to switch you're portable class library to a class library. otherwise you will have trouble calling the File.WriteAllText()
You can see how to Convert a portable class library to a regular here
This will potentially not appropriately work for when trying to apply all changes to document/project/solution. When Calling from a document/project/solution, the changes are precalcuated and applied in a preview window. If you cancel, an undo action is triggered to undo all changes, if you write to a file during this time, and do not register an undo action you will not undo the changes to the file.
I've opened a bug with roslyn but you can handle instances by override the preview you can see how to do so here
And one more final thing you may need to know is how to access the Solution from the analyzer which, Currently there is a hack I've written to do so here
As Tamas said you can use additional files you can see how to do so here
You can use additional files, but I know on the version I'm using resource files, are not marked as additional files by default they are embeddedResources.
So, for my users to not have to manually mark the resource as additonalFiles I wrote a function to get out the Designer.cs files associated with resource files from the csproj file using xDoc you can use it as an example if you choose to parse the csproj file:
protected List<string> GetEmbeddedResourceResxDocumentPaths(Project project)
{
XDocument xmldoc = XDocument.Load(project.FilePath);
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
var resxFiles = new List<string>();
foreach (var resource in xmldoc.Descendants(msbuild + "EmbeddedResource"))
{
string includePath = resource.Attribute("Include").Value;
var includeExtension = Path.GetExtension(includePath);
if (0 == string.Compare(includeExtension, RESX_FILE_EXTENSION, StringComparison.OrdinalIgnoreCase))
{
var outputTag = resource.Elements(msbuild + LAST_GENERATED_TAG).FirstOrDefault();
if (null != outputTag)
{
resxFiles.Add(outputTag.Value);
}
}
}
return resxFiles;
}
For config files you can use the AdditionalFiles msbuild property, which is passed to the analyzers through the context. See here.

Data Driven MSTest: DataRow is always null

I am having a problem using Visual Studio data driven testing. I have tried to deconstruct this to the simplest example.
I am using Visual Studio 2012. I create a new unit test project.
I am referencing system data.
My code looks like this:
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[DeploymentItem(#"OrderService.csv")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "OrderService.csv", "OrderService#csv", DataAccessMethod.Sequential)]
[TestMethod]
public void TestMethod1()
{
try
{
Debug.WriteLine(TestContext.DataRow["ID"]);
}
catch (Exception ex)
{
Assert.Fail();
}
}
public TestContext TestContext { get; set; }
}
}
I have a very small csv file that I have set the Build Options to to 'Content' and 'Copy Always'. I have added a .testsettings file to the solution, and set enable deployment, and added the csv file.
I have tried this with and without |DataDirectory|, and with/without a full path specified (the same path that I get with Environment.CurrentDirectory). I've tried variations of "../" and "../../" just in case. Right now the csv is at the project root level, same as the .cs test code file.
I have tried variations with xml as well as csv.
TestContext is not null, but DataRow always is.
I have not gotten this to work despite a lot of fiddling with it. I'm not sure what I'm doing wrong.
Does mstest create a log anywhere that would tell me if it is failing to find the csv file, or what specific error might be causing DataRow to fail to populate?
I have tried the following csv files:
ID
1
2
3
4
and
ID, Whatever
1,0
2,1
3,2
4,3
So far, no dice.
I am using ReSharper, could it be interfering in some way?
Updated
I have it mostly working now! I am able to use XML, but when I use CSV my column, which is named ID comes back as ID
Not sure why. I've checked the actual file of course, and no weird characters are present.
For anyone having a similar problem, I turned off Just My Code and enabled Net Framework source stepping, etc. so that I could get more detailed debug information. This allowed me to determine that ReSharper was causing me problems. I disabled resharper and modified my attributes like this:
[DeploymentItem("UnitTestProject1\\OrderService.csv")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\bin\\Debug\\OrderService.csv", "OrderService#csv", DataAccessMethod.Sequential)]
And it worked (except as noted). I am still suspicious of the "bin\debug" in my path, but I'm just happy my DataRow is no longer null.
Thanks!
Any ideas?
I was struggling with a similar problem today when trying to make data-driven tests work with CSV input file. The name of the first column had some garbage at the beggining of it, i.e. ID instead of just ID.
It turned out it was an encoding issue. The CSV file was saved in UTF-8 which adds a byte order mark at the beginning, obviously confusing the parser. Once I saved the file in ANSI encoding, it worked as expected.
I know it's an old question, but this information might help someone else ending up on this page.
Have you tried adding it through the properties window?
Go to Test menu -> Windows -> Test View -> the tests will load up.
Click on the test to alter i.e. TestMethod1 and press F4 (properties).
Look for 'Data Source' and click the ellipses next to it
It will walk you through a wizard that sets up the attributes properly for the TestMethod
You have the deployment part set up properly, which is normally the big stumbling block.
You also don't have to set the build action to Copy Always as the deployment does this for you. This option is used if you include items like .xml files you use for configs, or icons/images as part of your project.
Update 1:
Also try this tutorial on MSDN.
Update 2:
Try this post, involving ProcMon
I see that you said you tried putting the CSV itself into the testsettings file, but have you tried just putting in the directory?
<Deployment>
<DeploymentItem filename="Test\Data\" />
</Deployment>
Then your DataSource line will look something like this:
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\YOURCSV.csv", "YOURCSV#csv", DataAccessMethod.Sequential)]
If you do it this way, you don't need to specify the DeploymentItem line.
Our folder structure looks like this: Trunk\Test\Test\Data
We include: Test\Data in the deployment
We then access Test\Data via the |DataDirectory|\
All CSVs live within the \Data folder

C# - Sharing resources file between project

I would like two how to do to share Resources files between 2 (or more) projects?
So, to resume, I've three project :
the development project (CF.NET) that include the resource file (with all definition).
I've two other projects that are empty BUT linking to the development projects, it's just a different build each time, so when I modify the development project, all three projects are updated too. (Modification of the csproj file.)
Question is, what about Resources files? When I try to access from the development project I get all resources but when I try from the 2 others, it throws an "MissingManifestResourceException".
Any idea how to solve this issue?
Thanks.
[EDIT]
Here is what I've done :
Create a project named "RealProject" which contains all code (including resources files)
Create a project named "LinkedProject" which contains nothing (I deleted all files into it and modify the csproj file as the following :
<ItemGroup>
<Compile Include="..\RealProject\**\*.cs" />
</ItemGroup>
So in LinkedProject directory I've only :
[Directory] bin
[Directory] obj
[File ] LinkedProject.csproj
The whole LinkedProject uses the RealProject files, it's just a different configuration build (see here to know why : C# - Code compiler for .NET & CF.NET )
Once in that configuration, I've no access to the resources files from the RealProject ...
If you need screens or more detailed explanation, just ask.
[EDIT]
With this code, it works, Resource manager isn't loaded on the good Assembly name, but it should exists a better solution !!!
Assembly ass = Assembly.ReflectionOnlyLoadFrom(#"..\..\..\RealProject\bin\Debug\RealProject.dll");
ResourceManager manager = new ResourceManager("RealProject.Properties.Resources", ass);
[Solution]
Things to check :
The LinkedProject as the same
namespace as the RealProject
Add Resources as links
Clean up all your solution
Rebuild it
Test !
Try to add the resource file as a link to the other two projects and make sure the namespaces as defined in the project file is the same.
Try adding existing file in other projects as a link.
The problem with sharing resources files between different projects is that the root namespace has to be the same in all the projects you use the same file in.
Or not.
You can get the root namespace at runtime in the *Resources.designer.cs file. Note the links in the comments to related answers. Make sure you commit this and keep an eye on it, the code-generator has a habit of overwriting it which would break its universality. I used the xml doc comments to remind me what's going on, if the code-gen obliterates it I'll see it in the commit diff.
/// <summary> Returns the cached ResourceManager instance used by this class. </summary>
/// <remarks> DO NOT commit any version of this file the tool overwrites, it will break it for other projects</remarks>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null))
{
// https://stackoverflow.com/a/1329631/492 https://stackoverflow.com/a/51978052/492
Assembly thisAssembly = typeof(/*thisClassName*/).Assembly;
// you need a class called "App", or just change the name on the next line to one you have in the root namespace
var apps = thisAssembly?.GetTypes().Where(t => t.Name == "App");
if (apps.Count() != 1)
throw new InvalidOperationException($"Too Many App classes. Count: {apps.Count()}, Apps: {apps}");
Type appType = apps.FirstOrDefault();
string ns = appType.Namespace;
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager($"{ns}.OtherNames.Spaces.thisClassName", typeof(thisClassName).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}

Categories