I have a custom developed USB card reader. I am using the following code to interact and iterrate over the device:
http://www.codeproject.com/KB/system/usbeject.aspx
The code above provides an 'eject' method using the following line:
Native.CM_Request_Device_Eject_NoUi(device.InstanceHandle, IntPtr.Zero, null, 0, 0);
However this 'eject' method unmounts the entire drive instead of simply ejecting the media card.
Why this is a problem is because I want to 'eject' the media card, then put in a different one. However when the whole reader is ejected i have to unplug/replug the device for it to show back up.
In windows explorer when I right click 'eject' it operates as I am imagining, where it safely removes the memory card but not the card reader.
How can I go about implementing this different type of eject in c#?
I came here accidentally while doing a search on "CM_Request_Device_Eject_NoUi", and saw that it was similar to a solution I'd recently done by pulling together similar pieces of a solution. Forgive the late answers.
Here's what worked for me (this also addresses some issues I've seen on other SO questions regarding AutoEjectVolume from the Microsoft sample not "doing everything" that the system does when you Safely Remove Hardware using the OS):
Start with the steps outlined in How to Eject Removable Media in Windows.
Replace the call to AutoEjectVolume with code that is, in effect, the body of the RemoveDrive method from How to Prepare a USB Drive for Safe Removal. Note that this later work relies heavily on two other CodeProject articles — including the one you referenced in your question — ported to C#.
In 2, I say "in effect" because — in practice — you use the same hVolume in both solutions, and it makes more sense to do all the checks in the CodeProject RemoveDrive method before calling LockVolume, DismountVolume, or PrepareRemovalOfVolume in the Microsoft solution, and then call CM_Request_Device_Eject_NoUi as shown in the CodeProject solution.
A short pseudo-code summary:
Open the volume with CreateFile (CodeProject)
Obtain drive's device instance handle and drive's parent's device
instance handle (CodeProject)
Exit before calling — in particular — DismountVolume,
if any of the steps above fail (CodeProject)
Call LockVolume, DismountVolume, and PrepareRemovalOfVolume
using the hVolume returned from CreateFile (Microsoft)
You can close the hVolume at any time after this
Call CM_Request_Device_Eject_NoUi on the drive's parent's device
instance handle (CodeProject)
Related
Have been struggling with finding a way to stream audio, from a file or web, to a specific output device, not just the default one. Tried using mciSendString and while the open command does accept a device id/filename I haven't found a way to make use of it, am not even sure if this is what I am looking for or not, but considering it says ... or the filename of the device driver am guessing yes(?), but correct me if I am wrong, and this isn't a specify your output device type parameter.
If it is the correct thing then how do you enumerate the installed device drivers, have looked into the IMMDevice interface because it seamed like it could have the file names stored in the registry, but non of the output device registry keys had a driver filename type value entry, or at least I haven't found one.
So my question is, how would you go about streaming audio to a specific output device, it doesn't have to be done through mciSendString, that's just something I looked into as it's one of the most talked about function when it comes to playing audio.
Note: please do not recommend me 3rd party libraries like NAudio, the reason I am asking this question is not get recommendations for libraries, otherwise I would have already used one and would have never written this, have just seen a lot of answers be like: Use {LibName}, it has what you want or something along those lines.
In case what's written is odd or incorrectly worded in places, basically this is what the end goal should be:
Installed Output Devices:
- Output1
- Output2
- Output3
Method For Playing:
//will play x.mp3 through output device 1
PlayAudio(output: "Output1", mp3File: "x.mp3");
//will play x.mp3 through output device 2
PlayAudio(output: "Output2", mp3File: "x.mp3");
//will play x.mp3 through output device 3
PlayAudio(output: "Output3", mp3File: "x.mp3");
You seem to be looking for this API:mciSendCommand()
To set the WaveAudio device (soundcard) used by the Multimedia
Control, you must use the mciSendCommand API. The Multimedia Control
does not directly provide a method to let you set the device used for
playing or recording.
Call mciSendCommand() with MCI_SET & MCI_WAVE_SET_PARMS
setting wOutput to the desired playback device's ID.
Then get IDDevice for mciSendCommand() via
mciGetDeviceID("waveaudio")
Its not 100% clear what wOutput wants, its probably the same ID as returned by waveOutGetDevCaps()
I am just a porter.
Please refer:
https://stackoverflow.com/a/13320137/11128312
https://stackoverflow.com/a/10968887/11128312
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.
For my project I need a way to get data regarding screens that are connected.
In specific, I need to identify whether a monitor is a laptop internal screen or an external screen, and get all the screen data.
I need to get this information both in c++ and C#.
I read about Win32_DesktopMonitor, about EnumDisplayDevices and about Screen Class.
I read also some related questions here:
Monitor ID and Serial Number
Find Number and resolution to all monitors
EnumDisplayDevices vs WMI Win32_DesktopMonitor, how to detect active monitors?
I havn't found an answer yet. Any Ideas?
To get the information whether monitor is internal you can use WMI class WmiMonitorConnectionParams from root\wmi namespace.
Code would need to create a CimSession by connecting to WMI either through DCOM or WinRM (with authentication as needed if enumerating remote computer monitors), then call EnumerateInstances(#"root\wmi", "WmiMonitorConnectionParams") on that session.
Resulting collection will contain InstanceName (string) and VideoOutputTechnology (UInt32).
You will need both for each monitor so you can match them with the other stuff you need.
If VideoOutputTechnology is 0xFFFFFFFF, then that's the Default Monitor entry and it can be ignored. If it is 0x80000000, then it is internal. Other types of connection are documented in d3dkmdt.h header file (online documentation at the moment of this writing does not provide correct values for the enum).
The most reliable way to get model, serial number, as well as year and week of manufacture is by reading and parsing the raw EDID block (by calling WmiGetMonitorRawEEdidV1Block).
I hope you can get by on your own from here.
What you can do is query the Windows WMI classes:
http://msdn.microsoft.com/en-us/library/aa394554(v=vs.85).aspx
Those classes allows the user to collect various information about the computer (hardware, os, ...)
I don't know if you'll find the properties you need, but it might be worth a look.
You're looking for this class:
http://msdn.microsoft.com/en-us/library/aa394122(v=vs.85).aspx
Could anyone please give me any idea as to where to start my coding in order to get data from OPOS(Datalogic Magellan device) weighting and barcode scanning in C#?? For example, what library and what function I should be using for this case. I am clueless as I have already spent numerous of hours searching for an answer online. Not even came close online.
I don't know any api that I can use to get the weight and barcode for the usb device into my C# program.
I am currently using Datalogic scale. I tried the build-in windows reader but it didn't read in any data from the device.
First off, I used the Microsoft.PointOfService library which can directly create connection to most of the opos base machine. And make sure you have your Logical Device Name right! Very Very important. This is NOT any normal name you found in your regedit, it MUST be define manually by yourself inside the opos adk program that you installed along with the opos machine.
Then you can pass in the name as usual in your C# program.
For example: you set USB_Scale as your logical device name inside OPOS program
in C#
this.myDevice = explore.GetDevice("Scale", "USB_Scale");
Note: Make sure you set claim to 1000; It might not work if you didn't do so.
Also : this.myScale = ((Scale)explore.CreateInstance(myDevice)); <- this might help~
The rest is just straight forward.
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.