How to get values from Custom Actions Config File? - c#

I have created a custom action in WIX tool set. When i created a custom action project a config file was created by default.
Inside my config files i have some hard coded values which i want to use in my project. But i am getting null when i try to retrieve values from config.
How my config file looks like-:
<configuration>   
<appSettings>       
<add key="Employee" value="Ram,Piya,Ishani,Rahul"/>         
</appSettings>
</configuration>
How my custom action code looks like-:
[CustomAction]       
public static ActionResult CheckInfo(Session session)       
{                       
var names = ConfigurationManager.AppSettings["Employee"].Split(',');  
List<string> ls = new List<string>();
foreach(string s in names)
ls.Add(s);         
if (ls.Count > 0 && ls.Contains("Ram"))                   
return ActionResult.Success;
else  
{                   
MessageBox.Show("Current Employee does't exit", "Invalid info");           
return ActionResult.UserExit;  
}     
}
It is throwing error System.NullReferenceException: 'Object reference not set to an instance of an object.' at line (var names = ConfigurationManager.AppSettings["Employee"].Split(',');)
Requirement-:
How to retrieve values from config file in Custom Action Project?

Related

How to create a shared parameter that can be shared when project standards are transferred

I am working on a project where I need to create multiple revit files consisting of wall types and create shared parameters into them. I completed this process.
But on manually clicking on Manage > Transfer Project Standards
Copy from "project name" > Wall Types through the revit interface.
I imported the wall types of different revit files created into one.
But the shared parameters seems to repeat in the type parameter list of the wall type with data in one set and the repeated set has no data.
It looks like the parameters I created are not shareable.
if (Convert.ToString(value) != "")
{
Type type = value.GetType();
string originalFile = uiApp.Application.SharedParametersFilename;
string tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()) + ".txt";
using (File.Create(tempFile)) { }
uiApp.Application.SharedParametersFilename = tempFile;
try
{
if (ele.LookupParameter(param) == null)
{
ExternalDefinitionCreationOptions edco = null;
if (type.Name.Equals("Double"))
edco = new ExternalDefinitionCreationOptions(param, ParameterType.Number);
else
edco = new ExternalDefinitionCreationOptions(param, ParameterType.Text);
edco.Visible = true;
var definition = uiApp.Application.OpenSharedParameterFile().Groups.Create("Custom Parameters").Definitions.Create(edco);
var newCategorySet = uiApp.Application.Create.NewCategorySet();
newCategorySet.Insert(doc.Settings.Categories.get_Item(BuiltInCategory.OST_Walls));
Autodesk.Revit.DB.Binding binding = uiApp.Application.Create.NewTypeBinding(newCategorySet);
doc.ParameterBindings.Insert(definition, binding, BuiltInParameterGroup.PG_IDENTITY_DATA);
if (!string.IsNullOrEmpty((string)value))
ele.LookupParameter(param).Set((string)value);
}
else
{
if (!string.IsNullOrEmpty((string)value))
ele.LookupParameter(param).Set((string)
}
}
catch (Exception ex)
{
}
finally
{
uiApp.Application.SharedParametersFilename = originalFile;
}
}
Here, this block of code is executed in a loop where "element" is the element into whom the shared parameter needs to be added. "param" is the parameter name and "value" is the value for the parameter. Please let me know if this is the right way to create shared parameter that can be shared when project wall types are transferred to another project.
Thank you
definitely this will happen, as long as you are in a loop, and keeps creating a shared parameter for each file. this will lead to creating unique GUID for each revit file. and when you combine all you will find all the shared parameters with different Guids but with the same name.
you need to create the shared parameter once, then for each revit file, set the sharedparameter file (that is already created with sharedparameter) and get the sharedparameter from it, then assign it to the category you wish for each revit file.
moreinfo about shared parameters here
hope that helps.

Unity C# – Accessing subclass properties from variable defined as derived class

I'm trying to write an xml parser to take some data in a game and build out objects for me. Right now I want to go through the nodes and build out different config objects based on the node/attributes.
foreach (XmlNode node in actionList) {
ActionConfig config;
if (some checks determine action is "Fire") {
config = new FireActionConfig();
config.speed = (float)node.Attributes["speed"].Value;
}
// do something with config
}
The error I get is "ActionConfig does not contain a definition for speed...". I tried casting config as FireActionConfig even though it's already defined as one.
foreach (XmlNode node in actionList) {
ActionConfig config;
if (some checks determine action is "Fire") {
FireActionConfig fireConfig = new FireActionConfig();
fireConfig.speed = Single.Parse( node.Attributes["speed"].Value );
config = fireConfig;
}
// do something with config
}

ASP.NET Core: Custom IFileProvider prevents default IFileProvider from working

