Load Assembly in new Appdomain, needs parent assembly to be fully trusted - c#

I run a macro assembly inside my main application. Macro does not need to access parent assembly. This is the snippet:
Assembly ParentAssembly
{
class c1
{
void RunMacro()
{
System.Security.PermissionSet PS = new System.Security.PermissionSet(PermissionState.None);
PS.AddPermission(new SOME_PERMISSIONS....);
AppDomainSetup ADS = new AppDomainSetup();
ADS.ApplicationBase = "c:";
AppDomain domain = AppDomain.CreateDomain(SomeName, null, ADS, PS);
System.Runtime.Remoting.ObjectHandle handle = Activator.CreateInstanceFrom(domain, typeof(Sandboxer2).Assembly.ManifestModule.FullyQualifiedName, typeof(Sandboxer2).FullName);
Sandboxer2 m = (Sandboxer2)handle.Unwrap();
m.Execute();
}
}
}
I receive this exception:
Attempt by security transparent method
'SandBoxer.Sandboxer2.Execute()' to access security critical method
'System.AppDomain.add_AssemblyResolve(System.ResolveEventHandler)'
failed.
Assembly 'Parent Assembly full name...' is partially trusted, which
causes the CLR to make it entirely security transparent regardless of
any transparency annotations in the assembly itself. In order to
access security critical code, this assembly must be fully trusted.
My question:
Is there any way to avoid loading parent assembly in child assembly?
In second line of my code, what permissions can solve the problem?
There are some assemblies that will be loaded by AssemblyResolve event of SandBoxer at runtime. Assemblies get loaded from database as binary array or from GAC. They are not fully trusted. I control their behavior with permission objects added at second line of code. Are there special permissions that I have to add for letting them be only loaded as partially trusted assemblies?
I think everything can be done by adding security permissions like second line of code, If I'm misunderstanding the concept, I would be grateful to be guided.
EDIT1:
Parent Assembly is the assembly of main application that creates instance of SandBoxr and runs it. Please take a look at SandBoxer2 class and its Execute method:
public class Sandboxer2 : MarshalByRefObject
{
public void Execute()
{
AppDomain ad = AppDomain.CurrentDomain;
ad.AssemblyResolve += MyHandler;
.
.
.
}
}
Inside of Execute method, after ad is instantiated, I used ad.GetAssemblies() and this was the list of all assemblies already loaded. Line number 2 holds ParentAssembly from the very beginning of execution of sandboxer.
[0] {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[1] {System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[2] {ParentAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[3] {System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[4] {System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[5] {MacroBase_IO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[6] {System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[7] {System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}
[8] {System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} System.Reflection.Assembly
{System.Reflection.RuntimeAssembly}

Answer to questions 1 and 2:
Sandboxer must be in a separate assembly (Another DLL) and this separate assembly must be signed with a key. Then, main application will not be automatically loaded and this exception won't be raised.
Edit:
1- signing with a key is done through Properties of Assembly-Signing tab.
2- This sample helps understanding how to define an assembly as full trust and introduce strong names to Sandbox.

Related

Inconclusive tests with Jetbrains Rider

We have an old project with .Net Framework 4.5.2 and want to run some unit tests with newer versions of Rider. Test run with Rider 2021.3, but not with Rider 2022.2 and 2022.3
All of them fail with
Test has not run
Last runner error: Could not load file or assembly 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Reference assemblies cannot be loaded for execution. (0x80131058) Cannot load a reference assembly for execution.
--- EXCEPTION #1/3 [BadImageFormatException]
Message = “Cannot load a reference assembly for execution.”
ExceptionPath = Root.InnerException.InnerException
ClassName = System.BadImageFormatException
HResult = COR_E_LOADING_REFERENCE_ASSEMBLY=80131058
--- Outer ---
--- EXCEPTION #2/3 [BadImageFormatException]
Message = “Could not load file or assembly 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Reference assemblies cannot be loaded for execution. (0x80131058)”
ExceptionPath = Root.InnerException
ClassName = System.BadImageFormatException
InnerException = “Exception #1 at Root.InnerException.InnerException”
HResult = COR_E_LOADING_REFERENCE_ASSEMBLY=80131058
Source = System.ServiceModel
BadImageFormat_FileName = “System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”
StackTraceString = “
at System.ServiceModel.Description.ServiceCredentials..ctor()
at System.ServiceModel.ServiceHostBase..ctor()
at System.ServiceModel.ServiceHost..ctor(Object singletonInstance, Uri[] baseAddresses)
at JetBrains.ReSharper.UnitTesting.MSTest.Provider.Execution.DataCollector.StartLocalDataCollector()
at JetBrains.ReSharper.UnitTesting.MSTest.Provider.Execution.DataCollector.Initialize()
at JetBrains.ReSharper.UnitTesting.MSTest.Provider.New.TestWindow.TestWindowMsTestRunner.StartDataCollector()
at JetBrains.ReSharper.UnitTesting.MSTest.Provider.New.TestWindow.TestWindowMsTestRunner.<Initialize>b__13_0()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread,
....
--- Outer ---
--- EXCEPTION #3/3 [LoggerException]
Message = “Could not load file or assembly 'System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Reference assemblies cannot be loaded for execution. (0x80131058)”
ExceptionPath = Root
ClassName = JetBrains.Util.LoggerException
InnerException = “Exception #2 at Root.InnerException”
HResult = COR_E_APPLICATION=80131600
We`ve tried a lot but without success. Is there any idea?

RazorLight.Compilation Exception: Failed to compile generated Razor template

I'm creating a .NET 5 worker service app that watches few other apps and sends email when required.
I'm using FluentEmail to send those emails and everything works fine, until I deploy the app.
When I deploy the app and it attempts to send an email, it throws this exception:
RazorLight.Compilation.TemplateCompilationException: Failed to compile generated Razor template:
- (3:35) The type 'Attribute' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (3:10) The type 'Type' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (35:37) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (38:66) 'GeneratedTemplate.ExecuteAsync()': return type must be 'Task' to match overridden member 'TemplatePageBase.ExecuteAsync()'
- (38:66) The type 'Task' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (40:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (41:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (42:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (43:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (53:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (69:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (84:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (44:19) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (92:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (47:20) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (100:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (50:20) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (108:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (53:19) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (116:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
- (124:12) The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'.
See CompilationErrors for detailed information
at RazorLight.Compilation.RoslynCompilationService.CompileAndEmit(IGeneratedRazorTemplate razorTemplate)
at RazorLight.Compilation.RazorTemplateCompiler.CompileAndEmit(RazorLightProjectItem projectItem)
at RazorLight.Compilation.RazorTemplateCompiler.OnCacheMissAsync(String templateKey)
--- End of stack trace from previous location ---
at RazorLight.EngineHandler.CompileTemplateAsync(String key)
at RazorLight.EngineHandler.CompileRenderAsync[T](String key, T model, ExpandoObject viewBag)
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at FluentEmail.Razor.RazorRenderer.ParseAsync[T](String template, T model, Boolean isHtml)
at FluentEmail.Razor.RazorRenderer.FluentEmail.Core.Interfaces.ITemplateRenderer.Parse[T](String template, T model, Boolean isHtml)
at FluentEmail.Core.Email.UsingTemplateFromFile[T](String filename, T model, Boolean isHtml)
at WatchDog.Services.NotificationService.SendEmailAsync[TModel](String subject, String fileName, TModel model) in C:\Users\SomeOne\source\repos\WatchDog\WatchDog\Services\NotificationService.cs:line 41
My setup looks like this:
Views Folder
References
Views Folder
I added the Views folder and please note that this is a .NET 5 Worker Service project (if that matters instead of it being some Web project).
Program.cs file:
Inside the ConfigureServices, I've added the RazorRenderer as:
//Set email service using FluentEmail
services.AddFluentEmail("appname#domain.com")
.AddRazorRenderer(#$"{Directory.GetCurrentDirectory()}/Views/")
.AddSmtpSender("smtp.somesmtp.com", 25)
.AddSmtpSender(new System.Net.Mail.SmtpClient() { });
NotificationService.cs file:
private async Task SendEmailAsync<TModel>(string subject, TModel model)
{
try
{
using (var scope = _serviceProvider.CreateScope())
{
var email = await scope.ServiceProvider.GetRequiredService<IFluentEmail>()
.To(string.Join(";", _emailRecipients))
.Subject(subject)
.UsingTemplateFromFile("./Views/Emails/SomeReport.cshtml", model)
.SendAsync();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to send email. Check exception for more information.");
}
}
SomeReport.cshtml file:
SomeReport.cshtml is inside Views\Emails\SomeReport.cshtml which looks like this:
#using System.Collections.Generic;
#using WatchDog.Models;
#model IEnumerable<SomeReport>
#{
Layout = "./Shared/_Layout.cshtml";
}
#* Work with the Model here... *#
_Layout.cshtml file:
_Layout.cshtml is inside Views\Shared\_Layout.cshtml which looks like this:
#* Some common layout styles here *#
#RenderBody()
WatchDog.csproj file:
I've also added PreserveCompilationContext and PreserveCompilationReferences:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<PreserveCompilationContext>true</PreserveCompilationContext>
<PreserveCompilationReferences>true</PreserveCompilationReferences>
</PropertyGroup>
I've looked at everywhere and still haven't found a solution to this.
Please help.
Thanks!
I had the exact same issue, but only within my published application. While debugging the worker service i didn't get the error message.
What fixed it for me was removing the p:PublishTrimmed=true property from the dotnet publish command.
For the sake of completeness, that's how my .csproj file looks like:
<PropertyGroup>
<PreserveCompilationReferences>true</PreserveCompilationReferences>
<PreserveCompilationContext>true</PreserveCompilationContext>
<MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>
References:
https://github.com/toddams/RazorLight/issues/188#issuecomment-638876672
https://github.com/toddams/RazorLight#compilation-and-deployment-issues-faq

xunit testing web api 2 controller : throws Xunit.Sdk.IsTypeException

I wan't to test the insert method on a a web api controller. The method returns a CreatedNegotiatedContentResult. Everything goes fine up to the Assert...
Assert.IsType(typeof(CreatedNegotiatedContentResult<Justif>), result);
and boom...
Xunit.Sdk.IsTypeException was unhandled by user code
Actual=System.Web.Http.Results.CreatedNegotiatedContentResult`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
ActualTitle=Actual
Expected=System.Web.Http.Results.CreatedNegotiatedContentResult`1[[HubHacienda.Justif, HubHacienda, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
ExpectedTitle=Expected
HResult=-2146233088
Message=Assert.IsType() Failure
Expected: System.Web.Http.Results.CreatedNegotiatedContentResult`1[[HubHacienda.Justif, HubHacienda, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
Actual: System.Web.Http.Results.CreatedNegotiatedContentResult`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Source=xunit.assert
UserMessage=Assert.IsType() Failure
StackTrace:
at Xunit.Assert.IsType(Type expectedType, Object object) in C:\BuildAgent\work\cb37e9acf085d108\src\xunit.assert\Asserts\TypeAsserts.cs:line 99
at HubHacienda.Tests.JustifsControllerTest.Post_WhenModelValid_ShouldReturnSuccess() in C:\NotilusTNE\Sources\Hub\Hub Hacienda\Dev\HubHacienda\HubHacienda.Tests\JustifsControllerTests.cs:line 52
InnerException:
This is my test framework blowing up? This can't be right?
Ok this appears to be an xunit bug. The problem is I'm comparing a generic type, of the form SystemType<MyType>. The typeof() operator in the xunit project returns a strong name indicating my dll, whereas result.GetType() returns a strong name with the system dll.
The workaround is to compare just the Type.Name...
System.Type expectation = typeof(System.Web.Http.Results.CreatedNegotiatedContentResult<Justif>);
System.Type tristeRealite = result.GetType();
Assert.Equal(expectation.Name, tristeRealite.Name);

NGEN Display Returns A different result than Elevated CMD when run using Process.Start() in C# winforms

i have been trying to figure this out with my co-workers for a while now.
i use Ngen to Make Native images and boost my Applications performance on the clients.
lets assume the Exe Filename is Example.exe
what i try to do in the app is that i do ngen install example.exe,and the ngen will install native images for the assebmlies
however here is the problem :
if i try an Elevated CMD and run C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen Display example.exe
the example.exe file name and the version of the native image is displayed,however,using the following code which does the same thing in the windows forms c#,it does not display the filename and version of the example.exe file,and displays the dependencies instead,such as Telerik and so on.
so my question is why does the CMD return the correct result while the process returns the dependencies instead of the filename and version itself?
here is some of my code:
public static bool Run()
{
var f = new Loading();
bool state = false;
var b = new BackgroundWorker();
string runtimeStr = RuntimeEnvironment.GetRuntimeDirectory();
string ngenStr = Path.Combine(runtimeStr, "ngen");
Process process = new Process
{
StartInfo =
{
FileName = ngenStr,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = false
}
};
if (Environment.OSVersion.Version.Major >= 6)
{
process.StartInfo.Verb = "runas";
}
process.StartInfo.Arguments = "display " + Application.ProductName;
process.Start();
// process.WaitForExit();
string stdoutx = process.StandardOutput.ReadToEnd();
process.WaitForExit();
}
however the stdoutx string does not contain the example.exe filename or version
EDIT : examples of what should be and what is :
this is what the cmd returns which is the correct result :
Example, Version=1.0.0.19, Culture=neutral, PublicKeyToken=null <debug>
this is what is :
Microsoft (R) CLR Native Image Generator - Version 4.6.79.0
Copyright (c) Microsoft Corporation. All rights reserved.
NGEN Roots:
C:\Project\Example\bin\Debug\Example.EXE
NGEN Roots that depend on "Example":
C:\Project\Example\bin\Debug\Example.EXE
Native Images:
Klik.Windows.Forms.EntryLib.V2.2008, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
NCalc, Version=1.3.8.0, Culture=neutral, PublicKeyToken=973cde3f1cafed03
Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
RedGate.Migrations.Core, Version=1.0.0.1401, Culture=neutral, PublicKeyToken=7f465a1c156d4d57 <debug>
RedGate.Shared.ComparisonInterfaces, Version=1.0.2.278, Culture=neutral, PublicKeyToken=7f465a1c156d4d57
RedGate.Shared.SQL, Version=9.9.0.0, Culture=neutral, PublicKeyToken=7f465a1c156d4d57
RedGate.Shared.Utils, Version=9.9.0.0, Culture=neutral, PublicKeyToken=7f465a1c156d4d57
RedGate.SOCCompareInterface, Version=3.0.50.59, Culture=neutral, PublicKeyToken=7f465a1c156d4d57
RedGate.SQLCompare.ASTParser, Version=11.0.0.414, Culture=neutral, PublicKeyToken=7f465a1c156d4d57
RedGate.SQLCompare.Engine, Version=11.1.0.2, Culture=neutral, PublicKeyToken=7f465a1c156d4d57 <debug>
RedGate.SQLCompare.Rewriter, Version=11.1.0.2, Culture=neutral, PublicKeyToken=7f465a1c156d4d57
System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Data.SQLite, Version=1.0.85.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139
System.Deployment, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Threading, Version=1.0.2856.102, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Telerik.Reporting, Version=9.0.15.324, Culture=neutral, PublicKeyToken=a9d7983dfcc261be
Telerik.ReportViewer.WinForms, Version=9.0.15.324, Culture=neutral, PublicKeyToken=a9d7983dfcc261be
Telerik.WinControls.ChartView, Version=2015.1.331.40, Culture=neutral, PublicKeyToken=5bb2a467cbec794e
Telerik.WinControls, Version=2015.1.331.40, Culture=neutral, PublicKeyToken=5bb2a467cbec794e
Telerik.WinControls.GridView, Version=2015.1.331.40, Culture=neutral, PublicKeyToken=5bb2a467cbec794e
Telerik.WinControls.Themes.Office2010Black, Version=2015.1.331.40, Culture=neutral, PublicKeyToken=5bb2a467cbec794e
Telerik.WinControls.Themes.Office2010Silver, Version=2015.1.331.40, Culture=neutral, PublicKeyToken=5bb2a467cbec794e
Yes, you are not doing this correctly. The syntax of the command you are using is:
ngen.exe display [assemblyName | assemblyPath]
Note the difference between assemblyName and assemblyPath. When you ran it from cmd.exe you typed "example". And thus specified the (partial) assembly name. In your code, you used "example.exe". And the Environment.CurrentDirectory is set correctly by accident, a common accident. So Ngen.exe can find the file and it gets chatty. Listing not just the assembly name but also the native images for all of its dependencies. Like Klik.Windows.Forms.EntryLib etcetera.
Not the only problem, note that you specified the partial assembly name. You want to make sure that the specific version of your assembly was ngen-ed. Make the code look like this instead:
process.StartInfo.Arguments = "display \"" +
System.Reflection.Assembly.GetEntryAssembly().FullName + "\"";
And test it with Project > Properties > Debug tab > untick the "Enable the Visual Studio hosting process" checkbox.
Secondary things to fret about are the bitness of the native images (x86 vs x64) and getting your app elevated so you can install the native images, something you normally only have a shot at when your app is installed.

assembly discovery from library code

I have some code in a common library to support internationalization. The basic idea is that given the fully qualified name of a RESX file location, you can look up values using a markup extension:
resx:ResxProperty.Name="SampleApp.Common.Resources.MainWindow"
Title="{Resx Key=Window.Title}"
Icon="{Resx Key=Window.Icon}"
To find the RESX file there is a routine to search all assemblies as shown below, and it works fine when the RESX file is in the same assembly as the xaml. BUT it breaks down when it is not.
Consider the solution structure below, where SampleApp.Wpf has the calling XAML and has a dependency on both the LocalizationLib and SampleApp.Common.
AppDomain.CurrentDomain.GetAssemblies() does not have SampleApp.Common at run time (although it does at design time).
How can I modify this code so it will know about SampleApp.Common at runtime?
Cheers,
Berryl
Library code
/// <summary>
/// Find the assembly that contains the type
/// </summary>
/// <returns>The assembly if loaded (otherwise null)</returns>
public static Assembly FindResourceAssembly(string resxName)
{
// check the entry assembly first - this will short circuit a lot of searching
//
var assembly = Assembly.GetEntryAssembly();
if (assembly != null && HasSpecifiedResx(assembly, resxName))
return assembly;
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var searchAssembly in assemblies)
{
// skip system assemblies
var name = searchAssembly.FullName;
if (_isSystemAssembly(name)) continue;
if (HasSpecifiedResx(searchAssembly, resxName))
return searchAssembly;
}
return null;
}
UPDATE
More details.
SampleApp.Wpf is targeting .net 4.0. Below are the references for it as displayed in Visual Studio.
The only project references in there are Infralution.Localization.Wpf and SampleApp.Common, both of which also target .Net 4.0.
Based on Metro Smurf's input I tried using assembly.GetReferencedAssemblies(). When I use this method, the VS designer does NOT find SampleApp.Common, and the following AssemblyNames are known in the debugger at runtime:
{System.Reflection.AssemblyName[6]}
[0]: {PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[1]: {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[2]: {System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[3]: {Infralution.Localization.Wpf, Version=2.1.2.0, Culture=neutral, PublicKeyToken=547ccae517a004b5}
[4]: {System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[5]: {PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
And when I use the origional AppDomain.CurrentDomain.GetAssemblies(), the designer DOES know SampleApp.Common, and these assemblies are known at runtime:
?AppDomain.CurrentDomain.GetAssemblies()
{System.Reflection.RuntimeAssembly[21]}
[0]: {mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[1]: {Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[2]: {System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[3]: {System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[4]: {System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[5]: {Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[6]: {Microsoft.VisualStudio.Debugger.Runtime, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[7]: {vshost32, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[8]: {System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[9]: {System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[10]: {System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[11]: {Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[12]: {System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[13]: {System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[14]: {System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}
[15]: {WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[16]: {PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[17]: {PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
[18]: {SampleApp.Wpf, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
[19]: {System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a}
[20]: {Infralution.Localization.Wpf, Version=2.1.2.0, Culture=neutral, PublicKeyToken=547ccae517a004b5}
In both cases, SampleApp.Common isn't known at runtime. For the fun of it, I loaded that assembly in the debugger and got:
?Assembly.Load("SampleApp.Common")
{SampleApp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
[System.Reflection.RuntimeAssembly]: {SampleApp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}
CodeBase: "file:///C:/.../SampleApp.Wpf/bin/Release/SampleApp.Common.DLL"
EntryPoint: null
EscapedCodeBase: "file:///C:.../SampleApp.Wpf/bin/Release/SampleApp.Common.DLL"
Evidence: {System.Security.Policy.Evidence}
FullName: "SampleApp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
GlobalAssemblyCache: false
HostContext: 0
ImageRuntimeVersion: "v4.0.30319"
IsDynamic: false
IsFullyTrusted: true
Location: "C:\\...\\SampleApp.Wpf\\bin\\Release\\SampleApp.Common.dll"
ManifestModule: {SampleApp.Common.dll}
PermissionSet: {<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
}
ReflectionOnly: false
SecurityRuleSet: Level2
I also tried Metro Smurf's suggestion to reference a static string from SampleApp.Common in SampleApp.Wpf. No change on that one, although I guess it further proves that SampleApp.Common is properly referenced.
Other things to try on SampleApp.Common might include adding an EntryPoint, a SNK, or a HashAlgorithm.
the FIX
asm.GetReferencedAssemblies sounds like the ticket, but it only returns assemblies which are loaded in the memory, and assemblies aren't loaded if they aren't referenced in the code (as in it's confusing that while also quite proper to say one project has a reference to another, but that isn't the sort of reference this method returns).
It turns out that AppDomain.CurrentDomain.GetAssemblies() works the same way.
Metro Smurf was on the right track, but apparently a static reference won't get the assembly loaded, but creating a type instance from the assembly will. So:
Console.WriteLine(Class1.MyDummyString) // this won't do it
Console.WriteLine(new Class1()) // finally, the assembly is loaded
As much as I dislike creating a dummy class, in this case it is an easy fix; I can leave the original library code as is.
You may want to consider using the Assembly.GetReferencedAssemblies Method. However, if I'm not mistaken, you'll need to exclude the framework assemblies as well.

Categories