How to correctly save a WF4 ActivityBuilder - c#

I am currently saving my .NET FX 4.0.1 StateMachine activity like this:
var sb = new StringBuilder();
var xamlWriter = ActivityXamlServices.CreateBuilderWriter(
new XamlXmlWriter(new StringWriter(sb),
new XamlSchemaContext()));
XamlServices.Save(xamlWriter, activityBuilder);
return sb.ToString();
This works fine and the generated XAML looks good. Unfortunately, it is invalid. I can read it back in using ActivityXamlServices.Load but when I execute it, it says that it doesn't know the properties defined in the workflow. Opening it in the Visual Studio designer yields the same errors:
Compiler error(s) encountered processing expression "ActiveCall". "ActiveCall" is not declared. It may be inaccessible due to its protection level.
Through comparing the original XAML with the XAML produced by my code, I found out how to fix this problem. I have to have this tag before the StateMachine tag:
<mva:VisualBasic.Settings>
Assembly references and imported namespaces for internal implementation
</mva:VisualBasic.Settings>
By the way:
The text inside the tag must be exactly like this, otherwise there will be an error when opening the WF in VS:
Failed to create a 'Settings' from the text 'FooBar'
Question:
What do I have to change in my code to have this tag in the generated XAML?

I think I found the answer.
I have to use the following code before calling Save:
VisualBasic.SetSettings(activityBuilder, new VisualBasicSettings());
If the activityBuilder has been created from a DynamicActivity it is even better to use the following code:
VisualBasic.SetSettings(activityBuilder,
VisualBasic.GetSettings(dynamicActivity));
If this is not used, namespaces that are only needed for extension methods are not written to the XAML and will lead to an error when loading and executing the XAML.
I summarized my findings on code project.

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.

Get assembly name at compile time and use it in code [duplicate]

Is there a way to find out the assembly name at design-time (i.e. not using reflection or runtime APIs such as System.Reflection.Assembly.GetEntryAssembly) from within Visual Studio?
The scenario requires a tool to get the assembly name that a Visual Studio project will eventually compile into.
This is like parsing the AssemblyName property of the .csproj - I am wondering if there are any APIs that can give this information reliably.
Please do not respond back with runtime APIs that use reflection - there is no assembly file present at the time I need the assembly name - just the metadata of the assembly in the csproj file.
if you are calling the tool via a post/pre-build event, this data is very easy to access.
Just go to the "project properties->Build Events" tab, then select either "edit pre-build" or "edit post-build", depending on when you want the tool to run. This should bring up an edit window with the ever helpful "Macros >>" button. Press this and you will be given a heap of macros to use and should be pretty much everything you need.
The "API" you could use is LINQ to XML after all the .csproj file is just xml. (and you can get the location of the .csproj file if you need from the solution file which for some reason is not XML but can be easily parsed)
You can use "TargetName" available in Macros for Post-build events. It will give you the assembly name for your project.
After a quick run through MSDN I found this article which might be a good start for some further research:
Accessing Project Type Specific Project, Project Item, and Configuration Properties
I think you will need to write some regular expression that will give you the value of "AssemblyTitle" attribute in AssemblyInfo.cs file.
Something like this:
public class Assembly
{
public static string GetTitle (string fileFullName) {
var contents = File.ReadAllText (fileFullName); //may raise exception if file doesn't exist
//regex string is: AssemblyTitle\x20*\(\x20*"(?<Title>.*)"\x20*\)
//loading from settings because it is annoying to type it in editor
var reg = new Regex (Settings.Default.Expression);
var match = reg.Match (contents);
var titleGroup = match.Groups["Title"];
return (match.Success && titleGroup.Success) ? titleGroup.Value : String.Empty;
}
}

Rehosted Workflow Designer throws TypeLoadException upon Load

I'm trying to rehost the workflow designer in my WPF app.
However, when I try to initialise it I get a TypeLoadException dialog with the following message:
"Could not load type
'Reporting.Primitives.Documents.IDocField`1' from
assembly 'Reporting.Primitives, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null'."
I've tried stripping it down and have gotten to the simple invocation code here:
var wnd = new Window();
var grid = new Grid();
wnd.Content = grid;
var met = new DesignerMetadata();
met.Register();
var d = new WorkflowDesigner();
d.Load(new Sequence());
grid.Children.Add(d.View);
wnd.Show();
It is the call to Load that causes the exception.
Here's the weird part: There's no type in the solution called IDocField<T>.
There's an IDocField and a DocField<T> : IDocField, so it seems to be inventing this IDocField<T> type from somewhere.
I don't have any reflection calls looking for an IDocField<T> either.
I've also tried moving this code around the app into various modules that aren't directly referencing Reporting.Primitives to no avail.
There is an IUiDocField<T> interface floating around.
Curiously enough, I did write an interface IDocField<T> some time ago, but it's not in the solution now, so I don't see why it would be causing problems.
As usual It's always your (my) fault.
The app pulls in plugins via a directory using reflection, and it appears there was an old dll in there that was referencing the IDocField<T> interface.
It would seem that this wasn't a problem until the workflow designer attempted to probe the assembly for type information that something finally noticed it was referencing something that wasn't there!
facepalm