I am trying to serve some JavaScript from embedded resources in a class library. I managed to find out about the IFileProvider and created my own which is now working well. However, the problem I have now is that physical static files (from wwwroot) are no longer found.
I have the following in my Startup.cs file:
app.UseStaticFiles(
new StaticFileOptions()
{
// Override file provider to allow embedded resources
FileProvider = new CompositeFileProvider(
HostingEnvironment.ContentRootFileProvider,
new EmbeddedScriptFileProvider()),
//etc
});
I would have assumed using the CompositeFileProvider would mean that if the file is not found in one of the file providers, then it will try the other. I am also assuming that the default file provider is the one I specified as HostingEnvironment.ContentRootFileProvider. Is this incorrect?
The only other thing I can think of is that the problem is coming from inside my provider itself in the GetFileInfo() method. The definition of which is as follows:
public IFileInfo GetFileInfo(string subpath)
{
if (string.IsNullOrEmpty(subpath))
{
return new NotFoundFileInfo(subpath);
}
if (subpath.StartsWith("/", StringComparison.Ordinal))
{
subpath = subpath.Substring(1);
}
var metadata = EmbeddedScripts.FindEmbeddedResource(subpath);
if (metadata == null)
{
return new NotFoundFileInfo(subpath);
}
return new EmbeddedResourceFileInfo(metadata);
}
Could it be that returning NotFoundFileInfo(subpath) is causing my problems for physical css, js and other static files? If so, what should I be returning here instead so that the system knows to use the other file provider?
OK after a little digging in the source code (isn't it great that .NET is now open source?!), I managed to find the following links were very helpful indeed:
CompositeFileProvider.cs
- Based on the implementation in GetFileInfo(), I can see that I should pass back null instead of NotFoundFileInfo(subpath) if I want the other providers to try resolve it.
StaticFileMiddleware.cs
- This file shows that if the FileProvider is not specified (null) when setting up static file configuration with app.UseStaticFiles, then it will resolve one with the following line of code:
_fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv);
And looking at Helpers.cs shows the following code:
internal static IFileProvider ResolveFileProvider(IHostingEnvironment hostingEnv)
{
if (hostingEnv.WebRootFileProvider == null)
{
throw new InvalidOperationException("Missing FileProvider.");
}
return hostingEnv.WebRootFileProvider;
}
Therefore, my assumption of using HostingEnvironment.ContentRootFileProvider was incorrect. I should be using HostingEnvironment.WebRootFileProvider instead.
Everything now works as it should.

How to get result of a RFC

I am totally new when it comes to fetching the data from a SAP RFC. I am following many links to make a connection to the SAP with the following set of codes.
<appSettings>
<add key=”ServerHost” value=”127.0.0.1″/>
<add key=”SystemNumber” value=”00″/>
<add key=”User” value=”sample”/>
<add key=”Password” value=”pass”/>
<add key=”Client” value=”50″/>
<add key=”Language” value=”EN”/>
<add key=”PoolSize” value=”5″/>
<add key=”PeakConnectionsLimit” value=”10″/>
<add key=”IdleTimeout” value=”600″/>
</appSettings>
cs file
SAPSystemConnect sapCfg = new SAPSystemConnect();
RfcDestinationManager.RegisterDestinationConfiguration(sapCfg);
RfcDestination rfcDest = null;
rfcDest = RfcDestinationManager.GetDestination(“Dev”);.
Now I don't know how to call a specific RFC and get its result in Dataset or a list. I have installed SAP.net Connector also.
Please help.
After creating a working RFC destination you have to create an IRfcFunction object using the RfcDestionation-Method CreateFunction:
var rfc_read_table = rfcDest.CreateFunction("RFC_READ_TABLE");
now you can use the created object to set parameters. Import/Export-Parameters can be set or retrieved using the SetValue or GetValue-methods:
// we want to read from table kna1 (customer master data)
rfc_read_table.SetValue("QUERY_TABLE", "kna1");
// Delimiter ';'
rfc_read_table.SetValue("DELIMITER", ";");
table paramters are accessed using method GetTable. It returns an IRfcTable object representing the table parameter:
var fieldsTable = rfc_read_table.GetTable("FIELDS");
// append a new row
fieldsTable.Append();
// set value for field "FIELDNAME" on new row
fieldsTable.SetValue("FIELDNAME", "mandt");
fieldsTable.Append();
fieldsTable.SetValue("FIELDNAME", "kunnr");
now you can execute the function
rfc_read_table.Invoke(rfcDest);
RFC_READ_TABLE returns its data in parameter table "data" of type TAB512 with a single field called "WA". After invoking the function, create a new IRfcTable object using method GetTable and iterate over its contents.
var returnTable = rfc_read_table.GetTable("DATA");
foreach(IRfcStructure row in returnTable)
{
string[] fieldValues = row.GetValue("WA").Split(';');
// process field values
}
please note that this is just an example. The function module RFC_READ_TABLE for instance isn't released for customers, so no support from SAP for using this function. I hope i got the syntax right, i don't have an IDE available right now and can't check for errors.

