I need to resolve target paths from an MSI database, outside of the installation. I am currently doing this using the Wix SDK by querying the database's Directory and File tables and constructing the paths from there, but resolving paths seems like something that should already be built-in. Is there a library that does this, even something unofficial, or am I stuck with doing it on my own?
This question has already been asked for C++, but the only answer somehow misunderstood the question to be about strings.
I don't really mind performance. My real concern is with resolving special folders like ".:Fonts", ".:Windows", ".:WinRoot", etc. - which I can still do in my own code but not very elegantly.
I did the same thing you did when DTF first came out. I wrote all the queries and loops to get the data I was working for. And the performance was kind of painful.
Then I noticed the InstallPackage class in the Microsoft.Deployment.WindowsInstaller.Package assembly. I felt kind of silly when I saw how fast and simple the following code is using that class:
using System;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Package;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (var package = new InstallPackage("foo.msi", DatabaseOpenMode.ReadOnly))
{
foreach (var filePath in package.Files)
{
Console.WriteLine(filePath.Value);
}
Console.WriteLine("Finished");
Console.Read();
}
}
}
}
Related
I've been wrestling with Source Generators but there's a lack of tutorials and information that are hurting.
I want to generate some C# classes from a database. Using a T4 template to do this is difficult and problematic, because of issues I'm having with using SQL in T4 templates and similar.
The description of Source Generator is that "The generator can create new C# source files on the fly that are added to the user's compilation. In this way, you have code that runs during compilation. It inspects your program to produce additional source files that are compiled together with the rest of your code." which seems to match what I want.
This seems significantly more promising.
I've created a project, and put a [Generator] into it using this tutorial.
Full source:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace x
{
[Generator]
internal class TestGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
File.Create(#"C:\temp\ITRUNS.TXT");
var sourceBuilder = new StringBuilder(#"
using System;
namespace HelloWorldGenerated
{
public static class HelloWorld
{
public static void SayHello()
{
Console.WriteLine(""Hello from generated code!"");
Console.WriteLine(""The following syntax trees existed in the compilation that created this program:"");
");
Debugger.Launch();
// using the context, get a list of syntax trees in the users compilation
var syntaxTrees = context.Compilation.SyntaxTrees;
// add the filepath of each tree to the class we're building
foreach (SyntaxTree tree in syntaxTrees)
{
sourceBuilder.AppendLine($#"Console.WriteLine(#"" - {tree.FilePath}"");");
}
// finish creating the source to inject
sourceBuilder.Append(#"
}
}
}");
// inject the created source into the users compilation
context.AddSource("helloWorldGenerator", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
}
public void Initialize(GeneratorInitializationContext context)
{
}
}
}
I want this to run when I build the solution and create some .cs files
However, it does not run. I put some code in the execute method to create a file, and it does not create the file.
The tutorial says:
Add the source generator from a project as an analyzer and add preview to the LangVersion to the project file like this:
I don't really know what this means. Which project? I tried to download the samples as suggested, but I can't get them to build.
When I examine the code, it's quite hard to understand what they've done that is different.
And what they say in the tutorial about adding the analyzer, doesn't seem to present anywhere in the sample code!
I tried adding the project reference in the csproj that it said to add, however that didn't work - it did create an item within Analyzers but it just has a red - and says 'Ignored' on the tooltip.
I honestly don't know what else I can do to figure out how to get this to work.
I also don't know for sure if it will do what I want - autogenerate a bunch of .cs files with code in that I can use.
I'm going to give it one more go then I'll just write a console application to do it manually instead. Any ideas are welcome.
So I have two dlls, Algorithms.dll and Data_Structures.dll (I made these from projects I found on GitHub). Using the browse feature I have managed to add both of the DLL files as references to my Visual Studio 2017 console project. The problem is I can't do anything else with them. Whenever I try to reference something within either file, it simply cannot be found. The only thing that is recognized is the namespace, but nothing inside of that.
What do I need to do to get VS to find the classes these DLLs contain so I can use them? I am aware I need to use Algorithms.Sorting for the example but I can't call anything so I used this as an example.
P.S. If you need more info, please ask. I'm not sure what's relevant to this issue.
EDIT: Ok, it was misleading to have that kind of example. Corrected but please read the question.
EDIT: I tried this on Monodevelop and get the same issue. Maybe it's not the IDE that's the problem?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Algorithms.Sorting; // Error, Sorting cannot be found, and neither can the file container Sorting
using Data_Structures; //Perfectly ok, can find the namespace
namespace CS_HW2_Testing_App
{
class Program
{
static void Main(string[] args)
{
// I'd like to call MergeSort and so forth here. What am I missing?!
}
}
}
Here's the top piece of the file containing MergeSort if it helps
using System;
using System.Collections.Generic;
using Algorithms.Common;
namespace Algorithms.Sorting
{
public static class MergeSorter
{
//
// Public merge-sort API
public static List<T> MergeSort<T>(this List<T> collection, Comparer<T> comparer = null)
{
comparer = comparer ?? Comparer<T>.Default;
return InternalMergeSort(collection, 0, collection.Count - 1, comparer);
}
...
In the first code block, you're importing the wrong namespace: using Algorithms.MergeSort should be using Algorithms.Sorting. Then you can use MergeSorter.MergeSort<T>(...) in your code!
You need to reference the namespace not the class.
using Algorithms.Sorting; //instead of using Algorithms.MergeSort;
Plus make sure the classes are public
I'm currently doing a project where I have to use the Affectiva SDK to analyse some videos that I have recorded. I have downloaded the files, which they have given me and started writing the code for the SDK to work, however when calling the callback functions in my code, Visual Studio doesn't seem to accept the arguments that are put in. So I figured that the interfaces for the callback functions must be done. I'm not really clear on how to this though, since I thought this was all done in their assembly code. My code so far looks like this:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Affdex;
namespace ConsoleApplication2
{
class Program
{
public interface FaceListener { }
public interface ImageListener { }
public interface ProcessStatusListener { }
static void Main(string[] args)
{
VideoDetector detector = new VideoDetector(15);
String licensePath = "C:/Users/hamud/Desktop/sdk_ahmedmudi1992#gmail.com.license";
detector.setLicensePath(licensePath);
String classifierPath = "C:/Programmer/Affectiva/Affdex SDK/data";
detector.setClassifierPath(classifierPath);
detector.setFaceListener(this);
detector.setImageListener(this);
detector.setProcessStatusListener(this);
detector.setDetectSmile(true);
detector.setDetectSurprise(false);
detector.setDetectBrowRaise(false);
detector.setDetectAnger(false);
detector.setDetectDisgust(false);
detector.setDetectAllExpressions(false);
detector.start();
detector.stop();
}
}
}
As far as I know, I have to write code for the interfaces if I'm not mistaken... Or do I? Please help.
Here is a tutorial on getting started to analyze the video files.
As far as I know, I have to write code for the interfaces if I'm not mistaken... Or do I?
No you don't. You just have to implement the methods in the interfaces if you were to use them.
Here is the link to the sample app that uses Camera Detector which you can relate to since both the Camera Detector and the Video Detector implement the FaceListener, ProcessListener and ImageListener Interfaces.
EDIT: You have to implement the Listeners. For example in the code sample you are using the FaceListener so you need to write the implementation for the callbacks viz onFaceFound() and onFaceLost().
You may also want to create an object of processStatusListener and wait for the process to end for a video file something like this:
AffdexProcessStatusListener processStatusListener = new AffdexProcessStatusListener();
processStatusListener.wait();
Here is a link to our C# app AffdexMe which uses CameraDetector. You may find examples of CameraDetector, PhotoDetector, VideoDetector and FrameDetector in our getting started guide.
I'm looking to replicate the following in IronPython and searching has so far been fruitless and/or disappointing.
namespace Groceries
{
public class ChocolateMilk : Milk
{
// Other stuff here
}
}
The idea would be that the compiled Python DLL will be loaded into a C# program through System.Reflection.Assembly.Load and a GetType("Groceries.ChocolateMilk") on the loaded DLL would not return null.
The most recent answer I was able to find was in 2008 and said that it was impossible without using the Hosting API - http://lists.ironpython.com/pipermail/users-ironpython.com/2008-October/008684.html.
Any suggestions on how to accomplish this would be greatly appreciated. Any conclusions that this is currently impossible to do via IronPython will also be appreciated, but less so.
I'm a bit confused on what you're asking here. Are you trying to instantiate that C# code in your IronPython modules? Or do you have the equivalent classes written in IronPython and you want to instantiate them in your C# code?
Based on the link you posted, I suppose you're going for the latter and have IronPython classes that you want instantiated in your C# code. The answer is, you cannot directly instantiate them. When you compile IronPython code to an assembly, you cannot use the types defined there with your regular .NET code since there is not a one-to-one mapping between IronPython classes and .NET classes. You would have to host the assembly in your C# project and instantiate it that way.
Consider this module, Groceries.py compiled to Groceries.dll residing in the working directory:
class Milk(object):
def __repr__(self):
return 'Milk()'
class ChocolateMilk(Milk):
def __repr__(self):
return 'ChocolateMilk()'
To host the module in your C# code:
using System;
using IronPython.Hosting;
using System.IO;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var engine = Python.CreateEngine();
var groceriesPath = Path.GetFullPath(#"Groceries.dll");
var groceriesAsm = Assembly.LoadFile(groceriesPath);
engine.Runtime.LoadAssembly(groceriesAsm);
dynamic groceries = engine.ImportModule("Groceries");
dynamic milk = groceries.ChocolateMilk();
Console.WriteLine(milk.__repr__()); // "ChocolateMilk()"
}
}
Otherwise to go the other way and create an instance of your .NET type in your IronPython code (as your title suggests). You'd need to add the path to your assembly, reference it, then you could instantiate it as needed.
# add to path
import sys
sys.path.append(r'C:\path\to\assembly\dir')
# reference the assembly
import clr
clr.AddReferenceToFile(r'Groceries.dll')
from Groceries import *
chocolate = ChocolateMilk()
print(chocolate)
I want to write a simple hello world add in for Media Center on Windows 7, but I am having problems finding up to date functional documentation. I found this page: http://blogs.msdn.com/b/mcreasy/archive/2004/10/12/241449.aspx which looks to be exactly what I need. I implemented it and some of the interfaces it references are marked as obsolete, and even so when I try to launch it in media center is just pops up a dialog saying "unable to launch addin"
I updated the namespace interfaces from using Microsoft.MediaCenter.AddIn to using Microsoft.MediaCenter.Hosting which looks to be the up to date namespace according to the sdk docs, but I still have the same problem.
registering the assembly with the gac and with RegisterMCEApp both are successful, and I have unregistered and registered from both places in between builds.
I strongly signed the assembly with a .snk file and got the public key token to update the registration.xml
Can anyone either tell me what I am doing wrong or direct me to some up to date tutorial /docs?
Here is the little bit of code I have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.MediaCenter.Hosting;
namespace MCPluginTakeTwo
{
public class HelloWorldAddIn: MarshalByRefObject, IAddInModule, IAddInEntryPoint
{
public void Initialize(Dictionary<string, object> appInfo, Dictionary<string, object> entryPointInfo)
{
}
public void Uninitialize()
{
}
public void Launch(AddInHost host)
{
}
}
}
Maybe looking at some open source mc plugins would help.
Here's another getting started tutorial, with some tips for getting started with Visual Studio 2010 (because the SDK only comes with VS 2008 templates).
http://david.gardiner.net.au/2010/10/writing-media-center-application-in.html