Its about the copying image files from one directory to another - c#

I have 3 directories. These are images,good, bad. I'm getting images from images directory and I'm sending it the other directories. My question is, if good or bad directory have these images how can I change the name of images such as "I have car.jpg and if i copy it again , its name changes to car(1).jpg. I hope you understand my question..

I use code like this
internal static partial class IOUtilities
{
/// <summary>
/// Move a file to an archive folder
/// </summary>
/// <remarks>Renames file if necessary to avoid collision.
/// See <see cref="File.Move"/> for exceptions</remarks>
/// <param name="file">path to file to move</param>
/// <param name="targetFolder">folder to move file to</param>
public static void ArchiveFile(string file, string targetFolder) {
if (file == null)
throw new ArgumentNullException("file");
if (targetFolder == null)
throw new ArgumentNullException("targetFolder");
string targetFilename = Path.Combine(targetFolder, Path.GetFileName(file));
File.Move(file, FindAvailableFilename(targetFilename));
}
/// <summary>
/// Archive file in the same folder
/// </summary>
/// <remarks>Renames file by adding first free "(n)" suffix
/// See <see cref="File.Move"/> for exceptions</remarks>
/// <param name="file">path to file to archive</param>
public static void ArchiveFile(string file) {
if (file == null)
throw new ArgumentNullException("file");
File.Move(file, FindAvailableFilename(file));
}
/// <summary>
/// Find a "free" filename by adding (2),(3)...
/// </summary>
/// <param name="targetFilename">Complete path to target filename</param>
/// <returns>First available filename</returns>
private static string FindAvailableFilename(string targetFilename) {
if (!File.Exists(targetFilename))
return targetFilename;
string filenameFormat = Path.GetFileNameWithoutExtension(targetFilename) + "({0})" + Path.GetExtension(targetFilename);
string format = Path.Combine(Path.GetDirectoryName(targetFilename), filenameFormat);
for (int ii = 2;; ++ii) {
// until we find a filename that doesn't exist
string newFilename = string.Format(CultureInfo.InvariantCulture, format, ii);
if (!File.Exists(newFilename)) // returns false on illegal paths, security problems etc
return newFilename;
}
}
}

You can try out the sample code here:
http://www.codeproject.com/Questions/212217/increment-filename-if-file-exists-using-csharp

Related

Detect Fingerprint Reader Input outside of Console App

