Programmatically-created subfolder not visible in Windows Explorer - c#

I'm trying to add a subdirectory to an existing path.
Win-7 64, Intel SSD
Logged into company domain as a user with admin priv, but not as "Administrator"
Visual Studio 2008, launched normally (not "Run as Admin")
Here's MyApp (WinForms, Debug, x86):
[STAThread]
private static void Main(string[] args)
{
string p = #"C:\ProgramData\MyCompany\MyApp";
Directory.CreateDirectory(p);
string f = "a.txt";
string fullPath = Path.Combine(p, f);
File.WriteAllText(fullPath, string.Empty);
Directory.Delete(p);
As expected, the last line throws IOException: "The directory is not empty". Should mean the subdir and file got created.
Problem: Windows Explorer does not show the MyApp subdir (even after refresh, type path in address bar, close/reopen, or reboot).
C:\ProgramData\MyCompany\ was created by another application's installer; Windows Explorer says its current owner is System.
Used same IDE to create a console app (Debug, x86), copied the above lines and ran; Windows Explorer was happy to show me DigitalTestApps and the file inside.
If I do any one of the following to MyApp, the problem goes away (i.e. Windows Explorer shows me the "MyApp" subdir and the file inside):
Build as x64
Launch Visual Studio using "Run as Admin"
Use any name other than "MyApp" (but I need to use MyApp for legacy reasons)
What could be causing this?

#dtb was too humble (or busy) to repost his comment (which solved my problem) as an answer, so I'll copy his comments here to make it easier for others to see how this turned out:
"Check if you can find your directory & file somewhere in C:\Users\JimC\AppData (Folder virtualization).
related: Why Virtualization on ProgramData folder in MS Vista?"
So here is what I did after reading his advice:
I deleted the virutalized directory from under C:\Users and it started working fine. Not sure how it got created in the first place, but seemingly, while it exists, attempts to create the directory where I was expecting it finds the virtualized one instead.
Thanks again dtb.

Related

FileSystemWatcher on folder on desktop (or C drive)

I am creating a winforms project which checks files in folder. It only works when new file put in the folder. I am using FileSystemWatcher. It works fine on D drive but fails on C drive.
I gave EVERYONE full privilige on that folder
I tried publishing it with click once for full trust application. But it failed also with published edition
Tried to run exe file and visual studio as administrator. Nothing changed
Tried absolute path and Extra filters.
It does not raise any errors. Simply does nothing.
Non Working Code
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
teklifwatcher.Path = desktop+"\\XMLTeklif";
teklifwatcher.NotifyFilter = NotifyFilters.LastWrite;
teklifwatcher.Filter = "*.xml";
teklifwatcher.Changed += new FileSystemEventHandler(TeklifXML);
teklifwatcher.EnableRaisingEvents = true;
private void TeklifXML(object sender, FileSystemEventArgs e)
{
//dostuff
}
I solved this problem on my own. I assume filesystemwatcher can't watch c: drive files directly. Because of the security reasons.
But we can use Program Files (X86) folders just like any other application.
Anyone who have similar problems just use filesystemwatcher on a folder at program filex(x86). And give permissions to that folder. Voila! It works

C# File.Exists returns false, file does exist

Using VS 15, C# with .Net 4.5.2
The computer is on an AD network, with the ad name "AD".
This problem happens with AD normal-user rights, AD admin rights, and local admin rights. It doesn't matter what rights the program gets, the same problem occurs.
Our test file is "C:/windows/system32/conhost.exe".
The file above exists, it is very much existing. I can see it with explorer.
This is the file in explorer:
This is the file properties:
You can see that it is there, right?
The following cmd command checks if the file exists:
IF EXIST "C:\windows\system32\conhost.exe" (echo does exist) ELSE (echo doesnt exist)
It returns "does exist" as promised.
The following C# code checks if the file exists:
FileInfo file = new FileInfo("C:/windows/system32/conhost.exe");
MessageBox.Show(file.Exists + "");
This returns "False".
This code also returns "False":
MessageBox.Show(File.Exists("C:/windows/system32/conhost.exe") + "");
This code also doesn't find it:
foreach (string file in Directory.GetFiles("C:/windows/system32/"))
{
//conhost is NEVER mentioned, like it doesn't exist
}
This code also doesn't find it:
foreach (string file in Directory.EnumerateFiles("C:/windows/system32/"))
{
//conhost is NEVER mentioned, like it doesn't exist
}
False, False, False:
MessageBox.Show(File.Exists("C:/windows/system32/conhost.exe") + "");
MessageBox.Show(File.Exists("C:\\windows\\system32\\conhost.exe") + "");
MessageBox.Show(File.Exists(#"C:\windows\system32\conhost.exe") + "");
What am I doing wrong?
Extra note: I copied conhost to C:\conhost.exe, and my program can find that without problem. My program also finds other files in system32, just not conhost and a few others. For example, it finds "connect.dll" which is in system32, so it's not the directory's read permission.
More extra notes: conhost.exe and connect.dll has the same security attributes (Security tab in the file properties).
If you are using x64 system, you will have different content of the c:\Windows\System32 directory for x86 and x64 applications. Please be sure that you are using same architecture running batch file and your C# app.
In the MSDN documentation for System.IO.File.Exists(path), it states:
If the caller does
not have sufficient permissions to read the specified file, no
exception is thrown and the method returns false regardless of the
existence of path.
For this reason, we can safely assume that your application does not have read access to that specific file. Check the security settings and grant read access if not already done so.
Build your application (in release mode) and run as administrator.
This is the problem that come over 64-bit operating system... here is a work around,
go to the project's properties > click on build tab > untick Prefer 32-bit
after that, it should work correctly over 64-bit os.

.NET executables do not work after overwritten with new versions

I faced very strange behaviour - after I overwrite .NET exectables with new versions from network drive it cannot start.
When try to start from Windows Explorer it shows me following error:
[Window Title]
C:\Programs\zzz\clients.net\zzzNet.exe
[Content]
C:\Programs\zzz\clients.net\zzzNet.exe
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
I tried to execute following commands:
SxsTrace Trace -logfile:SxsTrace.etl
SxStrace Parse -logfile:SxSTrace.etl -outfile:SxSTrace.txt
And got following result:
=================
Begin Activation Context Generation.
Input Parameter:
Flags = 0
ProcessorArchitecture = AMD64
CultureFallBacks = en-US;en;ru-RU;ru
ManifestPath = C:\Programs\zzz\clients.net\zzzNet.exe
AssemblyDirectory = C:\Programs\zzz\clients.net\
Application Config File = C:\Programs\zzz\clients.net\zzzNet.exe.Config
-----------------
INFO: Parsing Application Config File C:\Programs\zzz\clients.net\zzzNet.exe.Config.
INFO: Parsing Manifest File C:\Programs\zzz\clients.net\zzzNet.exe.
INFO: Manifest Definition Identity is (null).
ERROR: Line 0: XML Syntax error.
ERROR: Activation Context generation failed.
End Activation Context Generation.
It is quite simple .NET application (1 exe + 8 dll files). It was built for .NET 3.5 Client Profile.
I not defined any special "manifest" there. Just clicked "New Windows Forms Project" in Visual Studio and developed it.
Also app.config does not contain anything special - only primitive standard settings - appSettings and userSettings sections.
On PC where I developed it all is perfectly works. Problems only began when I copy these binaries to this particular VM and try to start.
Also please note - these executables were not installed in GAC or such, I just copied them into a folder on VM and started. And when it was 1st time all was working fine.
So, the problem pattern is following:
Copy .NET execuatbles to new VM (it is Win 7 x64), run it, all is working fine. Close it.
Build new version of .NET execuatbles on host PC, copy new .NET execuatbles to VM (with files overwriting).
Try to start - got mentioned problem.
After some shaman-style actions (like OS reboot, etc) it begin to work but why that happened at all?!
Why replacing .NET executables with new versions is causing SUCH HUGE PROBLEMS?!
Also the BIG QUESTION - is there any special procedure to replace .NET executables to keep them working? Because it is a new app development, I do not want lost so much time on every new executables installation. :-\
Could you please help? Because it looks completely weird!
Thank you in adance.
PS. I checked all VS projects - all they have PlatformTarget=AnyCPU. Also in run-time I can see ProcessType=MSIL (I show this info in AboutBox for application). So, there is no mix of x86/x64 binaries.
It seems that was related to mapped network drive behavior.
When I copied new files from network drive folder it copied wrong files - a strange random mess of new files and older ones (which were there before I updated them on VM host).
The scenario to make it working:
on VM: delete all files in a folder on network drive
on VM host: copy new files into a folder which is mapped as network drive on VM
on VM: copy files into target folder
on VM: run application - it works now
Weird thing. I remember I have seen something similar with Windows Explorer on Windows 2008 behaviour when copying updated win32 binaries.

Can not copy files to Environment.SpecialFolder.Startup in WPF

To make my application to start on Windows sturup I decided to put a shortcut to Startup folder.
I tried to use:
File.Move(AppDomain.CurrentDomain.BaseDirectory + "ApplicationName.exe", Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "ApplicationName.lnk");
It works, but it moves my shortcut not to the folder I need.
Environment.GetFolderPath(Environment.SpecialFolder.Startup)
works well, it returns:
C:\Users\Germanov\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
But my shortcut appears in
C:\Users\Germanov\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
Just 1 folder "behind".
File.Delete(Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "ApplicationName.lnk");
also works "strange". It actually deletes this file, but again not in "Startup" folder.
If I try to manually add "\Startup" to the path like this:
Environment.GetFolderPath(Environment.SpecialFolder.Startup) + #"Startup\ApplicationName.lnk"
I get a System.IO.Excseption.
I can't type this path manually, I neen my application to work at diferent PCs with different versions of Windows. I also can't use Registry to make my application start with windows startup.
I use Windows 7, Visual Studio 2010, .NET 4.0, this is a WPF project.
Any ideas?
Did you tried Environment.SpecialFolder.CommonStartup instead of Startup, I don't know why startup is not working for your requirement. Most of installer package do this for you; why do you want to do this for your self? Any reason not for using Registry?
I tried this code on my machine
var startup = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartup);
string file = Path.Combine(startup, "MyApp.lnk");
using (StreamWriter sw = new StreamWriter(file))
{
sw.WriteLine("Test");
}
And its coming on my startup
You should use System.IO.Path.Combine() so that you won't create StartupApplication1.exe. Note the missing backslash.

How to get installation path of an application?

In Windows using C#, how can I get the installation path of a software (for example consider NUnit or any other software like MS word, etc.) from my project? Also how to set the path variables that we set in Environment variables so that we can run the application just by giving in command prompt.
Like if I install NUnit in "C:\Program Files" I can run it by giving 'NUnit' in cmd prompt but if I install in a different location I can't do the same.
I need to get the location or path of NUnit or any other software installed in my system (having Windows XP) from my project.
EDIT:
Like I can get the path of installed program from registry.
HKEY_CURRENT_USER->SOFTWARE
Use the system and application classes. This will give you all sorts of information.
EG: Application.ExecutablePath
It also provides methods to do what you want to.
Edit: Also see registry read/write instructions here:
http://www.c-sharpcorner.com/UploadFile/sushmita_kumari/RegistryKeys102082006061720AM/RegistryKeys1.aspx?ArticleID=0ce07333-c9ab-4a6a-bc5d-44ea2523e232
Application.ExecutablePath (includes filename)
Application.StartupPath (not includes filename)
This will give you the path where the application started. Hopefully it will be the installation path.
string appFileName = Environment.GetCommandLineArgs()[0];
will give you the full path of the executable and
string directory = Path.GetDirectoryName(appFileName);
extracts the directory.
string envPath = Environment.GetEnvironmentVariable("PATH");
Environment.SetEnvironmentVariable(envPath + ";" + yourPath);
edits the PATH environment variable for the current process.
Application.StartupPath is used to get installation location in c#.
Like if i install Nunit in "C:\Program
Files" i can run it by giving 'nunit'
in cmd prompt but if i install in a
different location i cant do the same.
May be you are using Windows Vista, which can search in Program Files, but won't look in other folders.
In windows using C#, how to get the
installation path of a software(for
example consider nunit).?
It depends, how you are installing the application. The installer knows the path, you may program the installer to write that path to somewhere, say registry.
Also how to set the path variables
that we set in Environment variables
so that we can run the application
just by giving in command prompt.
How do I get and set Environment variables in C#?
Steps to extract value from registry are shown in following code snippet.
You may already know that there are no standard rules for applications to place their installation info.
The steps shown below are for COM based applications where the appplication must provide Local executable path in a reasonably standard manner.
For non-com applications, check to see if some data can be extracted from installed applications cache.
I hate to admit that the solution is not as elegant as I want it to be. Each subkey has to opened in series and opening in single method does not work.
//string hiveName = #"CLSID"; // for 64 bit COM 7applications
string hiveName = #"WOW6432Node\CLSID"; // for 32 bit COM applications
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(hiveName))
{
if (key != null) {
using (RegistryKey key2 = key.OpenSubKey("{<YourAppGUID>}"))
{
if (key2 != null) {
using (RegistryKey key3 = key2.OpenSubKey("LocalServer32"))
{
if (key3 != null) {
return key3.GetValue("").ToString();
}
}

Categories