Convert all values from dictionary into list in C++/CLI - c++-cli

I have a Dictionary which Values i wanted to transform into a List. In C# I would use this approach:
var dict = new Dictionary<int, int>();
var list = dict.Values.ToList();
So I wanted to do the same in C++/CLI:
auto dict = gcnew Dictionary<int, int>();
auto list = dict->Values->ToList(); // error C2039
But this doesn't work, because of the error:
Error C2039
'ToList': is not a member of 'System::Collections::Generic::Dictionary<int,int>::ValueCollection'
I don't know, what I am doing wrong, I am new to C++/CLI.
Minimal reproducable example:
#using "System.Linq.dll"
using namespace System::Collections::Generic;
using namespace System::Linq;
int main()
{
auto dict = gcnew Dictionary<int, int>();
auto list = dict->Values->ToList();
}
Compiled with:
cl /clr test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27035
for Microsoft (R) .NET Framework version 4.08.4121.0
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
test.cpp(10): error C2039: 'ToList': is not a member of 'System::Collections::Generic::Dictionary<int,int>::ValueCollection'

C++ CLI does not support calling extension methods as members of target type:
targetType.ExtensionMethod(args);
You should call ToList() as a regular static method:
Linq::Enumerable::ToList(list);

Related

How to query for installed "packaged COM" extension points

