I am writing an app (something like Notepad) in C#. I'm using Properties.Settings class to save user preferences. It was working fine until suddenly when it started showing this exception message anytime I try to run it.
Configuration system failed to initialize
I noticed that the error originated from this part of the code:
private void TextPad_Load(object sender, EventArgs e)
{
rtbText.WordWrap = Properties.Settings.Default.WordWrap;
rtbText.Font = Properties.Settings.Default.DefFont;
rtbText.ForeColor = Properties.Settings.Default.ForeColor;
rtbText.BackColor = Properties.Settings.Default.BackColor;
if (Properties.Settings.Default.ShowLast)
{
OpenLocalFile(Properties.Settings.Default.LastFile);
}
// There are other lines which are not relevant to this question
}
I moved the supposedly lines to the form constructor immediately after InitializeComponent(); but I still got the same error.
Actually the compiler is telling the error originates from this in Settings.Designer.cs:
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool WordWrap {
get {
return ((bool)(this["WordWrap"]));
}
set {
this["WordWrap"] = value;
}
If I remove rtbText.WordWrap = Properties.Settings.Default.WordWrap; from TextPad_Load, it shows
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("Consolas, 9.75pt")]
public global::System.Drawing.Font DefFont {
get {
return ((global::System.Drawing.Font)(this["DefFont"]));
}
set {
this["DefFont"] = value;
}
The only solution now is either to remove those lines from TextPad_Load (which makes the idea loading user preferences useless) or starting a new project (which I have done, anyway). Can someone please explain what the exception message means and maybe I can get a solution (in case I run into it again)? Microsoft VS Help is not giving me anything tangible.
Thanks
It might help to throw away your existing .config files.
After changes in the Properties.Settings the old file might not be valid any more (changed names, or removed items no longer recognized).
Note that user scoped settings are stored in (drive):\Users(usr)\AppData\Local\Microsoft...something
Related
I have this control (db is the Entity Framework context):
if (db.Sites.Any(s => s.Name.Equals(name))) throw new NameAlreadyInUseException(name);
When I run my tests and debug it fails giving me the error:
Error CS0103: the name 's' does not exist in the current context.
I honestly can't get my head around it and Google hasn't really been helping... any help is appreciated, thanks in advance. Isn't s used correctly here? (I'm still learning, so maybe I missed something but my code here looks ok to me)
Edit:
the debugger triggers the error on this line and I am not using s in any other place other than inside that if statement. (I edited the line to show what happens with the if)
Edit2: complete code of the function
public void CreateSiteOnDb(string connectionString, string name, int timezone, int sessionExpirationTimeInSeconds,
double minimumBidIncrement)
{
CheckInput_CreateSiteOnDb(connectionString, name, timezone, sessionExpirationTimeInSeconds, minimumBidIncrement);
try
{
using (var db = new AuctionSiteContext(connectionString))
{
if (db.Sites.Any(s => s.Name.Equals(name))) throw new NameAlreadyInUseException(name);
var site = new Entities.Site
{
Name = name,
Timezone = timezone,
MinimumIncrement = minimumBidIncrement,
SessionExpirationInSeconds = sessionExpirationTimeInSeconds
};
db.Sites.Add(site);
db.SaveChanges();
}
}
catch(NameAlreadyInUseException)
{
throw;
}
catch(Exception)
{
throw new UnavailableDbException();
}
}
Edit3: Error as shown during debugging
It is not in the right scope.
In the screenshot you are in the scope of CreateSiteOnDb -> try -> using, but s does not belong to that context.
In very basic terms s => .... is converted to function of a class, and it is called from inside Any. so let's assume that our expression is function named Steve. Steve would look like this:
bool Steve(ISite s)
{
return s.Name.Equals(name);
}
this means s is the parameter of Steve, and is only valid inside Steve, which becomes CreateSiteOnDb -> try -> using -> Any -> Steve
So to see s you need to be in two more levels. Please, put your cursor inside the expression and then put a breakpoint.
Basically the problem is that each time the assembly version changes (i.e. the user installs a new version of the application) all their settings are reset the the defaults (or more accurately a new user.config file is created in a folder with a different version number as the name)
How can I keep the same settings when upgrading versions, since using ini files or the registry seem to be discouraged?
When we used Clickonce it seemed to be able to handle this, so it seems like it should be able to be done, but I'm not sure how.
ApplicationSettingsBase has a method called Upgrade which migrates all settings from the previous version.
In order to run the merge whenever you publish a new version of your application you can define a boolean flag in your settings file that defaults to true. Name it UpgradeRequired or something similar.
Then, at application start you check to see if the flag is set and if it is, call the Upgrade method, set the flag to false and save your configuration.
if (Settings.Default.UpgradeRequired)
{
Settings.Default.Upgrade();
Settings.Default.UpgradeRequired = false;
Settings.Default.Save();
}
Read more about the Upgrade method at MSDN. The GetPreviousVersion might also be worth a look if you need to do some custom merging.
The next short solution works for me when we need to upgrade only once per version. It does not required additional settings like UpgradeRequired:
if (!ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).HasFile)
Settings.Default.Upgrade();
I know it's been awhile...
In a winforms app, just call My.Settings.Upgrade() before you load them. This will get the latest settings, whether the current version or a previous version.
Here's my research in case anyone else is having a hard time with migrating settings that have been changed/removed. Basic problem is that GetPreviousVersion() does not work if you have renamed or removed the setting in the new version of your application. So you need to keep the setting in your Settings class, but add a few attributes/artifacts to it so that you don't inadvertently use it in the code elsewhere, making it obsolete. A sample obsolete setting would look like this in VB.NET (can easily be translated to C#):
<UserScopedSetting(),
DebuggerNonUserCode(),
DefaultSettingValue(""),
Obsolete("Do not use this property for any purpose. Use YOUR_NEW_SETTING_NAME instead."),
NoSettingsVersionUpgrade()>
Public Property OldSettingName() As String
Get
Throw New NotSupportedException("This property is obsolete")
End Get
Set
Throw New NotSupportedException("This property is obsolete")
End Set
End Property
Make sure you add this property to the same namespace/class that has your application settings. In VB.NET, this class is named MySettings and is available in My namespace. You can use partial class functionality to prevent your obsolete settings from mixing up with your current settings.
Full credit to jsharrison for posting an excellent article about this issue. You can read more details about it there.
Here's a variation on the solutions presented here that encapsulates the upgrade logic into an abstract class that settings classes can derive from.
Some proposed solutions use a DefaultSettingsValue attribute to specify a value that indicates when previous settings were not loaded. My preference is to simply use a type whose default value indicates this. As a bonus, a DateTime? is helpful debugging information.
public abstract class UserSettingsBase : ApplicationSettingsBase
{
public UserSettingsBase() : base()
{
// Accessing a property attempts to load the settings for this assembly version
// If LastSaved has no value (default) an upgrade might be needed
if (LastSaved == null)
{
Upgrade();
}
}
[UserScopedSetting]
public DateTime? LastSaved
{
get { return (DateTime?)this[nameof(LastSaved)]; }
private set { this[nameof(LastSaved)] = value; }
}
public override void Save()
{
LastSaved = DateTime.Now;
base.Save();
}
}
Derive from UserSettingsBase:
public class MySettings : UserSettingsBase
{
[UserScopedSetting]
public string SomeSetting
{
get { return (string)this[nameof(SomeSetting)]; }
set { this[nameof(SomeSetting)] = value; }
}
public MySettings() : base() { }
}
And use it:
// Existing settings are loaded and upgraded if needed
MySettings settings = new MySettings();
...
settings.SomeSetting = "SomeValue";
...
settings.Save();
If your changes to user.settings are done programmatically, how about maintaining a copy of (just) the modifications to user.settings in a separate file, e.g. user.customized.settings?
You probably still want to maintain and load the modified settings in user.settings as well. But this way when you install a newer version of your application with its newer version of user.settings you can ask the user if they want to continue to use their modified settings by copying them back into the new user.settings. You could import them wholesale, or get fancier and ask the user to confirm which settings they want to continue to use.
EDIT: I read too quickly over the "more accurately" part about assembly versions causing a new user.settings to be installed into a new version-specific directory. Thus, the idea above probably doesn't help you, but may provide some food for thought.
This is how I handled it:
public virtual void LoadSettings(ServiceFileFormBaseSettings settings = null, bool resetSettingsToDefaults = false)
{
if (settings == null)
return;
if (resetSettingsToDefaults)
settings.Reset();
else
{
settings.Reload();
if (settings.IsDefault)
settings.Upgrade();
}
this.Size = settings.FormSize;
}
and in the settings class, I defined the IsDefault property:
// SaveSettings always sets this to be FALSE.
// This will have the default value TRUE when first deployed, or immediately after an upgrade.
// When the settings exist, this is false.
//
[UserScopedSettingAttribute()]
[DefaultSettingValueAttribute("true")]
public virtual bool IsDefault
{
get { return (bool)this["IsDefault"]; }
set { this["IsDefault"] = value; }
}
In the SaveSettings, I set IsDefault to false:
public virtual void SaveSettings(ServiceFileFormBaseSettings settings = null)
{
if (settings == null) // ignore calls from this base form, if any
return;
settings.IsDefault = false;
settings.FormSize = this.Size;
settings.Save();
}
I can't sort this weird issue out and I have tried anything and everything I can think of.
I got 5 pages, everyone of them passing variables with navigation this way:
Pass:
NavigationSerice.Navigate(new Uri("/myPage.xaml?key=" + myVariable, UriKind.Relative));
Retrieve:
If (NavigationContext.QueryString.ContainsKey(myKey))
{
String retrievedVariable = NavigationContext.QueryString["myKey"].toString();
}
I open a list on many pages and one of the pages automatically deletes an item from the list actualProject (actualProject is a variable for a string list). Then, when I go so far back that I reach a specific page - the app throws an exception. Why? I have no idea.
The code that deletes the item:
// Remove the active subject from the availible subjects
unlinkedSubjects.Remove(actualSubject);
unlinkedsubjectsListBox.ItemsSource = null;
unlinkedsubjectsListBox.ItemsSource = unlinkedSubjects;
Then the page that throws the exception's OnNavigatedTo event:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.ContainsKey("key"))
{
actualProject = NavigationContext.QueryString["key"];
try
{
//Read subjectList from IsolatedStorage
subjectList = readSetting(actualProject) != null ? (List<String>)readSetting(actualProject) : new List<String>();
//Put the subjectList into the subjectListBox
subjectListBox.ItemsSource = subjectList;
//Set the subjectsPageTitle to the "actualProject" value, to display the name of the current open project at the top of the screen
subjectsPageTitle.Text = actualProject;
}
catch (Exception)
{
if (language.Equals("en."))
{
// Language is set to english
MessageBox.Show("Couldn't open the project, please try again or please report the error to Accelerated Code - details on the about page");
}
else if (language.Equals("no."))
{
// Language is set to norwegian
MessageBox.Show("Kunne ikke åpne prosjektet, vennligst prøv igjen eller rapporter problemet til Accelerated Code - du finner detaljer på om-siden");
}
}
}
}
Exception:
_exception {System.ArgumentException: Value does not fall within the expected range.} System.Exception {System.ArgumentException}
My theory:
The app kind of loads the currently opened and modified List. Is that possible? No idea.
So there are a number of ways to pass data between pages.
The way you have chosen is the least suggested.
You can use the PhoneApplicationService.Current dictionary but this is messy also if you have a ton of variables, doesn't persist after app shut down and could be simplified.
I wrote a free DLL that kept this exact scenario in mind called EZ_iso.
You can find it here
Basically what you would do to use it is this.
[DataContractAttribute]
public class YourPageVars{
[DataMember]
public Boolean Value1 = false;
[DataMember]
public String Value2 = "And so on";
[DataMember]
public List<String> MultipleValues;
}
Once you have your class setup you can pass it easily between pages
YourPageVars vars = new YourPageVars { /*Set all your values*/ };
//Now we save it
EZ_iso.IsolatedStorageAccess.SaveFile("PageVars",vars);
That's it! Now you can navigate and retrieve the file.
YourPageVars vars = (YourPageVars)EZ_iso.IsolatedStorageAccess.GetFile("PageVars",typeof(YorPageVars));
This is nice because you can use it for more than navigation. You can use it for anything that would require Isolated storage. This data is serialized to the device now so even if the app shuts down it will remain. You can of course always delete the file if you choose as well.
Please make sure to refer to the documentation for any exceptions you have. If you still need help feel free to hit me up on twitter #Anth0nyRussell or amr#AnthonyRussell.info
I'm trying to save two Lists of objects in the phone ApplicationSettings, but I'm stuck at a strange issue (But it's probably me making a silly mistake somewhere).
If I only save one of the lists, it works as supposed - It'll save it, and reload it when app is launched next time.
But if I try to save 2 lists, none of them seem to be saved correctly. No errors or anything, just "blankness".
See code below.
//My save method
public void Gem()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains(INDTASTNINGER_LIST))
{
settings[INDTASTNINGER_LIST] = _indtastningsListe;
}
else
settings.Add(INDTASTNINGER_LIST, _indtastningsListe);
if (settings.Contains(INDTASTNINGER_LIST2))
{
settings[INDTASTNINGER_LIST2] = _indtastningsListe2;
}
else
settings.Add(INDTASTNINGER_LIST2, _indtastningsListe2);
settings.Save();
}
//Constructor supposed to load settings
public Indtastninger()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains(INDTASTNINGER_LIST))
{
_indtastningsListe = null;
_indtastningsListe = (List<Indtastning>)settings[INDTASTNINGER_LIST];
}
if (settings.Contains(INDTASTNINGER_LIST2))
{
_indtastningsListe2 = null;
_indtastningsListe2 = (List<Indtastning>)settings[INDTASTNINGER_LIST2];
}
}
What am I doing wrong?
If I comment out the part with "list2" stuff, the first one will be saved/retrieved perfectly.
I have faced the same issue some time ago, the problem is that you only can save on the IsolatedStorage objects that are XML serializables.
if you save other object, it will work even with the debugger but when the app is restarted, all the saved data is lost.
I'm creating a custom workflow activity in VS2010 targeting .NET 3.5. The DLL is actually being used in a Microsoft System Center Service Manager custom workflow, but I don't think that is my issue.
I have a public string property, that the user types in the string of what the activity should use. However, when the WF runs, it errors out 'value cannot be null'. I want to target if it is my code or something else.
When we drag my custom activity onto the designer, I'm able to type in the text of the string on the designer for that property.
public static DependencyProperty ChangeRequestStageProperty = DependencyProperty.Register("ChangeRequestStage", typeof(String), typeof(UpdateChangeRequestStage));
[DescriptionAttribute("The value to set the ChangeRequestStage Property in the ChangeRequest Extension class.")]
[CategoryAttribute("Change Request Extension")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public String Stage
{
get { return ((String)(base.GetValue(UpdateChangeRequestStage.ChangeRequestStageProperty))); }
set { base.SetValue(UpdateChangeRequestStage.ChangeRequestStageProperty, value); }
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
EnterpriseManagementGroup emg = CreateEMG();
//System.WorkItem.ChangeRequest Extension - ClassExtension_928bec0a_cac4_4a0a_bd89_7146c9052fbe
ManagementPackClass mpcChangeRequest = emg.EntityTypes.GetClass(new Guid("8c6c6057-56ad-3862-47ec-dc0dde80a071"));
//System.WorkItemContainsActivity Relationship Class
ManagementPackRelationship workItemContainsActivityRelationship = emg.EntityTypes.GetRelationshipClass(new Guid("2DA498BE-0485-B2B2-D520-6EBD1698E61B"));
EnterpriseManagementObject changeRequest = null;
//Loop thru each emo (Change Request in this case), and assign it. There will never be more than 1 emo returned
foreach (EnterpriseManagementObject obj in emg.EntityObjects.GetRelatedObjects<EnterpriseManagementObject>(executionContext.ContextGuid, workItemContainsActivityRelationship, TraversalDepth.OneLevel, ObjectQueryOptions.Default))
{ changeRequest = obj; }
EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(changeRequest);
if (emop != null)
{ emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage; }
emop.Commit();
return base.Execute(executionContext);
}
Since it is getting a 'value cannot be null' error, I'm guessing it's on this line:
emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage;
I'm going to test and see if hardcoding a value works or not. Any ideas?
enter code here
try this
if (emop != null && emop.Object[mpcChangeRequest, "ChangeRequestStage"] != null)
emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage
I didn't want to leave this question wide open, so I'm updating it as to how I resolved this (a long time ago).
Rather than working with an EnterpriseManagementObjectProjection (emop), I worked with a standard EnterpriseManagementObject (emo). From there, I was able to follow a similar format from above:
ManagementPackClass mpcChangeRequest = emg.EntityTypes.GetClass(new Guid("8c246fc5-4e5e-0605-dc23-91f7a362615b"));
changeRequest[mpcChangeRequest, "ChangeRequestStage"].Value = this.Stage;
changeRequest.Commit();