Enterprise Library not logging in setup project - setup-project

I need your opinion on this: Is it possible to use enterprise library logging dll in the setup project?
Here's what I did:
I created a setup project which will call a windows form to install the database. When I installed the project, it did call the windows form. However, when I click on the "Install" button, it seems that there's a problem and I don't know where it is. Then another popup message is displayed which said that it cannot locate the logging configuration.
But the config file for the windows form is there which includes the configuration for the logging dll. I don't have any idea where to look into.
Please help me with this?
Below is the error message:
UPDATE
I observed that when I run the exe file as is, the enterprise library logging config works. But with the setup project, it does not look for it. Any help on this?
Below is the code for this:
[RunInstaller(true)]
public partial class IPWInstaller : Installer
{
public IPWInstaller()
{
InitializeComponent();
}
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
string targetPath = Context.Parameters["TargetDir"];
InstallDatabase db = new InstallDatabase(targetPath);
DialogResult dbResult = db.ShowDialog();
if (dbResult != DialogResult.OK)
{
throw new InstallException("Database is not installed.");
}
ConfigureFiles config = new ConfigureFiles(targetPath);
DialogResult configResult = config.ShowDialog();
if (configResult != DialogResult.OK)
{
throw new InstallException("Config files are not saved correctly.");
}
}
}
LATEST UPDATE:
I tried to set the value of a certain configuration to my messagebox. This is the result of it when I run the install project.
Is there a way to call my app.config in the setup project

There are at least a couple of things that can go wrong.
The app is not running as it would if you ran it as an interactive user. It is being called from an msiexec.exe process that knows nothing about your intended environment, such as working directory. None of the automatic things that happen because you run from an explorer shell will happen. Any paths you use need to be full and explicit. I think you may need to explicitly load your settings file.
Something else that can happen in a per machine install is that custom actions run with the system account so any code which assumes you have access to databases, user profile items like folders can fail.
Another problem is that Windows Forms often don't work well when called from a VS custom action. It's not something that works very well because that environment is not the STA threading model that is required for window messages etc.
In general it's better to run these config programs after the install the first time the app starts because then you are in a normal environment, debugging and testing is straightforward, and if the db gets lost the user could run the program again to recreate it instead of uninstalling and reinstalling the setup.

Related

SQLite no longer seems to work on xamarin android

We have a Xamarin.Forms project that needed to use the sqlite local db to store date. EF Core's sqlite library was used to set this up and by different developers from different PCs (vs 2019). Initially, it was used with the Database.EnsureCreated() function and later with ef core's migrations. All went smooth for more than a month.
Last week all of a sudden the android app wouldn't start on any one's PC due to some error with sqlite. It showed the following error:
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
I spent a while trying all kinds of fixes and rollbacks thinking it was an issue with the code. This included the following:
Deleted obj and bin folders, cleaned and rebuilt for all below steps.
Downgraded the version of ef to 2.2.3 (the version we started with)
Rolled back to git commits up to a week back
Upgraded the versions of dependencies of ef core
Removed the past few migrations
Downgraded xamarin forms to 3.6.x
After trying the above and several other fixes, finally upgrading the versions of java and android SDK worked last Friday (on all PCs). Once this fix worked everything went smooth that day. On Tuesday once again the issue was back (no library updates or code changes). A deeper look at EF Cores logging shows that it crashes the moment it attempts to connect to a db.
The issue can be replicated on the android devices but not the emulators. I am not sure if there is some new permission in android we need to request for.
I finally created a new xamarin forms project with sqlite setup. I used the pcl library and ef core. I still found the same error.
Here is the git hub that replicates the issue https://github.com/neville-nazerane/xamarin-site
Update
Just something i noticed. eariler my database file was named "main.db". Now no matter what i change this file name to or no matter what variables i change. it always shows database name as "main" in logs. Not sure if changing the db name would fix the issue. However, never found a way to change this db name. I tried different connection strings, it just said "database" and "db" were unknown keys
Update
Steps to replicate:
using (var db = new AppDbContext())
{
db.Add(new Person {
Age = 55,
Name = "Neville"
});
db.SaveChanges();
Person[] alldata = db.People.ToArray();
}
The definitions of Person and AppDbContext are quite obvious. So, with the spirit of not making the question too long, I am not posting it here. However, if required I can post them too.
This is a bug with the Xamarin.Forms and Mono.
It was detected since a couple of months ago, it was fixed but then there was some regression (with VS 2019 v16.1).
Even with the latest release (v16.1.2) the bug still happens, so we need to wait for a fix.
Sources:
https://github.com/mono/mono/issues/14170
https://github.com/xamarin/xamarin-android/issues/3112
https://github.com/xamarin/xamarin-android/issues/2920
Due to slight differences of the particular file systems on the native side, I would suggest creating an interface to handle the actual database file handling on the native application level.
So here is how I implemented SQLite using the nuget package SQLite.Net-PCL:
In the shared project, create a new interface, for instance FileHandler.cs
public interface IFileHandler
{
SQLite.SQLiteConnection GetDbConnection();
}
You may want to extend that with more methods to save or retrieve various files, but for now we will just have the GetDbConnection Method to retrieve a working SQLite Connection.
Now in your Android implementation, we add the native implementation to that interface:
Create a new class called FileHandler.cs in your android project:
[assembly: Dependency(typeof(FileHandler))]
namespace YourProjectName.Droid
{
public class FileHandler : IFileHandler
{
public SQLite.SQLiteConnection GetDbConnection()
{
string sqliteFilename = "YourDbName.db3";
string path = Path.Combine(GetPersonalPath(), sqliteFilename);
SQLiteConnectionString connStr = new SQLiteConnectionString(path, true);
SQLiteConnectionWithLock connection = new SQLiteConnectionWithLock(connStr, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.NoMutex);
return connection;
}
private string GetPersonalPath()
{
return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
}
}
}
Now back again in your shared code you can access that connection with the following code:
using (SQLiteConnection connection = DependencyService.Get<IFileHandler>().GetDbConnection())
{
// Do whatever you want to do with the database connection
}
Alright mate, I don't understand what issue you are facing. It might be an issue with your machine, I'd suggest using another computer/laptop.
I took the exact code that you shared on the Github. I was able to build it on my Mac computer in VS 2019 and installed the application in debug mode on my phone. I was able to add a date successfully, as you can see in the picture, and I placed an Exception Catchpoint and faced no exceptions.
I then proceeded to add another entry with the same details and it errored out with the message that you can see here
I would also suggest using Xamarin Profiler or any other Android logger to see the Stack Trace that you aren't able to see in your application output. It will give you details of the error, that you can share here for us to understand better.

