Take disks online/offline - c#

I have a program that is doing raw IO to disks within Windows.
All works fine if the target disk is online. However, the default behavior in some Windows OSes is to have new disks initially offline.
I am having a hard time finding the correct API to do this on Windows. The command line equivalent would be something like:
"select disk 2", "online disk" | diskpart
However I need to be able to do this in code. I looked through the DeviceIoControl Win32 API (which I think is right) but cannot determine which control code to use. The fact that I can't find it makes me think I might be missing a better API to use.

For future generations, the answer (on Win 2k3/Vista and later) is the Virtual Disk Service (VDS). There's some work getting it all together, especially if you don't use COM objects within .NET that much.
Disk online/offline is done with IVdsDrive::SetStatus. At least it should; I found that I could solve my problem with simply disabling read-only status on my disk. I was able to do this with IVdsDisk::SetFlags with the appropriate flag value.

This question has a couple useful links to the Windows API, including the DeviceIOControl method.
After looking through all of the enumerations, I could not find anything related to bringing a disk online, or make any interesting change to the disk beyond formatting/partitions. This is likely because only hot-swappable hard drives are supported by this functionality. The market for hot-swappable hard drives is very small, and the vast majority of those situations there are drivers to support any needed operations. Finally the remainder should be able to use the diskpart tool for whatever is necessary.
You need to look again at your requirements I think. You are running a process that has the rights necessary to online a hard disk, but cannot access a command line program? Here are some suggestions for common reasons to not use a command line program:
Can't have a black screen pop up - tons of solutions to this problem available online
Security team won't allow it - you are already running the process as an administrator so you trust it, why wouldn't you trust the built in Windows function
Technical problems preclude calling other processes - I would be interested in how this was managed given the process is running as an administrator
Coding guidelines such as "Always use the API" - there isn't one due to lack of need

Not sure about C#, but I'm using this in C++:
Try calling DeviceIoControl() with IOCTL_DISK_SET_DISK_ATTRIBUTES. The file handle must have read and write access. I think it requires at least Windows 7. It doesn't work on Windows 2003 x64. Windows 8 successfully takes the disk offline and then you can rewrite it from a backup.
BOOL disk_offline(HANDLE h_file, bool enable){
DWORD bytes_returned = 0;
BOOL b_offline = 0;
if(get_size_volume_disk(h_file)){
SET_DISK_ATTRIBUTES disk_attr;
ZeroMemory(&disk_attr, sizeof(disk_attr));
disk_attr.Version = sizeof(SET_DISK_ATTRIBUTES);
disk_attr.Attributes = enable? DISK_ATTRIBUTE_OFFLINE: 0;
disk_attr.AttributesMask = DISK_ATTRIBUTE_OFFLINE;
b_offline = DeviceIoControl(h_file, IOCTL_DISK_SET_DISK_ATTRIBUTES, &disk_attr, disk_attr.Version, NULL, 0, &bytes_returned, NULL);
// Invalidates the cached partition table and re-enumerates the device.
if(!enable) BOOL b_update = DeviceIoControl(h_file, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &bytes_returned, NULL);
}
return b_offline;
}

Using DeviceIoControl and IOCTL_DISK_IS_WRITABLE control code, it is possible to check if disk is writable. If the disk is offline it returns false. This means that it is possible to determine if disk is offline and it works fine with Windows 2003 and after. However, I could not find any useful IOCTL to bring the disk online on Windows 2003. IOCTL_DISK_SET_DISK_ATTRIBUTES only works with Windows 2008 and after.

Related

c# create media at runtime

