views:

558

answers:

4

This question is kind of anecdotical but still interesting to me; I was wondering why Visual Studio 2008 is not loving the following use of constants:

public class Service101 : ServiceBase
{
    /// <remarks>
    /// Shown at Start -> Settings -> Control Panel -> Administrative Tools -> Services
    /// </remarks>
    internal const string SERVICE_NAME = "WinSvc101";
    /// <remarks>
    /// Shown at Start -> Settings -> Control Panel -> Administrative Tools -> Services
    /// </remarks>
    internal const string DISPLAY_NAME = "Windows Service 101";
    /// <summary>
    /// Public constructor for Service101.
    /// </summary>      
    public Service101()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
        this.ServiceName = Service101.SERVICE_NAME;
        this.EventLog.Source = Service101.DISPLAY_NAME;
        this.EventLog.Log = "Application";

        if (!EventLog.SourceExists(Service101.DISPLAY_NAME))
        {
            EventLog.CreateEventSource(Service101.DISPLAY_NAME, "Application");
        }
    }
    #region Events
    /// <summary>
    /// Dispose of objects that need it here.
    /// </summary>
    /// <param name="disposing">Whether or not disposing is going on.</param>
    protected override void Dispose(bool disposing)
    {
        // TODO: Add cleanup code here (if required)
        base.Dispose(disposing);
    }

As it's showing the following Warning at design time:

Warning 1 The designer cannot process the code at line 68: 

if (!EventLog.SourceExists(DISPLAY_NAME))
{
    EventLog.CreateEventSource(DISPLAY_NAME, "Application");
}

The code within the method 'InitializeComponent' is generated by the designer and should not be manually modified.  Please remove any changes and try opening the designer again. E:\Proyectos\beanstalk\dotnetfx\trunk\WinSvc101\WinSvc101\Service101.cs 69 0

Any comment would be quite appreciated. Thanks much in advance.

+4  A: 

It actually told you. That code is generated by the designer. The designer needs it to be the way it left it. Do not change that code, unless you want the designer to do unpleasant things with it.


There's a sort of equilibrium between what you see in a visual designer and the code that it has generated.

  1. You start with an empty design surface, so there's no generated code
  2. You drag something onto the design surface. The designer generates the code necessary to create it.
  3. You set properties of that object, and the designer generates the code that sets the properties as you have specified.
  4. You Save and close
  5. You reopen the document in the designer. The designer has to figure out what to display on the design surface. It reads the code that it generated, and since it knows the code was generated by itself, it knows what that code means in terms of the design surface.
  6. Next time there's a change or save, it will regenerate the code.

Now, let's say you make some modification to the generated code. Unless you make that change in exactly the same way the designer would have done, it will not recognize the change. Your change will not show on the design surface. Next time there's a change or save, the designer will regenerate the code without your changes.

So, if you don't want to lose your changes to generated code, then don't make any changes to generated code.

John Saunders
John, thanks a lot for such elaborated comment!
Nano Taboada
That's all fine but doesn't exactly help to resolve anything. The root cause question is really what does designer actually run and see. I just opened some old code which is loading and populating a few UI fields from a config file and "designer" doesn't seem to even see or run non-const assignments on the form's own privates.
ZXX
@ZXX: The point was that the designer created that code, and the designer does what it wants with that code - don't touch it, unless you are the designer.
John Saunders
Except that in real life you have to. People ask that kind of question hoping to learn some mechanincs of what is reasonably doable so "honor thy lord" doesn't really help. One can always backup and diff if designer really messes something, but one needs to know how much he can change before designer refuses to load so you can see a visual correspondence. Looks like there's a custom serializer involved. I see new-s honored and even array assignments, but not statics, or maybe just CLR's statics, or maybe object from referenced dll-s but not from the current build ...
ZXX
@ZXX: Microsoft has documented the set of "reasonable changes" you can make to designer-generated code. The set is empty. If you find yourself needing to change generated code, then you're doing something wrong, and you should ask for help. **NEVER** change generated code. Would partial classes help you?
John Saunders
If I docs were ever my limits I'd still be locking Hashtables :-) Reality takes presedence and it says that I'm messing with the code from someone who new winforms inside out so he had no use for a lame "designer" and did a few things to stop it :-) But I do since I'm a backend dev in need of a quick fix. Backup and diffing comes natural to me and I need to grasp as much gray-zone info as I can in no time. Every time I touch that code I'm bleeding perf so I'm going to revert most changes anyway. You can actually see it at http://webservicestudio.codeplex.com/SourceControl/list/changesets
ZXX
Btw taking autogens apart is quite a common practice for hi-perf codebases where you have to justify every changed line and "autogen did it" counts as much as a "cat did it". My favs are still from xsd and linq but they are one way so it's easier. We need the autogen-modder section here :-) Lots of good stuff to learn as well.
ZXX
+2  A: 

The designer is not happy when you add code to InitializeComponent(). Try something like this instead:

public Service101()
{
    InitializeComponent();
    this.createEventSource();
}

private void InitializeComponent()
{
    this.ServiceName = SERVICE_NAME;
    this.EventLog.Source = DISPLAY_NAME;
    this.EventLog.Log = "Application";
}

void createEventSource()
{
    if (!EventLog.SourceExists(DISPLAY_NAME))
    {
     EventLog.CreateEventSource(DISPLAY_NAME, "Application");
    }
}
Andrew Hare
Andrew, thanks much for the comment! With your changes now the messages change to:Warning 1 The variable 'SERVICE_NAME' is either undeclared or was never assigned.Warning 2 The variable 'DISPLAY_NAME' is either undeclared or was never assigned.
Nano Taboada
To solve the warning I had to use Service101.SERVICE_NAME and Service101.DISPLAY_NAME respectively.
Nano Taboada
+3  A: 

Seems quite clear to me. It's telling you that you have modified automatically generated code and you shouldn't do that.

In the worst case, you probably could lose your changes. In the best, it finds some unexpected code and it doesn't change anything so you don't lose your changes. But it also can't understand your code. You should place your constants in any other location.

Jaime Pardos
Thanks for your contribution Jaime!
Nano Taboada
+1  A: 

Slightly off the point, but I don't really see why you are using constants (and public ones at that), anyway. Couldn't you just do this?

private void InitializeComponent()
{
    this.ServiceName = "WinSvc101";
    this.EventLog.Source = "Windows Service 101";
    // ....
}
Dan Diplo
Hey Dan, thanks much for your comment. To answer your question, I'm using constants there because I want to guarantee the condition where the serviceInstaller.ServiceName property always matches Service101.ServiceName. Don't hesitate to comment if you know a better way to achieve that!
Nano Taboada
They're public basically because I need to use them in other class as well.
Nano Taboada
Instead of public, you could use internal - that way they are accessible within your classes but not outside.When I've written Services I've normally stored configuration values in the special app.config file and then read them into static internal properties when the service starts. These properties are then accessible to your classes, but not exposed publicly. Of course, there may well be a better way than that - I'm no expert! Good luck.For app.config See: http://geekswithblogs.net/akraus1/ articles/64871.aspx
Dan Diplo
Thanks much for the comment! I've modified the comment with the _internal_ modifiers.
Nano Taboada