NLog application level variables - c#

I'm tasked with a WPF app & have chosen NLog for our logging.
I note answers here and here I would like to do something similar but with .net Desktop & with more control.
I would like to set a guid once at app start and each log entry (at any level) have this guid included automatically, so I can search on that guid. Creating a new guid when the user logs in.
Going further it would actually be good knowledge to know if I can programmatically add any variables that get included with every Log I make, so I dont have to add them to each and every Log.AnyLevel, an example output:
DateTime | LoginID | SessionGuid | MyMessage
to get this output I like to only do:
logger.Trace("MyMessage")
LoginID & SessionGuid being set either when App starts or I instantiate a ViewModel or the User Logs in.
I note at present I can do this per log with
LogEventInfo
How can I add a variable once (from code) and have it always included?

You can setup a NLog GDC variable:
GlobalDiagnosticsContext.Set("AppGuid",Guid.NewGuid().ToString());
And then reference that in your layouts:
${gdc:item=AppGuid}
See also https://github.com/NLog/NLog/wiki/Gdc-layout-renderer

Related

How to reset a password via BAPI in a CUA environment?

I am currently developing a C# application with SAP NCo 3.
I am wondering if I could invoke BAPI into CUA and this BAPI would pass details to child system.
This field is available through Test Function Module (field "RFC target sys"), but it is unavailable directly in standard BAPIs when accessed from SAP NCo.
In ABAP, devs can use:
call function 'BAPI_USER_CHANGE' destination '<TARGET_SYS>'
Can I use something similar in NCo library?
IRfcFunction rfcs = rfcDest.Repository.CreateFunction("BAPI_USER_CHANGE");
Does anybody know how this could be achieved?
Main intent is to reset user passwords to initial ones through App(BAPI) --> CUA --> ChildSystem
Without direct access into child systems.
Hmm, it looks like you have not yet fully understood the meaning of "RFC target sys".
In SE37 "RFC target sys" you enter the name of an RFC destination, which provides details about in which SAP system you want to execute the function module. These details are then defined in SM59, where you can specify parameters like hostname, system number, client, user, password, language, etc.
In the NCo library you do the same via the Class RfcDestinationManager. Here you define the parameters (hostname, system number, client, user, password, language, etc.) of the target system in which you want to execute the function module.
So the line
"RFC target sys: TARGET_SYS"
in SE37 corresponds to a line like
RfcDestination myDest = RfcDestinationManager.GetDestination("TARGET_SYS");
in your .NET program.
And a line of ABAP code like
call function 'BAPI_USER_CHANGE' destination 'TARGET_SYS'
would then correspond to some .NET code like
RfcDestination targetSys = RfcDestinationManager.GetDestination("TARGET_SYS");
IRfcFunction bapiUserChange = targetSys.Repository.CreateFunction("BAPI_USER_CHANGE");
targetSys.Invoke(bapiUserChange);
Note: setting of the input values and error handling is omitted here.
Ok, so I found out that what I wanted to achieve is not possible with just sapnco.
But, in SAP I created function module, which calls function module and uses DESTINATION 'target_sys' to run in end system. This way I achieved what I wanted. By calling my Z_FUNC_MODULE from sapnco I pass variable target_sys and FN is called in child system of CUA.
Hope this helps to someone.

Get other user's Outlook availability information

