How do you create a file in assembly with a dynamically specified file path?
System calls that take a const char*
without a length arg always take C strings: 0-terminated, implicit length.
Like open(const char *path, int flags, int mode)
, unlike write(int fd, void *buf, size_t len)
.
This is why they work when called from C like open("input.txt", O_RDONLY)
, or open(argv[1], O_WRONLY|O_CREAT)
. Remember that C string literals give you a pointer to an array of char
in static storage with a 0
terminator.
BTW, NULL is a pointer constant. NUL is ASCII '\0'
. Just call them "0
terminated" strings.
So yes, you should use , 0
at the end of your db
.
Command-line args are always in this C-string format; it's how Unix passes around string data across system-call / process boundaries, as well as to ISO C standard library functions. This includes all pathnames.
In Linux, on entry to _start
, the stack pointer points at argc
. Above that are the elements of the char *argv[]
array. (Not a char **argv
pointer, just an array of values right there on the stack, from ESP+4 to ESP+argc*4. Also terminated by a NULL pointer (0
)). This is documented in the i386 and x86-64 System V ABI docs.
Linux Assembly x86_64 create a file using command line parameters shows an example of loading argv[1]
into the pathname
arg of a system call.
Reading from a file in assembly is a 32-bit example.
How to create a folder and file inside of the folder where the app is installed? c#
What you are trying to do is not advisable; if your application is installed using recommended default methods (following Microsoft guidelines) the app will be in a directory under C:\Program Files
(or where the program files folder may be redirected) and the user that runs the app will not have write access to that directory, so the directory creation will fail.
That said, you cannot use the Environment.CurrentDirectory
, because it may or may not be the directory where your application's executable files reside, neither CurrentDomain.BaseDirectory
, because that is not significative too (documentation says it's the directory where the loader will search for assemblies, but that may or may not be the directory of your application's executable files).
Copying from this other answer, the correct way to find the directory of your assembly is
public static string AssemblyDirectory
{
get
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
Once you have the path, you can try to create the directory with System.IO.Directory.CreateDirectory()
and a file with System.IO.File.WriteAllText()
or its siblings, or any other standard method of creating files.
You may also want to use the newer Assembly.GetExecutingAssembly().Location
property, and use Path.GetDirectoryName()
on that.
Dynamically Load Assembly and manually force path to get referenced assemblies
You could load the dependent assemblies yourself before loading the one that requires them.
How to create dynamic instance of assembly ( C# ) and loading the dependencies of instance assembly dynamically as well?
Finally I found solution for my problem.
This is what worked for me. Perfect and what I was looking for !! :)
static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
var implementor = string.Concat(Directory.GetCurrentDirectory(), @"\Implementations\Calculator.dll");
var implementorBytes = File.ReadAllBytes(implementor);
AppDomain.CurrentDomain.Load(implementorBytes);
Console.WriteLine(GetObject<IAdd>().SumNew(2, 2));
Console.WriteLine(GetObject<IAdd>().SumNew(2, 5));
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var dependencyResolverBaseDirectory = string.Concat(Directory.GetCurrentDirectory(), @"\Implementations");
return Directory.GetFiles(dependencyResolverBaseDirectory, "*.dll")
.Select(Assembly.LoadFile)
.FirstOrDefault(assembly => string.Compare(args.Name, assembly.FullName, StringComparison.CurrentCultureIgnoreCase) == 0);
}
public static T GetObject<T>()
{
var t = typeof(T);
var objects = (
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetExportedTypes()
where typeof(T).IsAssignableFrom(type) && (string.Compare(type.FullName, t.FullName, StringComparison.CurrentCultureIgnoreCase) != 0)
select (T)Activator.CreateInstance(type)
).ToList();
return objects.FirstOrDefault();
}
Best way to dynamically set an appender file path
You are doing this the hard way! Define your log4net config as XML in your application's configuration file and use %property{}
to advantage:
<appender name="YourAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="~/App_Data/%property{LogName}" />
....
</appender>
This is dynamic -- you just have to set the log4net property "LogName
" before you initialize log4net. Thus, in your code any time before you configure log4net, set the desired value of this property:
string LogName = GetType().Assembly.GetName().Name + ".log";
log4net.GlobalContext.Properties["LogName"] = LogName;
Of course, you may use any property name. I've chosen "LogName" for a simple example, but you can have one per application if you want, as long as your code knows what the correct property name is and what the correct value should be.
Related Topics
Mpc/Mpd on Linux: How to Play Local Wav File
Binding on a Port with Netpipes/Netcat
Nasm X86_64 Assembly in 32-Bit Mode: Why Does This Instruction Produce Rip-Relative Addressing Code
Using Curl with Commands in Go
Linux Process Context and Svc Call in Arm
How to Tell Linux to Keep a Page and Not Evict It
How to Get a Faster Output Pipe Than /Dev/Null
Compare Two Different Urls Using Linux
How to Play an Audio File from Haskell Code, Cross-Platform
Qt - How to Detect Whether The Application Is Running on Gnome or Kde
How to Remove File with Special Characters
Pte Structure in The Linux Kernel
Ssh Command Output to Save in a Text File in Shell Script
How Event Packet Header Is Getiing in Hci_Send_Req API Implementation
Javafx: Tested/Confirmed Hardware (Gpu) Acceleration on Linux