We have a situation where a C# application is working with SQL CE 3.5 . To allow for a legacy program to use some of its features we have produced a C++ dll which uses interop to extract the info that it needs from the C# program. For this to work, the C#-program needs to access the database. Its not a very complex scenario.
When trying to deploy with a private install some problems occur though.
There is no problem with the C# program, it can access the database and work with it without any problems.
But when trying to access functions in the C#-program through the C++ interop which forces the C#-program to access the database, we get a crash with the exception saying that "...the Provider: System.Data.SqlServerCe.3.5 is not installed".
This is obviously because we cannot add a App.config file to the executing program.
How can we get around this? Is there another way to fix this? Any other forms of SQL CE 3.5 install methods are out of the question. So we must get this to work.
Regards,
P
Edit:
I'm not working against SQL CE directly, but through Linq2SQL. I have tried to add config files to all my dll's, it does not help. It seems to only matter if the executable file have got a app.config.
The exception thrown says - The provider System.Data.SqlServerCe.3.5 is not installed.
And the latest function to be called according to the stack trace is
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Initialize(...).
Edit 2
I have added all the files necessery for the deployment to work. As I wrote above, it works if I use the program dll (which uses Linq 2 Sql) through a .net executable with a app.config file that specifies where to look for the SQL CE 3.5 dll. Deployment will not work with only the files, an app.config file is necessary.
The problem is that we have to use the dll file through a C++ executable which have no means of telling .net where to look for the Sql Ce 3.5 dll.
add the following files to your application folder:
sqlceca35.dll
sqlcecompact35.dll
sqlceer35E.dll
sqlceme35.dll
sqlceoledb35.dll
sqlceqp35.dll
sqlcese35.dll
System.Data.SqlServerCe.dll
then it will work.
that is necessary if you have not explicitely installed sql server ce 3.5 on the target machine (which is case for most deployments i think).
You can add a foo.dll.config file and make sure it lives alongside the DLL. You just need to make sure that you have code in your DLL to determine where it lives on disk, and read the configuration from the same location.
Good luck!
This is obviously because we cannot add a App.config file to the executing program.
Why not? Okay, so Visual Studio won't automatically build the config file and rename it and move it to the output directory, but have you tried a .exe.config file alongside your C++ application?
I have also seen an instance where the System.Data.SqlServerCe.dll in the GAC was the wrong file version and I had replace the dll in the GAC from a cmd command prompt.
The point about the files having to be in the folder is true - unless the GAC gets itself confused by have multiple versions
Do not use LINQ, but use SqlCeConnection, SqlCeCommand etc for the methods you call from your C++ program
Related
I have a c# console application which is scheduled to import bulk data from oracle to sql database. I am leaning towards using the oracle client dlls from the installation folder instead of having it installed on server. I read many existing SO answers on copying required dlls in installation folder.
https://jeremybranham.wordpress.com/2011/04/25/oracle-instant-client-with-odp-net/
The application works fine on my windows 10 machine where no oracle client is installed. But on Windows Server 2008 R2 it throws error saying OraOps12.dll is not found. Though I have the dll available. What can I do to troubleshoot the issue?
Make sure the dll is referenced in the project and it's set to copy to the output directory. I can't explain why, but I have had referenced dll's not set to copy and have run into similar issues as you are describing.
I think it is a bad idea to copy the DLL's from the Oracle Client manually. You may provide a copy of Oracle.DataAccess.dll - for all the rest ask your customer to install an appropriate Oracle Client, i.e. the version and architecture has to match the Oracle.DataAccess.dll.
Or use the ODP.NET Managed Driver (Oracle.ManagedDataAccess.dll), this is a stand-alone DLL which does not require any additional file.
Finally I could work it out without actually installing Oracle Client on the server. I was receiving error about not able to load OraOps12.dll but eventually I found out that the dll I was missing was msvcr120.dll. The dll is Microsoft Visual C++ Runtime. So now, I have following Oracle dlls in my deployment folder & the application is working. No changes in configuration are required.
msvcr120.dll
Oracle.DataAccess.dll
OraOps12.dll
oraociei12.dll
oraons.dll
oci.dll
I have a application that must run on any plain Windows installation (from Vista up to 10).
On Vista you got framework 3.5, on Win10 there's framework 4.6 installed.
To run on both, the application must target different frameworks.
Therefore I made use of multiple supportedRuntime entries in app.config, which makes this possible - works perfect.
Now I got a second problem, I have to ship app.config together with the application.
This is a problem, because of the way the application is distributed, app.config can get lost and the whole thing blows up.
So the idea was to embed app.config into the executable, against the principle of the file "user should be able to change it".
In this case, the user should not be able to change it, because it would no longer work.
Here's what I found so far:
How do you embed app.config in C# projects?
How do I compile my App.config into my exe in a VS2010 C# console app?
The essence is 'you can't do that'.
So the question is:
Is there either a way to embed app.config or is there another way to specify supportedRuntime somewhere else than app.config?
There seems to be no compiler switches that addresses the configuration.
Are there further tools to manipulate the configuration?
I'm a bit late.
I use 7zip Self-Extract feature to create an archive that will extract itself in the user's temp folder and run a specified exe. That way you can have your exe and your app.config together.
I have oracle 10g client(full) and 11g instant client installed on my machine.
I am trying to use ODP.NET 12c. Here is what I did.
Added Oracle.DataAccess.dll to References.
Copied OraOps12.dll to the folder where my executable is.
When running I got "Unable to load DLL 'OraOps12.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)".
I think it could be due to dependency issue. So I further copied 12c's
oci.dll
oraociei12.dll
orannzsbb12.dll
I then still got other dependency errors. I don't want to copy the whole InstantClient though.
My goal is to get the app to work with other versions of Oracle client.
Our customers have different version of Oracle client installed. So any way to get the app (ODAC12c) work with customers' current version of Oracle client without having to install 12c client?
Thanks,
Update:
I forgot to mention a few things
my ODAC is 32bit and I compiled my app on x86.
I didn't use Oracle.ManagedDataAccess.dll because it does not include BULKCOPY classs. If anyone knows a version of Oracle.ManagedDataAccess.dll that includes bulkcopy class please let me know.
Our customers already has different versions of Oracle client installed for other apps and they don't want to change their environment just for this new app. So my goal becomes to make one version of ODAC in my app work with different versions of existing Oracle client (each customer environment is different). Is this possible and if yes, how?
You know, I just spent 5 minutes looking for the guy that I remember attempting this before...and it turned out to be you shawn ;).
Honestly, to rely on what the client has installed is a crap-shoot. I would use the full xcopy package, get it working, and then work backwards, deleting what is not needed.
Don't run the install.bat that comes with it. Doing so adds registry entries that aid in locating the unmanaged binaries, but you also risk messing with a client installed copy.
Drop the whole xcopy install into your app's folder as a subfolder.
Instead, set the DllPath to this new subfolder
Example:
<oracle.dataaccess.client>
<settings>
<add name="DllPath" value="C:\app\user\product\11.1.0\client_1\BIN"/>
Then set the Oracle_Home environment variable
Example:
Environment.SetEnvironmentVariable("ORACLE_HOME", #"C:\app\user\product\11.1.0\client_1\");
This article does something similar:
http://dbaportal.eu/2013/02/22/true-xcopy-runtime-for-oracle-odp-net-application/
He even adds a policy to redirect in case he has referenced projects that reference a particular version of Oracle.DataAccess.dll
He adds his oracle home with a batch file though. The part I'm not so sure of is that he also adds his new xcopy install to the path with that same batch file. DllPath should take care of that, but if I'm wrong, you can also do that at runtime:
Environment.SetEnvironmentVariable("PATH", #"C:\app\user\product\11.1.0\client_1\BIN");
From here, I'd setup some basic unit tests using all the ODP.net functionality you are using and get some positive tests and then work backwards - start deleting what you don't need, running your tests each time. You might be able to use sysinternals procexp to show loaded dlls (or procmon to show access to the files). Just loading your tests might be enough to lock the files so you can delete all the ones that aren't locked.
I'm not sure doing this is supported. Then again Oracle does list "the current application's directory" in the unmanaged search order so they didn't close the door either.
EDIT:
Found one of the links of other people doing this:
http://alderprogs.blogspot.com/2009/04/deploying-odpnet-with-oracle-instant.html
I'm not sure why but they download the instant client separately (it's already part of the xcopy package).
EDIT 4/15/2016: If you're reading this these days note two things. 1) I don't think setting the environment variables are necessary if you are already setting DllPath. 2) I don't think this is worth doing when the managed provider now only requires one or two dlls.
It's a bad idea to copy single DLL's to different directories and hope it will work.
In general ODP.NET provider works only together with corresponding Oracle Client, i.e. in order to use ODP.NET 12 you must also install Oracle Client 12. Same applies for version 11 or 10.
Only exception is the ODP.NET Managed Driver, there you need only a single DLL (Oracle.ManagedDataAccess.dll).
Furthermore the architecture (32 bit vs. 64 bit) has to match.
In case you use OLEDB provider it's even not possible to have more than one provider installed (for each architecture) - unless you hack your system by manipulating PATH variable and Registry all the time.
My proposal would be: Remove all Oracle Clients from your machine and install only one (or one per architecture) Oracle Client properly. It's very unlikely that an application works with one Oracle Client version only. It is also a good approach to install both 32bit and 64bit on one machine, follow this instruction to do it: Install Oracle x86 and X64 on one machine
In case you really need to test your application with different Oracle Client version, setup a couple of test-PC (maybe in a Virtual-Box) each with a different Client version. Otherwise it will be very challenging to handle it.
Update:
I think each (Unmanaged) ODP.NET version works only with according version of Oracle Client. Maybe by chance there are some combinations which work out but in general the versions should match.
I see two different solutions:
(1) Ask your client to install his Oracle Client including ODP.NET. He can choose the version, only the architecture (32 bit or 64 bit) has to match. Then you don't supply any ODP.NET with your application.
In your *.csproj, resp. *.vbproj file define your reference like this:
<Reference Include="Oracle.DataAccess">
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
Attributes like Version=... or processorArchitecture=... are not required. Then your application should run with any Oracle/ODP.NET version.
Your customer can download ODP.NET provider from here: Oracle Data Access Components (ODAC) for Windows Downloads and install it on top of existing Oracle Client installation. In readme.txt it says "The files of this zip file is NOT to be installed on top of an existing
Oracle Universal Installer (OUI) based Oracle Home installation.", however I don't see any reason why not doing it. It works well, you just have to carefully provide correct folder for existing Oracle installation and correct ORACLE_HOME name and do not install dependencies.
(2) In your setup script/exe determine the Version of customer installed Oracle Client and copy according ODP.NET to customer machine.
In order to determine version of Oracle Client you can to search for file oci.dll in folders provided by PATH environment. oci.dll is a normal .NET assembly, so you can read out the version easily.
For a proper installation of ODP.NET follow the file configure.bat which is part of downloaded ODP.NET XCopy version. In my opinion this batch file is easy to understand.
Basically it does
1 - Copy file Oracle.DataAccess.dll to target machine
2 - Copy different resource files *\Oracle.DataAccess.resources.dll to target machen
3 - Add these DLL's to the GAC. This can be done by gacutil.exe or OraProvCfg.exe (included in downloader ZIP file) or your setup application provides this operation.
4 - Make a few Regristy entries. Newer ODP.NET versions write/read into HKLM\SOFTWARE\Wow6432Node\Oracle\ODP.NET (for 32 bit), resp. HKLM\SOFTWARE\Oracle\ODP.NET (for 64 bit). Older ODP.NET versions use HKLM\SOFTWARE\Oracle\KEY_{ORACLE_HOME_KEY}\ODP.NET\ (for 64 bit), resp HKLM\SOFTWARE\Wow6432Node\Oracle\KEY_{ORACLE_HOME_KEY}\ODP.NET\ (for 32 bit) instead
That's it, you should be able to include this in your setup.
I have application use SDF file and I use System.Data.SqlServerCe, Version 3.5.0.0 I make it copy Local = true ; after make l'app in other PC without sql compact installation I got this error
Could not load file or assembly 'System.Data.SqlServerCe, Version 3.5.0.0
I tried Embed Interop Types but it not work with ce dll.
the file existe in application directry; and I know that it read from Programme file but I have to install sql compact in any Pc I have to use application into ?
I'd suggest you to check out the following answer: Sql Server CE 4 and EF 4.1 CF Win 64 bit deployment. It really helped me. It directs to another resource: http://erikej.blogspot.com/2011/02/using-sql-server-compact-40-with.html.
Using this approach you don't need to install the SQL Server CE runtime. All the runtime travels with your app as a part of it.
The dll needs to be registered as it wont work by just copying the dll in bin folder. You need to do the installation on 2nd pc as well or try including x64 and x86 binaries with your app.
rename the user.config file located at
C:\Users[USER_NAME\AppData\Local\Microsoft_Corporation\LandingPage.exe_StrongName_ryspccglaxmt4nhllj5z3thycltsvyyx\10.0.0.0
TO (USER.CONFIG.BAK)
I made a piece of software that makes it possible for me to delete folders recursively through a console and what I want to do is make it possible to reach the program from any directory using CMD.EXE.
When I try to copy the software to the System32 directory and then run it from CMD it gives me the following error:
unable to find a version of the runtime to run this application
I tried building it as a 64 bit program but that didn't change anything.
Is there something wrong with my code or is it the way I'm building it?
Thanks in advance.
This is because the required .NET runtime you specified in your project options or in app.config file through <supportedRuntime> is not found in the system.
In short, the targeted .NET runtime for your application is not found on the system.