I am writing an application that creates an overview of peoples Outlook calendars, i.e it will show the amount of unplanned time per week for the coming [n] weeks.
The basics are working, but there's one thing that I am having trouble with. Some users have shared their Outlook calendar in a way so that other users can only see availability information (the time and description of the appointments), but not any details.
I verified this by opening Outlook manually and opening a shared calendar; hovering the mouse over an appointment will show a popup with begin and end time, description and location, but double clicking it gives an error: "You are not authorized to display the calendar, do you want to ask [person] to share it?".
The relevant lines from my code are:
var outlook = new Application();
var mapiNamespace = outlook.GetNamespace("MAPI");
var recipient = mapiNamespace.CreateRecipient("Scott");
recipient.Resolve();
var calendarFolder = mapiNamespace.GetSharedDefaultFolder(recipient, OlDefaultFolders.olFolderCalendar);
var calendarItems = calendarFolder.Items;
Everything I now try to do with calendarItems will raise an exception. For instance, getting Count will raise a TargetInvocationException (The client process failed, but I'm not quite sure about the exact English translation). Calling Sort("[Start]") will raise a COMException with message Unknown property: Start. Both do work for fully shared calendars.
Now, for the overview, all I need is begin and end times, so I don't really want to ask everyone to change their sharing settings, especially when that shouldn't be necessary.
My questions are:
Most important: Is there another way to get availability info that I'm overlooking?
And related: Is Interop still the way to go these days, or are there alternatives? Maybe an Office365 webservice?
Instead of using GetSharedDefaultFolder and accessing the items in that folder, you can use Recipient.FreeBusy method.

How can I change a default global key used in my app in a windows form application?

I have an app with a global key by default and it works perfectly, but I want when somebody else use my app, use their desired global key by changing it in setting form in my app.
There are 3 checkboxes, one for ctrl, alt and shift, and one combobox from A to Z and a button for saving the new global key and can save it for future using, but I don't know how to do it.
I'm using visual studio 2013, Windows Forms and I want the setting be saved for loading it after closing and opening the app again.
How can I create and save this setting so I can use even after closing the application?
You could do this to build your keys object:
Keys keys = Keys.None;
if (chkControl.Checked)
keys |= Keys.Control;
if (chkShift.Checked)
keys |= Keys.Shift;
if (chkAlt.Checked)
keys |= Keys.Alt;
Keys selectedKey;
Enum.TryParse(cbSelectedKey.SelectedValue.ToString(), out selectedKey);
keys |= selectedKey;
And then save the value in the project settings for example:
Right click your project, go to properties then settings. Add a new field of type int.
And then you can save it: (using YourPrjName.Properties;)
// Shortcut is the name of the property I created.
Settings.Default.Shortcut = (int)keys;
Settings.Default.Save();
To retrieve the value when it is already saved just access:
var keys = (Keys)Settings.Default.Shortcut;
Some resources to understand better each step described here:
Application Settings Overview
How to Create Application Settings
Keys Enumeration
Flags Attribute
It seems like you're asking for help with allowing your end-users to modify the keyboard settings of your application. There's a few possible ways you could do this:
Keep an internal reference to the saved key in the application settings.
Have your application parse its configuration data from an external configuration file (e.g. a .txt/.xml/etc.). Overwrite this configuration file with the new settings each time the user changes and saves their configuration.
for .txt: http://msdn.microsoft.com/en-us/library/aa287535%28v=vs.71%29.aspx
for .xml: http://msdn.microsoft.com/en-us/library/cc189056%28VS.95%29.aspx
Create a class to encapsulate the behavior which implements Serializable. Load an instance of this at launch and save a new instance of this class when the user modifies the configuration.
This can get you started with the process of saving the objects: http://tech.pro/tutorial/618/csharp-tutorial-serialize-objects-to-a-file

Count the number of times the Program has been launched

How can I get the number of times a program has previously run in c# without keeping a file and tallying. Is there a Application class or something in c# to check the count.
Please give a detailed explantion as i know nothing about it.This is A windows console application not windows forms.
You can do that my creating an Entry in the Registry. And another way is by using an Application Settings.
But I prefer Application Settings because it has less task to do.
See HERE: Creating an Application Settings.
Tutorial From Youtube
Recent versions of Windows automatically maintain this information in the registry under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist.
The data is obfuscated with ROT13, but that's easy to "decrypt". A free utility (with source code) is available and can serve as your starting point.
You could send a message to a database or webservice every time the program starts up (assuming there's a network connection).
You could keep a count on some form of hardware thet's not a standard storage device (therefore not technically being a file).
You could make a registry entry that you keep the count in (if you ignore the fact that the registry entry is, at some level, persisted into a file somewhere).
You could just have a file somewhere that keeps track of the count. Not sure why you're so opposed to this one in the first place....
If you are running a Winforms application, the you can easily use the Application Settings. Right click on your Solution Name --> Properties --> Settings Tab. More info and tutorial here.
Then, every time your program starts, increment this setting and save it.
Ref: Count the number of times the Program has been launched
In my knowledge Windows does not keep this information for you. You would have to tally the value somewhere (file, database, registry setting).
Better way is Application Settings as:
Create setting in app.config and then use it as:
Properties.Settings.Default.FirstUserSetting = "abc";
then, you usually do this in the Closing event handler of the main form. The following statement to Save settings method.
Properties.Settings.Default.Save();
Implementation using Registry:
static string AppRegyPath = "Software\\Cheeso\\ApplicationName";
static string rvn_Runs = "Runs";
private Microsoft.Win32.RegistryKey _appCuKey;
public Microsoft.Win32.RegistryKey AppCuKey
{
get
{
if (_appCuKey == null)
{
_appCuKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(AppRegyPath, true);
if (_appCuKey == null)
_appCuKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(AppRegyPath);
}
return _appCuKey;
}
set { _appCuKey = null; }
}
public int UpdateRunCount()
{
int x = (Int32)AppCuKey.GetValue(rvn_Runs, 0);
x++;
AppCuKey.SetValue(rvn_Runs, x);
return x;
}
If it's a WinForms app, you can hook the Form's OnClosing event to run UpdateCount.
Then Check tutorial to Read, write and delete from registry with C#

How to correctly iterate application settings in C# using reflection

I am trying to iterate through application properties in C# using reflection (.NET 3.5 using VS 2010). The code "works" in that it successfully gets properties. However, it always gets the property values that were defined at design time and does not see the current values in myapp.exe.config. Properties that I access directly by name do reflect what is in the .config file. Here is the reflection-based code which only sees design-time properties:
List<StringDictionary> dictList = new List<StringDictionary>();
StringCollection bogus = new StringCollection();
foreach (PropertyInfo info in Properties.Settings.Default.GetType().GetProperties())
{
if (!("logLevel".Equals(info.Name) || "eventURL".Equals(info.Name)))
{
if (bogus.GetType().IsAssignableFrom(info.PropertyType))
{
StringCollection rawConfig = (StringCollection)info.GetValue(Properties.Settings.Default, null);
// do something
}
}
}
This code does pick up the current values in myapp.exe.config.
String logLevelStr = Properties.Settings.Default.logLevel
What am I doing wrong in my reflection code that causes me to pull only the properties defined at design time and not what is currently in myapp.exe.config?
To get the current value you need to use something like this which looks at Default.PropertyValues instead of Default.Properties
foreach (SettingsPropertyValue property in Properties.Settings.Default.PropertyValues)
{
Debug.WriteLine(string.Format("Property {0}'s value is {1}",property.Name,property.PropertyValue));
}
// note: the above may not work in some multi-form app, even if the applicaton prefix is prepended in front of Properties esp for visual studio 2010 compiled app with .net frame work 4
I think that there is a fundamental misunderstanding here. Settings can be one of two types- Application settings and User settings.
Application settings are intended to be written only at design time. As Henk points out it is possible to edit them after deployment if you are admin, but that isn't really the intent. Also, it should be noted that while Application settings are stored in the .config file, they are only read once and then cached in memory. That's why you don't see the new values when you edit the file.
User settings can be overwritten at run time by application code and saved, but they are saved at a user scope, so a different user running the same application can have different values. The intention there was things like user preferences. There is a drop down in the settings designer grid to switch between Application and User scope for each Setting.
Either way, you shouldn't be accessing them via reflection.
There must be some kind of misunderstanding here.
If you want to read the configurations from myapp.exe.config you should use ConfigurationManager. This class allows you to access AppSettings and ConnectionString directly through static properties or read custom sections by the GetSection method.
Beside, application configurations are meant to be design-time only. You shouldn't alter myapp.exe.config at runtime. Never. This file must be the same for each execution of your application.
Beside, what is Properties.Settings.Default.logLevel ???
Consider:
foreach (SettingsProperty sp in Settings.Default.Properties)
{
Console.WriteLine(sp.Name + "=" + Settings.Default.Properties.Default[sp.Name].ToString());
}

Categories