So I need to make a Metro GUI App that uses an external fingerprint reader for user identification.
I've come so far as to make a DLL in C++ so I can call a method I made called CaptureSample() in C# referencing that DLL. The CaptureSample() method provides me with a byte array that represents the scanned fingerprint (a greyscale image from the fingerprint reader). So good so far. The way it does this, is to use the Microsoft Biometrics Framework to access the reader, wait for the reader to detect that a finger was laid on top of it, then send the data back of the scanned fingerprint.
This all works great. There is one catch however: I HAVE to run whatever application I am making as Administrator to make use of the framework. This is also why I can't just run the framework from the Webservice because the Webservice is run as a Network User or similar, making the library deny any access when tried to using it. So I have to make an extra console program that can run it instead.
Now here is where things get hairy. In order to make the fingerprint reader work with a Windows Metro GUI App, you'd have to run the app as admin. This is not possible as all Metro GUI apps run in a sandbox. I have to make an external console application that calls the DLL functionality for the app and then send the result of that back to the app.
To make things even more complicated I've found out that the Windows Phone subset of .NET does not have MSMQ which would have been nice to use. So instead, I made a local WCF Service that the Metro app needs to call, then the WCF Service calls the console program via MSMQ and sends the info back to the Metro GUI App whenever it receives it from the Console app.
So far so good. In theory. I've run into a problem in this process because the Console Application does run and is ready to scan when asked. But when I scan my finger nothing happens. The console needs focus in order to work, and that's out of the question as the app runs like a Kiosk and should never leave the Metro GUI App at all unless for maintenance.
I've looked at various solutions for detecting keyboard input outside a C# application but I don't think that applies to a Fingerprint Reader or if it does, I don't know how I'd do that. Any suggestions?
Just for good meassure I included a workflow chart so it's easier to understand. (It's a P5100 Zvetcobiometrics Fingerprint Reader, if anyone is curious):
So, I ran across an issue like this with Windows Forms, but not exactly with the issues that you described.
I understand that my solution isn't a pre-coded easy-day solution for you but I feel that with some minor modifications, an obstacle I overcame a few years ago may be of use to you. If you think my solution may help you, I can send you any missing pieces.
I created an inventory management system that utilized barcode scanners and I decided to implement the capability of being able to handle the input from a device by marshalling in some C++ classes without requiring the use of an input control such as a textbox. I needed the application to be able to process barcode input and make decisions without any additional user interactions or requirements. Just scan and go. The immediate use of the input from a keyboard/HID device is why I feel that this solution fits your question.
While testing the application I wrote, I was able to be inside of a full-screen game and still was able to utilize the barcode scanner as expected in the windows forms inventory application. This same functionality should work just as well in a console environment as console applications don't stop when they're in the background. You can even set it as NT AUTHORITY and prevent it from displaying to the desktop while running as a service and it should still chug away.
What I did was I used the Win32API to reflect through the devices, matched the device with the device specified via the application (User-chosen) and basically established a listener for that specific device.
You could use your console application to trigger the fingerprint sensor by running the console application as the local service account or programmatically obtaining necessary authorization (which would allow you to run it in elevated permissions without the UAC stuff getting in your way) and then use this inside of your metro app to read the input from the device as the device sends it.
Below are some of the code files for going about what I describe and have been modified to be specific towards my barcode scanner functionality.
Again, please contact me privately if you'd like to see any missing pieces.
PS: This technically could be used as a hack for intercepting keys and the sort so I will put a disclaimer for you to use at your own discretion and I am not responsible for anything that someone stupid may do with this code.
BarcodeScannerListenerInteropHelper.h:
#include <winuser.h>
BEGIN_INTEROP_NAMESPACE
using namespace System;
using namespace System::Collections::Generic;
using namespace HFSLIB::Barcode;
using namespace HFSLIB::Barcode::Interop;
using namespace HFSLIB::Barcode::Infrastructure::BarcodeScannerListener;
/// <summary>
/// Provides some helper methods that help the BarcodeScannerListener use native
/// Windows APIs without resorting to P/Invoking from C#.
/// </summary>
public ref class BarcodeScannerListenerInteropHelper
{
public:
/// <summary>
/// Returns a dictionary of barcode device handles to information about
/// the device.
/// </summary>
/// <param name="hardwareIds">The enumerable of hardware IDs to filter by.</param>
/// <returns>The device handle-to-information mapping of the filtered hardware IDs.</returns>
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ InitializeBarcodeScannerDeviceHandles(
IEnumerable<String^>^ hardwareIds);
/// <summary>
/// Registers ourselves to listen to raw input from keyboard-like devices.
/// </summary>
/// <param name="hwnd">the handle of the form that will receive the raw
/// input messages</param>
/// <exception cref="InvalidOperationException">if the call to register with the
/// raw input API fails for some reason</exception>
void HookRawInput(IntPtr hwnd);
/// <summary>
/// Gets information from a WM_INPUT message.
/// </summary>
/// <param name="rawInputHeader">The LParam from the WM_INPUT message.</param>
/// <param name="deviceHandle">[Out] The device handle that the message came from.</param>
/// <param name="handled">[Out] True if the message represents a keystroke from that device.</param>
/// <param name="buffer">[Out] If handled is true, this contains the characters that the keystroke represents.</param>
void GetRawInputInfo(
IntPtr rawInputHeader,
IntPtr% deviceHandle,
bool% handled,
String^% buffer);
private:
/// <summary>
/// Converts a native raw input type into our version.
/// </summary>
/// <param name="rawInputType">The raw input type.</param>
/// <returns>Our version of the type.</returns>
static BarcodeScannerDeviceType GetBarcodeScannerDeviceType(DWORD rawInputType);
};
END_INTEROP_NAMESPACE
BarcodeScannerListenerInteropHelper.cpp:
#include "BarcodeScannerListenerInteropHelper.h"
using namespace System::ComponentModel;
BEGIN_INTEROP_NAMESPACE
/// <summary>
/// Gets information from a WM_INPUT message.
/// </summary>
/// <param name="rawInputHeader">The LParam from the WM_INPUT message.</param>
/// <param name="deviceHandle">[Out] The device handle that the message came from.</param>
/// <param name="handled">[Out] True if the message represents a keystroke from that device.</param>
/// <param name="buffer">[Out] If handled is true, this contains the characters that the keystroke represents.</param>
void BarcodeScannerListenerInteropHelper::GetRawInputInfo(
IntPtr rawInputHeader,
IntPtr% deviceHandle,
bool% handled,
String^% buffer)
{
UINT cbSize;
HRAWINPUT hRawInput;
hRawInput = (HRAWINPUT)rawInputHeader.ToPointer();
if (GetRawInputData(hRawInput, RID_INPUT, NULL, &cbSize, sizeof(RAWINPUTHEADER)) == 0)
{
RAWINPUT* raw;
raw = (RAWINPUT*)malloc(cbSize);
if (GetRawInputData(hRawInput, RID_INPUT, raw, &cbSize, sizeof(RAWINPUTHEADER)) == cbSize)
{
deviceHandle = IntPtr(raw->header.hDevice);
handled = raw->header.dwType == RIM_TYPEKEYBOARD &&
raw->data.keyboard.Message == WM_KEYDOWN;
if (handled)
{
BYTE state[256];
// Force the keyboard status cache to update
GetKeyState(0);
// Note: GetKeyboardState only returns valid state when
// the application has focus -- this is why we weren't
// getting shift keys when the application was not focused
if (GetKeyboardState(state))
{
WCHAR unmanagedBuffer[64];
if (ToUnicode(raw->data.keyboard.VKey,
raw->data.keyboard.MakeCode,
state,
unmanagedBuffer,
64,
0) > 0)
{
buffer = gcnew String(unmanagedBuffer);
}
}
}
}
free(raw);
}
}
/// <summary>
/// Registers ourselves to listen to raw input from keyboard-like devices.
/// </summary>
/// <param name="hwnd">the handle of the form that will receive the raw
/// input messages</param>
/// <exception cref="InvalidOperationException">if the call to register with the
/// raw input API fails for some reason</exception>
void BarcodeScannerListenerInteropHelper::HookRawInput(IntPtr hwnd)
{
RAWINPUTDEVICE rid[1];
rid[0].dwFlags = 0;
rid[0].hwndTarget = (HWND)hwnd.ToPointer();
rid[0].usUsage = 0x06; // Keyboard Usage ID
rid[0].usUsagePage = 0x01; // USB HID Generic Desktop Page
if (!RegisterRawInputDevices(rid, 1, sizeof(RAWINPUTDEVICE)))
{
InvalidOperationException^ e;
e = gcnew InvalidOperationException(
"The barcode scanner listener could not register for raw input devices.",
gcnew Win32Exception());
throw e;
}
}
/// <summary>
/// Returns a dictionary of barcode device handles to information about
/// the device.
/// </summary>
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ BarcodeScannerListenerInteropHelper::InitializeBarcodeScannerDeviceHandles(IEnumerable<String^>^ hardwareIds)
{
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ devices;
UINT uiNumDevices;
UINT cbSize;
devices = gcnew Dictionary<IntPtr, BarcodeScannerDeviceInfo^>();
uiNumDevices = 0;
cbSize = sizeof(RAWINPUTDEVICELIST);
if (GetRawInputDeviceList(NULL, &uiNumDevices, cbSize) != -1)
{
PRAWINPUTDEVICELIST pRawInputDeviceList;
if (pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(cbSize * uiNumDevices))
{
if (GetRawInputDeviceList(pRawInputDeviceList, &uiNumDevices, cbSize) != -1)
{
for (UINT i = 0; i < uiNumDevices; ++i)
{
UINT pcbSize;
RAWINPUTDEVICELIST rid;
rid = pRawInputDeviceList[i];
if (GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, NULL, &pcbSize) >= 0 &&
pcbSize > 0)
{
WCHAR* deviceName;
deviceName = (WCHAR*)malloc(sizeof(WCHAR) * (pcbSize + 1));
if (GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, deviceName, &pcbSize) >= 0)
{
bool add;
IntPtr deviceHandle;
BarcodeScannerDeviceInfo^ info;
String^ managedDeviceName;
add = false;
deviceHandle = IntPtr(rid.hDevice);
managedDeviceName = gcnew String(deviceName);
for each (String^ hardwareId in hardwareIds)
{
if (managedDeviceName->IndexOf(hardwareId, StringComparison::OrdinalIgnoreCase) >= 0)
{
add = true;
break;
}
}
if (add)
{
info = gcnew BarcodeScannerDeviceInfo(
managedDeviceName,
BarcodeScannerListenerInteropHelper::GetBarcodeScannerDeviceType(rid.dwType),
deviceHandle);
devices->Add(deviceHandle, info);
}
}
free(deviceName);
}
}
}
free(pRawInputDeviceList);
}
}
return devices;
}
/// <summary>
/// Converts a native raw input type into our version.
/// </summary>
/// <param name="rawInputType">The raw input type.</param>
/// <returns>Our version of the type.</returns>
BarcodeScannerDeviceType BarcodeScannerListenerInteropHelper::GetBarcodeScannerDeviceType(DWORD rawInputType)
{
BarcodeScannerDeviceType type;
switch (rawInputType)
{
case RIM_TYPEHID:
type = BarcodeScannerDeviceType::HumanInterfaceDevice;
break;
case RIM_TYPEKEYBOARD:
type = BarcodeScannerDeviceType::Keyboard;
break;
default:
type = BarcodeScannerDeviceType::Unknown;
break;
}
return type;
}
END_INTEROP_NAMESPACE
BarcodeScannerListener.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
using HFSLIB.Barcode.Infrastructure.BarcodeScannerListener;
using HFSLIB.Barcode.Interop;
namespace HFSLIB.Barcode
{
/// <summary>
/// This class uses Windows's native Raw Input API to listen for input from
/// a certain set of barcode scanners and devices. This way, the application
/// can receive input from a barcode scanner without the user having to
/// worry about whether or not a certain text field has focus, which was a
/// big problem
/// </summary>
public class BarcodeScannerListener : NativeWindow
{
/// <summary>
/// A mapping of device handles to information about the barcode scanner
/// devices.
/// </summary>
private Dictionary<IntPtr, BarcodeScannerDeviceInfo> devices;
/// <summary>
/// The WM_KEYDOWN filter.
/// </summary>
private BarcodeScannerKeyDownMessageFilter filter;
/// <summary>
/// The barcode currently being read.
/// </summary>
private StringBuilder keystrokeBuffer;
/// <summary>
/// The interop helper.
/// </summary>
private BarcodeScannerListenerInteropHelper interopHelper =
new BarcodeScannerListenerInteropHelper();
/// <summary>
/// Event fired when a barcode is scanned.
/// </summary>
public event EventHandler BarcodeScanned;
/// <summary>
/// Attaches the listener to the given form.
/// </summary>
/// <param name="form">The form to attach to.</param>
public void Attach(Form form)
{
IntPtr hwnd;
if (form == null)
{
throw new ArgumentNullException("form");
}
hwnd = form.Handle;
this.keystrokeBuffer = new StringBuilder();
this.InitializeBarcodeScannerDeviceHandles();
this.interopHelper.HookRawInput(hwnd);
this.HookHandleEvents(form);
this.AssignHandle(hwnd);
this.filter = new BarcodeScannerKeyDownMessageFilter();
Application.AddMessageFilter(this.filter);
}
/// <summary>
/// Hook into the form's WndProc message. We listen for WM_INPUT and do
/// special processing on the raw data.
/// </summary>
/// <param name="m">the message</param>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case NativeMethods.WM_INPUT:
if (this.ProcessRawInputMessage(m.LParam))
{
this.filter.FilterNext = true;
}
break;
}
base.WndProc(ref m);
}
/// <summary>
/// Fires the barcode scanned event.
/// </summary>
/// <param name="deviceInfo">information about the device that generated
/// the barcode</param>
private void FireBarcodeScanned(BarcodeScannerDeviceInfo deviceInfo)
{
string barcode;
EventHandler handler;
barcode = this.keystrokeBuffer.ToString();
if (barcode != null && barcode.Length > 0)
{
handler = this.BarcodeScanned;
this.keystrokeBuffer = new StringBuilder();
if (handler != null)
{
handler(this, new BarcodeScannedEventArgs(barcode, deviceInfo));
}
}
}
/// <summary>
/// Hooks into the form's HandleCreated and HandleDestoryed events
/// to ensure that we start and stop listening at appropriate times.
/// </summary>
/// <param name="form">the form to listen to</param>
private void HookHandleEvents(Form form)
{
form.HandleCreated += this.OnHandleCreated;
form.HandleDestroyed += this.OnHandleDestroyed;
}
/// <summary>
/// Initializes the barcode scanner device handles.
/// </summary>
private void InitializeBarcodeScannerDeviceHandles()
{
BarcodeScannerListenerConfigurationSection config;
BarcodeScannerListenerConfigurationElementCollection hardwareIdsConfig;
IEnumerable<string> hardwareIds;
config = BarcodeScannerListenerConfigurationSection.GetConfiguration();
hardwareIdsConfig = config.HardwareIds;
hardwareIds = from hardwareIdConfig in hardwareIdsConfig.Cast<BarcodeScannerListenerConfigurationElement>()
select hardwareIdConfig.Id;
this.devices = this.interopHelper.InitializeBarcodeScannerDeviceHandles(hardwareIds);
}
/// <summary>
/// When the form's handle is created, let's hook into it so we can see
/// the WM_INPUT event.
/// </summary>
/// <param name="sender">the form whose handle was created</param>
/// <param name="e">the event arguments</param>
private void OnHandleCreated(object sender, EventArgs e)
{
this.AssignHandle(((Form)sender).Handle);
}
/// <summary>
/// When the form's handle is destroyed, let's unhook from it so we stop
/// listening and allow the OS to free up its resources.
/// </summary>
/// <param name="sender">the form whose handle was destroyed</param>
/// <param name="e">the event arguments</param>
private void OnHandleDestroyed(object sender, EventArgs e)
{
this.ReleaseHandle();
}
/// <summary>
/// Process the given WM_INPUT message.
/// </summary>
/// <param name="rawInputHeader">the rawInputHeader of the message</param>
/// <returns>whether or not the keystroke was handled</returns>
private bool ProcessRawInputMessage(IntPtr rawInputHeader)
{
BarcodeScannerDeviceInfo deviceInfo;
bool handled;
bool keystroke;
string localBuffer;
IntPtr rawInputDeviceHandle;
handled = false;
keystroke = false;
localBuffer = string.Empty;
rawInputDeviceHandle = IntPtr.Zero;
this.interopHelper.GetRawInputInfo(
rawInputHeader,
ref rawInputDeviceHandle,
ref keystroke,
ref localBuffer);
if (this.devices.TryGetValue(rawInputDeviceHandle, out deviceInfo) && keystroke)
{
handled = true;
if (localBuffer.Length == 1 && localBuffer[0] == 0xA)
{
this.FireBarcodeScanned(deviceInfo);
}
else
{
this.keystrokeBuffer.Append(localBuffer);
}
}
return handled;
}
}
}

