Include external .dll in Visual Studio Extension - c#

I have a problem using external libraries for my visual studio extension. Currently I have my own NuGet server on which I host my libraries, now since I dont want functionality twice I extracted some functions out of my extension into an existing library.
The problem is however that whenever I want to use anything from that assembly I can not do so, since visual studio does not include the .dlls in the .vsix package.
So far I have tried:
using Assets to include the libraries from their package location. This creates two items in the solution which also have their "Include in VSIX" property set to true, this did not work
including the projects and then adding the BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroup; to the "Other Groups included in VSIX" property of the reference, which did not work
using Assets to include the libraries as projects, which did not work
So now I am at my end since there is nothing that seems to work....
The solutions I found are already suggesting all the steps I tried, but at this point
I also found these two post which are the same as my question but those answerts did not work for me like I said.
this
this

Okay I found a way to do it, its a combonation of two answers I found here on stack overflow.
And eventhough its a bit hacky I suppose its the only way possible.
So I simply used the existing ManualAssemblyResolver and adjusted it to my needs, the Result being this:
public class ManualAssemblyResolver : IDisposable
{
#region Attributes
/// <summary>
/// list of the known assemblies by this resolver
/// </summary>
private readonly List<Assembly> _assemblies;
#endregion
#region Properties
/// <summary>
/// function to be called when an unknown assembly is requested that is not yet kown
/// </summary>
public Func<ResolveEventArgs, Assembly> OnUnknowAssemblyRequested { get; set; }
#endregion
#region Constructor
public ManualAssemblyResolver(params Assembly[] assemblies)
{
_assemblies = new List<Assembly>();
if (assemblies != null)
_assemblies.AddRange(assemblies);
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
}
#endregion
#region Implement IDisposeable
public void Dispose()
{
AppDomain.CurrentDomain.AssemblyResolve -= OnAssemblyResolve;
}
#endregion
#region Private
/// <summary>
/// will be called when an unknown assembly should be resolved
/// </summary>
/// <param name="sender">sender of the event</param>
/// <param name="args">event that has been sent</param>
/// <returns>the assembly that is needed or null</returns>
private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
foreach (Assembly assembly in _assemblies)
if (args.Name == assembly.FullName)
return assembly;
if (OnUnknowAssemblyRequested != null)
{
Assembly assembly = OnUnknowAssemblyRequested(args);
if (assembly != null)
_assemblies.Add(assembly);
return assembly;
}
return null;
}
#endregion
}
After that I used an Addition ExtensionManager to get the installation path of the extension. Which looks like this
public class ExtensionManager : Singleton<ExtensionManager>
{
#region Constructor
/// <summary>
/// private constructor to satisfy the singleton base class
/// </summary>
private ExtensionManager()
{
ExtensionHomePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Definitions.Constants.FolderName);
if (!Directory.Exists(ExtensionHomePath))
Directory.CreateDirectory(ExtensionHomePath);
SettingsFileFullname = Path.Combine(ExtensionHomePath, Definitions.Constants.SettingsFileName);
InstallationPath = Path.GetDirectoryName(GetType().Assembly.Location);
}
#endregion
#region Properties
/// <summary>
/// returns the installationPath
/// </summary>
public string InstallationPath { get; private set; }
/// <summary>
/// the path to the directory where the settings file is located as well as the log file
/// </summary>
public string ExtensionHomePath { get; private set; }
/// <summary>
/// the fullpath to the settingsfile
/// </summary>
public string SettingsFileFullname { get; private set; }
#endregion
}
Then in the Initialize() method of the Package you will need to create an instance of the ManualAssemblyResolver and provide the Path to the assemblies you need like this:
#region Attributes
private ManualAssemblyResolver _resolver;
#endregion
#region Override Microsoft.VisualStudio.Shell.Package
/// <summary>
/// Initialization of the package; this method is called right after the package is sited, so this is the place
/// where you can put all the initialization code that rely on services provided by VisualStudio.
/// </summary>
protected override void Initialize()
{
_resolver = new ManualAssemblyResolver(
Assembly.LoadFrom(Path.Combine(ExtensionManager.Instance.InstallationPath, Definitions.Constants.NameOfAssemblyA)),
Assembly.LoadFrom(Path.Combine(ExtensionManager.Instance.InstallationPath, Definitions.Constants.NameOfAssemblyB))
);
Note that you will need to call this before anythingelse that even touches anything from the referenced assemblies, otherwise a FileNotFoundException will be thrown.
In any case this seems to work for me now but I wish there was a cleaner way to do it. So if anybody has a better way (a way that actually includes and lloks up the assemblies from the .vsix package) then please post an answer.
EDIT:
Okay now I found the real issue, it was simply the fact that the dlls were satellite dll (the had their assembly culture set) so they were not visible....
However the above fix worked when they were still satillite dlls.

Related

Inaccessible due to protection level in C#

I have references object which contains abstract LoggerFile class. I am trying to access it. But it is showing inaccessible due to protection level. Please anyone help me to understand it.
abstract class LoggerFile
{
private static String logFile = null;
/// <summary>
/// Logfile Property
/// </summary>
public static string LogFile { get => logFile; set => logFile = value; }
/// <summary>
/// Set logFile
/// </summary>
/// <param name="logFile">The absolute path to file for writting logs</param>
public static void SetLogFile(String logFile)
{
LogFile = LogFile ?? logFile;
if (!File.Exists(LogFile))
{
File.Create(LogFile).Close();
}
}
}
}
I am calling this in another class.
using DriverAutomation.Loggin[enter image description here][1]g;
public class Devcon
{
private static Devcon devcon = null;
private readonly String devconEXE;
private readonly String devconPath;
private readonly String devconExeName;
private readonly Logger logger;
/// <summary>
/// DevconStatus Property for devcon status outcome backup
/// </summary>
public readonly String devconStatus;
/// <summary>
/// Initializes the Devcon Singleton Instance
/// </summary>
private Devcon()
{
devcon = this;
logger = Logger.GetLogger(GetType().Name, LoggerFile.LogFile);
devconExeName = "devcon.exe";
devconEXE = Path.Combine(Directory.GetCurrentDirectory(), devconExeName);
}
}
This is working within created solution. But using reference object it is showing error. Please find image.
Declare your class as public and non-Abstract and I think it will solve your problem.
public class LoggerFile
By the way, why is it even Abstract. If you only have some static members in it, maybe you should just turn it to static itself.
Though in most logger implementations, it makes sense to follow the singleton pattern (one of the few cases)

