Valid path not so valid in Vista using ParseDisplayName. Why? - c#

In the following code example... where filePath is: E:\[D]\My Collection (a folder generated by picasa when it archives media) works okay on XP (32-bit). I recent ran this on vista 64-bit... and ParseDisplayName errors with "Value does not fall within the expected range." All other folders (without the '[D]') work okay. Any help would be appreciated.
try
{
int cParsed = 0;
int pdwAttrib = 0;
string filePath = Path.GetDirectoryName(file);
pidlMain = IntPtr.Zero;
folder.ParseDisplayName(IntPtr.Zero,IntPtr.Zero,filePath,out cParsed,out pidlMain,out pdwAttrib);
}
catch (Exception ex)
{
Marshal.ReleaseComObject(folder);
throw ex;
}

This happens (irrespective of the code pack; you can repro it by using the shell API directly and getting the parsing name) on Vista when you select the folders in the Common File Dialog (or any type of Open dialog) from the left side tree view.
For e.g - using the example you mention - Code pack's sample. Run the sample, select browse, from the CFD, select your folder from the left side tree view. You will also get the same problem if you go inside the folder and then click on "Open". The parsing name that you get is:
c:\folder\folder (notice the duplicate folder).
This is a known issue in Vista... I am afraid there is no patch for it (or atleast that I am aware of - unless you switch to Win7 :-) )

Related

Server shares can be listed in Windows File explorer, but net view \\MyServerName returns error 53

I am struggling with finding a way to get a list of shares on a Remote Server. The server is a Linux based videoserver that I have no access to what so ever in terms of changing settings etc.
My issue is that after starting the servers client manager software on my local computer, I can list all Shares in a normal file explorer window by just entering \\MyServerName as the path
But all tries to access the list of shares via net view or C# DirectoryInfo(..) returns Error 53.
I have tried all ideas I have found on line:
Adding the login in the local machine user account vault
net use \\MyServerName /user:MyID MyPassword
PowerShell Get-WmiObject Win32_MappedLogicalDisk -computer | select name, providername (returns RPC-server not available)
The weird thing is that File Explorer has no problem listing the shares!
If I create a DirectoryInfo with one of the existing shares on the server, then it works fine:
var d = new DirectoryInfo(#"\\MyServerName\OneOfTheShares");
I am aware that DirectoryInfo cannot use a servername only. It needs a folder. But what I can't understand is why File Explorer can list the shares, but net view \\MyServerName can't!
Can anyone please help me with some thoughts?
Ok, so being teased by Anton Anpilogov ;-) to take a WinApi aproach to this issue, I found a 16 year old CodeProject by Rob Manderson https://www.codeproject.com/Articles/6235/Enumerating-Network-Resources
that put me on the right track :-)
By using WNetEnumResource to enumerate connected server resources filtering them with my known Server name, I can return a list of all shares on that server!
result = WNetOpenEnum(scope, type, usage, pRsrc, out handle);
if (result == ErrorCodes.NO_ERROR)
{
do
{
result = WNetEnumResource(handle, ref cEntries, buffer, ref bufferSize);
if (result == ErrorCodes.NO_ERROR)
{
Marshal.PtrToStructure(buffer, pRsrc);
if(pRsrc.lpRemoteName.StartsWith(<MyServerName>))
{
Shares.Add(pRsrc.lpRemoteName);
}
}
else if (result != ErrorCodes.ERROR_NO_MORE_ITEMS)
break;
} while (result != ErrorCodes.ERROR_NO_MORE_ITEMS);
WNetCloseEnum(handle);
}
The code obviously needs some tidying up, but it works!
Thanx!

Custom Uninstall not deleting file in .net Application

