LinqPad is my goto REPL and there isn't much I throw at it that it cant handle.
However I cannot for the life of me get CefSharp (specifically OffScreen) to run.
I'm constantly met with either of the below errors
Could not load file or assembly 'CefSharp.Core.Runtime, Version=95.7.141.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138' or one of its dependencies. The system cannot find the file specified.
BadImageFormatException: Could not load file or assembly 'CefSharp.Core.Runtime, Version=95.7.141.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138'. An attempt was made to load a program with an incorrect format.
I have tried
LP5/6 32 and 64 bit
Adding Cefsharp via nuget
Referencing .dll's manually from the file system
Referencing x86 or x64 .dll's
Copying .dll's into assembly search paths
Adding nuget paths to Environment path
And what seems like every combination of the above.
I don't understand the assembly resolution process that Visual Studio uses with the nuget package, but whatever it does I would like to at least simulate in Linqpad so I can avoid the VS ceremony when testing something simple.
I assume that manually referencing the correct .dll's and maybe setting a path somewhere should be sufficient, but I'm ideas=>EOF.
Can CefSharp be run outside of VS / MSBuild ?
It doesn't work because of the shadow-copying that LinqPad is using. Here is a hack to make your problem go away (spoiler alert: not really, read on):
For LinqPad v5
Copy all CefSharp libraries to a separate folder (don't forget cef.redist).
In LinqPad Preferences dialog (Advanced/Execution), set Do not shadow assembly references to True, restart LinqPad.
Write your code in the LinqPad query.
Reference CefSharp libraries from the folder you've set up on step 1.
Run the query.
For previous LinqPad (earlier than v5)
Write your code in the LinqPad query.
Reference CefSharp libraries, so you get an exception from your question
Find a LinqPad working directory (usually something like C:\Users\<user>\AppData\Local\Temp\LINQPad5\_yyigmhzg).
Copy all CefSharp libraries to this folder (don't forget cef.redist).
In LinqPad, click Ctrl + Shift + F5; this will reset the query state.
Rerun the query.
Now all the referenced libraries should load. But you will likely face more problems after that.
I couldn't make CefSharp.MinimalExample work. LinqPad kept crashing for me with the cryptic message Query ended because an uncatchable exception was thrown and a crashdump.
Although I am not sure if you will make CefSharp work as intended under LinqPad, maybe this can get you a bit further.
Found the answer with motivation from #Sasha's post and #amaitland's note about BadImageFormatException's being more than just incorrect architectures.
The below is all in reference to LP6 and CefSharp.Offscreen.NetCore. I have not pushed the efforts into LP5 but the process should be similar.
After some trial and error I narrowed down all of the necessary dependencies and worked out why CefSharp would not run in LinqPad.
Here are the steps to make it run -
Add CefSharp.Offscreen.NetCore package as normal to query
Enable Copy all NuGet assemblies into a single local folder (F4->Advanced)
Add the OnInit() and queryPath code as below to the query
Ensure the BrowserSubprocessPath is set before Initializing Cef
Here is the code.
async Task Main()
{
var are = new AutoResetEvent(false);//my technique for waiting for the browser
var sett = new CefSettings();
sett.BrowserSubprocessPath = this.queryPath + #"\CefSharp.BrowserSubprocess.exe"; //CefSharp will complain it cant find it
if (!Cef.IsInitialized)
Cef.Initialize(sett);
var browser = new ChromiumWebBrowser("http://www.google.com");
browser.LoadingStateChanged += (sender, args) => { if (!args.IsLoading) are.Set(); };
are.WaitOne();
await browser.WaitForInitialLoadAsync();
var html = await browser.GetBrowser().MainFrame.GetSourceAsync();
html.Dump("winner winner chicken dinner");
}
//this is the location of the queries shaddow folder
string queryPath = Path.GetDirectoryName(typeof(CefSettings).Assembly.Location);
void OnInit() // Executes when the query process first loads
{
if (!Directory.Exists(queryPath + #"\locales")) //subdirectory of cef.redist
{
var nugetPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var sources = new[] {
/*paths here are hardcoded version dependant. Can get cefsharp.common.netcore version
from Util.CurrentQuery.NuGetReferences, but cef.redist not available via that method. */
#"cef.redist.x64\95.7.14\CEF", //contans all the Cef dependencies needed
#"cefsharp.common.netcore\95.7.141\runtimes\win-x64\lib\netcoreapp3.1", //mainly for ijwhost.dll
#"cefsharp.common.netcore\95.7.141\runtimes\win-x64\native"}; //contains BrowserSubprocess & friends
var dst = new DirectoryInfo(queryPath);
foreach (var path in sources)
{
var src = new DirectoryInfo($#"{nugetPath}\.nuget\packages\{path}");
CopyFilesRecursively(src, dst);
}
}
}
//curtesy of https://stackoverflow.com/a/58779/2738249 with slight mod
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
foreach (DirectoryInfo dir in source.GetDirectories())
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
foreach (FileInfo file in source.GetFiles())
{
var dst = Path.Combine(target.FullName, file.Name);
if (!File.Exists(dst))
file.CopyTo(dst);
}
}
The why for those interested -
CefSharp needs every dependency to be in the same directory so they can be resolved at runtime, but Linqpad only copies a few key dll's from the NuGet package. None of the cef.redist files, ijwhost.dll or BrowserSubprocess.exe et al. come across. Dependencies are scattered between NuGet packages and trying to resolve them directly from the .nuget cache just does not work. So all these need to be brought in manually to the running query shadow path.
I did initially copy all files into the Assembly.GetExecutingAssembly().Location path, but this approach requires adding the assembly directory to the "path" environment variable.
Internally Linqpad seems to have the shadow path set, so copying the dependencies to the shadow folder skips the need to set the environment variable.
Related
After finally recovering from the System.Net.Http package hell we would like to block the package entirely.
I'm looking for a way to block the package from ever installing, so not blocking or locking a version but the entire package (due to a dependency or developer error). The block should be in the solution folder of the application so that every developer will have the block once updating from SVN.
I've looked at the NuGet.config and .nuspec documentation but was unable to find such a feature. My Google-fu also didn't yield any results. So I was wondering if there was anybody here that knows if and how it can be done.
I've opened up a GitHub issue
I can maybe offer a workaround. We wanted a similar thing (prevent referencing WinForms dependencies) and added a unit test that checks whether specific assemblies are referenced:
private static readonly IEnumerable<string> BlockedAssemblies = new List<string>
{
"System.Net.Http"
};
[Test]
public void SpecificAssembliesAreNotReferenced()
{
var asm = Assembly.Load("Your.Assembly.File");
var refs = asm.GetReferencedAssemblies();
foreach(var a in refs)
{
Assert.False(BlockedAssemblies.Contains (a.Name), $"{a.Name} must not be referenced.");
}
}
It's not perfect, and doesn't actually block the package from being downloaded, but it prevents accidental referencing and usage of an assembly.
I've been using TuesPechkin for some time now and today I went to update the nuget package to the new version 2.0.0+ and noticed that Factory.Create() no longer resolved, so I went to read on the GitHub the changes made and noticed it now expects the path to the dll?
IConverter converter =
new ThreadSafeConverter(
new PdfToolset(
new StaticDeployment(DLL_FOLDER_PATH)));
For the past few hours I've tried almost all the paths I can think of, "\bin", "\app_data", "\app_start", etc and I can't seem to find or figure out what it wants for the path and what dll?
I can see the TuesPechkin dll in my bin folder and it was the first path I tried, but I got the following error:
Additional information: Unable to load DLL 'wkhtmltox.dll': The
specified module could not be found. (Exception from HRESULT:
0x8007007E)
Where is that dll and now can I get it as the library doesn't seem to contain it, I tried installing the TuesPechkin.Wkhtmltox.Win32 package but the dll still is nowhere to be found. Also I am using this in a asp.net website project so I assume that using the following should work for obtaining the path, right?
var path = HttpContext.Current.Server.MapPath(#"~\bin\TuesPechkin.dll");
Further information: https://github.com/tuespetre/TuesPechkin/issues/57
The Tuespechkin has a zip file as a resource in the Win32 and Win64 embedded packages for the 'wkhtmltox.dll' file.
What it does when you use the Win32 or Win64 Embedded package is unzips the file and places it in the directory that you specify.
I have been putting a copy of the wkhtmltox dll at the root portion of my web app directory and pointing the DLL_FOLDER_PATH to it using the server physical path of my web app to get to it.
According to the author, you must set the converter in a static field for best results.
I do that, but set the converter to null when I am finished using it, and that seems to work.
Tuespechkin is wrapper for the wmkhtmlox dll file.
The original file is written in C++ and so will not automatically be usable in C# or VB.NET or any of the other managed code domains.
The Tuespechkin.dll file DOES NOT contain a copy of 'wkhtmltox.dll'. You either have to use one of the other embedded deployment modules or install a copy of the 'wkhtmltox.dll' in your web app after downloading it from the internet. That is what I do, and it seems to work just fine.
I am using Team Foundation Server, and attempts to compile code after using the Tuespechkin routines will fail the first time because the 'wkhtmltox.dll' file gets locked, but all you have to do is simply retry your build and it will go through.
I had issues with the 32-bit routine not working in a 64-bit environment and the 64-bit environment not being testable on localhost. I went with the workaround I came up with after examining the source code for Tuespechkin and the Win32 and Win64 embedded deployment packages.
It works well as long as you specify a url for the input rather than raw html.
The older package didn't render css very well.
If you are using a print.aspx routine, you can create the url for it as an offset from your main url.
I don't have the source code I am using with me at this point to offset to your base url for your web application, but it is simply an offshoot of HttpRequest.
You have to use the physical path to find the .dll, but you can use a web path for the print routine.
I hope this answers your question a bit.
If you are getting this error -> Could not load file or assembly 'TuesPechkin.Wkhtmltox.Win64' or one of its dependencies. An attempt was made to load a program with an incorrect format.
In Visual Studio Go to -
Tools -> Options -> Projects and Solutions -> Web Projects -> Use the 64 bit version of IIS Express for web sites and projects.
I installed TuesPechkin.Wkhtmltox.Win64 Nuget package and used the following code in a singleton:
public class PechkinPDFConvertor : IPDFConvertor
{
IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
public byte[] Convert(string html)
{
// return PechkinSync.Convert(new GlobalConfig(), html);
return converter.Convert(new HtmlToPdfDocument(html));
}
}
The web application then has to be run in x64 otherwise you will get an error about trying to load an x64 assembly in an x86 environment. Presumably you have to choose x64 or x86 at design time and use the corresponding nuget package, it would be nicer to choose this in the web.config.
EDIT: The above code failed on one server with the exact same message as yours - it was due to having not installed VC++ 2013. So the new code is running x86 as follows
try
{
string path = Path.Combine(Path.GetTempPath(), "MyApp_PDF_32");
Converter = new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win32EmbeddedDeployment(
new StaticDeployment(path))));
}
catch (Exception e)
{
if (e.Message.StartsWith("Unable to load DLL 'wkhtmltox.dll'"))
{
throw new InvalidOperationException(
"Ensure the prerequisite C++ 2013 Redistributable is installed", e);
}
else
throw;
}
If you do not want run the installer for wkhtmltox just to get the dll, you can do the following:
As #Timothy suggests, if you use the embedded version of wkhtmltox.dll from TuesPechkin, it will unzip it and place it in a temp directory. I copied this dll and referenced it with the StaticDeployment option without any issues.
To find the exact location, I just used Process Monitor (procmon.exe). For me it was C:\Windows\Temp\-169958574\8\0.12.2.1\wkhtmltox.dll
In my case, I am deploying on a 64-bit VPS then I got this error. I have solved the problem by installing the wkhtmltopdf that I downloaded from http://wkhtmltopdf.org/downloads.html. I chose the 32-bit installer.
In my case, I have solved the problem by installing the Wkhtmltox for win32 at https://www.nuget.org/packages/TuesPechkin.Wkhtmltox.Win32/
This error: Unable to load DLL 'wkhtmltox.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E) is returned in two situations:
1- Deploy dependency not installed:
For solve this, you can install nuget package "TuesPechkin.Wkhtmltox.Win64" and use this code (for WebApplications running in IIS):
IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
// Keep the converter somewhere static, or as a singleton instance!
// Do NOT run the above code more than once in the application lifecycle!
byte[] result = converter.Convert(document);
In runtime this code will copy the dependency "wkhtmltox.dll" in a temporary directory like: "C:\Windows\Temp\1402166677\8\0.12.2.1". It's possible to get the destination of file using:
var deployment = new Win64EmbeddedDeployment(new TempFolderDeployment());
Console.WriteLine(deployment.Path);
2- Microsoft Visual C++ 2013 Redistributable not installed:
As described here:
https://github.com/tuespetre/TuesPechkin/issues/65#issuecomment-71266114, the Visual C++ 2013 Runtime is required.
The solution from README is:
You must have Visual C++ 2013 runtime installed to use these packages. Otherwise, you will need to download the MingW build of wkhtmltopdf and its dependencies from their website and use that with the library. https://github.com/tuespetre/TuesPechkin#wkhtmltoxdll
or, you can install the Microsoft Visual C++ 2013 Redistributable:
choco install msvisualcplusplus2013-redist
Here is AnyCpu version, also support iis-base or winform application
using TuesPechkin.Wkhtmltox.AnyCPU;
...
var converter = PDFHelper.Factory.GetConverter();
var result = converter.Convert(This.Document);
Reference : https://github.com/tloy1966/TuesPechkin
Installing the Visual C++ Redistributable for Visual Studio 2013 resolved the error for me.
https://www.microsoft.com/en-us/download/details.aspx?id=40784
From C# code I'm trying to retrieve all the namespaces from powershell... (Later more complex things, like creating namespaces)
PowerShell ps = PowerShell.Create();
ps.AddCommand("Import-Module").AddArgument("ServiceBus").Invoke();
var result = ps.AddCommand("Get-SBNamespace").Invoke();
Above code gives the following exception:
The 'Get-SBNamespace' command was found in the module 'ServiceBus',
but the module could not be loaded. For more information, run
'Import-Module ServiceBus'.
Does anyone know how to solve this error?
CURRENT STATUS: after some debugging I've found that no modules are loaded by default in the PowerShell object. Using the code:
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[]{#"serviceBus"});
PowerShell ps = PowerShell.Create(iss);
doesn't work to load the service bus module. Also the code:
ps.AddCommand("Import-Module").AddParameter("-Name", "serviceBus").Invoke();
doesn't work to import the service bus module. Running Visual Studio in administrator mode also doesn't make a difference
Thanks in advance
You didn't say which version of Visual Studio you're using. If it's VS 2012, when you tried the x64 platform target did you make sure that "Prefer 32-bit" was not checked? Even if it was not checked try checking it, saving the project configuration, clearing it and saving again - this worked for me on another project.
UPDATE
It's been suggested elsewhere that there's a bug in VS2012 that shows "Prefer 32-bit" as greyed-out and unchecked when it's actually active. I'm running Update 2 and I don't see that. But it sounds like you might be. I suggest you edit the .csproj file directly.
Whilst "Platform Target" is set at "Any CPU", in Solution Explorer, right-click on the Project name (or, with go to the PROJECT menu) and select "Unload Project". Project files will close and Solution Explorer will display project name (unavailable) > The project file was unloaded:
Right-click on the Project name again and select "Edit project name.csproj". The file is XML and mostly comprises PropertyGroup and ItemGroup elements. In a console project, the first PropertyGroup usually contains a Platform element which should read AnyCPU if you followed my instructions above. The next two PropertyGroups are normally for Debug and Release configurations. If you've added another configuration, it will have its own PropertyGroup. In each of these, look for an element which reads:
<Prefer32Bit>true</Prefer32Bit>
What you should have is an element which reads:
<Prefer32Bit>false</Prefer32Bit>
Either change it or insert it (in each configuration ProjectGroup), save the file and close it. Back in Solution Explorer, right-click the project and select "Reload Project". Let me know if that solves it. You can confirm your PowerShell is now running 64-bit by get the result of
[System.IntPtr]::Size
e.g.
ps.AddScript("[System.IntPtr]::Size");
which will be 4 in an x86 process and 8 in an x64 process.
Which my project set up like this, I was able to load ServiceBus using:
ps.AddCommand("Import-Module").AddArgument("ServiceBus");
Hopefully, you will, too.
I don't have ServiceBus installed so I can't verify exactly what you've tried but
ps.AddCommand("Import-Module").AddArgument("ActiveDirectory").Invoke();
worked for me, so your original syntax looks good.
Just to test for failure, I tried:
ps.AddCommand("Import-Module").AddArgument("CheeseDirectory");
ps.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
var importResult = ps.Invoke();
foreach (PSObject result in importResult)
{
Console.WriteLine(result);
}
and got
The specified module 'CheeseDirectory' was not loaded because no valid
module file was found in any module directory.
Have you tried similar?
Do you take care of your Assembly target in your C# program (x86 versus X64). The module may exist in one target, not in the other. PowerShell exists in both.
Seems you're trying to import some modules and execute the cmdlet or function inside the module, right?
So I think you could try the following code:
PowerShell ps = PowerShell.Create();
Assembly ass = Assembly.LoadFile(#"yourServiceBus.dll");
ps.AddCommand("Import-Module").AddParameter("Assembly", ass).Invoke();
var result = ps.AddCommand("Get-SBNamespace").Invoke();
Hope this could help.
I have two DLL files which I'd like to include in my EXE file to make it easier to distribute it. I've read a bit here and there how to do this, even found a good thread here, and here, but it's far too complicated for me and I need real basic instructions on how to do this.
I'm using Microsoft Visual C# Express 2010, and please excuse my "low standard" question, but I feel like I'm one or two level below everyone else's expercise :-/ If someone could point out how to merge these DDL files into my EXE in a step-by-step guide, this would be really awesome!
For .NET Framework 4.5
ILMerge.exe /target:winexe /targetplatform:"v4,C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0" /out:finish.exe insert1.exe insert2.dll
ILMerge
Open CMD and cd to your directory. Let's say: cd C:\test
Insert the above code.
/out:finish.exe replace finish.exe with any filename you want.
Behind the /out:finish.exe you have to give the files you want to be
combined.
Use Costura.Fody.
You just have to install the nuget and then do a build. The final executable will be standalone.
Download ilmerge and ilmergre gui . makes joining the files so easy
ive used these and works great
Reference the DLL´s to your Resources and and use the AssemblyResolve-Event to return the Resource-DLL.
public partial class App : Application
{
public App()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();
//Get the Name of the AssemblyFile
var name = args.Name.Substring(0, args.Name.IndexOf(',')) + ".dll";
//Load form Embedded Resources - This Function is not called if the Assembly is in the Application Folder
var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(name));
if (resources.Count() > 0)
{
var resourceName = resources.First();
using (Stream stream = thisAssembly.GetManifestResourceStream(resourceName))
{
if (stream == null) return null;
var block = new byte[stream.Length];
stream.Read(block, 0, block.Length);
return Assembly.Load(block);
}
}
return null;
};
}
}
Download
ILMerge
Call
ilmerge /target:winexe /out:c:\output.exe c:\input.exe C:\input.dll
Install ILMerge
as the other threads tell you to
Then go to the installation folder, by default
C:\Program Files (x86)\Microsoft\ILMerge
Drag your Dll's and Exes to that folder
Shift-Rightclick in that folder and choose open command prompt
Write
ilmerge myExe.exe Dll1.dll /out:merged.exe
Note that you should write your exe first.
There you got your merged exe. This might not be the best way if your going to
do this multiple times, but the simplest one for a one time use, I would
recommend putting Ilmerge to your path.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
/* PUT THIS LINE IN YOUR CLASS PROGRAM MAIN() */
AppDomain.CurrentDomain.AssemblyResolve += (sender, arg) => { if (arg.Name.StartsWith("YOURDLL")) return Assembly.Load(Properties.Resources.YOURDLL); return null; };
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
First add the DLL´s to your project-Resources. Add a folder "Resources"
2019 Update (just for reference):
Starting with .NET Core 3.0, this feature is supported out of the box. To take advantage of the single-file executable publishing, just add the following line to the project configuration file:
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
Now, dotnet publish should produce a single .exe file without using any external tool.
More documentation for this feature is available at https://github.com/dotnet/designs/blob/master/accepted/single-file/design.md.
Also you can use ilmergertool at codeplex with GUI interface.
Here is the official documentation. This is also automatically downloaded at step 2.
Below is a really simple way to do it and I've successfully built my app using .NET framework 4.6.1
Install ILMerge nuget package either via gui or commandline:
Install-Package ilmerge
Verify you have downloaded it. Now Install (not sure the command for this, but just go to your nuget packages):
Note: You probably only need to install it for one of your solutions if you have multiple
Navigate to your solution folder and in the packages folder you should see 'ILMerge' with an executable:
\FindMyiPhone-master\FindMyiPhone-master\packages\ILMerge.2.14.1208\tools
Now here is the executable which you could copy over to your \bin\Debug (or whereever your app is built) and then in commandline/powershell do something like below:
ILMerge.exe myExecutable.exe myDll1.dll myDll2.dll myDlln.dll myNEWExecutable.exe
You will now have a new executable with all your libraries in one!
I answered a similar question for VB.NET. It shouldn't however be too hard to convert. You embedd the DLL's into your Ressource folder and on the first usage, the
AppDomain.CurrentDomain.AssemblyResolve event gets fired.
If you want to reference it during development, just add a normal DLL reference to your project.
Embedd a DLL into a project
NOTE: if you're trying to load a non-ILOnly assembly, then
Assembly.Load(block)
won't work, and an exception will be thrown:
more details
I overcame this by creating a temporary file, and using
Assembly.LoadFile(dllFile)
I Found The Solution Below are the Stpes:-
Download ILMerge.msi and Install it on your Machine.
Open Command Prompt
type cd C:\Program Files (x86)\Microsoft\ILMerge Preess Enter
C:\Program Files (x86)\Microsoft\ILMerge>ILMerge.exe /target:winexe /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319"
/out:NewExeName.exe SourceExeName.exe DllName.dll
For Multiple Dll :-
C:\Program Files (x86)\Microsoft\ILMerge>ILMerge.exe /target:winexe /targetplatform:"v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319"
/out:NewExeName.exe SourceExeName.exe DllName1.dll DllName2.dll DllName3.dll
The command should be the following script:
ilmerge myExe.exe Dll1.dll /target:winexe /targetplatform:"v4,c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\" /out:merged.exe /out:merged.exe
I have created a windows service in c# .Net 4.0.
In VS it works great, I have built the project and installed the exe as a service which does run.
I have found that when operating as a service the application does not reference application configuration files I have placed in the same directory as the service exe.
If I strongly type the full file path in code there is no problem, however this is not an ideal solution as users could install things where ever they like.
How can I make the application reference (look for) files local to the EXE and not I assume where the .Net service wrapper is located.
Nothing seems to be helpful on google.
Example
Does Work:
var config =
ClassLib.XmlInterface.DeserializeConfiguration(
"C:\\Users\\Damo\\Documents\\Visual Studio 2010\\Projects\\FileDownloadService\\FileDownloadService\\bin\\Debug\\config.xml");
Does not work: (dispute been local to the EXE)
var config =
ClassLib.XmlInterface.DeserializeConfiguration(
"config.xml");
There are a couple of ways to resolve this.
You could create an environment variable, and read the path from it. This is kind of kludgy, if you don't have a Setup application, and it's prone to breakage if users muck with their settings. But it will work if you do it correctly.
If you have a setup application, you could also store the path to your executable in the Registry, and read it at runtime.
Or, you can try retrieving the path to your assembly at runtime using something like this:
public static string GetCoreAssemblyPathRoot()
{
const string AssemblyName = "MyAssemblyName,";
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var path = (from assembly in loadedAssemblies
where assembly.FullName.StartsWith(AssemblyName)
select Path.GetDirectoryName(assembly.Location))
.FirstOrDefault();
if (path == null)
{
return null;
}
// The last part of the path is "\bin". Remove it, and return the remainder.
var index = path.IndexOf("\\bin\\");
return index == -1
? path
: path.Substring(0, index);
}