How to find out if a file is a shortcut file or not in windows 7 and 8? [duplicate]

I need to test if a file is a shortcut. I'm still trying to figure out how stuff will be set up, but I might only have it's path, I might only have the actual contents of the file (as a byte[]) or I might have both.
A few complications include that I it could be in a zip file (in this cases the path will be an internal path)
Shortcuts can be manipulated using the COM objects in SHELL32.DLL.
In your Visual Studio project, add a reference to the COM library "Microsoft Shell Controls And Automation" and then use the following:
/// <summary>
/// Returns whether the given path/file is a link
/// </summary>
/// <param name="shortcutFilename"></param>
/// <returns></returns>
public static bool IsLink(string shortcutFilename)
{
string pathOnly = System.IO.Path.GetDirectoryName(shortcutFilename);
string filenameOnly = System.IO.Path.GetFileName(shortcutFilename);
Shell32.Shell shell = new Shell32.ShellClass();
Shell32.Folder folder = shell.NameSpace(pathOnly);
Shell32.FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
return folderItem.IsLink;
}
return false; // not found
}
You can get the actual target of the link as follows:
/// <summary>
/// If path/file is a link returns the full pathname of the target,
/// Else return the original pathnameo "" if the file/path can't be found
/// </summary>
/// <param name="shortcutFilename"></param>
/// <returns></returns>
public static string GetShortcutTarget(string shortcutFilename)
{
string pathOnly = System.IO.Path.GetDirectoryName(shortcutFilename);
string filenameOnly = System.IO.Path.GetFileName(shortcutFilename);
Shell32.Shell shell = new Shell32.ShellClass();
Shell32.Folder folder = shell.NameSpace(pathOnly);
Shell32.FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
if (folderItem.IsLink)
{
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
return link.Path;
}
return shortcutFilename;
}
return ""; // not found
}
You can simply check the extension and/or contents of this file. It contains a special GUID in the header.
Read [this document][1].
Link deleted, for me it goes to a porn site
If you are using .NET 6.0, then you can use FileInfo or DirectoryInfo. Both have a property named LinkTarget. If it is a shortcut, then LinkTarget will be a string targeting the original file/folder. Otherwise, it will be null.
Suppose there is a folder shortcut named "folder", then:
var info = new DirectoryInfo("path/to/the/folder/shortcut");
bool isShortcut = info.LinkTarget != null;
Check the extension? (.lnk)