I have a settings file created when user run the wpf application.
I have created a custom uninstaller to delete some registry keys related to my app and to delete this setting file.
But my file is not getting deleted.
Here is the code -
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
try
{
using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
if (registryKey.GetValue("TeachingManagementTool") != null)
{
registryKey.DeleteValue("TeachingManagementTool", true);
}
}
if (File.Exists("Setting.ini"))
File.Delete("Setting.ini");
}
catch (Exception ex)
{
MessageBox.Show("Registry Keys exception " + ex.Message);
}
}
I tried Directory.GetCurrentDirectory() to get file names and delte it, but it doesnt work. So I checked this line of code works file.Delete(filename). It delets the specified file. So it should delete the file during uninstall as its in the same folder.
At the end I should say- I tried 2-3 different ways to access that file and delete it during uninstallation. but Its not delteting and throwing error some times and sometimes no exception at all.
The exception was related to Access to SysWOW64\AdvanceInstaller is
denied
FYI - MY App has <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> already.
I tried solutions available on StackOverflow but its not working So I needed to ask a new question. So please let me know where I am mistaking. I am sure it is something very minor that I might be missing here
Advanced Installer: So you are using Advanced Installer? In the Files and Folders view, select the destination folder in question. In the right pane, right click inside the folder where the file to remove resides. Do you see "New File Operation"? Select "File Removal" and configure options.
Remember to set the options properly. In particular "Remove On". Select on "Component Uninstall".

C# GetDirectories() System.IO.DirectoryNotFoundException: 'Could not find a part of the path