Default the LifetimeManager to the singleton manager (ContainerControlledLifetimeManager)?

I'm using a Unity IoC container to do Dependency Injection. I designed my system around the idea that, at least for a single resolution, all types in the hierarchy would behave as singletons, that is, same type resolutions within that hierarchy would lead to the same instances.
However, I (a) would like to scan my assemblies to find types and (b) don't want to explicitly tell unity that every type is to be resolved as a singleton when registering types in the configuration file.
So, is there a way to tell unity to treat all registered mappings as singleton?
In case anyone is still looking for this... The following extension will change the default, while still allowing you to override with some other manager:
/// <summary>
/// This extension allows the changing of the default lifetime manager in unity.
/// </summary>
public class DefaultLifetimeManagerExtension<T> : UnityContainerExtension where T : LifetimeManager
{
/// <summary>
/// Handle the registering event
/// </summary>
protected override void Initialize()
{
Context.Registering += this.OnRegister;
}
/// <summary>
/// Remove the registering event
/// </summary>
public override void Remove()
{
Context.Registering -= this.OnRegister;
}
/// <summary>
/// Handle the registration event by checking for null registration
/// </summary>
private void OnRegister(object sender, RegisterEventArgs e)
{
if (e.LifetimeManager == null)
{
var lifetimeManager = (LifetimeManager)Activator.CreateInstance(typeof (T));
// Set this internal property using reflection
lifetimeManager
.GetType()
.GetProperty("InUse", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(lifetimeManager, true);
Context.Policies.Set<ILifetimePolicy>(lifetimeManager, new NamedTypeBuildKey(e.TypeTo, e.Name));
if (lifetimeManager is IDisposable)
{
Context.Lifetime.Add(lifetimeManager);
}
}
}
}
You could add a Unity extension at the 'Lifetime' stage of the resolution pipeline and in it always use a ContainerControlledLifetimeManager instance.
Edit: In fact this post has the exact example:
https://unity.codeplex.com/discussions/352179

Method description from an interface [duplicate]

Suppose I have this interface
public interface IFoo
{
///<summary>
/// Foo method
///</summary>
void Foo();
///<summary>
/// Bar method
///</summary>
void Bar();
///<summary>
/// Situation normal
///</summary>
void Snafu();
}
And this class
public class Foo : IFoo
{
public void Foo() { ... }
public void Bar() { ... }
public void Snafu() { ... }
}
Is there a way, or is there a tool that can let me automatically put in the comments of each member in a base class or interface?
Because I hate re-writing the same comments for each derived sub-class!
You can always use the <inheritdoc /> tag:
public class Foo : IFoo
{
/// <inheritdoc />
public void Foo() { ... }
/// <inheritdoc />
public void Bar() { ... }
/// <inheritdoc />
public void Snafu() { ... }
}
Using the cref attribute, you can even refer to an entirely different member in an entirely different class or namespace!
public class Foo
{
/// <inheritdoc cref="System.String.IndexOf" />
public void Bar() { ... } // this method will now have the documentation of System.String.IndexOf
}
Use /// <inheritdoc/> if you want inheritance. Avoid GhostDoc or anything like that.
I agree it is annoying that comments are not inherited. It would be a fairly simple add-in to create if someone had the time (i wish i did).
That said, in our code base we put XML comments on the interfaces only and add extra implementation comments to the class. This works for us as our classes are private/internal and only the interface is public. Any time we use the objects via the interfaces we have full comments display in intellisence.
GhostDoc is good start and has made the process easier to write comments. It is especially useful keeping comments up-to-date when you add/remove parameters, re-run GhostDoc and it will update the description.
GhostDoc does exactly that. For methods which aren't inherited, it tries to create a description out of the name.
FlingThing() becomes "Flings the Thing"
I would say to directly use the
/// <inheritdoc cref="YourClass.YourMethod"/> --> For methods inheritance
And
/// <inheritdoc cref="YourClass"/> --> For directly class inheritance
You have to put this comments just on the previous line of your class/method
This will get the info of your comments for example from an interface that you have documented like :
/// <summary>
/// This method is awesome!
/// </summary>
/// <param name="awesomeParam">The awesome parameter of the month!.</param>
/// <returns>A <see cref="AwesomeObject"/> that is also awesome...</returns>
AwesomeObject CreateAwesome(WhateverObject awesomeParam);
Java has this, and I use it all the time. Just do:
/**
* {#inheritDoc}
*/
And the Javadoc tool figures it out.
C# has similar marker:
<inheritDoc/>
You can read more here:
http://www.ewoodruff.us/shfbdocs/html/79897974-ffc9-4b84-91a5-e50c66a0221d.htm
Another way is to use the <see /> XML documentation tag.
This is some extra effort but works out of the box...
Here are some examples:
/// <summary>
/// Implementation of <see cref="IFoo"/>.
/// </summary>
public class Foo : IFoo
{
/// <summary>
/// See <see cref="IFoo"/>.
/// </summary>
public void Foo() { ... }
/// <summary>
/// See <see cref="IFoo.Bar"/>
/// </summary>
public void Bar() { ... }
/// <summary>
/// This implementation of <see cref="IFoo.Snafu"/> uses the a caching algorithm for performance optimization.
/// </summary>
public void Snafu() { ... }
}
Update:
I now prefer to use /// <inheritdoc/> which is now supported by ReSharper.
ReSharper has an option to copy the comments from the base class or interface.
I ended up creating a tool to post-process the XML documentation files to add support for replacing the <inheritdoc/> tag in the XML documentation files themselves. Available at www.inheritdoc.io (free version available).
Well, there is a kind of native solution, I found for .NET Core 2.2
The idea is to use <include> tag.
You can add <GenerateDocumentationFile>true</GenerateDocumentationFile> your .csproj a file.
You might have an interface:
namespace YourNamespace
{
/// <summary>
/// Represents interface for a type.
/// </summary>
public interface IType
{
/// <summary>
/// Executes an action in read access mode.
/// </summary>
void ExecuteAction();
}
}
And something that inherits from it:
using System;
namespace YourNamespace
{
/// <summary>
/// A type inherited from <see cref="IType"/> interface.
/// </summary>
public class InheritedType : IType
{
/// <include file='bin\Release\netstandard2.0\YourNamespace.xml' path='doc/members/member[#name="M:YourNamespace.IType.ExecuteAction()"]/*'/>
public void ExecuteAction() => Console.WriteLine("Action is executed.");
}
}
Ok, it is a bit scary, but it does add the expected elements to the YourNamespace.xml.
If you build Debug configuration, you can swap Release for Debug in the file attribute of include tag.
To find a correct member's name to reference just open generated Documentation.xml file.
I also assume that this approach requires a project or solution to be build at least twice (first time to create an initial XML file, and the second time to copy elements from it to itself).
The bright side is that Visual Studio validates copied elements, so it is much easier to keep documentation and code in sync with interface/base class, etc (for example names of arguments, names of type parameters, etc).
At my project, I have ended up with both <inheritdoc/> (for DocFX) and <include/> (For publishing NuGet packages and for validation at Visual Studio):
/// <inheritdoc />
/// <include file='bin\Release\netstandard2.0\Platform.Threading.xml' path='doc/members/member[#name="M:Platform.Threading.Synchronization.ISynchronization.ExecuteReadOperation(System.Action)"]/*'/>
public void ExecuteReadOperation(Action action) => action();
End the question:
This feature has been added at VS2019 v16.4.
https://developercommunity.visualstudio.com/t/608809#T-N875117
It works on the interfeace and abstruct class overrideable members

Trial experience of app is allowing unrestricted access - Windows Phone 8

I launched my first app yesterday to the store. The app has a trial version which simply restricts full access to the game.
I downloaded the trial and played for a while, no problems - good.
I then purchased the full version by from the store and started the app again only to find that it didnt release it's restrited areas - NOT good.
I have implemented the following code in the app to implement the restrictions:
/// <summary>
/// The TrialExperienceHelper class can serve as a convenient building-block in your app's trial experience implementation. It queries
/// the license as infrequently as possible, and caches the results, for maximum performance. When built in debug configuration, the class simulates the purchase
/// experience when the Buy method is called. To customize what happens in debug when Buy is called, initialize the simulatedLicMode and/or
/// simulatedLicModeOnPurchase fields to different values. A release build of this class will have access to a license only when the app is
/// published to the Windows Phone Store. For a release build not published to the Store, the value of the LicenseMode property will be
/// LicenseModes.MissingOrRevoked.
/// </summary>
public static class TrialExperienceHelper
{
#region enums
/// <summary>
/// The LicenseModes enumeration describes the mode of a license.
/// </summary>
public enum LicenseModes
{
Full,
MissingOrRevoked,
Trial
}
#endregion enums
#region fields
#if DEBUG
// Determines how a debug build behaves on launch. This field is set to LicenseModes.Full after simulating a purchase.
// Calling the Buy method (or navigating away from the app and back) will simulate a purchase.
internal static LicenseModes simulatedLicMode = LicenseModes.Trial;
#endif // DEBUG
private static bool isActiveCache;
private static bool isTrialCache;
#endregion fields
#region constructors
// The static constructor effectively initializes the cache of the state of the license when the app is launched. It also attaches
// a handler so that we can refresh the cache whenever the license has (potentially) changed.
static TrialExperienceHelper()
{
TrialExperienceHelper.RefreshCache();
PhoneApplicationService.Current.Activated += (object sender, ActivatedEventArgs e) => TrialExperienceHelper.
#if DEBUG
// In debug configuration, when the user returns to the application we will simulate a purchase.
OnSimulatedPurchase();
#else // DEBUG
// In release configuration, when the user returns to the application we will refresh the cache.
RefreshCache();
#endif // DEBUG
}
#endregion constructors
#region properties
/// <summary>
/// The LicenseMode property combines the active and trial states of the license into a single
/// enumerated value. In debug configuration, the simulated value is returned. In release configuration,
/// if the license is active then it is either trial or full. If the license is not active then
/// it is either missing or revoked.
/// </summary>
public static LicenseModes LicenseMode
{
get
{
#if DEBUG
return simulatedLicMode;
#else // DEBUG
if (TrialExperienceHelper.isActiveCache)
{
return TrialExperienceHelper.isTrialCache ? LicenseModes.Trial : LicenseModes.Full;
}
else // License is inactive.
{
return LicenseModes.MissingOrRevoked;
}
#endif // DEBUG
}
}
/// <summary>
/// The IsFull property provides a convenient way of checking whether the license is full or not.
/// </summary>
public static bool IsFull
{
get
{
return (TrialExperienceHelper.LicenseMode == LicenseModes.Full);
}
}
#endregion properties
#region methods
/// <summary>
/// The Buy method can be called when the license state is trial. the user is given the opportunity
/// to buy the app after which, in all configurations, the Activated event is raised, which we handle.
/// </summary>
public static void Buy()
{
MarketplaceDetailTask marketplaceDetailTask = new MarketplaceDetailTask();
marketplaceDetailTask.ContentType = MarketplaceContentType.Applications;
marketplaceDetailTask.Show();
}
/// <summary>
/// This method can be called at any time to refresh the values stored in the cache. We re-query the application object
/// for the current state of the license and cache the fresh values. We also raise the LicenseChanged event.
/// </summary>
public static void RefreshCache()
{
TrialExperienceHelper.isActiveCache = CurrentApp.LicenseInformation.IsActive;
TrialExperienceHelper.isTrialCache = CurrentApp.LicenseInformation.IsTrial;
TrialExperienceHelper.RaiseLicenseChanged();
}
private static void RaiseLicenseChanged()
{
if (TrialExperienceHelper.LicenseChanged != null)
{
TrialExperienceHelper.LicenseChanged();
}
}
#if DEBUG
private static void OnSimulatedPurchase()
{
TrialExperienceHelper.simulatedLicMode = LicenseModes.Full;
TrialExperienceHelper.RaiseLicenseChanged();
}
#endif // DEBUG
#endregion methods
#region events
/// <summary>
/// The static LicenseChanged event is raised whenever the value of the LicenseMode property has (potentially) changed.
/// </summary>
public static event LicenseChangedEventHandler LicenseChanged;
#endregion events
}
Then in my code I'm using if's to determine what to allow with this:
if ((TrialExperienceHelper.LicenseMode == TrialExperienceHelper.LicenseModes.Trial)||
(TrialExperienceHelper.LicenseMode == TrialExperienceHelper.LicenseModes.MissingOrRevoked))
{
//Then add ad' etc
}
This call must be returning TRUE...!
For the life of me I can't see the mistake, maybe someone here more experienced can help? What have I done wrong here?

exposing .Net to COM

I have some .Net functionality I am trying to use in VB6. I have followed several tutorials. I wrote a test program with success using the formula here: http://www.codeproject.com/Articles/3511/Exposing-NET-Components-to-COM
However, when I try to do it with my actual project, my ProgId doesn't show in the registry like my test file. I made sure property ComVisible == true
using System.Runtime.InteropServices;
namespace Controls.Graph.Web
{
[Guid("5F9F6C6F-016A-4CFF-BD7A-3463761807E1")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _GraphScript
{
[DispId(1)]
string getGraphXml();
}
[Guid("35901BC6-EFF1-490C-84FA-786E8462C553")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId(ProgIds.GraphScript)]
public class GraphScript : _GraphScript
{
protected GraphScript()
{
}
/// <summary>
///
/// </summary>
/// <returns>The graphs xml and javascript</returns>
public string getGraphXml()
{
DisplayDefaults tempDefaults;
tempDefaults = new DisplayDefaults();
GraphConstructor graph = new GraphConstructor();
graph.constructGraph();
GraphModel completedGraph = graph.Graph;
return GraphControl.RenderGraph(completedGraph, tempDefaults, 1) + GraphControl.RenderGraphScript();
}
}
}
and my progid...
using System;
namespace Controls.Graph.Web
{
/// <summary>
/// ProgID Constant
/// </summary>
public static class ProgIds
{
public const string GraphScript = "GraphData";
}
}
I'm not sure which piece of the puzzle I'm missing here
EDIT: actually the Guid shows up in the registry however the Progid still is not. Any ideas/suggestions?
also made sure to do this:
I have figured out what was wrong. I needed to change some access modifiers to PUBLIC -- including my GraphScript() constructor.

Categories