I'm building a ExcelDNA plugin that requires the full version of .Net (4.0 or 3.5) (I'm using some parts of System.Web). Because of this, users that only have the client version are getting errors.
I like to prompt the user with an "get the latest" version popup on startup if only the client version is installed.
Is there any foolproof way to check if the full version is installed? By googling it seems many recommends checking the registry, byt this seems error prone as there are many .Net versions. In such a case what paths do I need to check to build:
bool IsFullDotNetVersion()
{
}
Would it be possible/good idea to check the existence for a feature that's only available in the full version? I.e. Is it possible to check is System.Web is present in the environment? (not included in client version of .Net right?)
As a side question: How can I easy test my application with different .net version installed on my system. Is there any .Net switcher?
Look in the GAC to see if System.Web (or whatever assembly you need) is present.
Here is some code that works on my machine.
private static const string BasePath = #"c:\windows\assembly";
public static bool HasDotNetFullversion()
{
var gacFolders = new List<string>()
{
"GAC", "GAC_32", "GAC_64", "GAC_MSIL",
"NativeImages_v2.0.50727_32", "NativeImages_v2.0.50727_64"
};
var assemblyFolders = from gacFolder in gacFolders
let path = Path.Combine(BasePath, gacFolder)
where Directory.Exists(path)
from directory in Directory.GetDirectories(path)
select directory;
var hasSystemWeb = assemblyFolders.Any(x =>
x.EndsWith("system.web", StringComparison.InvariantCultureIgnoreCase));
}
Possible duplicate. How to detect what .NET Framework versions and service packs are installed? short answer is that you need to read the registry
I would suggest that rather than try and detect which .net version the client computer has, you might just bundle the full .net installer into your installation program.
In other words, detect it at the point of install and take the appropriate actions. This is the usual way of dealing with potentially missing framework parts.
Related
I'm using WindowsAzure.Storage, in a .NET CORE 2.0 library (dll) but when I unit test I get StorageCredentials.cs not found.
public class AzureFileStorage : IDocumentStorage
{
CloudStorageAccount storageAccount;
CloudFileClient fileClient;
StorageCredentials credit;
public AzureFileStorage()
{
credit = new StorageCredentials(appSettings.Current.Settigns["azAccountName"],appSettings.Current.Settigns["keyValue"]);
storageAccount = new CloudStorageAccount(credit, true);
fileClient = storageAccount.CreateCloudFileClient();
}
}
I can navigate tot he file and the file/class is there, Am I missing something?
Also, the path starting C:\Program Files (x86)\Jenkins\ is nowhere to find on my computer.
According to your error message, I suppose the issue is related with Debug settings.
There are some ways you could have a try.
1.Open Tools>Debugging>General>tick Enable Just My Code. For more details, please refer to this article.
2.Right click "Solution >Properties and then go to "Debug Source Files". Check under "Do not look for these source files" window if you have your problematic file path written in it. For more details, please refer to this article.
Uncheck Enable source server support in Debugging/General.
4.The system has a StorageCredentials class. After I have installed WindowsAzure.Storage nuget package(like 8.7.0), I could use this class by adding using Microsoft.WindowsAzure.Storage.Auth reference;
5..Net core 2.0 compatibility.I also meet a similar error like you. Just the class is different. Above the package is an exclamation mark. It says this package version can not support .NET Standard 2.0. It supports in
version 5.2.4. You know the standard 2.0 is new, there are still some features can not support in it. You could also check your package dependencies of compatibility. If your error is this, you could to wait for core 2.0 to update to support for some packages. Or choose a compatible version of packages.
We have a .Net application that successfully "load" .dll libraries from a specific folder in Windows Operative System. The .Net framework we have been using so far is 4.6. All the .dll libraries that the application loads were compiled in x86. The following code is an excerpt of how we are loading the libraries and getting their types:
1. try{
2. AssemblyFileDescriptor assemblyFile = new AssemblyFileDescriptor(assemblyPath);
3. var assm = Assembly.LoadFrom(assemblyPath);
4. var types = assm.GetExportedTypes();
5. ...
6. }catch (Exception e) {
7. ...}
The libraries in a specific folder, let's say
C:\Program Files (x86)\FOLDER
, are loading to the variable assm without any exception. The problem occurs when we migrated our .Net "stand alone" application to a website application with a Web.config file. In the website application, the load function fails when getting the types. Then the 4th line throws the exception. We have been using the ISS Express.
We have already tried:
Using a different Load function such as "UnsafeLoadFrom".
Re-compiling all the .dll libraries in x86 and x64.
Setting up different configurations for the Web.Config file such as including <trust level="Full" /> or <loadFromRemoteSources enabled="true" />.
Debugging the loading function of each library. Some of them can load successfully, but there are others that throw a Loading Exception.
Setting in the ISS Express "True" the variable "Enable 32-bit applications".
The specific error states "System.Reflection.ReflectionTypeLoadException":
Any idea of how tackling this issue? Let me know if you need further information.
I'm guessing you're running this under IIS, and IIS usually runs as a different user than you (usually IUSR), and usually has limited permissions. Converting a standalone program to an ASP.NET program changes a lot of things in subtle ways. I'd check to make sure you aren't running into a file-permission issue because IIS is a restricted user.
Also, as others pointed out, you should probably provide the exception details (at least its typename and message) so people don't have to guess at it.
According to the answers of this question and several loading experiments that we had been performing in the website application. We observed a pattern related to the framework version that we used for compiling the DLLs and the ReflectionTypeLoadException. Some DLLs were compiled with framework 3.5, this version does not allow loading libraries in ISS with .Net CLR2. Then, we must rebuild all the DLLs and their dependencies with a higher version of the framework (.Net v4.0). Finally, we re-loaded the updated DLLs in ISS express with .NET CLR4. The DLLs were loaded without any exception.
The program below is supposed to get a resource string from a satellite resourcefile. It works fine when compiled with target framework='NET Framework 4.5.2' using VS2015. However, setting target framework='NET Framework 3.5' makes it unable to find the satellite resource file and fall back to the default resources.
I peeked in the .exe and satellite .dll files and found that they are compiled to different .net versions (Eventhough it was the same compilation that generated them):
Main exe got: .Net Framework v3.5
Satellite resource dll got: .Net Framework v4.0
It seams like the satellite dlls gets the wrong .Net version. Has anyone experienced this and is there a solution? (Other than upgrading the project to the newest .Net version)
class Program
{
static void Main(string[] args)
{
CultureInfo newCultureInfo = new System.Globalization.CultureInfo("da-DK");
Thread.CurrentThread.CurrentUICulture = newCultureInfo;
Console.WriteLine("Resource test");
ResourceManager rm = new ResourceManager("ResourceTest.Resources.MyResources", Assembly.GetExecutingAssembly());
Console.WriteLine(rm.GetString("hello"));
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
EDIT: Seams like I got a bad update to my development enviroment. A reinstall of the whole computer helped, but simply reinstalling .Net and Visual Studio didn't! (I wonder if there is something in the registry database that doesn't get reset by a simple reinstall)
I know this question is almost six years old but this is again an issue today, with Visual Studio 2019. I have confirmed it with 16.10.2 and 16.10.3 (may be more). Building a .Net 3.5 application left me with non-working resource dll's, which puzzled me until I found your question that hinted to investigate the resource dll .Net version, discovering that these were indeed linked to .Net 4 mscorlib instead of 3.5.
Problem confirmation
First confirm the issue.
In Visual Studio, go to Tools / Options / Projects and Solutions /
Build and Run and set MS Build project build output verbosity to
at least Normal (default is Minimal).
Rebuild your .Net 3.5 project.
In the Output / Build window look for the task GenerateSatelliteAssemblies:.
The command line below shows C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\al.exe, which is the .Net 4.8 version of the assembly linker. On an unaffected system, that should have been C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\al.exe.
So far the same problem as mentioned in the link by hultqvist's comment on the question. The cause and solution is different, however. The registry keys that are mentioned there, were perfectly fine on my system.
TL;DR - Solution (Workaround)
Go to C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets (exact path may differ a bit on your system, e.g. Professional instead of Enterprise).
Create a backup copy of this file.
Edit the file, and find a line containing the text _ALExeToolPath. It should be around line 3739. Looks like this:
<PropertyGroup>
<_ALExeToolPath>$(TargetFrameworkSDKToolsDirectory)</_ALExeToolPath>
<_ALExeToolPath Condition="'$(PlatformTarget)' == 'x64'">$(TargetFrameworkSDKToolsDirectory)$(PlatformTarget)\</_ALExeToolPath>
</PropertyGroup>
Now scroll a bit down into the AL tag below and find the SdkToolsPath attribute.
<AL AlgorithmId="$(Satellite_AlgorithmId)"
BaseAddress="$(Satellite_BaseAddress)"
...
SdkToolsPath="$(SdkToolsPathMaybeWithx64Architecture)" <!-- this is incorrect -->
Change the value of the attribute from $(SdkToolsPathMaybeWithx64Architecture) to $(_ALExeToolPath)
Save the file (needs elevation, probably)
Rebuild your project, the correct linker is used and your resource dll's will work again.
Cause
This issue was introduced here to fix a minor issue with the assembly linker when targeting x64 vs x86. If you follow the comment thread with that PR you will spot the mistake: the actual variable in the fix is renamed after discussion, but they forgot to update that in the AL attribute before the PR was merged.
Because of this, the sdk tools path for al.exe is empty (it mentions a non-existing variable) and that causes msbuild to always call the default, which is usually the x86 version of the newest installed framework sdk on your system -- instead of a version that matches the version of your project.
That version of the .targets file has been rolled out with a VS update.
They have since then spotted the mistake and fixed it. That fix has not rolled out as of today. If I understand the discussion correctly it is targeted for publish with v16.11.
If you cannot wait for that, follow the workaround I described above.
I'm new to using GAC and I am trying to get a handle on when you should and shouldn't use it. Here is my situation:
I develop software that is primarily add-ins to another commercial product so that product loads my products into it's code. There are several assemblies that I have developed that are used by all of my applications (my license module for example). The .dll file for these libraries get installed to the main application directory so the parent program loads them from there.
The problem is when a user has two of my software titles installed, there can be a conflict since the parent program only loads the first copy of an assembly it finds regardless of version. So if they have Software A version 1.0 with License1.0.dll in it and Software B version 2.5 with License 2.0 in it that has different methods and/or arguments than License1.0.dll it only loads 1.0 and then throws an exception on Software B because it can't find the right license methods.
In initial research it seemed like GAC was intended to be the answer to this and several sites seem to say it is, but then I also found this subject and the link in the answer that seems to be saying no don't use GAC for this.
I'm confused. Can someone give some direct guidance on if I should look into using GAC for this?
I wouldn't recommend use the GAC at all as you depend on registered dlls and I often had problems with that. Anyway, you can load the assembly that you like manually. I have a parent application that is either 64 bit or 32 bit and I have to load the corresponding SQLite x64 or x86 dll.
The referenced assembly has copy local false. That's the first place where the runtime will look to resolve the reference. If there is anything then it checks the GAC. The dll isn't registered there so the AssemblyResolve event will happen where I can say what I want to load:
AppDomain.CurrentDomain.AssemblyResolve += ResoveAssembly;
private static Assembly ResoveAssembly(object sender, ResolveEventArgs e)
{
string fullPath = Assembly.GetExecutingAssembly().Location;
string path = Path.GetDirectoryName(fullPath);
if (e.Name.StartsWith("System.Data.SQLite"))
{
return Assembly.LoadFrom(Path.Combine(path, Environment.Is64BitProcess
? "x64\\System.Data.SQLite.DLL"
: "x86\\System.Data.SQLite.DLL"));}
return null;
}
}
In case someone wonders why I'm doing that: As far as I know the new SQLite NuGet package handles this issue now. But it wasn't available when we want to use it.
We have been working on a booking system for a company. When we first tried to run it on their computer it said we needed to download the .NET Framework 4.0. So we did that (or rather we downloaded version 4.5 as the link for 4.0 didn't work). Now, when we try to run it, nothing happens.
We've built the program in C# with Entity Framework - Code First if that narrows it down.
Are we missing something in the settings when publishing? We've tried compiling it in release and the publish wizard but neither work.
This is most probably due to a missing assembly. In your development configuration, you have all of your libraries to run the program and in the deployment, there is/are missing dll(s).
What you may try is to control the GAC of the development machine, and try to locate if any of the libraries you are using except .net libraries are installed in the GAC. Then, you may have been referencing the dll from GAC, and in the deployment this library may be missing in the GAC. I have seen this in a sharepoint project before.
Also, checking the windows event log is useful. You may locate the actual exception.
p.s. if this is a asp.net project, do not forget to run regiis.exe after framework deployment.
If your application has a GUI and it doesn't show means, that your application fails in the constructor. The best thing you can do is to log every step from constructor with something like this:
public void log(string msg)
{
StreamWriter file2 = new StreamWriter(#"c:\file.txt", true);
file2.WriteLine(msg);
file2.Close();
}
and than call it after every line in constructor like
log("InitializeComponent");
If you use FormLoad events, you should also do it there. Also check your code for empty try catches.