I have a solution with several projects, a main project, a globalization project and a test project.
When code in the main project retreives a message from the Messages.de.resx file of the globalization project everything works fine.
But when I copy the same code to the test project, I get a MissingManifestResourceException telling me no resources were found for the specified or neutral culture:
System.Resources.MissingManifestResourceException ist aufgetreten.
Message=Für die angegebene Kultur oder die neutrale Kultur konnten
keine Ressourcen gefunden werden. Stellen Sie sicher, dass
EGR_IQone_Globalization.Messages.resources beim Kompilieren richtig in
die Assembly EGR_IQone_Globalization eingebettet wurde, oder dass die
erforderlichen Satellitenassemblys geladen werden können und
vollständig signiert sind. Source=mscorlib StackTrace:
bei System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing(String
fileName)
bei System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo
culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean
createIfNotExists, StackCrawlMark& stackMark)
bei System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo
requestedCulture, Boolean createIfNotExists, Boolean tryParents,
StackCrawlMark& stackMark)
bei System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo
culture, Boolean createIfNotExists, Boolean tryParents)
bei System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
bei System.Resources.ResourceManager.GetString(String name)
bei EGR_IQone_Globalization.UserMessage.GetMessage(String msgID, String[] arguments) in
C:\projects\EGR_IQoneH\EGR_IQone\EGR_IQone_Globalization\UserMessage.cs:Zeile
28. InnerException:
Normally, the code works just using the .resx file and even using resgen to compile it into a .resources file changes nothing.
I thought it might have to do with the ResourceManager or the specified Assembly, but I could not see any difference between the call from the main project and the call from the test project.
This is the code:
public static class UserMessage
{
private static ResourceManager _resourceManager;
static UserMessage()
{
string baseName = Assembly.GetAssembly(typeof(UserMessage)).GetName().Name + ".Messages.de";
Console.WriteLine(baseName);
_resourceManager = new ResourceManager(baseName, Properties.GlobalizationAssembly);
}
public static string GetMessage(string msgID, params string[] arguments)
{
string msg = "";
string error = "[Message Error] cannot read Message " + msgID;
try
{
//DefaultLanguage = 'de'
//using the GetString overload with or without CultureInfo paramter makes no difference
msg = _resourceManager.GetString(msgID, new CultureInfo(Properties.DefaultLanguage));
for (int i = 0; i < arguments.Length; i++)
{
msg = msg.Replace("{" + i.ToString() + "}", arguments[i]);
}
}
catch (Exception ex)
{
Console.WriteLine(error + "\r\n" + ex.ToString());
return error;
}
return msg;
}
}
http://pastebin.com/L0YNxyfK
Thanks!
I've had the same error - it suddenly occurred even though the application had been running for a while.
It helped to set the Thread.CurrentThread.CurrentUICulture before getting the resource.
Try the following or something similar:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-DE");
msg = _resourceManager.GetString(msgID);
Related
I have a simple C# project (SDK style, targetting .NET Framework 4.8). When I right click my project and add a new WinForm, the designer refuses to open the form. It just shows this error message:
Object reference not set to an instance of an object.
The callstack that is shown below the error message does not help (me) at all:
at System.Resources.Tools.StronglyTypedResourceBuilder.Create(IDictionary resourceList, String baseName, String generatedCodeNamespace, String resourcesNamespace, CodeDomProvider codeProvider, Boolean internalClass, String[]& unmatchable)
at System.Resources.Tools.StronglyTypedResourceBuilder.Create(IDictionary resourceList, String baseName, String generatedCodeNamespace, CodeDomProvider codeProvider, Boolean internalClass, String[]& unmatchable)
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObject.BuildType()
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObject.GetObjectType()
at Microsoft.VisualStudio.Shell.Design.GlobalType.get_ObjectType()
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObject.get_Children()
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObjectProvider.CreateGlobalObjectsForItem(ProjectItem item, GlobalObjectCollection oldObjects, GlobalObjectCollection newObjects, ITypeResolutionService typeResolver)
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObjectProvider.CreateGlobalObjectsForItem(ProjectItem item, GlobalObjectCollection oldObjects, GlobalObjectCollection newObjects, ITypeResolutionService typeResolver)
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObjectProvider.CreateGlobalObjectsForItem(ProjectItem item, GlobalObjectCollection oldObjects, GlobalObjectCollection newObjects, ITypeResolutionService typeResolver)
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObjectProvider.CreateGlobalObjects(Project project)
at Microsoft.VisualStudio.Design.Serialization.ResXGlobalObjectProvider.GetGlobalObjectsCore(Project project, Type baseType)
at Microsoft.VisualStudio.Shell.Design.GlobalObjectProvider.GetGlobalObjects(Project project, Type baseType)
at Microsoft.VisualStudio.Shell.Design.GlobalObjectService.GetGlobalObjects(Type baseType)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetTypeFromGlobalObjects(String name, Boolean throwOnError, Boolean ignoreCase)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name)
at System.ComponentModel.Design.Serialization.DesignerSerializationManager.GetRuntimeType(String typeName)
at System.ComponentModel.Design.Serialization.DesignerSerializationManager.GetType(String typeName)
at System.ComponentModel.Design.Serialization.DesignerSerializationManager.System.ComponentModel.Design.Serialization.IDesignerSerializationManager.GetType(String typeName)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.GetType(IDesignerSerializationManager manager, String name, Dictionary`2 names)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.FillStatementTable(IDesignerSerializationManager manager, IDictionary table, Dictionary`2 names, CodeStatementCollection statements, String className)
at System.ComponentModel.Design.Serialization.TypeCodeDomSerializer.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)
Has anyone seen this kind of behavior?
Is there any way to make the designer load the WinForm?
Below are the Stacktrace;
System.NotSupportedException
HResult=0x80131515
Message=The given path's format is not supported.
Source=mscorlib
StackTrace:
at System.Security.Permissions.FileIOPermission.EmulateFileIOPermissionChecks(String fullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
at EntryLog.Handlers.StreamEntryLogs.StreamWritter(String log, String foldername) in C:\Users\JNyingi\source\repos\EntryLog\EntryLog\Handlers\StreamEntryLogs.cs:line 31
at EntryLog.EntryLog.LogWarning(String Warning) in C:\Users\JNyingi\source\repos\EntryLog\EntryLog\EntryLog.cs:line 55
at EntryLogConsoleTest.Program.Main(String[] args) in C:\Users\JNyingi\source\repos\EntryLogConsoleTest\EntryLogConsoleTest\Program.cs:line 21
This exception was originally thrown at this call stack:
System.Security.Permissions.FileIOPermission.EmulateFileIOPermissionChecks(string)
System.IO.FileStream.Init(string, System.IO.FileMode, System.IO.FileAccess, int, bool, System.IO.FileShare, int, System.IO.FileOptions, Microsoft.Win32.Win32Native.SECURITY_ATTRIBUTES, string, bool, bool, bool)
System.IO.FileStream.FileStream(string, System.IO.FileMode, System.IO.FileAccess)
EntryLog.Handlers.StreamEntryLogs.StreamWritter(string, string) in StreamEntryLogs.cs
EntryLog.EntryLog.LogWarning(string) in EntryLog.cs
EntryLogConsoleTest.Program.Main(string[]) in Program.cs
The exception is coming about from the following lines;
string filePath = System.IO.Path.Combine(EntryLog.LogPath.AbsolutePath, currentTimeFilename + " - " + $"{foldername}.log");
var fileStreamer = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
var streamWriter = new StreamWriter(fileStreamer);
The LogPath is obtained by this method;
LogPath = new Uri(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
I have tried all manner of debugging but it always throws the above exception at StreamWriter. Kindly assist me in resolving this. I'm using 4.5.2 .net Framework
FILE PATH
The file path in question is this;
C:\Users\JNyingi\source\repos\EntryLogConsoleTest\EntryLogConsoleTest\bin\Debug
CURRENT TIME AND FOLDER NAME
string currentTimeFilename = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
string foldername = "Log"
the problem is the : in your filename
string currentTimeFilename = DateTime.Now.ToString("yyyy-MM-dd HH:mm");
^
Change it to - or _ or even a . for example and the error disappears
string currentTimeFilename = DateTime.Now.ToString("yyyy-MM-dd HH_mm");
Using ILSpy you can find that the code of the method EmulateFileIOPermissionChecks (which raises the NotSupportedException) is:
internal static void EmulateFileIOPermissionChecks(string fullPath)
{
if (AppContextSwitches.UseLegacyPathHandling || !PathInternal.IsDevice(fullPath))
{
if (PathInternal.HasWildCardCharacters(fullPath))
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
}
if (PathInternal.HasInvalidVolumeSeparator(fullPath))
{
throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported"));
}
}
}
So your path contains invalid chars.
EDIT
If in your settings hours - minutes separator is a colon (see your datetime formatted string), please consider that ':' cannot be used in a path, but after driver letter.
I tied to create simple program Console App C# .NET 4.0 to load DLL file remotely.
My code works as expected on load dll that on the local computer but I got problem resolve dll when trying to load remotely.
I have no idea to handle this since I can't find any code example that load dll remotely.
The error I got as following.
Could not load file or assembly 'http://codesanook.cloudapp.net/dll/ZupZip.Lib.I
nterfaces.dll' or one of its dependencies. Operation is not supported. (Exceptio
n from HRESULT: 0x80131515)
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String cod
eBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark&
stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntro
spection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String code
Base, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& s
tackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntros
pection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName as
semblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMar
k& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIn
trospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Ev
idence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm,
Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackM
ark)
at System.Reflection.Assembly.LoadFrom(String assemblyFile)
at LoadDllRemotely.Proxy.GetObject[T](String assemblyPath, String fullTypeNam
e, String[] referencedAssembliesPath) in C:\Projects\LoadDllRemotely\LoadDllRemo
tely\Program.cs:line 102
Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.
at LoadDllRemotely.Program.LoadRemotely() in C:\Projects\LoadDllRemotely\Load
DllRemotely\Program.cs:line 74
at LoadDllRemotely.Program.Main(String[] args) in C:\Projects\LoadDllRemotely
\LoadDllRemotely\Program.cs:line 28
Press any key to continue . . .
This is my implementation that load dll remotely with new AppDomain
using System;
using System.IO;
using System.Reflection;
using ZupZip.Lib.Interfaces;
namespace LoadDllRemotely
{
public class Program
{
private const string ASSEMBLY_PATH =
#"C:\Projects\LoadDllRemotely\ZupZip.Lib\bin\Debug\ZupZip.Lib.dll";
private const string ASSEMBLY_URL =
#"http://codesanook.cloudapp.net/dll/ZupZip.Lib.dll";
private const string REFERENCED_ASSEMBLY3_URL =
#"http://codesanook.cloudapp.net/dll/ZupZip.Lib.Interfaces.dll";
private const string REFERENCED_ASSEMBLY2_URL =
#"http://codesanook.cloudapp.net/dll/system.core.dll";
private const string REFERENCED_ASSEMBLY1_URL =
#"http://codesanook.cloudapp.net/dll/mscorlib.dll";
public static void Main(string[] args)
{
//LoadLocally();
LoadRemotely();
}
public static void appDomain_DomainUnload(object sender, EventArgs e)
{
Console.WriteLine("domain loaded sender: {0}",
sender.GetType().FullName);
}
public static void LoadLocally()
{
var appDomain = AppDomain.CreateDomain("dynamicDll");
appDomain.DomainUnload += new EventHandler(appDomain_DomainUnload);
var proxy = (Proxy)appDomain.CreateInstanceAndUnwrap(
typeof(Proxy).Assembly.FullName,
typeof(Proxy).FullName);
var calculator = proxy.GetObject<IGradeCalculator>(
ASSEMBLY_PATH,
"ZupZip.Lib.GradeCalculator");
var score = 80;
Console.WriteLine("you got grad: {0} from score: {1}", calculator.GetGradeForScore(score), score);
AppDomain.Unload(appDomain);
File.Delete(ASSEMBLY_PATH);//you can delete referece dll after remove
}
public static void LoadRemotely()
{
//app domain setup
//load as byte array
var appDomain = AppDomain.CreateDomain("dynamicDll");
appDomain.DomainUnload += new EventHandler(appDomain_DomainUnload);
var proxy = (Proxy)appDomain.CreateInstanceAndUnwrap(
typeof(Proxy).Assembly.FullName,
typeof(Proxy).FullName);
var calculator = proxy.GetObject<IGradeCalculator>(
ASSEMBLY_URL,
"ZupZip.Lib.GradeCalculator",
REFERENCED_ASSEMBLY3_URL);
var score = 80;
Console.WriteLine("you got grad: {0} from score: {1}", calculator.GetGradeForScore(score), score);
AppDomain.Unload(appDomain);
}
}
public class Proxy : MarshalByRefObject
{
public T GetObject<T>(
string assemblyPath,
string fullTypeName,
params string[] referencedAssembliesPath) where T : class
{
try
{
//find reference
var assemblyToLoad = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
AssemblyName[] referencedAssemblies = assemblyToLoad.GetReferencedAssemblies();
//foreach (var referencedAssembly in referencedAssemblies)
//{
// Console.WriteLine("referenceAssemblyName: {0}", referencedAssembly.Name);
// Assembly.Load(referencedAssembly.Name);
//}
//solve reference assembly
foreach (var referencedAssemblyPath in referencedAssembliesPath)
{
Assembly.LoadFrom(referencedAssemblyPath);
}
//this dll will load in new domain
var assembly = Assembly.LoadFrom(assemblyPath);
var type = assembly.GetType(fullTypeName);
var obj = (T)Activator.CreateInstance(type);
return obj;
}
catch (Exception ex)
{
// throw new InvalidOperationException(ex);
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
return null;
}
}
}
}
I also add this source code to my open source on Bitbuckget
enter link description here
Fixed
just add this configuration to App.Config to run in full trust
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<loadFromRemoteSources enabled="true"/>
</runtime>
</configuration>
and I also update this code at
https://bitbucket.org/theeranitp/loaddllremotely
I have a dotnet script which is for encryption and decryption. I have to pass the parameters for the setvalues function in installshield. How can I achieve this? Dotnet code is as follows. I have the assembly (.dll) file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Security;
using System.Xml;
using System.Collections.Specialized;
namespace EncryptionDecryption
{
public class EncrptionHelper
{
#region Member variables
static byte[] entropy = { 0, 8, 2, 3, 5 };
#endregion
#region Public Methods
public static void SetValue(string configFilePathName, string appSettingKey, string appSettingValue)
{
appSettingValue = EncryptString(ToSecureString(appSettingValue));
SetSetting(appSettingKey, appSettingValue, configFilePathName);
}
public static string GetValue(string configFilePathName, string appSettingKey)
{
string value = GetSetting(appSettingKey, configFilePathName);
value = ToInsecureString( DecryptString(value));
return value;
}
#endregion
#region Private Methods
private static bool SetSetting(string Key, string Value, string configFilePath)
{
bool result = false;
try
{
// System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(configFilePath);
// config.AppSettings.File = configFilePath;
// config.AppSettings.Settings[Key].Value = Value;
// config.Save(ConfigurationSaveMode.Modified);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(configFilePath);
xmlDoc.SelectSingleNode("//appSettings/add[#key='" + Key +"']").Attributes["value"].Value = Value;
xmlDoc.Save(configFilePath);
ConfigurationManager.RefreshSection("appSettings");
result = true;
}
finally
{ }
return result;
}
private static string GetSetting(string Key, string configFilePath)
{
string result = null;
try
{
XmlDocument appSettingsDoc = new XmlDocument();
appSettingsDoc.Load(configFilePath);
XmlNode node = appSettingsDoc.SelectSingleNode("//appSettings");
XmlElement value = (XmlElement)node.SelectSingleNode(string.Format("//add[#key='" + Key + "']"));
result = (value.GetAttribute("value").ToString());
}
finally
{ }
return result;
}
private static SecureString ToSecureString(string input)
{
SecureString secure = new SecureString();
foreach (char c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
private static string ToInsecureString(SecureString input)
{
string returnValue = string.Empty;
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
private static string EncryptString(System.Security.SecureString input)
{
byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)), entropy, System.Security.Cryptography.DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
private static SecureString DecryptString(string encryptedData)
{
try
{
byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
Convert.FromBase64String(encryptedData),
entropy,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
}
catch
{
return new SecureString();
}
}
#endregion
}
}
Update: Action start 14:31:36: Encryption.
MSI (c) (84:40) [14:31:36:525]: Invoking remote custom action. DLL: C:\Users\<username>\AppData\Local\Temp\MSIE259.tmp, Entrypoint: m1
InstallShield: Attempting to load through CLR 4 APIs...
InstallShield: Getting meta host...
InstallShield: Enumerating available runtimes...
InstallShield: Highest available runtime: v4.0.30319
InstallShield: Trying to use highest runtime...
InstallShield: Using highest version runtime...
InstallShield: Loading assembly Security.Encryption from resource 4097
InstallShield: Calling method with parameters [(System.String)C:\Program Files (x86)\<Installdir>\<configfilename>.config, (System.String)VWFPassword, (System.String)]
InstallShield: Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Program Files (x86)\<Installdir>\<configfilename>.config'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
at System.Xml.XmlTextReaderImpl.OpenUrlDelegate(Object xmlResolver)
at System.Threading.CompressedStack.runTryCode(Object userData)
at
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.CompressedStack.Run(CompressedStack compressedStack, ContextCallback callback, Object state)
at System.Xml.XmlTextReaderImpl.OpenUrl()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.Load(String filename)
at Security.Encryption.EncrptionHelper.SetSetting(String appSettingKey, String appsettingValue, String configFilePathName)
at Security.Encryption.EncrptionHelper.SetValue(String configFilePathName, String appSettingKey, String appSettingValue)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at InstallShield.ClrHelper.CustomActionHelper.CallMethod(EntryPointInfo info)
at InstallShield.ClrHelper.CustomActionHelper.RunAction(UInt32 installHandle, Int32 entryNumber, Int64 instanceHandle)
InstallShield: Managed code threw an unhandled exception.
This is the error I receive after doing all that is mentioned in the screenshots below and doing some R&D. The directory mentioned "C:\Program Files (x86)\\.config" exists when the encryption custiom action is being called but it throws an exception.
Yes, it can be done with following steps:
1- write your required functionality in c# installer class (make sure your are using installer class)
2- Compile and add your dll into installshield (recomended create a separate component for this dll)
3- Select component view -> select above component and go to .Net settings section, set the ".Net Installer class" to true. Set the ".net installer class parameters"
Parameters are passed as key/value pair e.g
/targetDirectory="[INSTALLDIR]\"
All steps are same, just added screenshots.
Create a dll with an installer class and your encrypt/decrypt class.
Add dll and config file to component(above mentioned), if config file is already added to some other component then its fine. no need to add again.
I have added and retrieved INSTALLDIR variable as argument which is predefined. if you want to receive some input from user (from some custom textboxes) then you will need to define your own variables to store and pass values as arguments.
Creating dll with installer class and your requred logic for other task
Creating component and adding files
Mark the dll as installer class and pass arguments
Here goes installer class:
using System;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
using System.Configuration.Install;
using System.Collections.Generic;
namespace EncryptionDecryption
{
[RunInstaller(true)]
public class InstallerClassDemo : Installer
{
private string installationDirectory=string.Empty;
private string testString=string.Empty ;
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
//For testing purpose only.. work only in debug mode when pdb files are deployed as well.
//Debugger.Break();
installationDirectory = Context.Parameters["INSTALLDIR"];
//I believe, the config file must be located in the installation directory if so, then use the following way to compute path
string configFilePath = Path.Combine(installationDirectory, "myConfigFile.config");
EncrptionHelper.SetValue(configFilePath, "testKey", "testValue");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
protected override void OnCommitted(System.Collections.IDictionary savedState)
{
base.OnCommitted(savedState);
}
public override void Uninstall(System.Collections.IDictionary savedState)
{
base.Uninstall(savedState);
}
}
}
I think installshield cannot (or need extra work) for read your assemblies, but you can run simple console application which consume your assemblies from installscript and passing parameter from installshield.
Create simple console application
Include console application on Support Files
Copy to installation folder or assemblies location, so console application can access your assemblies
Launch from installscript using launchappandwait
If consoleapp.exe not use anymore, just delete it.
I am trying to load a strongly named assembly that is located at a user-defined location into an AppDomain using this code:
AppDomainSetup ads1 = new AppDomainSetup();
if (ads1.PrivateBinPath != null)
{
ads1.PrivateBinPath += ads1.PrivateBinPath.Length == 0 ? "" : Path.PathSeparator.ToString();
}
ads1.PrivateBinPath += #"c:\work\abc1";
sandbox1 = AppDomain.CreateDomain("sandbox1", null, ads1);
Object o1 = sandbox1.CreateInstanceFromAndUnwrap(#"abc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f10808f3df0adc34", "Abc.Def");
When I run I get this error:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'file:///C:\Users\gel\Documents\Visual Studio 2012\Projects\ConsoleApplicat
ion1\ConsoleApplication1\bin\Debug\abc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f10808f3df0adc34' or one of its dependencies. The system cannot find the fil
e specified.
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stack
Mark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& st
ackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& st
ackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boole
an forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence securityEvidence)
at System.Activator.CreateInstanceFromInternal(String assemblyFile, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, C
ultureInfo culture, Object[] activationAttributes, Evidence securityInfo)
at System.AppDomain.CreateInstanceFrom(String assemblyFile, String typeName)
at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)
at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)
at ConsoleApplication1.Program.Main(String[] args) in c:\Users\gel\Documents\Visual Studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:li
ne 69
It is as though the AppDomain is not looking in the PrivateBinPath at all. What am I not doing right? I've double checked in an Explorer window and I can see the assembly at the location that I specified in the PrivateBinPath. It works fine if I just do Assembly.LoadFile and specify the right path, but that'd defeating the purpose of trying to load it in another AppDomain.
I've modified your code and this works just great. See the changes you needs to be done.
AppDomainSetup ads1 = new AppDomainSetup();
if (ads1.PrivateBinPath != null)
{
ads1.PrivateBinPath += ads1.PrivateBinPath.Length == 0 ? "" : Path.PathSeparator.ToString();
}
ads1.PrivateBinPath += #"D:\ConsoleApplication1\ClassLibrary1\bin\debug";
AppDomain sandbox1 = AppDomain.CreateDomain("sandbox1", null, ads1);
Object o1 = sandbox1.CreateInstanceFromAndUnwrap(#"ClassLibrary1.dll", "ClassLibrary1.Class1");
I belive it fails to load that assembly into your current AppDomain, not to the new one (where it likley loaded ok).
The behavior sometimes called "leaking types to aother domain" and casued by attempt to use the created object directly. To work around it one need to create class completely in the other AppDomain (i.e. by running some custom code that deal with creation) and than exposing only interface/classes known to both domain. Check out Unloadable plugins for details.
Short portion of code adopted from the article - create RemoteLoader class in other AppDomain with CreateInstanceFromAndUnwrap and use that object to load/manage other types in the new AppDomain.
public class RemoteLoader : MarshalByRefObject
{
public void Load(string assemblyName, string typeName)
{
object instance = Activator.CreateInstance(assemblyName, typeName);
//Do something with instance, or return shared interface of it.
}
}
Side note: unless you doing it for education purposes consider using existing plugin frameworks like MEF.