C# File Open frequently, already open exception

Hey so I have a logger class that is called frequently, sometimes when its called fast repeatedly it will throw an exception that the file is already open being used by another application. The only way we found a way around this was to catch the exception then try to open it again... I'm not sure how to handle this properly.
/// <summary>
/// Open a log file based on a date
/// </summary>
/// <param name="date"> Date of the file to open </param>
public static void OpenLogFile(DateTime date)
{
while (true)
{
try
{
logStream = File.Open("Logs/ems." + date.ToString("yyyy-MM-dd") + ".log", FileMode.Append);
break;
}
catch
{
continue;
}
}
}
/// <summary>
/// Writes to a log file the specified input
/// </summary>
/// <param name="input"> Content to write to the log file </param>
public static void Log(string className, string methodName, string input)
{
OpenLogFile(DateTime.Now);
using (StreamWriter s = new StreamWriter(logStream))
{
s.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + '[' + className + '.' + methodName + "] " + input);
}
CloseLogFile();
}
/// <summary>
/// Closes the current log file
/// </summary>
public static void CloseLogFile()
{
if (logStream != null)
{
logStream.Close();
logStream = null;
}
}
Since this is a log file, I think the obvious (and correct) solution, is to leave the file open for the duration of your program's execution.
If you don't want to use an already-implemented 3rd party logger, like Apache's log4net, you could write your own little logger class that uses thread-safe mechanisms for writing lines to the file.
It would probably be a static class, or singleton. Generally, execution at the beginning and end of your program is quite predictable, so it should be clear where to initialize, and close out the object/class.
A bit of order is required, not a disk free-for-all. Store log messages in a queue and have a single thread dequeue and write items.