I work on a plugin-based application that is currently scanning the Windows registry for compatible COM servers that expose certain "Implemented Categories" entries. This works well for "regular" COM servers installed through MSI installers.
However, I'm now facing a problem with COM servers installed through MSIX installers that expose COM extension points through the "Packaged COM" catalog as described in https://blogs.windows.com/windowsdeveloper/2017/04/13/com-server-ole-document-support-desktop-bridge/ . These COM servers can still be instantiated through CoCreateInstance, but RegOpenKey/RegEnumKey searches aren't able to detect their presence.
I'm not sure how to approach this problem. The best outcome would be some sort of Windows API for querying the "Packaged COM" catalog for installed COM servers that I can run in addition to the registry search. However, I don't know if that even exist? I'm also open for other suggestions, as long as they still allows my application to dynamically detect the presence of new COM-based plugins.
PLEASE DISREGARD THIS ANSWER. There's a better answer based on ICatInformation::EnumClassesOfCategories below.
Answering myself with sample code to query the "Packaged COM" catalog for installed COM servers. Based on suggestion from #SimonMourier.
using System.Collections.Generic;
using System.IO;
/** Use Target Framework Moniker as described in https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/desktop-to-uwp-enhance */
class PackagedComScan {
static void Main(string[] args) {
var packageManager = new Windows.Management.Deployment.PackageManager();
// this call require the "packageQuery" capability if called from a UWP app (add <rescap:Capability Name="packageQuery" /> to the appxmanifest)
IEnumerable<Windows.ApplicationModel.Package> my_packages = packageManager.FindPackagesForUser("");
foreach (var package in my_packages) {
try {
ParseAppxManifest(package.InstalledLocation.Path + #"\AppxManifest.xml");
} catch (FileNotFoundException) {
// Installed package missing from disk. Can happen after deploying UWP builds from Visual Studio.
}
}
}
static void ParseAppxManifest(string manifest_path) {
var doc = new System.Xml.XmlDocument();
using (var fs = new FileStream(manifest_path, FileMode.Open, FileAccess.Read, FileShare.Read))
doc.Load(fs);
var nsmgr = new System.Xml.XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("a", "http://schemas.microsoft.com/appx/manifest/foundation/windows10"); // default namespace
nsmgr.AddNamespace("com", "http://schemas.microsoft.com/appx/manifest/com/windows10");
// detect exported COM servers
var nodes = doc.SelectNodes("/a:Package/a:Applications/a:Application/a:Extensions/com:Extension/com:ComServer/com:ExeServer/com:Class/#Id", nsmgr);
foreach (System.Xml.XmlNode node in nodes)
System.Console.WriteLine("Exported COM CLSID: {0}", node.Value);
}
}
This is admittedly a bit ad-hoc since it relies on parsing the AppxManifest.xml files. Still, it seems to get the job done. Please note that UWP applications that runs within sandboxed AppContainer processes only seem to have read access to some of the AppxManifest.xml files, and not all. The code therefore only works for "regular" Win32 or .Net processes.
Answering myself with sample code to query all installed COM servers, including the "Packaged COM" catalog, using ICatInformation::EnumClassesOfCategories. Based on suggestion by Aditi_Narvekar:
#include <atlstr.h>
#include <vector>
static void CHECK(HRESULT hr) {
if (FAILED(hr))
abort(); // TODO: More graceful error handling
}
/** Return COM classes that implement any of the provided "Implemented Categories". */
inline std::vector<CLSID> GetClassesWithAnyOfCategories(std::vector<CATID> impl_categories) {
CComPtr<ICatInformation> cat_search;
CHECK(cat_search.CoCreateInstance(CLSID_StdComponentCategoriesMgr));
CComPtr<IEnumGUID> class_list;
CHECK(cat_search->EnumClassesOfCategories((ULONG)impl_categories.size(), impl_categories.data(), -1, nullptr, &class_list));
std::vector<CLSID> app_clsids;
app_clsids.reserve(64);
for (;;) {
CLSID cur_cls = {};
ULONG num_read = 0;
CHECK(class_list->Next(1, &cur_cls, &num_read));
if (num_read == 0)
break;
// can also call ProgIDFromCLSID to get the ProgID
// can also call OleRegGetUserType to get the COM class name
app_clsids.push_back(cur_cls);
}
return app_clsids;
}

SymmetricAlgorithm' does not contain a definition for 'Create'

I'm trying to work on ASP.NET 5 application. Here is a class and it looks good (no red curly underlines). But when I try to build, it gives error - SymmetricAlgorithm' does not contain a definition for 'Create'
using System;
using System.IO;
using System.Security.Cryptography;
namespace SalesBook
{
public static class Encryptor
{
private static byte[] EncryptString(string data)
{
byte[] byteData = Common.GetByte(data);
SymmetricAlgorithm algo = SymmetricAlgorithm.Create();
}
}
}
I'm using .net 4.6.1.
Any help?
This method has not been ported to .NET Core. The recommended alternative is to use the specific Create method associated with the algorithm you need:
var algorithm = Aes.Create();
On CoreCLR, it will automatically determine and return the best implementation, depending on your OS environement.
If you don't need .NET Core support, you can remove the dnxcore50/dotnet5.4 from your project.json.

Json.Net.Schema error when two string arrays

I get errors when I try to print a schema with two string[] or two List . A string[] and a List are ok .
having this in target class.
public string[] ovoList;
public string[] procList;
Causes an error on lines where schema is converted to string not where it is generated.
static void Main(){
JSchemaGenerator generator = new JSchemaGenerator();
JSchema schema = generator.Generate(typeof(UNIKK.UIEngine.UIFrame));
//Error is thrown on two lines below
Console.WriteLine(schema);
File.WriteAllText(#"OVOSchema.json", schema.ToString());
I tried with both Newtonsoft.JSON 6.0.8 and latest 7.x and with Newtonsoft.JSON.Schema 1.0.11 I grabbed them with nuget and am running on
Xamarin Studio
Version 5.9.5 (build 10)
Mono 4.0.3 ((detached/d6946b4)
on OS X
Errors trace is
System.Uri.EnsureAbsoluteUri () in /private/tmp/source-mono-mac-4.0.0-branch-c5sr3/bockbuild-mono-4.0.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.0.3/mcs/class/System/System/Uri.cs:2062
System.Uri.GetComponents (components=System.UriComponents.Host|System.UriComponents.Port|System.UriComponents.Scheme|System.UriComponents.UserInfo, format=System.UriFormat.Unescaped) in /private/tmp/source-mono-mac-4.0.0-branch-c5sr3/bockbuild-mono-4.0.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.0.3/mcs/class/System/System/Uri.cs:1731
System.Uri.Compare (uri1={#}, uri2={#/properties/ovoList}, partsToCompare=System.UriComponents.Host|System.UriComponents.Port|System.UriComponents.Scheme|System.UriComponents.UserInfo, compareFormat=System.UriFormat.Unescaped, comparisonType=System.StringComparison.InvariantCultureIgnoreCase) in /private/tmp/source-mono-mac-4.0.0-branch-c5sr3/bockbuild-mono-4.0.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.0.3/mcs/class/System/System/Uri.cs:1768
System.UriParser.IsBaseOf (baseUri={#}, relativeUri={#/properties/ovoList}) in /private/tmp/source-mono-mac-4.0.0-branch-c5sr3/bockbuild-mono-4.0.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.0.3/mcs/class/System/System/UriParser.cs:208
System.Uri.IsBaseOf (uri={#/properties/ovoList}) in /private/tmp/source-mono-mac-4.0.0-branch-c5sr3/bockbuild-mono-4.0.0-branch/profiles/mono-mac-xamarin/build-root/mono-4.0.3/mcs/class/System/System/Uri.cs:1740
The problem is that there is not Id. The scheme.ToString function wants procList properties to reference the ovoList properties but it is unable to create a ref because there is no base URI for the schema.
adding
schema.Id = new Uri ("http://www.example.com/");
Solved this.

CSS Intellisense not working for MVC 4 project in Visual Studio 2012 Ultimate

Have created a brand new Visual Studio 2012 Ultimate SP2 MVC4 project but unable to get CSS class selector intellisense to work?
When I type <p class="m" .... I should get the class "myClass" appearing in intellisense dropdown but nothing happens.
The file I have listed below is: \Views\Shared\_Layout.cshtml
Any Ideas ?
Edit: Have re-installed VS2012 on brand new windows 7 system (running on Mac OSX parallels 8) and still acting in the same way. Also seems the same for MVC 3 projects.
Extensions installed:
Try adding Web Essentials 2012 extension for Visual Studio 2012: http://visualstudiogallery.msdn.microsoft.com/07d54d12-7133-4e15-becb-6f451ea3bea6?SRC=VSIDE
And/Or
Try adding Microsoft Web Developer Tools extension.
I have both of these and using your same example the intellisense works like a charm.
I tried all the above mentioned remedies and suggestions. None of these worked in my environment. According to Microsoft (Under Microsoft connect's bug id 781048), they have not implemented CSS class intellisense for MVC/Razor files but are working on including this in a future release.
I have a 10 minute webcast example of extending VS2012 intellisense that adds one solution that will add intellisense to your VS2012 environment: a Visual Studio Intellisense Extension
The webcast uses MEF to extend Visual Studio to add an intellisense completion source that scans the currently loaded project for CSS class names to add as an intellisense completion set. Here is the css completion source class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
using EnvDTE;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Collections.Specialized;
namespace CssClassIntellisense
{
internal class cssClassList
{
public string cssFileName { get; set; } //Intellisense Statement Completion Tab Name
public HashSet<string> cssClasses { get; set; }
}
internal class CssClassCompletionSource : ICompletionSource
{
private CssClassCompletionSourceProvider m_sourceProvider;
private ITextBuffer m_textBuffer;
private List<Completion> m_compList;
private Project m_proj;
private string m_pattern = #"(?<=\.)[A-Za-z0-9_-]+(?=\ {|{|,|\ )";
private bool m_isDisposed;
//constructor
public CssClassCompletionSource(CssClassCompletionSourceProvider sourceProvider, ITextBuffer textBuffer, Project proj)
{
m_sourceProvider = sourceProvider;
m_textBuffer = textBuffer;
m_proj = proj;
}
public void AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets)
{
ITextSnapshot snapshot = session.TextView.TextSnapshot;
SnapshotPoint currentPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot);
if (TargetAttribute.Inside(currentPoint))
{
var hash = new List<cssClassList>();
//read any .css project file to get a distinct list of class names
if (m_proj != null)
foreach (ProjectItem _item in m_proj.ProjectItems)
{
getCssFiles(_item, hash);
}
//Scan Current Editor's text buffer for any inline css class names
cssClassList cssclasslist = ScanTextForCssClassName(
"Inline", snapshot.GetText());
//If file had any css class names add to hash of files with css class names
if (cssclasslist != null)
hash.Add(cssclasslist);
var _tokenSpanAtPosition = FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer), session);
foreach (cssClassList _cssClassList in hash)
{
m_compList = new List<Completion>();
foreach (string str in _cssClassList.cssClasses.OrderBy(x => x)) //alphabetic sort
m_compList.Add(new Completion(str, str, str, null, null));
completionSets.Add(new CompletionSet(
_cssClassList.cssFileName, //the non-localized title of the tab
_cssClassList.cssFileName, //the display title of the tab
_tokenSpanAtPosition,
m_compList,
null));
}
}
}
private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session)
{
SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1;
ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer);
TextExtent extent = navigator.GetExtentOfWord(currentPoint);
return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
}
private void getCssFiles(ProjectItem proj, List<cssClassList> hash)
{
foreach (ProjectItem _item in proj.ProjectItems)
{
if (_item.Name.EndsWith(".css") &&
!_item.Name.EndsWith(".min.css"))
{
//Scan File's text contents for css class names
cssClassList cssclasslist = ScanTextForCssClassName(
_item.Name.Substring(0, _item.Name.IndexOf(".")),
System.IO.File.ReadAllText(_item.get_FileNames(0))
);
//If file had any css class names add to hash of files with css class names
if (cssclasslist != null)
hash.Add(cssclasslist);
}
//recursively scan any subdirectory project files
if (_item.ProjectItems.Count > 0)
getCssFiles(_item, hash);
}
}
private cssClassList ScanTextForCssClassName(string FileName, string TextToScan)
{
Regex rEx = new Regex(m_pattern);
MatchCollection matches = rEx.Matches(TextToScan);
cssClassList cssclasslist = null;
if (matches.Count > 0)
{
//create css class file object to hold the list css class name that exists in this file
cssclasslist = new cssClassList();
cssclasslist.cssFileName = FileName;
cssclasslist.cssClasses = new HashSet<string>();
}
foreach (Match match in matches)
{
//creat a unique list of css class names
if (!cssclasslist.cssClasses.Contains(match.Value))
cssclasslist.cssClasses.Add(match.Value);
}
return cssclasslist;
}
public void Dispose()
{
if (!m_isDisposed)
{
GC.SuppressFinalize(this);
m_isDisposed = true;
}
}
}
}
As an FYI, you can also address this issue using Resharper. But that is a 3rd party product that needs to be purchased for Visual Studio
Is it just CSS intellisense that's failed or has it completely stopped throughout Visual Studio?
I had a similar issue that effected the whole of my Visual Studio 2012. It was a while back but I remember deleting a folder from my appdata. Take a look at this link, hopefully it will help:
http://www.haneycodes.net/visual-studio-2012-intellisense-not-working-solved/
You are not going to get intellisense for CSS in VS2012 for Razor views. There is a workaround to use intellisense. Just create one test view(.aspx) using ASPX view engine and include your css file there. Now intellisense will work in new aspx view. All you have to do is copy paste the css class from aspx to Razor view(.cshtml or .vbhtml). I hope this helps.

How to extract class IL code from loaded assembly and save to disk?

How would I go about extracting the IL code for classes that are generated at runtime by reflection so I can save it to disk? If at all possible. I don't have control of the piece of code that generates these classes.
Eventually, I would like to load this IL code from disk into another assembly.
I know I could serialise/deserialise classes but I wish to use purely IL code. I'm not fussed with the security implications.
Running Mono 2.10.1
Or better yet, use Mono.Cecil.
It will allow you to get at the individual instructions, even manipulating them and disassembling them (with the mono decompiler addition).
Note that the decompiler is a work in progress (last time I checked it did not fully support lambda expressions and Visual Basic exception blocks), but you can have pretty decompiled output in C# pretty easily as far as you don't hit these boundary conditions. Also, work has progressed since.
Mono Cecil in general let's you write the IL to a new assembly, as well, which you can then subsequently load into your appdomain if you like to play with bleeding edge.
Update I came round to trying this. Unfortunately I think I found what problem you run into. It turns out there is seems to be no way to get at the IL bytes for a generated type unless the assembly happened to get written out somewhere you can load it from.
I assumed you could just get the bits via reflection (since the classes support the required methods), however the related methods just raise an exception The invoked member is not supported in a dynamic module. on invocation. You can try this with the code below, but in short I suppose it means that it ain't gonna happen unless you want to f*ck with Marshal::GetFunctionPointerForDelegate(). You'd have to binary dump the instructions and manually disassemble them as IL opcodes. There be dragons.
Code snippet:
using System;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using System.Reflection.Emit;
using System.Reflection;
namespace REFLECT
{
class Program
{
private static Type EmitType()
{
var dyn = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Emitted"), AssemblyBuilderAccess.RunAndSave);
var mod = dyn.DefineDynamicModule("Emitted", "Emitted.dll");
var typ = mod.DefineType("EmittedNS.EmittedType", System.Reflection.TypeAttributes.Public);
var mth = typ.DefineMethod("SuperSecretEncryption", System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Static, typeof(String), new [] {typeof(String)});
var il = mth.GetILGenerator();
il.EmitWriteLine("Emit was here");
il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
il.Emit(System.Reflection.Emit.OpCodes.Ret);
var result = typ.CreateType();
dyn.Save("Emitted.dll");
return result;
}
private static Type TestEmit()
{
var result = EmitType();
var instance = Activator.CreateInstance(result);
var encrypted = instance.GetType().GetMethod("SuperSecretEncryption").Invoke(null, new [] { "Hello world" });
Console.WriteLine(encrypted); // This works happily, print "Emit was here" first
return result;
}
public static void Main (string[] args)
{
Type emitted = TestEmit();
// CRASH HERE: even if the assembly was actually for SaveAndRun _and_ it
// has actually been saved, there seems to be no way to get at the image
// directly:
var ass = AssemblyFactory.GetAssembly(emitted.Assembly.GetFiles(false)[0]);
// the rest was intended as mockup on how to isolate the interesting bits
// but I didn't get much chance to test that :)
var types = ass.Modules.Cast<ModuleDefinition>().SelectMany(m => m.Types.Cast<TypeDefinition>()).ToList();
var typ = types.FirstOrDefault(t => t.Name == emitted.Name);
var operands = typ.Methods.Cast<MethodDefinition>()
.SelectMany(m => m.Body.Instructions.Cast<Instruction>())
.Select(i => i.Operand);
var requiredTypes = operands.OfType<TypeReference>()
.Concat(operands.OfType<MethodReference>().Select(mr => mr.DeclaringType))
.Select(tr => tr.Resolve()).OfType<TypeDefinition>()
.Distinct();
var requiredAssemblies = requiredTypes
.Select(tr => tr.Module).OfType<ModuleDefinition>()
.Select(md => md.Assembly.Name as AssemblyNameReference);
foreach (var t in types.Except(requiredTypes))
ass.MainModule.Types.Remove(t);
foreach (var unused in ass.MainModule
.AssemblyReferences.Cast<AssemblyNameReference>().ToList()
.Except(requiredAssemblies))
ass.MainModule.AssemblyReferences.Remove(unused);
AssemblyFactory.SaveAssembly(ass, "/tmp/TestCecil.dll");
}
}
}
If all you want is the IL for your User class, you already have it. It's in the dll that you compiled it to.
From your other assembly, you can load the dll with the User class dynamically and use it through reflection.
UPDATE:
If what you have is a dynamic class created with Reflection.Emit, you have an AssemblyBuilder that you can use to save it to disk.
If your dynamic type was instead created with Mono.Cecil, you have an AssemblyDefinition that you can save to disk with myAssemblyDefinition.Write("MyAssembly.dll") (in Mono.Cecil 0.9).