I want to add a backup functionality to my app in the sense that the app will allow users to create a self-contained environment (data + executable + autorun.inf file) on an external device (CD, CD-ROM or USB key) so that users can retrieve (in read only mode) their stored environment at a given point in time.
I've read here about making an auto-bootable USB (which I suspect will be the same for a CD or DVD).
edit I meant "auto-executing", not "auto-bootable"!
I know about IMAPI or other approaches that are now several years old. Is there any alternative/standard approach to create media this way? I'd like a generic way to create either CD/DVD or USB devices (non-bootable).
You need to make sure to not confuse Booting and Windows Autorun.
auto-bootable USB
refers to an external USB drive from which you can boot your computer.
I doubt that's what you are looking for, given the linked Stackexchange question. The information you already found is actually what you are looking for, and the advice given there seems pretty accurate.
What you need to do is:
Create the media with your data. In case of USB sticks this is as easy as copying the data to the stick. Optical media (CD/DVD) need to be burned, and that can only be done using the Windows API, which has already be discussed here.
If you want to use the Windows autorun feature (which I would ignore*), you'll need to create a file called Autorun.ini in the root directory of your media. You already have found the required content of that file here.
* Why I would skip the autorun feature.
First of all, there's no real alternative to the Windows autorun feature.
It was controversial, at best, in earlier versions of Windows. Since USB sticks went mainstream, autorun became nothing more than an automatic virus installation feature. Soon after everyone started disabling it. Because of this recent versions of Windows seem to have dropped it or disable it by default.
An exception to this would be the Icon=diskicon.ico option, which allows you to change the icon of the drive. This might be still working, even if autorun is disabled.

How to access kernel operations by process

Above is a screen shot I took in Windows PE environment while applying an image to a machine. As you can see I have filtered the results of Windows Sysinternals Process Monitor so that only ReadFile operations on the Win8 32-bit image by the Dism.exe process are shown.
I am in need of finding a way to access this same information using C/C#/C++ without the .NET framework (because supposedly the .NET framework doesn't exist in PE environment). I have searched, asked around, and searched again for Namespaces and Classes that would allow me to extract this information from the kernel without luck.
I am most interested in having the ability to access the value "Offset" that you can see in the image. This number is the location offset of the Read operation on the file and I need this value for the program I am required to make.
Does anybody know how I can achieve my goal? This is obviously possible to do in the PE environment because Process Monitor does it, so how can I do the same thing?
You might want to look at file mini-filters. Process Explorer basically installs one on the system when you start it for the first time. The mini-filter can be installed and started without the need for a reboot.
The mini-filter runs inside the kernel like any other device drivers and from there you can monitor any file activity (read, write, create, delete, close, execute, etc.)
You'd have to write this in C. You can also get info from the OSR distribution list.

Defragmenting the registry

Does any body know how to defragment windows registry.
We googled and found several free tools doing the same.But no tool is having open source. One tool is there - 'UltraDefrag' which is open source tool written in 'C' for file defragmentation.
Please provide help in searching open source/ sample code to defragment windows registry...or any windows API functions or libraries for doing the same.
Regards.
The way this works is by executing code during the Windows boot process. Registry hive files cannot be defragged like other files, and nor can the pagefile. But they can be treated as ordinary files before Windows has finished booting, when they are not yet in use by the system. It is at this stage that a kernel mode driver-like component can defragment them.
I've seen tools that did this, but they seemed to treat it as an exciting technical challenge (well, about fifteen years ago it was), rather than as something that might be useful - how fragmented do registry hive files become? Probably not that fragmented. Depends how often they have to grow in size.

C# How to to tell what process is using a file?