File extension restriction to .cor (only)

How can I restrict only .cor files to be added to the list.
The code bellow allows .corx, .corxx, .corxxx to be added to the list.
I only want .cor files. Is that possible?
private void btn_models_Click(object sender, EventArgs e)
{
DialogResult res = dlg_find_folder.ShowDialog();
if (res == DialogResult.OK)
{
tbx_models.Text = dlg_find_folder.SelectedPath;
populateChecklist(tbx_models.Text, "cor");
cbx_all.CheckState = System.Windows.Forms.CheckState.Checked;
}
}
/// <summary>
/// Function populates the models checklist based on the models found in the specified folder.
/// </summary>
/// <param name="directory">Directory in which to search for files</param>
/// <param name="extension">File extension given without period</param>
private void populateChecklist(String directory, String extension)
{
clb_run_list.Items.Clear();
System.Collections.IEnumerator enumerator;
String mdl_name;
try
{
enumerator = System.IO.Directory.GetFiles(directory, "*." + extension).GetEnumerator();
while (enumerator.MoveNext())
{
mdl_name = parse_file_name((String)enumerator.Current, directory, extension);
clb_run_list.Items.Add(mdl_name);
}
}
catch
{
//above code will fail if the initially specified directory does not exist
//MessageBox.Show("The specified directory does not exist. Please select a valid directory.");
}
return;
}
How about;
if (Path.GetExtension(mdl_name).Equals(".cor", StringComparison.OrdinalIgnoreCase))
clb_run_list.Items.Add(mdl_name);
Do a check for FileName.EndsWith(extension) before adding to your list?
This is an artifact of Windows support for old DOS 8.3 filenames. Files with an extension like .corxxx get mapped to a 8.3 name like Blah~1.cor. And will match your wildcard.
Nothing you can do but double-check the filename you get. Use Path.GetExtension()

