2016-09-28 5 views
3

Я установил свойство «Types Код Interop» из Netwonsoft.Json библиотеки true и он возвращает ошибку:Может ли Json.Net быть встроенным в исполняемый файл?

Cannot embed interop types from assembly 
'c:\path\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll' 
because it is missing either the 'ImportedFromTypeLibAttribute' attribute or 
the 'PrimaryInteropAssemblyAttribute' attribute 
c:\path\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll 

Похоже, ищу отсутствующие ссылки внутри Newtonsoft.Json библиотеки, но я не совсем уверен. Можно ли встраивать Json.Net в исполняемый файл?

ответ

3

Вы не сказали, какой язык вы используете, но здесь, как вы могли бы сделать это для C#


Во-первых, отключить «Типы Вставить Interop»

Затем к основной исполняемый файл проекта, выгружать и редактировать файл .csproj, и ниже в следующей строке:

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 

Добавить этот XML в файл проекта, сохранить и загрузить его обратно.

<Target Name="AfterResolveReferences"> 
    <ItemGroup> 
    <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> 
     <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> 
    </EmbeddedResource> 
    </ItemGroup> 
</Target> 

Вы затем добавить новый файл кода в основной проект и добавьте следующий код к нему (изменен, чтобы соответствовать, как приложение называется/структурированы в приложении WPF, хорошее место, чтобы положить его будет App.xaml.cs):

[STAThread] 
public static void Main() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; 

    App.Main(); // Run WPF startup code. 
} 

private static Assembly OnResolveAssembly(object sender, ResolveEventArgs e) 
{ 
    var thisAssembly = Assembly.GetExecutingAssembly(); 

    // Get the Name of the AssemblyFile 
    var assemblyName = new AssemblyName(e.Name); 
    var dllName = assemblyName.Name + ".dll"; 

    // Load from Embedded Resources - This function is not called if the Assembly is already 
    // in the same folder as the app. 
    var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(dllName)); 
    if (resources.Any()) 
    { 

     // 99% of cases will only have one matching item, but if you don't, 
     // you will have to change the logic to handle those cases. 
     var resourceName = resources.First(); 
     using (var stream = thisAssembly.GetManifestResourceStream(resourceName)) 
     { 
      if (stream == null) return null; 
      var block = new byte[stream.Length]; 

      // Safely try to load the assembly. 
      try 
      { 
       stream.Read(block, 0, block.Length); 
       return Assembly.Load(block); 
      } 
      catch (IOException) 
      { 
       return null; 
      } 
      catch(BadImageFormatException) 
      { 
       return null; 
      } 
     } 
    } 

    // in the case the resource doesn't exist, return null. 
    return null; 
} 

Наконец, убедитесь, что вы обновляете целевой метод для основного приложения, чтобы быть основным методом для проекта, который вы только что добавили

Источник:http://www.paulrohde.com/merging-a-wpf-application-into-a-single-exe/