System.Diagnostics.Process.Start() opens/runs wrong directory? - c#

I think I found a bug. In my opinion Process.Start runs wrong directory.
To test, create default console application template and paste following:
using System;
using System.Diagnostics;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
bool test = false;
DirectoryInfo root = Directory.CreateDirectory(
System.IO.Path.Combine(Directory.GetCurrentDirectory(), "folder"));
DirectoryInfo bug = Directory.CreateDirectory(
System.IO.Path.Combine(root.FullName, "bug"));
DirectoryInfo bugDotCom = Directory.CreateDirectory(
System.IO.Path.Combine(root.FullName, "bug.com"));
ProcessStartInfo bugPSI = new ProcessStartInfo(bug.FullName);
ProcessStartInfo bugDotComPSI = new ProcessStartInfo(bugDotCom.FullName);
if (test)
{
Console.WriteLine(bug.FullName);
Process.Start(bugPSI);
}
else
{
Console.WriteLine(bugDotCom.FullName);
Process.Start(bugDotComPSI);
}
Console.ReadKey();
}
}
}
when variable test is set to false, bug.com directory should be opened, otherwise bug directory. However, this example shows that always bug.com is opened (no matter to test variable) - at least for me.
What's wrong? I'm missing something or that's just a bug?

.com is part of %PATHEXT%, so Windows will use it if it exists.
Changing the extension so that there is no bug.com folder avoids the problem.
To fix the problem, add a \ to the end of the path.

Related

Fail to make directory in C#