I'm working on a simple File Explorer exe which leads to this error and I tried a few methods and couldn't solve it.
MyCode:
private void GetDirectories(DirectoryInfo[] subDirs, TreeNode nodeToAddTo)
{
TreeNode aNode;
DirectoryInfo[] subSubDirs;
foreach (DirectoryInfo subDir in subDirs)
{
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = subDir;
aNode.ImageKey = "folder";
subSubDirs = subDir.GetDirectories();
if (subSubDirs.Length != 0)
{
GetDirectories(subSubDirs, aNode);
}
nodeToAddTo.Nodes.Add(aNode);
}
}
But then I get this error:
System.IO.DirectoryNotFoundException HResult=0x80070003
Message=Could not find a part of the path
'C:\Users\zero_000\Documents\DAZ 3D\Studio\My Library\data\DAZ3D - G3
Superhero Pack\24205 - Super Bodysuit Casual Style
Textures\IM00024205-01_SuperBodysuitCasualStyleTextures\Content\People\Genesis
3 Male\Clothing\Super Bodysuit\Materials\Casual Style\3Delight'.
Source=mscorlib
I have tried shorten the file path using:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string path,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder shortPath,
int shortPathLength
);
But this just leads to another problem which is essentially the same.
Anyway to resolve this?
[Update 1]
The program is supposed to look into every files and folders i have, and sometimes the names are long and they aren't created by me, but by the installer or some other user's zip file naming.
Here's some screenshot as requested.
Screenshot: The error coming from my IDE
Screenshot: The folder that exist when i open from my Explorer
Screenshot: The path that seems to be not found when I access from CMD
I'm running on:
Win 10 Pro (64 bit)
VS2017
.NET Framework 4.7.1
My App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
<runtime>
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
</runtime>
</configuration>
[Update 2]
Okay,some of you might not get what I'm trying to show here.
Basically here's the problem, the C# Desktop App i'm coding throws me an error suspect due to long file path.
But here's what's funny.
In my c# code, the nested function to .GetDirectories() keeps going deeper and deeper into the subfolders. Hence it produced a long file path. But it throws and error shown above.
VS.NET 2017: "C:\Users\zero_000\Documents\DAZ 3D\Studio\My
Library\data\DAZ3D - G3 Superhero Pack\24205 - Super Bodysuit Casual
Style
Textures\IM00024205-01_SuperBodysuitCasualStyleTextures\Content\People\Genesis
3 Male\Clothing\Super Bodysuit\Materials\Casual Style\3Delight"
But when I paste this path into Windows's Explorer in Win10Pro, it automatically changes the path into shorter version. Which works and it shows the folder and it's content.
Win10 Explorer:
"C:\Users\zero_000\Documents\DAZ3D~1\Studio\MYLIBR~1\data\DAZ3D-~1\24205-~1\IM0002~1\Content\People\GENESI~1\Clothing\SUPERB~1\MATERI~1\CASUAL~1\3Delight"
Then I pasted the same path into CMD and it shows error as well by saying the path doesn't exist (As shown in the screenshot above).
[Update 3]
I thought I should check again on the most simplest method to see if it was really it by doing:
DirectoryInfo da = new DirectoryInfo(#"C:\Users\zero_000\Documents\DAZ3D~1\Studio\MYLIBR~1\data\DAZ3D-~1\24205-~1\IM0002~1\Content\People\GENESI~1\Clothing\SUPERB~1\MATERI~1\CASUAL~1\3Delight");
Console.WriteLine(#"C:\Users\zero_000\Documents\DAZ3D~1\Studio\MYLIBR~1\data\DAZ3D-~1\24205-~1\IM0002~1\Content\People\GENESI~1\Clothing\SUPERB~1\MATERI~1\CASUAL~1\3Delight");
DirectoryInfo db = new DirectoryInfo(#"C:\Users\zero_000\Documents\DAZ 3D\Studio\My Library\data\DAZ3D - G3 Superhero Pack\24205 - Super Bodysuit Casual Style Textures\IM00024205-01_SuperBodysuitCasualStyleTextures\Content\People\Genesis 3 Male\Clothing\Super Bodysuit\Materials\Casual Style\3Delight");
Console.WriteLine(#"C:\Users\zero_000\Documents\DAZ 3D\Studio\My Library\data\DAZ3D - G3 Superhero Pack\24205 - Super Bodysuit Casual Style Textures\IM00024205-01_SuperBodysuitCasualStyleTextures\Content\People\Genesis 3 Male\Clothing\Super Bodysuit\Materials\Casual Style\3Delight");
It doesn't seems to be generating any errors in this case.
[Update 4]
Apparently, if i do da.GetDirectories(); it will throw error instantly because any directories collected from that path will be added into the DirectoryInfo resulted super long path.
Is there anyway to resolve this even if it's long file path?
Ok. After I've tested out a bit.
I noticed there are no straight answer to this because the whole issue is due to long file path.
I tested the path "C:\Users\zero_000\Documents\DAZ3D~1\Studio\MYLIBR~1\data\DAZ3D-~1\24205-~1\IM0002~1\Content\People\GENESI~1\Clothing\SUPERB~1\MATERI~1\CASUAL~1\3Delight" which is the shorter version generated by File Explorer.
If I navigate to this folder, it works.
But if I tries to create a folder inside this folder, it will just throw an error to me somewhat similar to the errors shown in my C# App.
Which means, given by the default behavior of my staff or any users, they wouldn't even be able to reach this stage. (unless like me, this folder was extracted via 7zip).
My option is to just throw a warning message box to force user not to have long file path.
You can make those AppContext switch settings machine-wide by putting the change in the Windows registry. This way, you don't have to manually add the overrides to all of your App.config files.
This could be especially relevant if you need to set a switch to 'true' in .NET Framework 4.7, because it has a known issue where switch values are unilaterally reported as 'false' under certain poorly explained circumstances:
CauseWhen the program reads the value of an AppContext switch in the registry, the data cannot be retrieved. In this case, it is assumed that something is wrong with the way the setting is specified in the registry, and a value of False is returned to the application.https://support.microsoft.com/en-us/help/4036977

Why is StreamReader.ReadLine() and File.ReadAllText() returning null or empty

I did find a few similar questions, but they weren't able to point me in the right direction... This may be something entirely stupid, but if anyone could tell me why I can't get a string populated I'd appreciate it. Here's my method that's failing:
private static string passwordTrace { get; set; }
// ... lots of other code
private static void RefreshPassword()
{
try
{
string filePath = "\\\\[server ip]\\share\\folder\\file.abcd";
string npDecrypted;
DateTime lastRefreshDate = Properties.Settings.Default.lastRefresh;
if (DateTime.Now >= lastRefreshDate.AddDays(30))
{
using (StreamReader sr = new StreamReader(filePath))
{
string npEncrypted = sr.ReadLine();
if (npEncrypted.Length != 24)
{
string fr = File.ReadAllText(filePath);
npEncrypted = fr.Substring(0, 24);
}
npDecrypted = Decryptor(npEncrypted);
passwordTrace = npDecrypted; // added for debugging only! remove when done.
secureString npSecure = new SecureString();
foreach (char c in npDecrypted)
{
npSecure.AppendChar(c)
}
Properties.Settings.Default.adminpw = npSecure;
Properties.Settings.Default.Save();
}
}
}
catch (FileNotFoundException fnfe)
{
// code for handling this type of exception
}
catch (NullReferenceException nre)
{
// code for handling this type of exception
}
catch (Exception e)
{
// code to catch ANY other type of exception
}
}
Now, there are no errors or warnings when the VS debugger compiles everything, and it works correctly when debugging. But, if I copy the compiled exe (from C:\project\bin\Debug directory) and run it the issue arises.
The point that says passwordTrace = ... is called at another point by a message box. This works correctly when running via debugger and there aren't any exceptions thrown anywhere (I do have try/catches all over the place), but for whatever reason the PasswordTrace and the Properties.Settings.Default.adminpw don't seem to be holding their value throughout the applications execution.
Also, the file that is being read is an encrypted text file which will always have only 1 line of characters and that line is always 24 characters long. An example would be:
09sdjf09ausd08uf9!%38==
As a final statement, I also copied the app.exe.config and app.pdb to the server directory where I copied the compiled .exe file to see if that had anything to do with it and it didn't fix anything. I also tried running the .exe directly from the Debug directory (the same file that I'm copying elsewhere) and it works correctly. As soon as I move it off of the Local Disk it doesn't work.
So, my suspicions are that it has something to do with the environments working directory, or something to do with how the app is executing. I read something somewhere that noted the default users is not set, but I think that was specifically regarding ASP.NET. If that was the case and the user double-clicking on the .exe didn't have a proper network authentication then what would I do? And if it has something to do with the working directory, how can I circumvent this?
I'm gonna keep fiddling and if I figure it out I'll update this, but I'm so lost at the moment! lol! And for the last time - everything it/was working correctly until copying it to the server location.
Thanks in advance! :)

Saving image to a folder in IIS localhost

I have to save images to a folder located in "c:\inetpub\wwwroot\" and named as "UploadedImages". Here is my code:
public string SaveImage(string base64,int compno)
{
string res = "";
try
{
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64)))
{
using (Bitmap bm2 = new Bitmap(ms))
{
bm2.Save(Server.MapPath("~/UploadedImages/ID"+compno+".jpg"));
}
}
res = "done";
}
catch (Exception ex) {
res = ex.ToString();
}
return res;
}
but it throws "A generic error occured in GDI+ at System.Drawing.Image.Save" exception. What am I doing wrong? This code works fine when saving image locally as
bm2.Save("D:Embasy\UploadedImages\ID"+compno+".jpg"));
What changes do I need to make to save images in localhost directory?
Your not going to believe this -- the site running v1.1 had a virtual directory set-up which was mapped to the directory in which the image was saved to -- things worked fine.
The v2.0 site also had the same virtual directory name, but the physical path was different -- I changed the path to point to the same directory as the v1.0 site and now the code works.
So in short -- you were right about the "path must exist".
Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions. For a supported alternative, see Windows Imaging Components.
and kindly refer this link
http://msdn.microsoft.com/en-us/library/xs6ftd89.aspx
When you are using Server.Mappath
bm2.Save(Server.MapPath("~/UploadedImages/ID"+compno+".jpg"));
"~(tield)" : is point to project/application root folder c:\inetpub\wwwroot\yourproject
then find remaining your path /UploadedImages and then create ID1.jpg.
But your imagefolder "UploadImages" is exist in d: not in c:\inetpub\wwwroot\yourproject
if you want to exist your image folder in D: then you should to create
virtual directory and then you need to apply path as relevant
My problem actually was that every time i published website, I replaced the "UploadedImages" folder too and thus permissions were changed. So, i didnt replaced the folder again after changing its permissions and creating "everyone" group and giving full rights to it. Now code is working perfectly :)

Categories

Resources