Programmatically access Enterprise Library Logging configuration (object model)?

I'm using Enterprise Library 3.1 and want to programmatically access the Logging Block (runtime, object model) specifically its Trace Listeners and Sources.
For example, I want to access the Filename property of a trace listener object so I can know where the log file is located on disk.
Update: Looking for answers that use the runtime object model, not by parsing the XML configuration.
You can access the logging configuration programmatically using the object model (used for configuration).
To get the specific data for the trace listener you should look at TraceListenerData (and the specific subclasses).
This example shows how to read in the configuration and then get the TraceListeners:
// Open config file
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = #"MyApp.exe.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
// Get EL log settings
LoggingSettings log = config.GetSection("loggingConfiguration") as LoggingSettings;
// Get TraceListener info
foreach(TraceListenerData listener in log.TraceListeners)
{
// Check for listener types you care about
if (listener is RollingFlatFileTraceListenerData)
{
RollingFlatFileTraceListenerData data = listener as RollingFlatFileTraceListenerData;
Console.WriteLine(string.Format("Found RollingFlatFileLIstener with Name={0}, FileName={1}, Header={2}, Footer={3}, RollSizeKB={4}, TimeStampPattern={5},RollFileExistsBehavior={6}, RollInterval={7}, TraceOutputOptions={8}, Formatter={9}, Filter={10}",
data.Name, data.FileName, data.Header, data.Footer, data.RollSizeKB,
data.TimeStampPattern, data.RollFileExistsBehavior, data.RollInterval,
data.TraceOutputOptions, data.Formatter, data.Filter);
}
else // other trace listener types e.g. FlatFileTraceListenerData
{
}
}
Apparently some needed info is privately encapsulated in a LogWriterStructureHolder instance (its field is named structureHolder) on the Enterprise Library Logger.Writer instance (of Type LogWriter).
So I'm effectively looking for: Logger.Writer.structureHolder (but that field is private).
I used reflection to pull it out....
These are the significant namespaces:
using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.Logging;
This is reflection code to pull out the needed private data:
// Get the private field.
FieldInfo fiLogStructHolder
= typeof(LogWriter).GetField("structureHolder", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic);
// Obtain field value to get the private data.
LogWriterStructureHolder structureHolder
= (LogWriterStructureHolder)fiLogStructHolder.GetValue(Logger.Writer);
// Access the value's .TraceSources property of Type Dictionary<string, LogSource>.
// The string is the name of the category from configuration.
int numSources = structureHolder.TraceSources.Count;
// Furthermore, access the listeners of any logging source by specifying:
int numListeners = structureHolder.TraceSources[0].Listeners.Count
// ^-- Note: Picked first source for example.
If anybody can find a non-private entry point for this same data please post it in an answer. Thanks.
Kudos to .NET Reflector for facilitating this answer.
public static EmailTraceListenerData GetEmailLogConfiguration()
{
var rootWebConfig1 = WebConfigurationManager.OpenWebConfiguration("/");
var section = rootWebConfig1.GetSection("loggingConfiguration");
var loggingSection = section as Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings;
if (loggingSection != null) {
// Reference to Microsoft.Practices.EnterpriseLibrary.Logging.dll and
// Microsoft.Practices.EnterpriseLibrary.Common.dll required for the code below
foreach (Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.TraceListenerData listener in loggingSection.TraceListeners) {
var emailTraceListenerData = listener as EmailTraceListenerData;
if (emailTraceListenerData != null) {
// Can obtain FromAddress, ToAddress, SmtpServer and SmtpPort
// as property of emailTraceListenerData;
return emailTraceListenerData;
}
}
}
return null;
}
Web.config file is as follow:
For Windows application, you can open the .config file withSystem.Configuration.ConfigurationManager.OpenExeConfigurationinstead of WebConfigurationManager.
The other answers seem very verbose, here is my solution:
public static TraceListenerData GetTraceListener(string name)
{
var log = ConfigurationManager.GetSection("loggingConfiguration") as LoggingSettings;
return log.TraceListeners.Single(tl => tl.Name == name);
}
Once you've called this helper method you can cast the result to whatever type the listener is such as RollingFlatFileTraceListenerData, EmailTraceListenerData, FormattedEventLogTraceListenerData, FormattedDatabaseTraceListenerData

Categories