|
I apologize for thinking "your time" might be better served if you asked "better questions". You're wasting your own time.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
of course with a person like you, I believe you taking your buggers out because you have nothing to do rather than bother and waste of your own time to reply me. get a life! turn the page.
|
|
|
|
|
One of the best resources on the planet ==> free code camp[^]
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
Wonder how stupid people to take time and reply, you got it men. you respond you own answer.. take time and reply i know its hard to be you and must hurt.
|
|
|
|
|
And you came to learn.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
I came here to see the stupid they reply to my add and has nothing better to do with their life, Thank you, my research its been successfully completed
|
|
|
|
|
It's called Google. Since using google seems never to have occurred to you, I'll help:
free coding camp .net at DuckDuckGo[^]
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
I see lot idiots here they think are Mr knows everything.. Including your self, Please do not bother to reply or those things I do not think help thank once of the user I am onion i can find weather i want.
|
|
|
|
|
Blah, blah blah...
The first thing you need to learn is how to use google. Even people like you - that aren't know-it-alls - need to learn this. If you can't master that simple skill, you won't be successful as a programmer.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
#realJSOP wrote: The first thing you need to learn is how to use google. Even people like you - that aren't know-it-alls - need to learn this. If you can't master that simple skill, you won't be successful as a programmer. That's a nice one for the old guys: "I am so old that I could be successful as a programmer without mastering the skill of using Google." (The main reason being that Google didn't exist then.)
|
|
|
|
|
tamalera i can see you complain about your life a lot its hard to be you, I can see you have nothing to do more than to remove the snot from your nose. I can see how successful you are that you are here stuck reply to me
|
|
|
|
|
Hello all
I have a project where I from C# code need to use a COM object and consume events.
My COM object can send events by the use of Connectable Objects.
In the good old days when C++ and COM were used, I used the IConnectionPoint and Advice.
But, is there in .NET a way to consume COM events? I guess it will be in the System.Runtime.InteropServices.
|
|
|
|
|
For an early-bound library, you should be able to add event handlers in the same way as any other .NET class.
For a late-bound library, you'll want to use the System.Runtime.InteropServices.ComTypes.IConnectionPoint interface[^], which should be familiar to you from C++.
IIRC, the event sink parameter to the Advise method needs to be public , [ComVisible(true)] , and [ClassInterface(ClassInterfaceType.None)] .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
When creating a .NET Framework 4.7.2 class library that uses a lot of Microsoft's NuGet packages, and creating an internal NuGet package from the library, is there a way to wrap all those MS packages into the library so that they aren't all required in apps built using my library?
Background:
I've got a legacy .NET Framework 4.7.2 console app, initially deployed a few years ago to an app server using a setup project. Updates and enhancements were deployed by merely copying the exe to the installation location, as well as any new DLLs the enhancements required.
We recently decided to have all our internal applications write their logs to Application Insights in Azure, so I created a .NET Framework 4.7.2 class library with this functionality, and added the 20-odd NuGet packages required (this overhead is insane) to support writing to AI. I built my own NuGet package for this library, uploaded it to our DevOps Artifacts. Then I added my package to the legacy app, and when I built the app it added all those MS DLLs to the obj/Release folder. I copied the new DLLs and the new exe to the deployed folder on the server, but running it fails as it can't find the MS DLLs. Setup projects are no longer supported (why???), so I don't know how to get this to work.
Any ideas?
If you think 'goto' is evil, try writing an Assembly program without JMP.
|
|
|
|
|
Would have stuck with the EXE.
Create a (web) server for handling the logging to Azure; your apps talk to the server instead of "NuGet", etc.
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
TNCaver wrote: running it fails as it can't find the MS DLLs
That's the problem you need to fix, but unfortunately you haven't provided enough information about it.
You need to get the full exception details to try to diagnose the problem.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies. The system cannot find the file specified.
If you think 'goto' is evil, try writing an Assembly program without JMP.
|
|
|
|
|
Double-check that the folder your app is running from contains Microsoft.Extensions.DependencyInjection.Abstractions.dll , and that its version is precisely 5.0.0.0 .
v5 of that library[^] doesn't have any additional dependencies, so either the file is missing, or you've got the wrong version.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Yep, did that at the beginning of my troubleshooting. All 20 package DLLs are in the same folder as the exe, just as all the previous DLLs it has been using all along have been. All the correct versions, copied from the obj\x64\Release folder where they were pushed to when I built the project.
If you think 'goto' is evil, try writing an Assembly program without JMP.
|
|
|
|
|
I am using VS 2019, .Net 4.5.2 on Windows 7.
I have an application which manages a configuration file for another application. The abridged version looks like:
<configuration>
<configSections>
<sectionGroup name="ServiceConfiguration" type="My.ServiceConfiguration" >
<section name="CustomSection" type="My.CustomSection" />
<sectionGroup name="ServiceStepGroups" type="My.StepGroups" >
<sectionGroup name="MyGroup1" type="My.StepGroup" />
</sectionGroup>
</sectionGroup>
</configSections>
<ServiceConfiguration>
<CustomSection />
<ServiceStepGroups>
<MyGroup1 />
</ServiceStepGroups>
</ServiceConfiguration>
</configuration>
When I run the program to modify the configuration file to add a new group with code such as:
namespace My
{
public class StepGroups : ConfigurationSectionGroup
{
public My.StepGroup AddNewGroup()
{
My.StepGroup newGroup = new My.StepGroup();
SectionGroups.Add("MyGroup2", newGroup);
}
}
}
and then save the configuration file I get
<configuration>
<configSections>
<sectionGroup name="ServiceConfiguration" type="My.ServiceConfiguration" >
<section name="CustomSection" type="My.CustomSection" />
<sectionGroup name="ServiceStepGroups" type="My.StepGroups" >
<sectionGroup name="MyGroup1" type="My.StepGroup" />
</sectionGroup>
</sectionGroup>
<sectionGroup name="ServiceConfiguration" >
<sectionGroup name="ServiceStepGroups" >
<sectionGroup name="MyGroup2" type="My.StepGroup" />
</sectionGroup>
</sectionGroup>
</configSections>
<ServiceConfiguration>
<ServiceStepGroups>
<CustomSection />
<MyGroup1 />
<MyGroup2 />
</ServiceStepGroups>
</ServiceConfiguration>
</configuration>
As can be seen, the new MyGroup2 declaration element gets wrapped in a new ServiceConfiguration/ServiceStepGroups construct but 1) AFTER the first construct, 2) WITHOUT type attributes and 3) WITHOUT a CustomSection section; however, the MyGroup2 configuration group IS in the right place in the configuration file below.
Why?
I would have expected the declaration of MyGroup2 to immediately follow the declaration of MyGroup1 without a second construct created.
Digging through the source code and [limited] documentation online has not been fruitful.
Is this a bug? Am I forgetting something?
It should be noted that when I load the new configuration file an exception is thrown (duplicate ServiceStepGroups section group) as would be expected; however, if I manually fix the configuration file as per my expectations previously stated the file loads successfully with the new MyGroup2 included.
Any help or insight is appreciated.
Thanks!
|
|
|
|
|
I've never had to save anything from code in the config file, but it would seem that you would want to get the object for the ServiceConfiguration sectionGroup first, add your sectionGroup to that, then resave.
|
|
|
|
|
Hi Dave,
Thanks for responding.
Yes, you are correct. Perhaps I was too brief in my code snippet. But I am able to go in with the debugger and everything appears as it should be; the right sections and groups have the right children, etc.
I have written configuration files before but I can't recall if I was attempting to write multiple groups (different names but same type) as I am now. But again, when I make changes manually and read the file back in everything works, which tells me that the internal mechanisms can handle multiple groups (different names but same type) just fine. Hence the perplexing puzzle.
|
|
|
|
|
Thanks for sharing with us!
|
|
|
|
|
After laborious effort I was able to understand what was happening. Generally, I would consider the behavior in the OP as a bug with the .NET code since it can't read in what it writes out; however, the code seems structured and designed to produce this behavior; therefore, the behavior doesn't appear to be a mistake, just a sore and undocumented design with unintuitive behavior. Since this is such odd, undocumented and unintuitive behavior I felt compelled to share my findings with posterity.
Here is what I found:
Public APIs:
System.Configuration.ConfigurationSectionGroup
This is the configuration construct used to group sections and other groups, essentially a container. It can be subclassed but itself derives from nothing and offers little functionality so it offers little opportunity for customization.
System.Configuration.Configuration
Similar to ConfigurationSectionGroup in that it essentially acts as a container for sections and groups and derives from nothing; however, it is sealed and cannot be subclassed. It provides contextual information, some fundamental constructs for processing connection strings and application settings and the API for saving the configuration to file. It provides some flexibility for customization via delegate actions.
So, by and large, most of the processing of configuration files is behind the scenes and internal to the .NET framework. Therefore, to study these mechanisms required looking into the .NET code base and decompiling the necessary code in the VS debugger.
System.Configuration.MgmtConfigurationRecord
System.Configuration.BaseConfigurationRecord
These classes are internal to the .NET framework and provide much of the guts of configuration management. Simply, each configuration [file] is associated with one configuration record. The configuration record provides bookkeeping of what is in the configuration file and how the configuration information is written.
SaveAs(string filename, ConfigurationSaveMode saveMode, bool forceUpdateAll)
This method is called whenever a user wants to save the configuration file. It manages the save process, essentially providing a wrapper around save functionality and providing error handling. It calls CopyConfig(...) whose job it is to copy over all original configuration file content (comments and all) and integrate the new changes. It calls the following methods:
CopyConfigDeclarationsRecursive(...)
This method copies all content from the declarations section
<configuration>
<configSections>
</configSections>
</configuration>
of the original configuration file. It then calls
WriteUnwrittenConfigDeclarations(...)
which writes any new declarations.
Herein lies the rub!
NEW SECTIONS AND SECTION GROUPS ARE WRITTEN AFTER EXISTING SECTIONS AND GROUPS.
Intuitive, yes? Wrong!
Consider the configuration file XML from the OP:
<configuration>
<configSections>
<sectionGroup name="ServiceConfiguration" type="My.ServiceConfiguration" >
<section name="CustomSection" type="My.CustomSection" />
<sectionGroup name="ServiceStepGroups" type="My.StepGroups" >
<sectionGroup name="MyGroup1" type="My.StepGroup" />
</sectionGroup>
</sectionGroup>
<sectionGroup name="ServiceConfiguration" >
<sectionGroup name="ServiceStepGroups" >
<sectionGroup name="MyGroup2" type="My.StepGroup" />
</sectionGroup>
</sectionGroup>
</configSections>
<ServiceConfiguration>
<ServiceStepGroups>
<CustomSection />
<MyGroup1 />
<MyGroup2 />
</ServiceStepGroups>
</ServiceConfiguration>
</configuration>
We have the main custom section group ServiceConfiguration which holds all business-type configuration information which is unique or specific to the application (as opposed to standard types of configuration constructs such application settings, runtime, service model, etc.). Inside this main group we have the ServiceStepGroups group which in turn declares various groups of steps for the application to perform (MyGroup1 and MyGroup2 ).
However, there are two (2) ServiceConfiguration declarations, a clear violation of the configuration specification which requires uniquely named groups. In the original configuration file we only had MyGroup1 defined where it and its containing groups were declared with the type attribute, necessary for declaring the .NET group type when loading a configuration file. But, we added MyGroup2 after loading the configuration file so that we could re-save the configuration file with the new group.
Here begins the unintuitive behavior .
Because CopyConfigDeclarationsRecursive(...) is called first it writes a complete ServiceConfiguration declaration as copied from the original file. When WriteUnwrittenConfigDeclarations(...) is called it has no choice but to write a second ServiceConfiguration declaration in order to maintain the declaration hierarchy; however, it does so without type attributes, presumably since the .NET type is not required for writing but only when reading. If a declaration (such as ServiceStepGroups ) was not present in the original declaration then the type is written; if a declaration was present a type is not written.
So, this behavior would seem to be a design flaw in SaveAs(...) . However, in the interest of open-mindedness I will hold back eternal judgment since there may be competing objectives or other behavioral scenarios of which I am not aware which drove Microsoft's design. Nonetheless, I think we can all agree that better documentation would have been helpful in understanding the behavior and function of programmatically modifying and saving configuration files. If there is better documentation I could not find it.
The Solution:
After all was discovered and understood I was able to produce a proper configuration file by implementing a post-processing step . It was a workaround: manually modify the XML of the new configuration file (I used the System.Xml libraries) to move new group declarations to their proper place within the original ServiceStepGroups declaration and remove the duplicate hierarchical constructs.
I could have done this in the beginning but I had assumed I didn't need to (based on expectations of intuitive functionality and lack of documentation) and that the problem was with me and my code utilizing the .NET configuration mechanisms. While vindicated technically it was a good (but agonizing ) lesson in the underlying mechanisms of .NET configuration processing and its limitations.
So ending on a positive note maybe this technical dive and case study can provide some documentation or reference to others experiencing a similar issue in the future. I am reminded of a quote from John Adams:
> Posterity! you will never know how much it cost the present generation to preserve your freedom.
> I hope you will make a good use of it. If you do not, I shall repent in Heaven that I ever
> took half the pains to preserve it
Posterity, I hope you make good use of this information.
modified 28-Oct-21 16:29pm.
|
|
|
|
|
This is definitely worth writing up as a Tip/Trick!
That will make the results of your spelunking more permanently visible and searchable.
Forum messages like this are, by their very nature, transient.
Cheers,
Peter
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|