Handling development time web.config conflicts

I am looking for a way to handle this challenge: we are a geographically dispersed dev team using ASP.NET Web API and Angular to build a web app.
The thing that causes the grief is the fact that not all team members use the same database setup for their dev work. Yes, I know - I can use web.config transforms to set the proper connection strings for test, staging and production (and I'm already doing this) - but this is not what I'm talking about.
Due to reasons beyond our control at this time, we have
some developers working on a local SQL Server instance using server=(local);database=OurDB as their connection string
other developers using a central developer SQL Server in their location, using something like server=someserver.mycorp.com;database=OurDB
and a few exotic cases with yet other settings
Now every time someone commits a change to the Git repo, and happens to also change something in the web.config, his connection string is committed to the repo. So when I then go pull that latest commit, my settings to my local DB server are overwritten by this other guy's settings.
I am looking for a way to handle this - I was hoping I might be able to
hook into the Git pull process and automagically update the web.config connection string to my local needs whenever I pull something
somehow reference a connection string (or external config file) based on e.g. my currently logged in user's name or something like that
But I can't seem to find any way of doing this. I was wondering if I need to build a VS extension to handle this - any starters for that? Has anyone done something like this before and could share his code? (or has it up on Github)
The web.config configuration system used in ASP.NET is not flexible enough to support the more advanced scenario you have described. So, why use it? You could store the configuration in files within the repository, one per developer. Or they could be stored outside the repository or otherwise ignored.
The real trick is that most older applications don't have a single root that retrieve the configuration, so you have to refactor your application to utilize a flexible configuration system. For your staging/production environments you probably still want to use the config in web.config. The following code can give you a basic idea of one way to structure it:
public class MyApplicationConfiguration
{
public string MainConnectionString { get; set; }
}
public class ConfigurationRetriever
{
public MyApplicationConfiguration GetConfiguration()
{
// You might look for the absence or presence of an environment variable to determine this
bool isLocalDevelopment = IsApplicationLocalDevelopment();
var config = new MyApplicationConfiguration();
if(isLocalDevelopment)
{
config.MainConnectionString = Environment.GetEnvironmentVariable("MyApplication_MainConnectionString");
//or get it from a JSON file or XML file or config database
}
else
{
config.MainConnectionString = ConfigurationManager.ConnectionStrings["MainConnectionString"].ConnectionString;
}
}
}
Rather than rolling your own config building logic, you might refactor your application to leverage Microsoft.Extensions.Configuration. It's not just for .NET Core. It's for .NET Standard. So you can use it even in your legacy ASP.NET applications. For reading the web.config, you could probably use Microsoft.Extensions.Configuration.Xml. Or you can write your own adapter that pulls values out of ConfigurationManager. I did a basic test, and this worked as expected.

ASP.NET unit testing Windows7/IIS7

Spent several hours today trying to write some unit tests against an ASP.NET project. It's Visual Studio 2010.
Using Windows 7 Enterprise with IIS7.
Steps I took were:
Added a new test project to the solution
Opened a class file as part of the web site (Member.vb)
Right clicked within the class file and "Generate unit tests"
Select the methods I wish to generate stubs for, choose to add to my test project, click OK
Open up the generated MemberTest.vb file in the test project, click within one of the generated tests, click "Run tests in curent context"
When following these precise steps on my Windows XP Professional with IIS6 machine it works fine.
However on the Windows 7 Enterprise machine on IIS7 I get:
The URL specified ('http://localhost/MyProject') does not
correspond to a valid directory. Tests configured to run in ASP.NET in
IIS require a valid directory to exist for the URL. The URL may be
invalid or may not point to a valid Web application.
So what's going on, I can confirm I can browse to http://localhost/MyProject and it displays perfectly.
I feel sure I'm missing some sort of config in Windows/IIS but I'm really at a loss.
Generated test method:
<TestMethod(), _
HostType("ASP.NET"), _
UrlToTest("http://localhost/MyProject")> _
Public Sub MyMethodTest()
Dim target As Member_Accessor = New Member_Accessor() ' TODO: Initialize to an appropriate value
Dim CurrentVal As Short = 0 ' TODO: Initialize to an appropriate value
Dim expected As Short = 0 ' TODO: Initialize to an appropriate value
Dim actual As Short
actual = target.MyMethod(CurrentVal)
Assert.AreEqual(expected, actual)
Assert.Inconclusive("Verify the correctness of this test method.")
End Sub
(Cross-posted at ASP.NET Forums)
This could be a permissions issue.
If you're using the default directory (C:\users\\Documents\Visual Studio 2010\Projects), the app identity pool does not have permissions there. You'd have to create a project in something like C:\webs and make sure app pool identity has permission to the folder.
Refer to Rick Anderson's blog post at http://blogs.msdn.com/b/rickandy/archive/2011/04/22/test-you-asp-net-mvc-or-webforms-application-on-iis-7-in-30-seconds.aspx and see if that helps.
If you have not done unit testing before, I would really recommend that you start by just testing the functionality of your classes as cleanly as possible. Try to break you you functionality into small pieces that can be tested individually without and dependencies to the web context.
Have a look at this question for an idea about What is unit testing
Here is an MSDN Magazine article about testing
You can also have a look at this Blog. The examples are using NUnit but the principal is the same if you are using MSTest.
I can also recommend Roy Osheroves Book Art of unit testing
In you case if the Member class does not have dependencies to web context you don't need the IIS and could instead just do something like this:
<TestMethod()> _
Public Sub MyMethodTest()
Dim target = New Member()
Dim CurrentVal As Short = 0 ' TODO: Initialize to an appropriate value
Dim expected As Short = 0 ' TODO: Initialize to an appropriate value
Dim actual As Short
actual = member.MyMethod(CurrentVal)
Assert.AreEqual(expected, actual)
End Sub
I ran into the same problem today. After some research, I found this thread which suggested I check my event log. Upon doing that, I discovered numerous errors similar to the following:
(QTAgent32.exe, PID 12348, Thread 61) WebSites.GetWebServer: failed to
create AspNetHelper:
Microsoft.VisualStudio.Enterprise.Common.AspNetHelperException: The
website metabase contains unexpected information or you do not have
permission to access the metabase. You must be a member of the
Administrators group on the local computer to access the IIS metabase.
Therefore, you cannot create or open a local IIS Web site. If you
have Read, Write, and Modify Permissions for the folder where the
files are located, you can create a file system web site that points
to the folder in order to proceed. --->
System.Runtime.InteropServices.COMException: Unknown error
(0x80005000)
That lead me to this blog post which seems to have resolved the issue.
I just needed to go to "Turn Windows features on or off" and add IIS 6 Management Compatibility and all four subcomponents. I'm running Windows 7 Home Premium which doesn't have the Windows Authentication option, but that didn't seem to be an issue. Give it a shot and see if that resolves the issue for you.
You may need to enable "Use IIS" in the project properties, then click "Create Virtual Directory". Do you have IIS Express installed?

eventlog not working in an asp.net application

from an ASP.Net 3.5 web application, I'm trying to log messages to the Windows EventLog.
I first tried with the EntLib Logginh block, but when this failed I tried with the EventLog class directly. It failed too. They do not throw any exception... the just don't write the message. EntLib did write the message to a file, but not to the Windows EventLog.
Here is my code:
public static void LogMessage(string title, string message){
//EventLog log = new EventLog();
//log.Source = LOG_SOURCE;
//log.WriteEntry(message, EventLogEntryType.Error);
//EventLog.WriteEntry(LOG_SOURCE, message);
LogWriter writer = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
writer.Write(message);
}
I create the log & source in an installer class. Let me know if I should place that code here. The log is created correctly, since I can see it in the EventViewer. The source is created correctly, since I can see it in the "EventLog\MyLog" folder at the regedit.
I've been reading and there is an article stating following line could help:
EventLogPermission perm = new EventLogPermission(EventLogPermissionAccess.Administer, ".");
perm.PermitOnly();
but it didn't.
If it helps, my code structure is as follows:
Class library project (here is the LogMessage method)
Class Library project (here are the methods which catch exceptions and call LogMessage)
ASP Net web application project (web pages. This layer calls layer #2. Here is my installer class too)
Web setup project (this has custom actions pointing to web setup project output)
Could you please help to figure out what's happening???
Thanks
I found the following resource: "http://www.netframeworkdev.com/net-base-class-library/trouble-writing-to-eventlog-16723.shtml", so it seems it is not possibly to create custom logs from ASP... still investigating
Try giving the Network Service account the appropriate permissions

How to do mocks for Web tests?

I want to write a few web tests (over WatiN/Selenium + CassiniDev web server) for my asp.net web application.
Problem I encountered is that I dont know what to do in such situations:
there is a page where user can click the button to call some third-party service. In my web test i want to create mock of this service, which will always return static value (some value in these test case and other value in other test case).
How can i do that?
Currently i use IoC/DI container Microsoft Unity. And my pages gets his dependencies in a manner described in http://msdn.microsoft.com/en-us/library/ff664622%28v=pandp.50%29.aspx.
The only solution that comes to my head is: place all dependencies in web.config for each test case and copy necessary web.config on SetUp of test. This solution completly painful!
Any ideas?
I use WatiN and Cassini-dev in my integration tests as well and have had to deal with similar issues. In my setup fixture I deploy my Asp.Net web application to a temporary folder in my test folder which allows me to play around with the configuration before starting up cassini-dev. I use Windsor for my CI which allows me to change injected components at the configuration level. You may also be able to acheive this with Unity.
If the service you are referring to is a web service you just mock out a web service using the interface you have been coding to.
Here are the steps that I take when running my integration tests:
Create a temp web directory
Publish the Asp.Net web application to the temp directory (I use MSBuild to do this)
Deploy temp database (Using MSbuild and database projects but could be done a number of ways)
Deploy temp membership database (see my blog post on how to do this in code)
Update the web.config of the deployed Asp.Net web application to point to the temp databases and change any other settings relevant for testing.
Start up the website using Cassini-Dev. I also hit the site with a http request so that I can verify the site is up before running any tests.
Run the tests.
After running the tests you should clean up.
Stop cassini-dev
Delete the temp hosting folder
Delete the temp databases. I use Sql server SMO objects that allow me to query the Sql Server which I use to delete up any old databases that have been left lying around after any previously failed test runs.
How to deploy a website using MSbuild in code
var properties = new Dictionary<string, string>
{
{"Configuration", isDebug ? "Debug" : "Release"},
{"WebProjectOutputDir", tempHostingDirectory.FullName},
{"DeployToDatabase", "true"},
{"OutDir", Path.Combine(tempHostingDirectory.FullName, "bin\\")}
};
using (var engine = new ProjectCollection(properties))
{
engine
.LoadProject(<web project path>, "4.0")
.Build(new[] {"Build", "ResolveReferences", "_CopyWebApplication"});
}
Unity configuration section usage: http://www.pnpguidance.net/Post/UnityContainerUnityConfigurationSectionAppConfigWebConfig.aspx
Generating asp.net membership database in code: http://bronumski.blogspot.com/2011/06/generating-creating-aspnet-application.html
Msbuild ProjectCollection on MSDN: http://msdn.microsoft.com/en-us/library/microsoft.build.evaluation.projectcollection.aspx
It sounds like you are trying to mock a web service.
Web services usually inherit from MarshalByRefObject, this means you can create a mock by inheriting from RealProxy to create a transparent proxy that pretends to be the webservice:
class Mock : RealProxy
{
public Mock()
: base(typeof(IStuff)) { }
public IStuff GetStuff()
{
return (IStuff)GetTransparentProxy();
}
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage message = (IMethodCallMessage)msg;
// the message object provides the MethodInfo that was called
// as well as the arguments.
// <Insert logic here>
return new ReturnMessage(new NotImplementedException("comming soon to a test near you ..."), message);
}
}
I belieave NMock2 uses RealProxy for it's mocks, so you should be able to use it to mock the web service instead.

Resources