I am getting a pretty common, "The process cannot access the file because it is being used by another process."
Now I am nearly certain that the only process accessing this file is from code that I have written and I've been careful to use a using statement around accessing it.
But to be 100% sure, is there anyway to check this programatically when this error occurs?
There is also a small tool handle.exe in Sysinternals Suite that does exactly what you need. Use it from the command line:
handle.exe -a <filename>
Of course under Vista and Windows 7 this tool must be run elevated.
e.g. oh.exe from the Resource Kit and Process Explorer from sysInternals both show who is using what
Both of them use techniques not available in C#.
Windows Vista adds a new function, GetRunningObjectTable which you can use to detect which program has a file open. This only works in Vista+, and it only works when the application that has the file open actually implements supports for IFileIsInUse (e.g. Office supports it, but most 3rd-party apps probably don't).
Other than that, the usual way this is implemented is by opening each process, enumerating the file handles they have open and searching for the filename in question. This is pretty low-level, and would require quite a bit of P/Invoke to implement in C#, but it's not impossible.
It's usually easy enough just to open up Process Explorer and let it do the search.

Writing USB Drive Portable Applications in C#

One of my favorite things about owning a USB flash storage device is hauling around a bunch of useful tools with me. I'd like to write some tools, and make them work well in this kind of environment. I know C# best, and I'm productive in it, so I could get a windows forms application up in no time that way.
But what considerations should I account for in making a portable app? A few I can think of, but don't know answers to:
1) Language portability - Ok, I know that any machine I use it on will require a .NET runtime be installed. But as I only use a few windows machines regularly, this shouldn't be a problem. I could use another language to code it, but then I lose out on productivity especially in regards to an easy forms designer. Are there any other problems with running a .NET app from a flash drive?
2) Read/Write Cycles - In C#, how do I make sure that my application isn't writing unnecessarily to the drive? Do I always have control of writes, or are there any "hidden writes" that I need to account for?
3) Open question: are there any other issues relating to portable applications I should be aware of, or perhaps suggestions to other languages with good IDEs that would get me a similar level of productivity but better portability?
1) There shouldn't be any problems
running a .NET app from a flash
drive.
2) You should have control of
most writes. Be sure you write to
temp or some other location on the
hard drive, and not on the flash
drive. But write-cycles shouldn't be
a problem - even with moderate to heavy
usage most flashdrives have a life
time of years.
3) Just treat it
like's it any app that has xcopy
style deployment and try to account
for your app gracefully failing if
some dependency is not on the box.
If you want to use com objects, use reg-free com and include the com objects with your program.
You should always have control of your writes. Applications should be loaded into RAM at startup, and then memory past that is allocated in RAM, so nothing is written to the flash drive.
The most important thing for a portable application is that basically no installation is necessary for your application. You do not want to be dependant on registry values especially, since your application will not be 'installed' on other computers.
One of the issues with portable applications you may consider is data persistence. Generally, you write to a user's Application Data folder to save data. If this is the case, any data saved will only apply to the user on that computer. If you want some local application data, you may wish to create a Seralized XML file for your settings and store it locally within your application's directory. This file writing would then likely be the only write actions you'd need to worry about.
For your .NET portability issue, you could also write a small entry program in C++, which checks if the computer has .NET installed. .NET has registry values you can check to see the versions installed, so if .NET is installed, run your application, else display a message stating that .NET needs to be installed first.
Edit: I'd like to add that I do application development for Ultrasound machines using XAML in C# 3.0. The application I write works perfectly from a USB Flash Drive, while all user settings are stored on a local AppData basis, so nothing is written to the USB. While the application can be installed through an .exe installer, the installer does not write any registry values the application depends on.
I don't really have answers for #1 or #3. But for #2, the .NET CLR shouldn't be writing to an app's "installation" folder (i.e. the flash drive) unless your code specifically tells it to or is using and modifying file-based settings (ini, xml, etc) that live with the app.
Number 1 is really the kicker if you're not just writing things for personal use. Obviously hosting a portable copy of the full CLR on the thumb drive is impossible. But there are tools that can scan your assembly for its dependencies and package them up into a standalone .exe so that the CLR doesn't necessarily need to be installed on the target system.
I don't actually have any experience with this so it might be best to take what I say with a pinch of salt. But here is my take on it:
You don't need to do anything special.
It is not really a consideration of an application developer as to how and when writes are made to a drive, that is something that is far better controlled by the OS. I know that Windows caches writes to USB drives so I would trust it do handle that.
The only thing you need to consider is that your application will not be installed. So you need to make sure that you design it to run entirely self contained within the directory it is deployed to. You could optionally also make some writes to the users home directory but this needs to be done through the appropriate environment variables.
I would get writing and see if there is anything special about a flash drive that the OS doesn't handle.

Categories