Below is my code to create a directory in my PC.
using System;
using System.IO;
using System.Text;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
DirectoryInfo dataDir = new DirectoryInfo(#"C:\CsharpData");
Console.WriteLine(dataDir.Attributes);
Console.ReadLine();
}
}
}
But, the result looks like this.
Attribute is equal to -1, and I can't get my desired directory.
Can anyone let me know what my mistake is?
Use below code. You need to use create ,ethod for creating the directory.
DirectoryInfo dataDir = new DirectoryInfo(#"C:\CsharpData");
if(!dataDir.Exists)
{
dataDir.Create();
}
System.Console.WriteLine(dataDir.Attributes);
System.Console.ReadLine();

C# code not starting .exe getting error cannot find file name

I really have no idea why this code isnt working. Everytime i get the error Cannot start process because a file name has not been provided. Even though i provided the path in which the EXE is located and verified it.
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
namespace ProcessExitSample
{
class testsandboxprogram
{
static void Main(string[] args)
{
Contract.Requires(args != null);
try
{
var firstProc = new Process();
Process.Start(#"PATH TO EXE I WANT TO LAUNCH");
firstProc.EnableRaisingEvents = true;
firstProc.Start();
firstProc.WaitForExit();
//so upon exit should run the second program here
Console.WriteLine("First process exited: " + firstProc.ExitCode);
var secondProc = new Process();
Process.Start(#"PATH TO PROGRAM I WANT TO LAUNCH");
secondProc.Start();
}
catch (Exception ex)
{
Console.WriteLine("Something went wrong sorry :(: " + ex.Message);
return;
}
}
}
}
String myexepath = #"C:\Program Files (x86)\Steam\steamapps\common\BattleBlock Theater\BattleBlockTheater.exe"
As this path contains, a space enclose it between double quotes:
Process.Start("\""+myexepath+"\"");
var firstProc = new Process();
// Process.Start(#"PATH TO EXE I WANT TO LAUNCH");
firstProc.EnableRaisingEvents = true;
firstProc.Start();
You do not provide a path for your process to start. I commented out the irrelevant code, since is not related to the firstProc variable.
You probably want:
firstProc.StartInfo.FileName = #"\Path\To\Exe";
The most obvious is try to run your PATH TO EXE I WANT TO LAUNCH in a command line environment and see if you get a self explanatory error.
If your path contains spaces you will see that your are trying to execute something problematic with spaces and you can then use the answer Graffito gave.

AppDomain.ResourceResolve event

MS Visual Studio, C#.
I need to locate all localized resource files into the .\resource subdirectory. I can't to use the probing XML element of config-file, i.e. my really project is dll (it will loaded in the external application and located not in the hosted application directory). I try to use the AppDomain.ResourceResolve event but I get a problem...
Now I wrote "Hello World" for showing it:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading;
namespace HelloWorld {
class Program {
static void Main(string[] args) {
AppDomain domain = AppDomain.CurrentDomain;
Thread thread = Thread.CurrentThread;
thread.CurrentUICulture = new CultureInfo("en");
domain.ResourceResolve += domain_ResourceResolve;
ResourceManager res = new ResourceManager(typeof(Program));
Console.WriteLine(res.GetString("Message"));
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
res.ReleaseAllResources();
}
static System.Reflection.Assembly domain_ResourceResolve(object sender,
ResolveEventArgs args) {
Assembly assembly = typeof(Program).Assembly;
String name = Path.Combine(Path.GetDirectoryName(assembly.Location),
String.Format("resources\\en\\{0}.resources.dll", Path.GetFileNameWithoutExtension(
assembly.Location)));
if (!File.Exists(name)) {
Console.WriteLine("'{0}' file not found.", name);
return null;
}
else {
Assembly result = Assembly.LoadFrom(name);
if (result != null)
Console.WriteLine("'{0}' loaded.", name);
return result;
}
}
}
}
The Program.resx is not exists i.e. if it exists the ResourceResolve event is not occur. Exist the Program.en.resx and Program.ru.resx files also. In the properties of my project I set the post-build event:
rmdir .\resources /S /Q
mkdir .\resources
move .\en .\resources\en
move .\ru .\resources\ru
My localized resource was found and loaded successfully, but I get an exception (look the screen)...
My "Hello World" project attached also: sources.
If I register my event handler on the AppDomain.AssemblyResolve instead of the AppDomain.ResourceResolve it works successful, but the AppDomain.AssemblyResolve generate twice in this case (I don't know why). This decision was found by #Josser - thank you. So problem is solved. If anybody knows why the AppDomain.ResourceResolve don't working in my case, and why the AppDomain.AssemblyResolve generate twice - I will be grateful for the explanation.
Try to use a different constructor:
ResourceManager res = new ResourceManager("Program", typeof(Program).Assembly);

How to get the current directory path of application's shortcut

I want to get the current directory path but not of the application location but of it's shortcut location.
I tried these but they return the application's location.
Directory.GetCurrentDirectory();
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
According to the process API reference in MSDN, the process STARTUPINFO struct for a given process contains the information about the shortcut .lnk file in the title member. There is a flag present in the dwFlags struct member that is set when this is the case - so it appears that this is not always set (im guessing if you ran the exe directly)
From MSDN:
STARTF_TITLEISLINKNAME: 0x00000800
The lpTitle member contains the path of the shortcut file (.lnk) that the user invoked
to start this process. This is typically set by the shell when a .lnk file pointing to
the launched application is invoked. Most applications will not need to set this value.
This flag cannot be used with STARTF_TITLEISAPPID.
Reference here.
If adding a COM Object reference is not a problem , Add COM Object Reference - Windows Script Host Object Model
i ran this code in my desktop folder and it did work. for current folder use - Environment.CurrentDirectory
using System;
using System.IO;
using IWshRuntimeLibrary; //COM object -Windows Script Host Object Model
namespace csCon
{
class Program
{
static void Main(string[] args)
{
// Folder is set to Desktop
string dir = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var di = new DirectoryInfo(dir);
FileInfo[] fis = di.GetFiles();
if (fis.Length > 0)
{
foreach (FileInfo fi in fis)
{
if (fi.FullName.EndsWith("lnk"))
{
IWshShell shell = new WshShell();
var lnk = shell.CreateShortcut(fi.FullName) as IWshShortcut;
if (lnk != null)
{
Console.WriteLine("Link name: {0}", lnk.FullName);
Console.WriteLine("link target: {0}", lnk.TargetPath);
Console.WriteLine("link working: {0}", lnk.WorkingDirectory);
Console.WriteLine("description: {0}", lnk.Description);
}
}
}
}
}
}
}
Code Reference from Forum : http://www.neowin.net/forum/topic/658928-c%23-resolve-lnk-files/
Try this:
Environment.CurrentDirectory
From MSDN:
Gets or sets the fully qualified path of the current working directory.
I think you will need to use COM and add a reference to "Microsoft Shell Control And Automation", as described in this blog post:
Here's an example using the code provided there:
namespace Shortcut
{
using System;
using System.Diagnostics;
using System.IO;
using Shell32;
class Program
{
public static string GetShortcutTargetFile(string shortcutFilename)
{
string pathOnly = System.IO.Path.GetDirectoryName(shortcutFilename);
string filenameOnly = System.IO.Path.GetFileName(shortcutFilename);
Shell shell = new Shell();
Folder folder = shell.NameSpace(pathOnly);
FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
return link.Path;
}
return string.Empty;
}
static void Main(string[] args)
{
const string path = #"C:\link to foobar.lnk";
Console.WriteLine(GetShortcutTargetFile(path));
}
}
}
using System.Reflection;
string currentAssemblyDirectoryName = Path.GetDirectoryName(
Assembly.GetExecutingAssembly()
.Location
);
Also for webapplications you can use:
Web Applications:
Request.PhysicalApplicationPath
http://msdn.microsoft.com/en-us/library/system.web.httprequest.physicalapplicationpath.aspx
to grap the applicationpath :)
Since creating the shortcut is part of the workflow, just set the working directory to "%cd%" for the shortcut then, in the app, use:
Environment.CurrentDirectory
Obviously, you would want to capture this value before any code your app calls can change it.
When creating a shortcut using Windows Explorer, you don't have the option of setting the working directory. So, after creating it, open its property page by right-clicking on it and selecting Properties, then set the Start in field to %cd%. After creating such a shortcut, you can move or copy it to the folders in which you want the app to run.
If you do not want to use a COM object as suggested in the other answers
You can open the file as a regular text file, split on the \x00 0 char, and inspect the resulting string array. One of them will be obviously the link target: something like "C:\path\to\file" or in case of UNC "\\computers\path\to\file".
string lnkFilePath "...";
var file = System.IO.File.ReadAllText(lnkFilePath);
var contents = Regex.Split(file, "[\x00]+");
var paths = contents.Where(line => Regex.IsMatch(line, #"^([A-Z]:\\|^\\\\)\S+.*?"));
Use GetStartupInfoW, it will tell you the .lnk file that was launched to start the program.

Getting and using current directory in c# script

This is just a sample, but it will help illustrate what I'm trying to do.
I know how to get the current directory as shown in the script below, and I can can set a file variable.
The problem I'm having is that I can't figure out how to make it create a folder and put the file in the folder
For example (using the variables below)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var cd = Directory.GetCurrentDirectory();
Directory.CreateDirectory(cd: \5app\);
File.Copy(c:\xyz.txt, cd: \5app\xyz.txt
}
}
}
I know what I have written above is not correct because vs10 tells me so, but doesn't give me very much help.
You're missing a parenthesis and a semicolon, and, especially, arguments of methods Directory.CreateDirectory() and File.Copy() are strings, put them inside quotes:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var cd = Directory.GetCurrentDirectory();
Directory.CreateDirectory(cd + #"\5app\");
File.Copy(#"c:\xyz.txt", cd + #"\5app\xyz.txt");
}
}
}
MSDN references: Directory.CreateDirectory, File.Copy
Thanks to Cole Johnson for pointing out that it shouldn't be #"cd: \5app\".
You don't use quotes.
In addition, I recommend against explicit parameter naming. If you look at the CIL generated when using explicit parameters, there is a performance downgrade as the parameter variables are saved to a local variable, then passed. This results in an unneeded strfld command.
There are several problems with your code, which Compiler Errors will likely help you to unravel:
The method Directory.CreateDirectory(string path) requires a string, which is encased in "".
Here is an MSDN article on how to use Directory.CreateDirectory
Same with the method File.Copy(string source, string destination)
Here is an MSDN article on how to use File.Copy
Since Directory.GetDirectory() returns a string, you can just concatinate your specific directory to the result. But remember to use proper Escape Sequences in your strings for things like Backslash.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string cd = Directory.GetCurrentDirectory();
Directory.CreateDirectory(cd + "\\5app\\");
File.Copy("c:\\xyz.txt", cd + "\\5app\\xyz.txt");
}
}
}

Categories

Resources