I just want to start by saying that I've done a lot of research but couldn't find an answer, hence the post.
I'm adding user settings functionality to my app which works as a plugin inside a common off the shelf program for architecture (called Autodesk Revit). The main project (let's call it MainProj) has several dependencies including a project that handles logging and usage (let's call it Loggers). I created a Settings file inside the Loggers project with the goal to have users change the logging level from Error to Debug when there are issues so I can ask them to make the change and send me the log.
The issue I'm facing is that when I change the log level directly inside the config file and re-run the command from within Revit, the change doesn't get translated into the log, as if the log level is somehow compiled during design and is never changed.
I actually tried to reproduce the problem in a simpler way and created a little console program and I'm facing the same issue. Below is the code from the Loggers project.
namespace Loggers
{
public static class Logger
{
public static string RunMe()
{
if (Properties.Settings.Default.LogMode == "Debug") { return "DEBUG"; }
else return "NOTHING";
}
}
}
I then changed the LogMode property from Debug to anything else in the config file but the console kept on returning DEBUG.
static void Main(string[] args)
{
Console.WriteLine(Logger.RunMe());
Console.Read();
}
I also tried changing the setting from user to application and editing its value in the config file and re-running the command but the outcome was the same.
Any help would be very much appreciated. I've been stuck on this for a while. Thank you.
Thanks to #BurnsBA, the link you shared had comments saying that the user.config lives in a different folder and it's not created until the user changes a setting. This made me understand that there wasn't a point in manually editing the app.config and expect the settings to work.
I then did some testing by creating a simple form with a checkbox linked to the Property I wanted to change and the user.config file gets created straight after I call the Save() method on the Properties.
private void btnOK_Click(object sender, EventArgs e)
{
if (chkDebugMode.Checked == true)
Loggers.Properties.Settings.Default.LogMode = "Debug";
else Loggers.Properties.Settings.Default.LogMode = "Error";
Loggers.Properties.Settings.Default.Save();
Close();
}
Related
Hi I created this WinForm Program. It has several Forms.
I looked for a tutorial or someting to help and found this on StackoverFlow.
How to use Localization in C#
It was really helpful but..
I created a ResourceString.de-DE.resx File and added it to the Properties Folder.
Added some Strings so i can test it. And changed the Access Modifier to Public.
Then i wanted to access the Properties Folder to Use the ResourceString.de-De.resx File.
But it doesn't get suggested.
The Code has to look like this in the end :
private void setLanguage()
{
btnSwitchLanguage.Text = Properties.ResourceString.de-DE.btnSwitchLanguage;
}
Am I missing something ?
Any Help is appreciated. :)
Thanks
You don't need to add the Strings.resx file, Your project already has the resource file Resources.resx. Therefore, you should add a new resource file with Resources.de.resx name, if required localization for the "de-DE". So, you can put into this resource file not only strings, but images, icons etc.
There is no need to change the Access Modifier to Public unless you are not going to access this resources from another assembly.
NOTE: When you are working in the Visual Studio the Visual Assist
suggestion will be the same for all languages, starting from
Properties.Resources.
You need to create a default 'ResourceString.resx' file along with al your language specific resx files. Make sure to add the same resources in all resx files. (btnSwitchLanguage, ...).
Well i found my mistake, after reading the Thread again, that i linked in my Post.
There should be a File called Strings.resx (or whatever Name you Choose), which contains the original strings.
And the File which contains another language. (German in my Example).
Should have the same name, except the language comes at the end.
Like this :
Strings.de-DE.resx
After that i just had to change my Code to :
private void btnSwitchLanguage_Click(object sender, EventArgs e)
{
if (Thread.CurrentThread.CurrentUICulture.ToString().Equals("de-DE"))
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-GB");
}
else
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-DE");
setLanguage();
}
}
private void setLanguage()
{
btnSwitchLanguage.Text = Properties.Strings.btnSwitchLanguage;
}
I've got some issues running Puma.Net. I've got all the functions looking fine in the code but when it comes this point:
Value = pumaPage.RecognizeToString();
It then gives an error saying the library dibapi.dll can't be found. But I just can't even add it as a reference it says something like
Can't add reference Make sure the file is accessible and that it is a assembly or Com-Component.
So I gave it all the rights it needs to be read, write & executed. I even gave it full controll on all the users but it just won't work.
Maybe I made a mistake somewhere so here is the full code of the programm.
static void Main()
{
string Image = "V:/Test_images/value.PNG";
Console.WriteLine("Running the Program!");
var pumaPage = new PumaPage(Image);
string Value;
using (pumaPage)
{
pumaPage.FileFormat = PumaFileFormat.RtfAnsi;
pumaPage.EnableSpeller = false;
pumaPage.Language = PumaLanguage.Digits;
Value = pumaPage.RecognizeToString();
}
Console.WriteLine("The Value is" + Value);
Console.ReadLine();
}
I've added the Puma.Net dll and "using Puma.Net;" so it should work. Does someone got any idea what could be wrong?
Here is also the errormessage that appears all the time.
The Error Message which appears
If you need a translation just tell me.
Btw it is a Console Application and I would love to keep it that way. If it is not possible then I can also try to use turn it into a Form Application but that's a whole new part for me so it could take a while to get into it.
You need to copy dibapi.dll to the output folder as described in the documentation:
Steps to add Puma.NET to your project:
1. Add reference to Puma.Net.dll;
2. Make sure that after project building the output folder (i.e. bin\Debug or bin\Release)
contains files Puma.Net.dll and puma.interop.dll. If the last is not present (IDE didn’t
copy it) copy it to the folder manually;
3. Copy dibapi.dll to the output folder;
I'm running coded ui automation and defined a method attribute called [ExternalDataSource()] to read a document (csv, xml...) and parse the data into some dictionaries. I'll copy it here so you can have a better insight:
[System.AttributeUsage(System.AttributeTargets.Method)]
public class ExternalDataSource : System.Attribute
{
public ExternalDataSource(string filename)
{
DirectoryInfo di = new DirectoryInfo(Assembly.GetExecutingAssembly().Location);
string file = Path.Combine(Path.GetDirectoryName(di.FullName), filename);
try
{
code
}
catch (Exception)
{
throw new UITestException("Cannot load data source document");
}
}
}
In it I try to access Assembly.GetExecutingAssembly().Location to get a file that is copied to the TestResult/Out folder. I assigned this attribute to only one TestMethod() in the whole application and while debugging, I found out that the application enters the attribute's c'tor twice. Both times the Location is different. Once it's from the bin/Debug folder, the other time it's from the TestResults/Out folder. Two questions:
Why does the debugger enter that attribute twice if I call it only once in my application?
Why does the location of the same assembly change?
Well it seems nobody had an answer, but while debugging a run from the command line using mstest.exe with the vs2012 JIT Debugger i found out a strange thing:
When putting a System.Diagnostics.Debugger.Break() in the class where this attribute is the jitter was called from MSTest.exe but when this breakpoint was in the testmethod decorated with this attribute, QTAgent32.exe was called. I had implemented a singleton class to handle my parameters, and while it was populated in ExternalDataSource in this attribute by MSTest, when entering QTAgent32 (the test) it was empty.
The solution that worked for me was just to initialize that Singleton with the data on [TestInitialize()].
Hope this helps somebody.
I have a WinForm project that contains several UserControls. This WinForm project has a reference to an assembly (lets call it lib.dll) that is created from another project (Class Library) that exists in a different solution.
Now, several of the UserControls make calls into lib.dll that return values from the app.config file. At runtime lib.dll works fine and returns the necessary data but at design time, I am getting an exception from lib.dll because the app.config sections are NULL (the exceptions are by design).
Now I could go through each control and wrap any code that calls into lib with
if(!DesignMode) { //code }
But that is a lot of controls to go and apply that to. Is there something I can do globally that would be more elegant then testing the DesignMode property?
Edit
In response to the two comments left below: the solutions provided don't appear to work. The assembly that is causing me a problem lives in the same directory as the app.config. The general directory structure looks like this
References Folder
Configurations (Folder)
appsettings.config
app.config
lib.dll
app.config pulls in several other config files (appsettings, cnx strings, etc) which reside in the Configurations directory. In the case of my exception the value I am trying to get resides in one of these ancillary config files that is referenced by app.config.
This is an interesting question. A solution could be to create in lib.dll a static class like this one :
public static class Config
{
private static readonly _param1;
static Config()
{
_param1 = ConfigurationManager.AppSettings["Param1"] ?? "Your default value";
}
public static string Param1
{
get { return _param1; }
}
}
Then, in your code, insted of writing ConfigurationManager.AppSettings["Param1"], you will use Config.Param1. So you won't need to test the property DesignMode.
There are so many ways to do this, IMHO.
One thought that immedidately comes to mind would be to use an inheritance-based approach for the user controls in question? That way, in the base class, you can put that if (DesignMode) check in, and do the correct branching from there.
// if i were to visualizeyour lib.dll data initializer call like this:
class BaseUserControl
{
// i'm guessing that you initialize the data somehow...
void InitializeData()
{
if (!DesignMode)
{
InitializeDataLocal();
}
}
protected virtual InitializeDataLocal()
{
// whatever base behavior you want should go here.
}
}
// in the derived classes, just put the code you currently have for
// fetching the data from lib.dll here...
class UserControl : BaseUserControl
{
protected override InitializeDataLocal()
{
// fetch from lib.dll...
// optionally invoke some base behavior as well,
// if you need to...
base.InitializeDataLocal();
}
}
I've been looking at modifying the source of the Doppler podcast aggregator with the goal of being able to run the program directly from my mp3 player.
Doppler stores application settings using a Visual Studio designer generated Settings class, which by default serializes user settings to the user's home directory. I'd like to change this so that all settings would be stored in the same directory as the exe.
It seems that this would be possible by creating a custom provider class which inherits the SettingsProvider class. Has anyone created such a provider and would like to share code?
Update: I was able to get a custom settings provider nearly working by using this MSDN sample, i.e. with simple inheritance. I was initially confused as Windows Forms designer stopped working until I did this trick suggested at Codeproject:
internal sealed partial class Settings
{
private MySettingsProvider settingsprovider = new MySettingsProvider();
public Settings()
{
foreach (SettingsProperty property in this.Properties)
{
property.Provider = settingsprovider;
}
...
The program still starts with window size 0;0 though.
Anyone with any insight to this?
Why the need to assing the provider in runtime---instead of using attributes as suggested by MSDN?
Why the changes in how the default settings are passed to the application with the default settings provider vs. the custom one?
Why not use the CodeProject PortableSettingsProvider solution as is (with a few minor changes) ?
I have done so in my project (StreamRecorder.NET) with success.
Some comments on the project's page were useful:
http://www.codeproject.com/Messages/2934144/Fixed-csharp-version.aspx
http://www.codeproject.com/Messages/3285411/Re-Win-Form-Designer-breaking-with-custom-Settings.aspx
And the code I ended up with:
static void Main(string[] args)
{
if (args.Contains("-p") || args.Contains("--portable"))
{
MakePortable(Properties.Settings.Default);
MakePortable(Properties.LastUsedSettings.Default);
MakePortable(Properties.DefaultSettings.Default);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(args));
}
private static void MakePortable(ApplicationSettingsBase settings)
{
var portableSettingsProvider =
new PortableSettingsProvider(settings.GetType().Name + ".settings");
settings.Providers.Add(portableSettingsProvider);
foreach (System.Configuration.SettingsProperty prop in settings.Properties)
prop.Provider = portableSettingsProvider;
settings.Reload();
}
Lastly I made these changes to the CP project:
string _fileName;
public PortableSettingsProvider(string fileName)
{
_fileName = fileName;
}
public virtual string GetAppSettingsFilename()
{
//Used to determine the filename to store the settings
//return ApplicationName + ".settings";
return _fileName;
}
I know this question is quite old already. I just want to share my own version of a portable settings provider which I published as nuget package here.
The usage is pretty simple:
// make the default settings class portable
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
I also explained the basic strategy of this implementation at https://www.codeproject.com/Articles/1238550/Making-Application-Settings-Portable.
Just to 'close' the question: The somewhat unsatisfactory solution I ended up with was
Create a custom settings provider, which inherits from SettingsProvider and stores the settings in a XML file
Set the Provider property of each of the setting (by selecting the entire grid in the designer) to the custom settings provider using the designer
Drawbacks: The forms designer breaks and gives an exception which basically says that the custom provider class cannot be found. The built exe however works OK. Setting the provider in the code as described in the question makes the designer work, but then for some reason, which I haven't looked closely at, the settings won't serialize.
It seems that making settings portable was all that was needed to make Doppler portable. Whether I'll start using Doppler as my main podcast aggregator or stick with my homebrew command line aggregator, I'll see.