Read DLL content programmatically in C# - c#

I am working on a small c# console application that will check my .net DLL and look for environment specific information from compiled dll.
Basically, I want to check c# Web published project and display any file contain production specific information developer forgot to update...
Issue: I am running into is when a developer switch between environment from Dev to test and test to prod. They forget to switch their environment value either in C# or web.config file.
Is there a way I can open individual DLL and extract the DLL content as a string using C# code and a free decompiler?

Try this:
using System;
using System.Linq;
using System.Reflection;
#if DEBUG
[assembly:AssemblyConfiguration("debug")]
#else
[assembly:AssemblyConfiguration("release")]
#endif
namespace ConsoleApp1
{
internal class Program
{
private static void Main()
{
// this should be the filename of your DLL
var filename = typeof(Program).Assembly.Location;
var assembly = Assembly.LoadFile(filename);
var data = assembly.CustomAttributes.FirstOrDefault(a => a.AttributeType == typeof(AssemblyConfigurationAttribute));
if (data != null)
{
// this will be the argument to AssemblyConfigurationAttribute
var arg = data.ConstructorArguments.First().Value.ToString();
Console.WriteLine(arg);
}
}
}
}

Related

Error 429 activex component can't create object while using self create reference

I created some add-in for excel in C#. In it is one public class for using in VBA. On my machine all works ok. When I install add-in on tester computer (I'm using InstallShield 2015 Limited Edition for Visual Studio to create setup file) I can't set object.
C# code
using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace PMTAddin
{
[Guid("B2350EC1-522E-4B75-BB02-86BB0FD1A60E")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class PublicClass
{
public void test()
{
System.Windows.Forms.MessageBox.Show(
"test."
, "test"
, System.Windows.Forms.MessageBoxButtons.OK
, System.Windows.Forms.MessageBoxIcon.Error
);
}
private int GetWorksheetID(Excel.Workbook wb, string worksheetName)
{
int result = 0;
foreach (Excel.Worksheet ws in wb.Worksheets)
{
if (ws.Name == worksheetName)
{
result = ws.Index;
break;
}
}
return result;
}
[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type)
{
Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"));
RegistryKey key = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true);
key.SetValue("", System.Environment.SystemDirectory + #"\mscoree.dll", RegistryValueKind.String);
}
[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type)
{
Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false);
}
private static string GetSubKeyName(Type type, string subKeyName)
{
System.Text.StringBuilder s = new System.Text.StringBuilder();
s.Append(#"CLSID\{");
s.Append(type.GUID.ToString().ToUpper());
s.Append(#"}\");
s.Append(subKeyName);
return s.ToString();
}
}
}
In VBA project I checked reference to it on the list. It calls PMT.
VBA
Sub dsf()
Dim o As PMT.PublicClass
Set o = New PMT.PublicClass 'at this lane on other computer I got error 429. On my computer all work smoothly and method test is running.
o.test
End Sub
I thought that maybe it was something .NET Framework, but it is installed. Any ideas?
EDIT:
I create two diffrent version for bittnes, but the same error.
But I found some new info. In registry on my computer it looks like this
and on tester machine it looks like this
There are no CodeBase value... Do you think this is the problem? If it is, how I need to modify RegisterFunction method to correct this?
After long seeking I found the solution. It's kind of partial, because for 64 bit Excel we need to register library manually (maybe someone knows, how to add bat file to installation file).
I found the answer on this site.
While creating Install Shield instalation file we need to do two things.
Add .tlb file to application files (this step was done by me, before posting on stackoverflow)
Click right on project.Primary output file and choose properities like in screenshot (for *.tlb file we need to check the same, but without "COM Interop")
Without this the installer will not properlly register add-in in registry.
Install file created like this would register add-in for 32-bit excel only. If you want to use it also in 64-bit Excel you need to register library manually. I created simple bat file like this:
c:
cd C:\Windows\Microsoft.NET\Framework64\v4.0.30319
regasm.exe "[pathToDLL]\AddInName.dll" /tlb:"[pathToDLL]\AddInName.tlb" /codebase
pause
Remember, that you need to run it with admin rights.

Microsoft.Build.Evaluation.Project add folder and file force refresh of project in VS

I am creating an app that will add some files and folders to an existing project which is loaded in Visual studio. That works but it will always pop up a message telling the user (me) to refresh the project to show the new files.
When using Entity Framework and adding a migration it will add a file to a project that is currently loaded and it doesn't ask the user. I would like to be able to do the same thing.
Is this possible? If someone doesn't know the answer do they know how I might delve into EF and add migration to see how they do it?
Here is the code that I am using to edit the project file:
using Microsoft.Build.Evaluation;
internal class ProjectFileHandler
{
private void AddMigrationFolder(Project project, string projectFileLocation, string name)
{
var loc = Path.Combine(projectFileLocation.Substring(0, projectFileLocation.LastIndexOf("\\")), name);
project.AddItem("Folder", loc);
}
internal void AddMigrationFile(string projectfileLocation, string migrationFolderName, string fileLocation)
{
var project = new Project(projectfileLocation);
AddMigrationFolder(project, projectfileLocation, migrationFolderName);
project.AddItem("Compile", fileLocation);
project.Save();
}
}
Pretty old, but I'll leave a comment. Maybe it helps someone else.
The problem is the "project.Save();"
The solution recognizes this as an "external" change.
Try your code without this line.
Even older, but I had to solve this problem today, so for what it's worth, here's what I did.
Firstly, as far as I can tell, you can't update a project using Microsoft.Build.Evaluation without Visual Studio prompting the user to reload it. You have to call project.Save() to write your updates to the project XML, and Visual Studio 'sees' the file change and displays the prompt.
What you can do - and this looks to be what Entity Framework does, albeit with Powershell - is use EnvDTE instead of Microsoft.Build.Evaluation. EnvDTE is available on NuGet and the latest version supports .NET Framework 4.5 and .NET Standard 2, so it should be pretty widely compatible.
With EnvDTE you get a reference to a Project object and call AddFromFile(absoluteFilePath) - there are also other Add() methods if needed.
If you have the full file path to your project, you can get a project file using:
using System.Linq;
using System.Runtime.InteropServices;
using EnvDTE;
var dte = (DTE)Marshal.GetActiveObject("VisualStudio.DTE");
var project = dte
.Solution
.EnumerateProjects()
.First(p => p.FullName == fullPathToProject);
...where EnumerateProjects() is the following extension method:
using EnvDTE;
using System.Collections;
using System.Collections.Generic;
internal static class EnvDteExtensions
{
public static IEnumerable<Project> EnumerateProjects(
this Solution solution)
{
return Enumerate(solution.Projects);
}
private static IEnumerable<Project> Enumerate(IEnumerable items)
{
foreach (var item in items)
{
var candidateProject = item;
if (candidateProject is ProjectItem projectItem &&
projectItem.SubProject != null)
{
candidateProject = projectItem.SubProject;
}
if (!(candidateProject is Project project))
{
continue;
}
yield return project;
try
{
if (project.ProjectItems == null)
{
continue;
}
}
catch
{
continue;
}
foreach (var subProject in Enumerate(project.ProjectItems))
{
yield return subProject;
}
}
}
}
A Project in EnvDTE might actually be a project, or it might be a solution folder containing projects - the candidateProject is ProjectItem projectItem && projectItem.SubProject != null check handles the latter scenario.
EnvDTE's Project.AddFromFile() pops the file into Solution Explorer with no project reload prompt.
Finally, AddFromFile() seems to be idempotent, so you can spam the same file into the project without worrying if it already exists.

Sikuli Integrator C#

I want to use SikuliIntegrator in C#.
I run VS as administrator, install SikuliIntegrator throught NuGet manager and want to test him on simple task.
Heres my code
using SikuliModule;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SikuliTrainingNet
{
class Program
{
static void Main(string[] args)
{
string MyPicture = #"c:\111\Sik\MyPicture.png";
SikuliAction.Click(MyPicture);
}
}
}
after running code (and have prepared MyPicture on screen), all i get is exception "###FAILURE" any idea why?
I dont wanna use Sikuli4Net, becose its look like it work on web aps and I need just few simple clicks on desktop aplication.
I try sikuli in Java, and there it works with no problem. But I need to make my program in C#.
I Used This Code For Sikuli4Net in C#,It Was Working For Me First You need add the References please see this link for Reference
http://interviews.ga/angularjs/sikulic/
static void Main(string[] args)
{
APILauncher launch = new APILauncher(true);
Pattern image1 = new Pattern(#"C:\Users\Ramesh\Desktop\Images\userName.png");
Pattern image2 = new Pattern(#"C:\Users\Ramesh\Desktop\Images\password.png");
Pattern image3 = new Pattern(#"C:\Users\Ramesh\Desktop\Images\Login.png");
launch.Start();
IWebDriver driver = new ChromeDriver();
driver.Manage().Window.Maximize();
driver.Url = "http://gmail.com";
Screen scr = new Screen();
scr.Type(image1, "abc#gmail.com", KeyModifier.NONE);
scr.Type(image2, "12345", KeyModifier.NONE);
scr.Click(image3, true);
Console.ReadLine();
}
I used this code and it was working fine. First you should open the webpage on which you want to click and then give a path of the image(it should be a part of the webpage)
here is my code:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SikuliModule;
using OpenQA.Selenium;
namespace WordPressAutomation.DifferentTests
{
[TestClass]
public class Sikuli
{
[TestMethod]
public void TestMethod1()
{
driver.Initialize();
driver.instance.Navigate().GoToUrl("https://www.google.co.in");
SikuliAction.Click("E:/img.png");
}
}
}
To use SikuliInyegrator, you need to check the execution results in these files:
C:\SikuliExceptionLog.txt
C:\SikuliOutputLog.txt
Also you need to:
Have installed JRE7 or superior
Have environment variable PATH with the location of the bin folder
See installed in your “control panel > program and features> visual C++ 2010 Redistributable Package” at x86 and x64 bits according to your java JRE runtime platform. If not, then download and install the Redistributable Package form Microsoft site.

Get relative file path in a class library project that is being referenced by a web project

I have an ASP.Net website that references a class library. In the class library I need to read a file into memory.
At the top level of my class library there is a folder called EmailTemplateHtml containing the file MailTemplate.html that I want to read in.
How can I do this?
In Visual Studio, you can configure your library such that the file is copied into the build directory of any project that depends upon it. Then you can get the path to the build directory at runtime in order to read your file.
Step by step instructions, starting from a fresh solution:
Create your application project and your class library project.
Add a reference to the class library project from the application project via Properties->Add->Reference from the application's context menu in Solution Explorer:
Create the file in your class library project that you need to read, then set its Copy to Output Directory property to either Copy always or Copy if newer via the Properties pane in Solution Explorer:
From within either the class library project or your application (either will work with exactly the same code), reference your file relative to Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location). For example:
using System.Reflection;
using System.IO;
namespace MyLibrary
{
public class MyClass
{
public static string ReadFoo()
{
var buildDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var filePath = buildDir + #"\foo.txt";
return File.ReadAllText(filePath);
}
}
}
(Note that back before .NET Core, you could use a file path relative to System.IO.Directory.GetCurrentDirectory() instead, but this doesn't work in a .NET Core application because the initial working directory for .NET Core apps is the source directory instead of the build directory, apparently because this was needed by ASP.NET Core.)
Go ahead and call your library code from your application code, and everything will work fine. e.g.:
using Microsoft.AspNetCore.Mvc;
using MyLibrary;
namespace AspCoreAppWithLib.Controllers
{
public class HelloWorldController : Controller
{
[HttpGet("/read-file")]
public string ReadFileFromLibrary()
{
return MyClass.ReadFoo();
}
}
}
using System.IO;
using System.Reflection;
public static string ExecutionDirectoryPathName()
{
var dirPath = Assembly.GetExecutingAssembly().Location;
dirPath = Path.GetDirectoryName(dirPath);
return Path.GetFullPath(Path.Combine(dirPath, "\EmailTemplateHtml\MailTemplate.html"));
}
If you want to find the path where the assembly is located; from within the assembly then use the following code:
public static string ExecutionDirectoryPathName
{
get
{
var dirPath = Assembly.GetExecutingAssembly().Location;
dirPath = Path.GetDirectoryName(dirPath);
return dirPath + #"\";
}
}
I am not sure what you mean by a folder in the class library but you can use the current working directory if you wish to build a path as follows:
System.IO.Directory.GetCurrentDirectory()
You can then use the Path.Combine() method to build file paths.
You can add a Static class in your class library with some static methods/properties to set. Set the values from Global.ascx.cs on start app method. Now you can get the values of class library.
Hope this makes clear.
Happy coding

Set Visual Studio 2010 properties programmatically

I am creating an application which build the code.But i want to set the Visual studio 2010 properties programmatically.
For example, I want to set INCLUDE Directories, Reference directories, Library Directories this all directories which will be set from the VS GUI but i want this programmatically.
you can see msdn article to do this:http://msdn.microsoft.com/en-us/library/microsoft.build.buildengine.engine.buildprojectfile(v=vs.90).aspx
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.BuildEngine;
namespace BuildAProjectCS
{
class Program
{
static void Main(string[] args)
{
// Instantiate a new Engine object
Engine engine = new Engine();
// Point to the path that contains the .NET Framework 2.0 CLR and tools
engine.BinPath = #"c:\windows\microsoft.net\framework\v2.0.xxxxx";
// Instantiate a new FileLogger to generate build log
FileLogger logger = new FileLogger();
// Set the logfile parameter to indicate the log destination
logger.Parameters = #"logfile=C:\temp\build.log";
// Register the logger with the engine
engine.RegisterLogger(logger);
// Build a project file
bool success = engine.BuildProjectFile(#"c:\temp\validate.proj");
//Unregister all loggers to close the log file
engine.UnregisterAllLoggers();
if (success)
Console.WriteLine("Build succeeded.");
else
Console.WriteLine(#"Build failed. View C:\temp\build.log for details");
}
}
}

Categories