XAML MarkupCompilePass2 fails on a WPF project

When I try to build my WPF project I get the folowing error:Samotorcan.Client.WPF.Windows8\Views\MainWindow.xaml(1,17): error MC3074: The tag 'Window' does not exist in XML namespace 'clr-namespace:Samotorcan.Client.WPF.Windows8.Controls'. Line 1 Position 17.The problem only occurs when I try to use linq. If I have a line like this new List<object>().ToArray<object>(); somewhere in the MainWindow.xaml.csfile I get the above error and if I change it to new List<object>().ToArray(); the error disappears and the project builds successfully.I also checked the build log and it contains the same error at task MarkupCompilePass2.I am using .NET Framework 4.5 and Visual Studio 2012.EDITAfter playing with it a bit I managed to find out that it's not specificly related to linq an random changes like removing an unused file from a project or just removing parts of code like a simple string creating string s = new String(); fixes the error.At one point a simple change in a constructor from this
public LoggedEventArgs(string message)
{
Message = message;
}
to this
public LoggedEventArgs(string message)
{
// Message = message;
}
fixed the error.
Managed to find a workaround for the above error by moving all my controls from the project into a separate project just for controls.
Now there are no random errors on build because as it looks like it can always find the window and other controls that are now in a separate assembly.

Code Contract : ccrewrite exited with code -1?

I'm new to code contracts. I downloaded the latest build of code contract project (1.4.40314.1) and started to implement it in my project. When i enabled 'Runtume Checking' through Code Contracts Tab in VS2010, i got this Error
Error 1 The command ""C:\Program Files (x86)\Microsoft\Contracts\Bin\ccrewrite" "#Application1ccrewrite.rsp"" exited with code -1.
everytime i build the project. Plz help.
Now it's a major problem for me.
Every project using code contracts is showing same error in VS2010 Errors window and 'Application1ccrewrite.rsp' not found in output window, but it is there.
I tried out everything. I installed both versions (Pro, Std) but the problem persist. Plz help !
I had this problem as well. In my case the problem was that ccrewrite cannot work with files in a network folder but requires the project to be on your local hard disk.
I had this problem. The Assembly name and Default namespace of the class library that causes the problem had the same name as an existing DLL in the destination folder. I had been refactoring my code and whilst the namespaces in the CS files had all be changed to namespace2 the default namespace in the properties file was still namespace1
When I corrected this the files all built successfully...
Sometimes you can get this when your solution path is too long, especially with many projects.
Try moving to c:\temp and building it, it might fix it (although of course, this might not be a solution if you need it in the folder it currently is).
This bug I noticed in earlier CC versions and may now be fixed.
I don't know if you had the same problem as me, but I also saw this error. In my case, I had a method with a switch statement, and depending on the branch taken, different requirements applied:
static ITransaction CreateTransaction(
String transType,
MyType1 parm1,
/* Other params unimportant to this example */
String parm5)
{
switch (transType) {
case Transaction.Type.SOME_TRANSFER:
Contract.Requires<ArgumentNullException>(parm1.Account != null, "Account cannot be null.");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(parm5), "parm5 cannot be null or empty.");
// Create instance
return someInst;
case Transaction.Type.SOME_OTHER_TRANSFER:
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(parm1.Type), "Type cannot be null or empty.");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(parm1.Number), "Number cannot be null or empty.");
// Create instance
return someInst;
/* Other cases */
default:
throw new ApplicationException("Invalid or unknown transaction type provided.");
}
}
This was giving me the error you noted in the Errors List when I tried to build. In the output window, I was getting this:
EXEC : Reference Assembly Generator
warning : Something is wrong with
contract number 1 in the method
'TerraCognita.LoanExpress.Domain.Loan.CreateLoanTransaction'
AsmMeta failed with uncaught
exception: Operation is not valid due
to the current state of the object.
I pushed each branch into a method of its own, making Contract.Requires the first lines of code in each method, and I no longer had a compilation problem. It appears that Contract.Requires must be the first lines of code in a method - which makes sense, since they are intended to be used to define pre-conditions.
Hope this helps.
The solution is to put the pre and pos conditions in the first lines. The ccrewrite does not accept that pre and post conditions are below command lines.

Categories