How to programmatically discover mapped network drives on system and their server names?

I'm trying to find out how to programmatically (I'm using C#) determine the name (or i.p.) of servers to which my workstation has current maps. In other words, at some point in Windows Explorer I mapped a network drive to a drive letter (or used "net use w: " to map it). I know how to get the network drives on the system:
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
if (d.IsReady && d.DriveType == DriveType.Network)
{
}
}
But the DriveInfo class does not have properties that tell me what server and shared folder the mapped drive is associated with. Is there somewhere else I should be looking?
Have you tried to use WMI to do it?
using System;
using System.Management;
using System.Windows.Forms;
public static void Main()
{
try
{
var searcher = new ManagementObjectSearcher(
"root\\CIMV2",
"SELECT * FROM Win32_MappedLogicalDisk");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_MappedLogicalDisk instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Access: {0}", queryObj["Access"]);
Console.WriteLine("Availability: {0}", queryObj["Availability"]);
Console.WriteLine("BlockSize: {0}", queryObj["BlockSize"]);
Console.WriteLine("Caption: {0}", queryObj["Caption"]);
Console.WriteLine("Compressed: {0}", queryObj["Compressed"]);
Console.WriteLine("ConfigManagerErrorCode: {0}", queryObj["ConfigManagerErrorCode"]);
Console.WriteLine("ConfigManagerUserConfig: {0}", queryObj["ConfigManagerUserConfig"]);
Console.WriteLine("CreationClassName: {0}", queryObj["CreationClassName"]);
Console.WriteLine("Description: {0}", queryObj["Description"]);
Console.WriteLine("DeviceID: {0}", queryObj["DeviceID"]);
Console.WriteLine("ErrorCleared: {0}", queryObj["ErrorCleared"]);
Console.WriteLine("ErrorDescription: {0}", queryObj["ErrorDescription"]);
Console.WriteLine("ErrorMethodology: {0}", queryObj["ErrorMethodology"]);
Console.WriteLine("FileSystem: {0}", queryObj["FileSystem"]);
Console.WriteLine("FreeSpace: {0}", queryObj["FreeSpace"]);
Console.WriteLine("InstallDate: {0}", queryObj["InstallDate"]);
Console.WriteLine("LastErrorCode: {0}", queryObj["LastErrorCode"]);
Console.WriteLine("MaximumComponentLength: {0}", queryObj["MaximumComponentLength"]);
Console.WriteLine("Name: {0}", queryObj["Name"]);
Console.WriteLine("NumberOfBlocks: {0}", queryObj["NumberOfBlocks"]);
Console.WriteLine("PNPDeviceID: {0}", queryObj["PNPDeviceID"]);
if(queryObj["PowerManagementCapabilities"] == null)
Console.WriteLine("PowerManagementCapabilities: {0}", queryObj["PowerManagementCapabilities"]);
else
{
UInt16[] arrPowerManagementCapabilities = (UInt16[])(queryObj["PowerManagementCapabilities"]);
foreach (UInt16 arrValue in arrPowerManagementCapabilities)
{
Console.WriteLine("PowerManagementCapabilities: {0}", arrValue);
}
}
Console.WriteLine("PowerManagementSupported: {0}", queryObj["PowerManagementSupported"]);
Console.WriteLine("ProviderName: {0}", queryObj["ProviderName"]);
Console.WriteLine("Purpose: {0}", queryObj["Purpose"]);
Console.WriteLine("QuotasDisabled: {0}", queryObj["QuotasDisabled"]);
Console.WriteLine("QuotasIncomplete: {0}", queryObj["QuotasIncomplete"]);
Console.WriteLine("QuotasRebuilding: {0}", queryObj["QuotasRebuilding"]);
Console.WriteLine("SessionID: {0}", queryObj["SessionID"]);
Console.WriteLine("Size: {0}", queryObj["Size"]);
Console.WriteLine("Status: {0}", queryObj["Status"]);
Console.WriteLine("StatusInfo: {0}", queryObj["StatusInfo"]);
Console.WriteLine("SupportsDiskQuotas: {0}", queryObj["SupportsDiskQuotas"]);
Console.WriteLine("SupportsFileBasedCompression: {0}", queryObj["SupportsFileBasedCompression"]);
Console.WriteLine("SystemCreationClassName: {0}", queryObj["SystemCreationClassName"]);
Console.WriteLine("SystemName: {0}", queryObj["SystemName"]);
Console.WriteLine("VolumeName: {0}", queryObj["VolumeName"]);
Console.WriteLine("VolumeSerialNumber: {0}", queryObj["VolumeSerialNumber"]);
}
}
catch (ManagementException ex)
{
MessageBox.Show("An error occurred while querying for WMI data: " + ex.Message);
}
}
to make it a little easier to get started download WMI Code Creater
You could use WMI to enumerate and query mapped drives. The following code enumerates mapped drives, extracts the server name portion, and prints that out.
using System;
using System.Text.RegularExpressions;
using System.Management;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"select * from Win32_MappedLogicalDisk");
foreach (ManagementObject drive in searcher.Get()) {
Console.WriteLine(Regex.Match(
drive["ProviderName"].ToString(),
#"\\\\([^\\]+)").Groups[1]);
}
}
}
}
}
You can find the documentaiton of the Win32_MappedLogicalDisk class here. An intro for accessing WMI from C# is here.
The WMI methods won't tell you whether the drive is set to reconnect on login. When you set a drive to reconnect on login, Windows creates a key under HKCU\Network\. The method below can be used to determine if the drive is set to be remapped at login.
private static bool DriveSetForReconnect(string ComputerName, string DriveLetter)
{
RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.CurrentUser, ComputerName);
key = key.OpenSubKey("Network\\" + DriveLetter);
return key != null;
}
HTH!
EDIT:
To adapt the WMI solutions to work on any arbitrary machine, you need to change the scope parameter like the code below. You obviously have to have have admin rights on the remote machine.
string scope = string.Format(#"\\{0}\root\CIMV2", ComputerName);
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(scope,
"SELECT * FROM Win32_MappedLogicalDisk");
You unfortunately have to use WinAPI via P/Invoke. It will require using WNetGetUniversalName and the UNIVERSAL_NAME_INFO structure. You check that if expanding the path using GetFullPath does not equal what the Universal Name is for the expanded path, then you know it is mapped. The basic pseudo-code is as follows (0 error checking, bare minimum):
var nfo = new UNIVERSAL_NAME_INFO();
var size = Marshal.SizeOf(nfo);
if (ERROR_MORE_DATA == WNetGetUniversalName(path, InfoLevel.UniversalName,
ref nfo, ref size)
{
var buffer = Marshal.AllocHGlobal(size);
if (NO_ERROR == WNetGetUniversalName(path, InfoLevel.UniversalName,
buffer, ref size))
{
nfo = (UNIVERSAL_NAME_INFO)Marshal.PtrToStructure(buffer,
typeof(UNIVERSAL_NAME_INFO));
}
}
Here are the P/Invoke declarations, which should help you along your way:
internal class NativeMethods
{
/// <summary>
/// The type of structure that the function stores in the buffer.
/// </summary>
public enum InfoLevel
{
/// <summary>
/// The function stores a <see cref="UNIVERSAL_NAME_INFO"/> structure in the
/// buffer.
/// </summary>
UniversalName = 1,
/// <summary>
/// The function stores a <c>REMOTE_NAME_INFO</c> structure in the buffer.
/// </summary>
/// <remarks>
/// Using this level will throw an <see cref="NotSupportedException"/>.
/// </remarks>
RemoteName = 2
}
/// <summary>
/// The <see cref="WNetGetUniversalName(string,int,UNIVERSAL_NAME_INFO,int)"/> function
/// takes a drive-based path for a network resource and returns an information
/// structure that contains a more universal form of the name.
/// </summary>
/// <param name="lpLocalPath">A pointer to a constant null-terminated string that
/// is a drive-based path for a network resource.</param>
/// <param name="dwInfoLevel">The type of structure that the function stores in
/// the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
/// <param name="lpBuffer">A pointer to a buffer that receives the structure
/// specified by the <paramref name="dwInfoLevel"/> parameter.</param>
/// <param name="lpBufferSize">A pointer to a variable that specifies the size,
/// in bytes, of the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
/// <returns>If the function succeeds, the return value is <see cref="NO_ERROR"/>.</returns>
[DllImport("mpr.dll", CharSet = CharSet.Auto)]
public static extern int WNetGetUniversalName(
string lpLocalPath,
InfoLevel dwInfoLevel,
ref UNIVERSAL_NAME_INFO lpBuffer,
ref int lpBufferSize);
/// <summary>
/// The <see cref="WNetGetUniversalName(string,int,IntPtr,int)"/> function
/// takes a drive-based path for a network resource and returns an information
/// structure that contains a more universal form of the name.
/// </summary>
/// <param name="lpLocalPath">A pointer to a constant null-terminated string that
/// is a drive-based path for a network resource.</param>
/// <param name="dwInfoLevel">The type of structure that the function stores in
/// the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
/// <param name="lpBuffer">A pointer to a buffer that receives the structure
/// specified by the <paramref name="dwInfoLevel"/> parameter.</param>
/// <param name="lpBufferSize">A pointer to a variable that specifies the size,
/// in bytes, of the buffer pointed to by the <paramref name="lpBuffer"/> parameter.</param>
/// <returns>If the function succeeds, the return value is <see cref="NO_ERROR"/>.</returns>
[DllImport("mpr.dll", CharSet = CharSet.Auto)]
public static extern int WNetGetUniversalName(
string lpLocalPath,
InfoLevel dwInfoLevel,
IntPtr lpBuffer,
ref int lpBufferSize);
/// <summary>
/// The <see cref="UNIVERSAL_NAME_INFO"/> structure contains a pointer to a
/// Universal Naming Convention (UNC) name string for a network resource.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct UNIVERSAL_NAME_INFO
{
/// <summary>
/// Pointer to the null-terminated UNC name string that identifies a
/// network resource.
/// </summary>
[MarshalAs(UnmanagedType.LPTStr)]
public string lpUniversalName;
}
}
I've found yet another way of doing this, which uses part of the technique sixlettervariables posted. I'd love some feedback about the pros and cons of the various techniques. For example, does mine have a downside, a scenario where it won't work, for instance?
[DllImport("mpr.dll")]
static extern uint WNetGetConnection(string lpLocalName, StringBuilder lpRemoteName, ref int lpnLength);
internal static bool IsLocalDrive(String driveName)
{
bool isLocal = true; // assume local until disproved
// strip trailing backslashes from driveName
driveName = driveName.Substring(0, 2);
int length = 256; // to be on safe side
StringBuilder networkShare = new StringBuilder(length);
uint status = WNetGetConnection(driveName, networkShare, ref length);
// does a network share exist for this drive?
if (networkShare.Length != 0)
{
// now networkShare contains a UNC path in format \\MachineName\ShareName
// retrieve the MachineName portion
String shareName = networkShare.ToString();
string[] splitShares = shareName.Split('\\');
// the 3rd array element now contains the machine name
if (Environment.MachineName == splitShares[2])
isLocal = true;
else
isLocal = false;
}
return isLocal;
}
This is called from this code:
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
bool isLocal = IsLocalDrive(drive.Name);
if (isLocal)
{
// do whatever
}
}
We can also use net use to find IP or Computer Name of mapped network drive
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c net use";
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
string driveName = "Y:";
var line = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
.Where(x => x.Contains(driveName)).FirstOrDefault();
if (!string.IsNullOrEmpty(line))
{
var host = line.Substring(line.IndexOf("\\"), line.Substring(line.IndexOf("\\")).IndexOf(" ")).Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
}
Inspired by map network drive path in C# here's another simple method using Scripting objects:
private static IDictionary<DriveInfo, string> GetMappedNetworkDrives()
{
var rawDrives = new IWshRuntimeLibrary.IWshNetwork_Class()
.EnumNetworkDrives();
var result = new Dictionary<DriveInfo, string>(
rawDrives.length / 2);
for (int i = 0; i < rawDrives.length; i += 2)
{
result.Add(
new DriveInfo(rawDrives.Item(i)),
rawDrives.Item(i + 1));
}
return result;
}
See https://msdn.microsoft.com/en-us/library/t9zt39at(v=vs.84).aspx for details about the IWshNetwork_Class.

Categories

Resources